diff --git a/.gitignore b/.gitignore index 184b8ef1b4c..a718e42dcd1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,6 +1,5 @@ *-debug.log *-error.log -/dist /tmp node_modules !**/__fixtures__/**/node_modules diff --git a/dist/commands/ai/ai-start.d.ts b/dist/commands/ai/ai-start.d.ts new file mode 100644 index 00000000000..5c96e8f1e3f --- /dev/null +++ b/dist/commands/ai/ai-start.d.ts @@ -0,0 +1,8 @@ +import type { OptionValues } from 'commander'; +import type BaseCommand from '../base-command.js'; +interface AIStartOptions extends OptionValues { + debug?: boolean; +} +export declare const aiStartCommand: (options: AIStartOptions, command: BaseCommand) => Promise; +export {}; +//# sourceMappingURL=ai-start.d.ts.map \ No newline at end of file diff --git a/dist/commands/ai/ai-start.d.ts.map b/dist/commands/ai/ai-start.d.ts.map new file mode 100644 index 00000000000..d9fda3f9b50 --- /dev/null +++ b/dist/commands/ai/ai-start.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ai-start.d.ts","sourceRoot":"","sources":["../../../src/commands/ai/ai-start.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAS7C,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAajD,UAAU,cAAe,SAAQ,YAAY;IAC3C,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAuYD,eAAO,MAAM,cAAc,GAAU,SAAS,cAAc,EAAE,SAAS,WAAW,KAAG,OAAO,CAAC,IAAI,CAsGhG,CAAA"} \ No newline at end of file diff --git a/dist/commands/ai/ai-start.js b/dist/commands/ai/ai-start.js new file mode 100644 index 00000000000..e12e11c88e8 --- /dev/null +++ b/dist/commands/ai/ai-start.js @@ -0,0 +1,439 @@ +import { resolve } from 'node:path'; +import { promises as fs } from 'node:fs'; +import { chalk, log, logAndThrowError } from '../../utils/command-helpers.js'; +import { normalizeRepoUrl } from '../../utils/normalize-repo-url.js'; +import { runGit } from '../../utils/run-git.js'; +import { startSpinner } from '../../lib/spinner.js'; +import { getContextConsumers } from '../../recipes/ai-context/context.js'; +import execa from '../../utils/execa.js'; +import { version } from '../../utils/command-helpers.js'; +import inquirer from 'inquirer'; +// Check if a command belongs to a known IDE (reusing ai-context logic) +const getConsumerKeyFromCommand = (command, consumers) => { + const match = consumers.find((consumer) => consumer.consumerProcessCmd && command.includes(consumer.consumerProcessCmd)); + return match ? match.key : null; +}; +// Get command and parent PID (same logic as ai-context) +const getCommandAndParentPID = async (pid) => { + const { stdout } = await execa('ps', ['-p', String(pid), '-o', 'ppid=,comm=']); + const output = stdout.trim(); + const spaceIndex = output.indexOf(' '); + const parentPID = output.substring(0, spaceIndex); + const command = output.substring(spaceIndex + 1).toLowerCase(); + const consumers = await getContextConsumers(version); // Use current CLI version + return { + parentPID: Number(parentPID), + command, + consumerKey: getConsumerKeyFromCommand(command, consumers), + }; +}; +// Detect IDE by walking up process tree (same logic as ai-context) +const detectIDE = async () => { + if (process.env.AI_CONTEXT_SKIP_DETECTION === 'true') { + return null; + } + const ppid = process.ppid; + let result; + try { + result = await getCommandAndParentPID(ppid); + while (result.parentPID !== 1 && !result.consumerKey) { + result = await getCommandAndParentPID(result.parentPID); + } + } + catch { + // Process detection failed + return null; + } + if (result.consumerKey) { + const consumers = await getContextConsumers(version); + const contextConsumer = consumers.find((consumer) => consumer.key === result.consumerKey); + if (contextConsumer) { + return contextConsumer; + } + } + return null; +}; +// Generate MCP configuration for the detected IDE +const generateMcpConfig = (ide) => { + const configs = { + vscode: JSON.stringify({ + servers: { + netlify: { + type: 'stdio', + command: 'npx', + args: ['-y', '@netlify/mcp'], + }, + }, + }, null, 2), + cursor: JSON.stringify({ + mcpServers: { + netlify: { + command: 'npx', + args: ['-y', '@netlify/mcp'], + }, + }, + }, null, 2), + windsurf: JSON.stringify({ + mcpServers: { + netlify: { + command: 'npx', + args: ['-y', '@netlify/mcp'], + }, + }, + }, null, 2), + }; + return (configs[ide.key] || + JSON.stringify({ + mcpServers: { + netlify: { + command: 'npx', + args: ['-y', '@netlify/mcp'], + }, + }, + }, null, 2)); +}; +// Trigger IDE-specific MCP configuration +const triggerMcpConfiguration = async (ide, projectPath) => { + log(`\n${chalk.blue('šŸ”§ MCP Configuration for')} ${chalk.cyan(ide.presentedName)}`); + const { shouldConfigure } = await inquirer.prompt([ + { + type: 'confirm', + name: 'shouldConfigure', + message: `Would you like to automatically configure MCP server for ${ide.presentedName}?`, + default: true, + }, + ]); + if (!shouldConfigure) { + log(chalk.gray('Skipped MCP configuration. You can set it up manually later.')); + return false; + } + try { + const config = generateMcpConfig(ide); + // IDE-specific configuration actions + switch (ide.key) { + case 'vscode': + await configureMcpForVSCode(config, projectPath); + break; + case 'cursor': + await configureMcpForCursor(config, projectPath); + break; + case 'windsurf': + await configureMcpForWindsurf(config, projectPath); + break; + default: + showGenericMcpConfig(config, ide.presentedName); + } + log(`${chalk.green('āœ…')} MCP configuration completed for ${chalk.cyan(ide.presentedName)}`); + return true; + } + catch (error) { + log(`${chalk.red('āŒ')} Failed to configure MCP: ${error instanceof Error ? error.message : 'Unknown error'}`); + return false; + } +}; +// VS Code specific MCP configuration +const configureMcpForVSCode = async (config, projectPath) => { + const configPath = resolve(projectPath, '.vscode', 'mcp.json'); + try { + // Create .vscode directory if it doesn't exist + await fs.mkdir(resolve(projectPath, '.vscode'), { recursive: true }); + // Write or update mcp.json + let existingConfig = {}; + try { + const existingContent = await fs.readFile(configPath, 'utf-8'); + existingConfig = JSON.parse(existingContent); + } + catch { + // File doesn't exist or is invalid JSON + } + const mcpConfig = JSON.parse(config); + const updatedConfig = { ...existingConfig, ...mcpConfig }; + await fs.writeFile(configPath, JSON.stringify(updatedConfig, null, 2), 'utf-8'); + log(`${chalk.green('āœ…')} VS Code MCP configuration saved to ${chalk.cyan('.vscode/mcp.json')}`); + } + catch (error) { + throw new Error(`Failed to configure VS Code MCP: ${error instanceof Error ? error.message : 'Unknown error'}`); + } +}; +// Cursor specific MCP configuration +const configureMcpForCursor = async (config, projectPath) => { + const configPath = resolve(projectPath, '.cursor', 'mcp.json'); + try { + await fs.mkdir(resolve(projectPath, '.cursor'), { recursive: true }); + await fs.writeFile(configPath, config, 'utf-8'); + log(`${chalk.green('āœ…')} Cursor MCP configuration saved to ${chalk.cyan('.cursor/mcp.json')}`); + } + catch (error) { + throw new Error(`Failed to configure Cursor MCP: ${error instanceof Error ? error.message : 'Unknown error'}`); + } +}; +// Windsurf specific MCP configuration +const configureMcpForWindsurf = async (config, _projectPath) => { + const { homedir } = await import('node:os'); + const configPath = resolve(homedir(), '.codeium', 'windsurf', 'mcp_config.json'); + try { + // Create .codeium/windsurf directory if it doesn't exist + await fs.mkdir(resolve(homedir(), '.codeium', 'windsurf'), { recursive: true }); + // Read existing config or create new one + let existingConfig = {}; + try { + const existingContent = await fs.readFile(configPath, 'utf-8'); + existingConfig = JSON.parse(existingContent); + } + catch { + // File doesn't exist or is invalid JSON + } + const mcpConfig = JSON.parse(config); + // Merge mcpServers from both configs + const existingServers = existingConfig.mcpServers ?? {}; + const newServers = mcpConfig.mcpServers ?? {}; + const updatedConfig = { + ...existingConfig, + mcpServers: { + ...existingServers, + ...newServers, + }, + }; + await fs.writeFile(configPath, JSON.stringify(updatedConfig, null, 2), 'utf-8'); + log(`${chalk.green('āœ…')} Windsurf MCP configuration saved to global config`); + log(`${chalk.gray('šŸ’”')} Restart Windsurf to activate the MCP server`); + } + catch (error) { + throw new Error(`Failed to configure Windsurf MCP: ${error instanceof Error ? error.message : 'Unknown error'}`); + } +}; +// Generic MCP configuration display +const showGenericMcpConfig = (config, ideName) => { + log(`\n${chalk.yellow('šŸ“‹ Manual Configuration Required')}`); + log(`Please add the following configuration to your ${ideName} settings:`); + log(`\n${chalk.gray('--- Configuration ---')}`); + log(config); + log(`${chalk.gray('--- End Configuration ---')}\n`); +}; +// Try to automatically activate MCP in the detected IDE +const tryActivateMcp = async (ide, projectPath) => { + try { + switch (ide.key) { + case 'vscode': + return await activateMcpInVSCode(projectPath); + case 'cursor': + return await activateMcpInCursor(projectPath); + case 'windsurf': + return await activateMcpInWindsurf(projectPath); + default: + return false; + } + } + catch (_) { + // Silent fail - activation is best effort + return false; + } +}; +// Activate MCP in VS Code +const activateMcpInVSCode = async (projectPath) => { + try { + // Try to reload VS Code window via command palette + // This uses VS Code's command line interface + await execa('code', ['--command', 'workbench.action.reloadWindow'], { + cwd: projectPath, + timeout: 5000, + }); + return true; + } + catch { + // Try alternative: send reload command via VS Code extension API + try { + await execa('code', ['--command', 'developer.reloadWindow'], { + cwd: projectPath, + timeout: 5000, + }); + return true; + } + catch { + return false; + } + } +}; +// Activate MCP in Cursor +const activateMcpInCursor = async (projectPath) => { + try { + // Cursor might support similar command line interface + await execa('cursor', ['--command', 'workbench.action.reloadWindow'], { + cwd: projectPath, + timeout: 5000, + }); + return true; + } + catch { + return false; + } +}; +// Activate MCP in Windsurf +const activateMcpInWindsurf = async (projectPath) => { + try { + // Windsurf-specific activation (placeholder - would need actual API) + // For now, try to signal the IDE to reload configuration + await execa('windsurf', ['--reload-config'], { + cwd: projectPath, + timeout: 5000, + }); + return true; + } + catch { + return false; + } +}; +// Move helper functions to a separate utils file +const decodeHash = (hash) => { + try { + return atob(hash); + } + catch (error) { + throw new Error(`Failed to decode hash: ${error instanceof Error ? error.message : 'Invalid base64 or URL'}`); + } +}; +const fetchProjectInfo = async (url) => { + try { + const response = await fetch(url, { + headers: { + 'content-type': 'text/plain', + }, + }); + if (!response.ok) { + throw new Error(`HTTP error! status: ${String(response.status)}`); + } + const data = (await response.text()); + const parsedData = JSON.parse(data); + return parsedData; + } + catch (error) { + throw new Error(`Failed to fetch project information: ${error instanceof Error ? error.message : 'Unknown error'}`); + } +}; +const getRepoUrlFromProjectId = async (api, projectId) => { + try { + const SiteInfo = (await api.getSite({ siteId: projectId })); + const repoUrl = SiteInfo.build_settings?.repo_url; + if (!repoUrl) { + throw new Error(`No repository URL found for project ID: ${projectId}`); + } + return repoUrl; + } + catch (error) { + if (error.status === 404) { + throw new Error(`Project with ID ${projectId} not found`); + } + throw new Error(`Failed to fetch project data: ${error.message}`); + } +}; +const savePrompt = async (instructions, targetDir) => { + try { + const filePath = resolve(targetDir, 'AI-instructions.md'); + await fs.writeFile(filePath, instructions, 'utf-8'); + log(`${chalk.green('āœ…')} AI instructions saved to ${chalk.cyan('AI-instructions.md')}`); + } + catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unknown error'; + log(`${chalk.yellow('āš ļø')} Warning: Failed to save AI instructions: ${errorMessage}`); + } +}; +const cloneRepo = async (repoUrl, targetDir, debug) => { + try { + await runGit(['clone', repoUrl, targetDir], !debug); + } + catch (error) { + throw new Error(`Failed to clone repository: ${error instanceof Error ? error.message : error?.toString() ?? ''}`); + } +}; +export const aiStartCommand = async (options, command) => { + const hash = command.args[0]; + // Validate hash parameter + if (!hash) { + log(`${chalk.red('Error:')} Hash parameter is required`); + log(`${chalk.gray('Usage:')} netlify ai:start `); + return; + } + // Authenticate first before any API operations + await command.authenticate(); + const { api } = command.netlify; + log(`${chalk.blue('šŸ¤– AI Start')} - Initializing AI project...`); + log(`${chalk.gray('Hash:')} ${hash}`); + log(`${chalk.gray('User:')} ${api.accessToken ? 'Authenticated āœ…' : 'Not authenticated āŒ'}`); + try { + // Step 1: Decode hash and fetch project information + log('\nšŸ“‹ Decoding project hash...'); + const decodedUrl = decodeHash(hash); + log(`${chalk.cyan('Decoded URL:')} ${decodedUrl}`); + log('\nšŸ” Fetching project information...'); + const projectInfo = await fetchProjectInfo(decodedUrl); + log(`${chalk.cyan('Project ID:')} ${projectInfo.projectId}`); + // Step 2: Get repository URL from project ID via Netlify site API + log('\nšŸ”— Linking to Netlify site and fetching repository...'); + const repositoryUrl = await getRepoUrlFromProjectId(api, projectInfo.projectId); + log(`${chalk.cyan('Repository:')} ${repositoryUrl}`); + // Step 3: Clone repository + const { repoUrl, repoName } = normalizeRepoUrl(repositoryUrl); + const targetDir = `ai-project-${repoName}-${hash.substring(0, 8)}`; + const cloneSpinner = startSpinner({ text: `Cloning repository to ${chalk.cyan(targetDir)}` }); + await cloneRepo(repoUrl, targetDir, Boolean(options.debug)); + cloneSpinner.success({ text: `Cloned repository to ${chalk.cyan(targetDir)}` }); + // Step 4: Save AI instructions to file + if (projectInfo.prompt) { + log('\nšŸ“ Saving AI instructions...'); + await savePrompt(projectInfo.prompt, targetDir); + } + // Step 5: Detect IDE and configure MCP server + log('\nšŸ” Detecting development environment...'); + const detectedIDE = await detectIDE(); + let mcpConfigured = false; + if (detectedIDE) { + log(`${chalk.green('āœ…')} Detected IDE: ${chalk.cyan(detectedIDE.presentedName)}`); + mcpConfigured = await triggerMcpConfiguration(detectedIDE, targetDir); + } + // Update working directory to cloned repo + process.chdir(targetDir); + command.workingDir = targetDir; + // Success message with next steps + log(); + log(chalk.green('āœ” Your AI project is ready to go!')); + log(`→ Project ID: ${chalk.cyanBright(projectInfo.projectId)}`); + log(`→ Project cloned to: ${chalk.cyanBright(targetDir)}`); + if (projectInfo.prompt) { + log(`→ AI instructions saved: ${chalk.cyanBright('AI-instructions.md')}`); + } + log(); + log(chalk.yellowBright(`šŸ“ Step 1: Enter your project directory`)); + log(` ${chalk.cyanBright(`cd ${targetDir}`)}`); + if (detectedIDE) { + if (mcpConfigured) { + log(chalk.yellowBright(`šŸ”§ Step 2: MCP Server Configured`)); + log(` ${chalk.green('āœ…')} ${chalk.cyan(detectedIDE.presentedName)} is ready with Netlify MCP server`); + // Try to automatically activate MCP in the IDE + const activated = await tryActivateMcp(detectedIDE, targetDir); + if (activated) { + log(` ${chalk.green('šŸš€')} MCP server automatically activated`); + } + else { + log(` ${chalk.gray('šŸ’” MCP will activate when you reload/restart your IDE window')}`); + } + } + else { + log(chalk.yellowBright(`šŸ”§ Step 2: Manual MCP Configuration`)); + log(` ${chalk.cyan(detectedIDE.presentedName)} detected - MCP setup was skipped`); + log(` ${chalk.gray('You can configure MCP manually later for enhanced AI capabilities')}`); + } + log(); + } + if (projectInfo.prompt) { + const stepNumber = detectedIDE ? '3' : '2'; + log(chalk.yellowBright(`šŸ¤– Step ${stepNumber}: Ask your AI assistant to process the instructions`)); + log(); + log(chalk.bgGreen.black.bold(` follow instructions in ${targetDir}/AI-instructions.md `)); + log(); + } + } + catch (error) { + return logAndThrowError(error); + } +}; +//# sourceMappingURL=ai-start.js.map \ No newline at end of file diff --git a/dist/commands/ai/ai-start.js.map b/dist/commands/ai/ai-start.js.map new file mode 100644 index 00000000000..6537e19de4a --- /dev/null +++ b/dist/commands/ai/ai-start.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ai-start.js","sourceRoot":"","sources":["../../../src/commands/ai/ai-start.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/ai/ai.d.ts b/dist/commands/ai/ai.d.ts new file mode 100644 index 00000000000..07ae9d0d9a1 --- /dev/null +++ b/dist/commands/ai/ai.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const aiCommand: (_options: OptionValues, _command: BaseCommand) => void; +//# sourceMappingURL=ai.d.ts.map \ No newline at end of file diff --git a/dist/commands/ai/ai.d.ts.map b/dist/commands/ai/ai.d.ts.map new file mode 100644 index 00000000000..68655da9b61 --- /dev/null +++ b/dist/commands/ai/ai.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../../src/commands/ai/ai.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAGxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,SAAS,GAAI,UAAU,YAAY,EAAE,UAAU,WAAW,SAsBtE,CAAA"} \ No newline at end of file diff --git a/dist/commands/ai/ai.js b/dist/commands/ai/ai.js new file mode 100644 index 00000000000..d91e1d60180 --- /dev/null +++ b/dist/commands/ai/ai.js @@ -0,0 +1,25 @@ +import { chalk, log } from '../../utils/command-helpers.js'; +export const aiCommand = (_options, _command) => { + log(`${chalk.greenBright('šŸ¤– Netlify AI Assistant')} + +Welcome to the Netlify AI command! This is a foundation for AI-powered development tools. + +${chalk.gray('This command is currently in development. More features coming soon!')} + +Available commands: + ${chalk.cyan('ai:start ')} Start AI project initialization with hash + +Available options: + ${chalk.cyan('--help')} Show this help message + +${chalk.gray('Usage examples:')} + ${chalk.gray('netlify ai:start abc123def456')} + +${chalk.gray('Future features will include:')} + • Project analysis and optimization suggestions + • Configuration generation and optimization + • Advanced AI-powered development assistance + +Use ${chalk.cyan('netlify ai --help')} or ${chalk.cyan('netlify ai start --help')} for more information.`); +}; +//# sourceMappingURL=ai.js.map \ No newline at end of file diff --git a/dist/commands/ai/ai.js.map b/dist/commands/ai/ai.js.map new file mode 100644 index 00000000000..c339e2ce522 --- /dev/null +++ b/dist/commands/ai/ai.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ai.js","sourceRoot":"","sources":["../../../src/commands/ai/ai.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAA;AAG3D,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,QAAsB,EAAE,QAAqB,EAAE,EAAE;IACzE,GAAG,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,yBAAyB,CAAC;;;;EAInD,KAAK,CAAC,IAAI,CAAC,sEAAsE,CAAC;;;IAGhF,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC;;;IAG7B,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC;;EAEtB,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC;;EAE7C,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC;;;;;MAKvC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,yBAAyB,CAAC,wBAAwB,CAAC,CAAA;AAC1G,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/ai/index.d.ts b/dist/commands/ai/index.d.ts new file mode 100644 index 00000000000..2ba935c799c --- /dev/null +++ b/dist/commands/ai/index.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const createAiCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/ai/index.d.ts.map b/dist/commands/ai/index.d.ts.map new file mode 100644 index 00000000000..b336768d013 --- /dev/null +++ b/dist/commands/ai/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/ai/index.ts"],"names":[],"mappings":"AAEA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,eAAe,GAAI,SAAS,WAAW,gBAoBnD,CAAA"} \ No newline at end of file diff --git a/dist/commands/ai/index.js b/dist/commands/ai/index.js new file mode 100644 index 00000000000..a0b50580c64 --- /dev/null +++ b/dist/commands/ai/index.js @@ -0,0 +1,21 @@ +export const createAiCommand = (program) => { + // Add ai:start subcommand following CLI convention + program + .command('ai:start') + .argument('', 'Project hash for AI initialization') + .description('Start AI project initialization with hash') + .action(async (hash, options, command) => { + // Set the hash as the first argument for the command + command.args = [hash]; + const { aiStartCommand } = await import('./ai-start.js'); + await aiStartCommand(options, command); + }); + return program + .command('ai') + .description('AI-powered development tools') + .action(async (options, command) => { + const { aiCommand: mainAiCommand } = await import('./ai.js'); + mainAiCommand(options, command); + }); +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/ai/index.js.map b/dist/commands/ai/index.js.map new file mode 100644 index 00000000000..3e69b409ea3 --- /dev/null +++ b/dist/commands/ai/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/ai/index.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,OAAoB,EAAE,EAAE;IACtD,mDAAmD;IACnD,OAAO;SACJ,OAAO,CAAC,UAAU,CAAC;SACnB,QAAQ,CAAC,QAAQ,EAAE,oCAAoC,CAAC;SACxD,WAAW,CAAC,2CAA2C,CAAC;SACxD,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;QAC1E,qDAAqD;QACrD,OAAO,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,CAAA;QACrB,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAA;QACxD,MAAM,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEJ,OAAO,OAAO;SACX,OAAO,CAAC,IAAI,CAAC;SACb,WAAW,CAAC,8BAA8B,CAAC;SAC3C,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;QAC5D,MAAM,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,CAAA;QAC5D,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACjC,CAAC,CAAC,CAAA;AACN,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/api/api.d.ts b/dist/commands/api/api.d.ts new file mode 100644 index 00000000000..89e448393bf --- /dev/null +++ b/dist/commands/api/api.d.ts @@ -0,0 +1,4 @@ +import type { OptionValues } from 'commander'; +import type BaseCommand from '../base-command.js'; +export declare const apiCommand: (apiMethodName: string, options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=api.d.ts.map \ No newline at end of file diff --git a/dist/commands/api/api.d.ts.map b/dist/commands/api/api.d.ts.map new file mode 100644 index 00000000000..fc86bd1ee07 --- /dev/null +++ b/dist/commands/api/api.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../../src/commands/api/api.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAG7C,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAOjD,eAAO,MAAM,UAAU,GAAU,eAAe,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,uBAwClG,CAAA"} \ No newline at end of file diff --git a/dist/commands/api/api.js b/dist/commands/api/api.js new file mode 100644 index 00000000000..e71aaca7115 --- /dev/null +++ b/dist/commands/api/api.js @@ -0,0 +1,42 @@ +import { methods } from '@netlify/api'; +import AsciiTable from 'ascii-table'; +import { chalk, logAndThrowError, exit, log, logJson } from '../../utils/command-helpers.js'; +const isValidApiMethod = (api, apiMethod) => Object.hasOwn(api, apiMethod); +export const apiCommand = async (apiMethodName, options, command) => { + const { api } = command.netlify; + if (options.list) { + const table = new AsciiTable(`Netlify API Methods`); + table.setHeading('API Method', 'Docs Link'); + methods.forEach((method) => { + const { operationId } = method; + table.addRow(operationId, `https://open-api.netlify.com/#operation/${operationId}`); + }); + log(table.toString()); + log(); + log('Above is a list of available API methods'); + log(`To run a method use "${chalk.cyanBright('netlify api methodName')}"`); + exit(); + } + if (!apiMethodName) { + return logAndThrowError(`You must provide an API method. Run "netlify api --list" to see available methods`); + } + if (!(isValidApiMethod(api, apiMethodName) && typeof api[apiMethodName] === 'function')) { + return logAndThrowError(`"${apiMethodName}"" is not a valid api method. Run "netlify api --list" to see available methods`); + } + const apiMethod = api[apiMethodName].bind(api); + let payload; + if (options.data) { + payload = typeof options.data === 'string' ? JSON.parse(options.data) : options.data; + } + else { + payload = {}; + } + try { + const apiResponse = await apiMethod(payload); + logJson(apiResponse); + } + catch (error_) { + return logAndThrowError(error_); + } +}; +//# sourceMappingURL=api.js.map \ No newline at end of file diff --git a/dist/commands/api/api.js.map b/dist/commands/api/api.js.map new file mode 100644 index 00000000000..7e878fca1c2 --- /dev/null +++ b/dist/commands/api/api.js.map @@ -0,0 +1 @@ +{"version":3,"file":"api.js","sourceRoot":"","sources":["../../../src/commands/api/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAmB,MAAM,cAAc,CAAA;AACvD,OAAO,UAAU,MAAM,aAAa,CAAA;AAGpC,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAK5F,MAAM,gBAAgB,GAAG,CAAC,GAAe,EAAE,SAAiB,EAA8B,EAAE,CAC1F,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;AAE/B,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,aAAqB,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IACrG,MAAM,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IAE/B,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,qBAAqB,CAAC,CAAA;QACnD,KAAK,CAAC,UAAU,CAAC,YAAY,EAAE,WAAW,CAAC,CAAA;QAC3C,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;YACzB,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,CAAA;YAC9B,KAAK,CAAC,MAAM,CAAC,WAAW,EAAE,2CAA2C,WAAW,EAAE,CAAC,CAAA;QACrF,CAAC,CAAC,CAAA;QACF,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAA;QACrB,GAAG,EAAE,CAAA;QACL,GAAG,CAAC,0CAA0C,CAAC,CAAA;QAC/C,GAAG,CAAC,wBAAwB,KAAK,CAAC,UAAU,CAAC,wBAAwB,CAAC,GAAG,CAAC,CAAA;QAC1E,IAAI,EAAE,CAAA;IACR,CAAC;IAED,IAAI,CAAC,aAAa,EAAE,CAAC;QACnB,OAAO,gBAAgB,CAAC,mFAAmF,CAAC,CAAA;IAC9G,CAAC;IAED,IAAI,CAAC,CAAC,gBAAgB,CAAC,GAAG,EAAE,aAAa,CAAC,IAAI,OAAO,GAAG,CAAC,aAAa,CAAC,KAAK,UAAU,CAAC,EAAE,CAAC;QACxF,OAAO,gBAAgB,CACrB,IAAI,aAAa,iFAAiF,CACnG,CAAA;IACH,CAAC;IACD,MAAM,SAAS,GAAG,GAAG,CAAC,aAAa,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IAE9C,IAAI,OAAO,CAAA;IACX,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,GAAG,OAAO,OAAO,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAA;IACtF,CAAC;SAAM,CAAC;QACN,OAAO,GAAG,EAAE,CAAA;IACd,CAAC;IACD,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,SAAS,CAAC,OAAO,CAAC,CAAA;QAC5C,OAAO,CAAC,WAAW,CAAC,CAAA;IACtB,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACjC,CAAC;AACH,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/api/index.d.ts b/dist/commands/api/index.d.ts new file mode 100644 index 00000000000..b1f09a66305 --- /dev/null +++ b/dist/commands/api/index.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const createApiCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/api/index.d.ts.map b/dist/commands/api/index.d.ts.map new file mode 100644 index 00000000000..757df350027 --- /dev/null +++ b/dist/commands/api/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/api/index.ts"],"names":[],"mappings":"AACA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,gBAAgB,GAAI,SAAS,WAAW,gBAgB/C,CAAA"} \ No newline at end of file diff --git a/dist/commands/api/index.js b/dist/commands/api/index.js new file mode 100644 index 00000000000..44d27ca2964 --- /dev/null +++ b/dist/commands/api/index.js @@ -0,0 +1,14 @@ +import { chalk } from '../../utils/command-helpers.js'; +export const createApiCommand = (program) => program + .command('api') + .argument('[apiMethod]', 'Open API method to run') + .description(`Run any Netlify API method +For more information on available methods check out https://open-api.netlify.com/ or run '${chalk.grey('netlify api --list')}'`) + .option('-d, --data ', 'Data to use') + .option('--list', 'List out available API methods', false) + .addExamples(['netlify api --list', `netlify api getSite --data '{ "site_id": "123456" }'`]) + .action(async (apiMethod, options, command) => { + const { apiCommand } = await import('./api.js'); + await apiCommand(apiMethod, options, command); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/api/index.js.map b/dist/commands/api/index.js.map new file mode 100644 index 00000000000..2b032e237e8 --- /dev/null +++ b/dist/commands/api/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/api/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAA;AAGtD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,OAAoB,EAAE,EAAE,CACvD,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,QAAQ,CAAC,aAAa,EAAE,wBAAwB,CAAC;KACjD,WAAW,CACV;4FACsF,KAAK,CAAC,IAAI,CAC9F,oBAAoB,CACrB,GAAG,CACL;KACA,MAAM,CAAC,mBAAmB,EAAE,aAAa,CAAC;KAC1C,MAAM,CAAC,QAAQ,EAAE,gCAAgC,EAAE,KAAK,CAAC;KACzD,WAAW,CAAC,CAAC,oBAAoB,EAAE,sDAAsD,CAAC,CAAC;KAC3F,MAAM,CAAC,KAAK,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;IAC5C,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,MAAM,CAAC,UAAU,CAAC,CAAA;IAC/C,MAAM,UAAU,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;AAC/C,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/base-command.d.ts b/dist/commands/base-command.d.ts new file mode 100644 index 00000000000..3e496ce542c --- /dev/null +++ b/dist/commands/base-command.d.ts @@ -0,0 +1,94 @@ +import { Project } from '@netlify/build-info'; +import { Command, Help, type OptionValues } from 'commander'; +import type { FeatureFlags } from '../utils/feature-flags.js'; +import type { NetlifyOptions } from './types.js'; +import type { CachedConfig } from '../lib/build.js'; +type Analytics = { + startTime: bigint; + payload?: Record; +}; +export type BaseOptionValues = { + auth?: string; + cwd?: string; + debug?: boolean; + filter?: string; + httpProxy?: string; + silent?: string; +}; +/** Base command class that provides tracking and config initialization */ +export default class BaseCommand extends Command { + #private; + /** The netlify object inside each command with the state */ + netlify: NetlifyOptions; + analytics: Analytics; + project: Project; + /** + * The working directory that is used for reading the `netlify.toml` file and storing the state. + * In a monorepo context this must not be the process working directory and can be an absolute path to the + * Package/Site that should be worked in. + */ + workingDir: string; + /** + * The workspace root if inside a mono repository. + * Must not be the repository root! + */ + jsWorkspaceRoot?: string; + /** The current workspace package we should execute the commands in */ + workspacePackage?: string; + featureFlags: FeatureFlags; + siteId?: string; + accountId?: string; + /** + * IMPORTANT this function will be called for each command! + * Don't do anything expensive in there. + */ + createCommand(name: string): BaseCommand; + /** don't show help options on command overview (mostly used on top commands like `addons` where options only apply on children) */ + noHelpOptions(): this; + /** The examples list for the command (used inside doc generation and help page) */ + examples: string[]; + /** Set examples for the command */ + addExamples(examples: string[]): this; + /** Overrides the help output of commander with custom styling */ + createHelp(): Help; + /** Will be called on the end of an action to track the metrics */ + onEnd(error_?: unknown): Promise; + authenticate(tokenFromFlag?: string): Promise; + expensivelyAuthenticate(): Promise; + /** Adds some data to the analytics payload */ + setAnalyticsPayload(payload: Record): void; + /** + * Initializes the options and parses the configuration needs to be called on start of a command function + */ + private init; + /** Find and resolve the Netlify configuration */ + getConfig(opts: { + cwd: string; + token?: string | null; + offline?: boolean; + /** An optional path to the netlify configuration file e.g. netlify.toml */ + configFilePath?: string; + packagePath?: string; + repositoryRoot?: string; + host?: string; + pathPrefix?: string; + scheme?: string; + }): Promise; + /** + * get a path inside the `.netlify` project folder resolving with the workspace package + */ + getPathInProject(...paths: string[]): string; + /** + * Returns the context that should be used in case one hasn't been explicitly + * set. The default context is `dev` most of the time, but some commands may + * wish to override that. + */ + getDefaultContext(): 'production' | 'dev'; + /** + * Retrieve feature flags for this site + */ + getFeatureFlag(flagName: string): T; +} +export declare const getBaseOptionValues: (options: OptionValues) => BaseOptionValues; +export {}; +//# sourceMappingURL=base-command.d.ts.map \ No newline at end of file diff --git a/dist/commands/base-command.d.ts.map b/dist/commands/base-command.d.ts.map new file mode 100644 index 00000000000..0cbbd53cb27 --- /dev/null +++ b/dist/commands/base-command.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"base-command.d.ts","sourceRoot":"","sources":["../../src/commands/base-command.ts"],"names":[],"mappings":"AAMA,OAAO,EAAiB,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAI5D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAU,KAAK,YAAY,EAAE,MAAM,WAAW,CAAA;AAyBpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAA;AAO7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAEnD,KAAK,SAAS,GAAG;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CAClC,CAAA;AAwHD,MAAM,MAAM,gBAAgB,GAAG;IAC7B,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAED,0EAA0E;AAC1E,MAAM,CAAC,OAAO,OAAO,WAAY,SAAQ,OAAO;;IAC9C,4DAA4D;IAC5D,OAAO,EAAG,cAAc,CAAA;IAGxB,SAAS,EAAE,SAAS,CAAyC;IAC7D,OAAO,EAAG,OAAO,CAAA;IAEjB;;;;OAIG;IAGH,UAAU,SAAgB;IAE1B;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,uEAAuE;IACvE,gBAAgB,CAAC,EAAE,MAAM,CAAA;IAEzB,YAAY,EAAE,YAAY,CAAK;IAC/B,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;IAElB;;;OAGG;IACH,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW;IAwCxC,mIAAmI;IACnI,aAAa;IAKb,mFAAmF;IACnF,QAAQ,EAAE,MAAM,EAAE,CAAK;IACvB,oCAAoC;IACpC,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE;IAK9B,iEAAiE;IACjE,UAAU,IAAI,IAAI;IA8HlB,kEAAkE;IAC5D,KAAK,CAAC,MAAM,CAAC,EAAE,OAAO;IA4BtB,YAAY,CAAC,aAAa,CAAC,EAAE,MAAM;IAQnC,uBAAuB;IA2D7B,8CAA8C;IAC9C,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;IAOpD;;OAEG;YACW,IAAI;IA0MlB,iDAAiD;IAC3C,SAAS,CAAC,IAAI,EAAE;QACpB,GAAG,EAAE,MAAM,CAAA;QACX,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;QACrB,OAAO,CAAC,EAAE,OAAO,CAAA;QACjB,2EAA2E;QAC3E,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,WAAW,CAAC,EAAE,MAAM,CAAA;QACpB,cAAc,CAAC,EAAE,MAAM,CAAA;QACvB,IAAI,CAAC,EAAE,MAAM,CAAA;QACb,UAAU,CAAC,EAAE,MAAM,CAAA;QACnB,MAAM,CAAC,EAAE,MAAM,CAAA;KAChB,GAAG,OAAO,CAAC,YAAY,CAAC;IAkDzB;;OAEG;IACH,gBAAgB,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM;IAI5C;;;;OAIG;IACH,iBAAiB,IAAI,YAAY,GAAG,KAAK;IAIzC;;OAEG;IACH,cAAc,CAAC,CAAC,SAAS,IAAI,GAAG,OAAO,GAAG,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,CAAC;CAKvE;AAED,eAAO,MAAM,mBAAmB,GAAI,SAAS,YAAY,KAAG,gBACc,CAAA"} \ No newline at end of file diff --git a/dist/commands/base-command.js b/dist/commands/base-command.js new file mode 100644 index 00000000000..ddb314e2b4b --- /dev/null +++ b/dist/commands/base-command.js @@ -0,0 +1,625 @@ +import { existsSync } from 'fs'; +import { join, relative, resolve } from 'path'; +import process from 'process'; +import { format } from 'util'; +import { NetlifyAPI } from '@netlify/api'; +import { DefaultLogger, Project } from '@netlify/build-info'; +import { NodeFS, NoopLogger } from '@netlify/build-info/node'; +import { resolveConfig } from '@netlify/config'; +import { isCI } from 'ci-info'; +import { Command, Option } from 'commander'; +import debug from 'debug'; +import { findUp } from 'find-up'; +import inquirer from 'inquirer'; +import inquirerAutocompletePrompt from 'inquirer-autocomplete-prompt'; +import merge from 'lodash/merge.js'; +import pick from 'lodash/pick.js'; +import { getAgent } from '../lib/http-agent.js'; +import { NETLIFY_CYAN, USER_AGENT, chalk, logAndThrowError, exit, getToken, log, version, normalizeConfig, padLeft, pollForToken, sortOptions, warn, logError, } from '../utils/command-helpers.js'; +import { getFrameworksAPIPaths } from '../utils/frameworks-api.js'; +import getGlobalConfigStore from '../utils/get-global-config-store.js'; +import { getSiteByName } from '../utils/get-site.js'; +import openBrowser from '../utils/open-browser.js'; +import CLIState from '../utils/cli-state.js'; +import { identify, reportError, track } from '../utils/telemetry/index.js'; +// load the autocomplete plugin +inquirer.registerPrompt('autocomplete', inquirerAutocompletePrompt); +/** Netlify CLI client id. Lives in bot@netlify.com */ +// TODO: setup client for multiple environments +const CLIENT_ID = 'd6f37de6614df7ae58664cfca524744d73807a377f5ee71f1a254f78412e3750'; +const NANO_SECS_TO_MSECS = 1e6; +/** The fallback width for the help terminal */ +const FALLBACK_HELP_CMD_WIDTH = 80; +const HELP_$ = NETLIFY_CYAN('$'); +/** indent on commands or description on the help page */ +const HELP_INDENT_WIDTH = 2; +/** separator width between term and description */ +const HELP_SEPARATOR_WIDTH = 5; +/** + * A list of commands where we don't have to perform the workspace selection at. + * Those commands work with the system or are not writing any config files that need to be + * workspace aware. + */ +const COMMANDS_WITHOUT_WORKSPACE_OPTIONS = new Set(['api', 'recipes', 'completion', 'status', 'switch', 'login']); +/** + * A list of commands where we need to fetch featureflags for config resolution + */ +const COMMANDS_WITH_FEATURE_FLAGS = new Set(['build', 'dev', 'deploy']); +/** + * Names of options whose values should be scrubbed + */ +const SCRUBBED_OPTIONS = new Set(['auth']); +const getScrubbedOptions = (command) => Object.entries(command.optsWithGlobals()).reduce((acc, [key, value]) => ({ + ...acc, + [key]: { + source: command.getOptionValueSourceWithGlobals(key), + value: SCRUBBED_OPTIONS.has(key) ? '********' : value, + }, +}), {}); +/** Formats a help list correctly with the correct indent */ +const formatHelpList = (textArray) => textArray.join('\n').replace(/^/gm, ' '.repeat(HELP_INDENT_WIDTH)); +/** Get the duration between a start time and the current time */ +const getDuration = (startTime) => { + const durationNs = process.hrtime.bigint() - startTime; + return Math.round(Number(durationNs / BigInt(NANO_SECS_TO_MSECS))); +}; +/** + * Retrieves a workspace package based of the filter flag that is provided. + * If the filter flag does not match a workspace package or is not defined then it will prompt with an autocomplete to select a package + */ +async function selectWorkspace(project, filter) { + // don't show prompt for workspace selection if there is only one package + if (project.workspace?.packages && project.workspace.packages.length === 1) { + return project.workspace.packages[0].path; + } + const selected = project.workspace?.packages.find((pkg) => { + if (project.relativeBaseDirectory && + project.relativeBaseDirectory.length !== 0 && + pkg.path.startsWith(project.relativeBaseDirectory)) { + return true; + } + return (pkg.name && pkg.name === filter) || pkg.path === filter; + }); + if (!selected) { + log(); + log(chalk.cyan(`We've detected multiple projects inside your repository`)); + if (isCI) { + throw new Error(`Projects detected: ${(project.workspace?.packages || []) + .map((pkg) => pkg.name || pkg.path) + .join(', ')}. Configure the project you want to work with and try again. Refer to https://ntl.fyi/configure-site for more information.`); + } + const { result } = await inquirer.prompt({ + name: 'result', + // @ts-expect-error(serhalp) -- I think this is because `inquirer-autocomplete-prompt` extends known + // `type`s but TS doesn't know about it + type: 'autocomplete', + message: 'Select the project you want to work with', + source: (_unused, input = '') => (project.workspace?.packages || []) + .filter((pkg) => pkg.path.includes(input)) + .map((pkg) => ({ + name: `${pkg.name ? `${chalk.bold(pkg.name)} ` : ''}${pkg.path} ${chalk.dim(`--filter ${pkg.name || pkg.path}`)}`, + value: pkg.path, + })), + }); + return result; + } + return selected.path; +} +async function getRepositoryRoot(cwd) { + const res = await findUp('.git', { cwd, type: 'directory' }); + if (res) { + return join(res, '..'); + } +} +/** Base command class that provides tracking and config initialization */ +export default class BaseCommand extends Command { + /** The netlify object inside each command with the state */ + netlify; + // TODO(serhalp) We set `startTime` here and then overwrite it in a `preAction` hook. This is + // just asking for latent bugs. Remove this one? + analytics = { startTime: process.hrtime.bigint() }; + project; + /** + * The working directory that is used for reading the `netlify.toml` file and storing the state. + * In a monorepo context this must not be the process working directory and can be an absolute path to the + * Package/Site that should be worked in. + */ + // here we actually want to disable the lint rule as its value is set + // eslint-disable-next-line no-restricted-properties + workingDir = process.cwd(); + /** + * The workspace root if inside a mono repository. + * Must not be the repository root! + */ + jsWorkspaceRoot; + /** The current workspace package we should execute the commands in */ + workspacePackage; + featureFlags = {}; + siteId; + accountId; + /** + * IMPORTANT this function will be called for each command! + * Don't do anything expensive in there. + */ + createCommand(name) { + const base = new BaseCommand(name) + // .addOption(new Option('--force', 'Force command to run. Bypasses prompts for certain destructive commands.')) + .addOption(new Option('--silent', 'Silence CLI output').hideHelp(true)) + .addOption(new Option('--cwd ').hideHelp(true)) + .addOption(new Option('--auth ', 'Netlify auth token - can be used to run this command without logging in')) + .addOption(new Option('--http-proxy [address]', 'Proxy server address to route requests through.') + .default(process.env.HTTP_PROXY || process.env.HTTPS_PROXY) + .hideHelp(true)) + .addOption(new Option('--http-proxy-certificate-filename [file]', 'Certificate file to use when connecting using a proxy server') + .default(process.env.NETLIFY_PROXY_CERTIFICATE_FILENAME) + .hideHelp(true)) + .option('--debug', 'Print debugging information'); + // only add the `--filter` option to commands that are workspace aware + if (!COMMANDS_WITHOUT_WORKSPACE_OPTIONS.has(name)) { + base.option('--filter ', 'For monorepos, specify the name of the application to run the command in'); + } + return base.hook('preAction', async (_parentCommand, actionCommand) => { + if (actionCommand.opts()?.debug) { + process.env.DEBUG = '*'; + } + debug(`${name}:preAction`)('start'); + this.analytics.startTime = process.hrtime.bigint(); + await this.init(actionCommand); + debug(`${name}:preAction`)('end'); + }); + } + #noBaseOptions = false; + /** don't show help options on command overview (mostly used on top commands like `addons` where options only apply on children) */ + noHelpOptions() { + this.#noBaseOptions = true; + return this; + } + /** The examples list for the command (used inside doc generation and help page) */ + examples = []; + /** Set examples for the command */ + addExamples(examples) { + this.examples = examples; + return this; + } + /** Overrides the help output of commander with custom styling */ + createHelp() { + const help = super.createHelp(); + help.commandUsage = (command) => { + const term = this.name() === 'netlify' + ? `${HELP_$} ${command.name()} [COMMAND]` + : `${HELP_$} ${command.parent?.name()} ${command.name()} ${command.usage()}`; + return padLeft(term, HELP_INDENT_WIDTH); + }; + const getCommands = (command) => { + const parentCommand = this.name() === 'netlify' ? command : command.parent; + return (parentCommand?.commands + .filter((cmd) => { + if (cmd._hidden) + return false; + // the root command + if (this.name() === 'netlify') { + // don't include subcommands on the main page + return !cmd.name().includes(':'); + } + return cmd.name().startsWith(`${command.name()}:`); + }) + .sort((a, b) => a.name().localeCompare(b.name())) || []); + }; + help.longestSubcommandTermLength = (command) => getCommands(command).reduce((max, cmd) => Math.max(max, cmd.name().length), 0); + /** override the longestOptionTermLength to react on hide options flag */ + help.longestOptionTermLength = (command, helper) => + // @ts-expect-error TS(2551) FIXME: Property 'noBaseOptions' does not exist on type 'C... Remove this comment to see the full error message + (command.noBaseOptions === false && + helper.visibleOptions(command).reduce((max, option) => Math.max(max, helper.optionTerm(option).length), 0)) || + 0; + help.formatHelp = (command, helper) => { + const parentCommand = this.name() === 'netlify' ? command : command.parent; + const termWidth = helper.padWidth(command, helper); + const helpWidth = helper.helpWidth || FALLBACK_HELP_CMD_WIDTH; + // formats a term correctly + const formatItem = (term, description, isCommand = false) => { + const bang = isCommand ? `${HELP_$} ` : ''; + if (description) { + const pad = termWidth + HELP_SEPARATOR_WIDTH; + const fullText = `${bang}${term.padEnd(pad - (isCommand ? 2 : 0))}${chalk.grey(description)}`; + return helper.wrap(fullText, helpWidth - HELP_INDENT_WIDTH, pad); + } + return `${bang}${term}`; + }; + let output = []; + // Description + const [topDescription, ...commandDescription] = (helper.commandDescription(command) || '').split('\n'); + if (topDescription.length !== 0) { + output = [...output, topDescription, '']; + } + // on the parent help command the version should be displayed + if (this.name() === 'netlify') { + output = [...output, chalk.bold('VERSION'), formatHelpList([formatItem(USER_AGENT)]), '']; + } + // Usage + output = [...output, chalk.bold('USAGE'), helper.commandUsage(command), '']; + // Arguments + const argumentList = helper + .visibleArguments(command) + .map((argument) => formatItem(helper.argumentTerm(argument), helper.argumentDescription(argument))); + if (argumentList.length !== 0) { + output = [...output, chalk.bold('ARGUMENTS'), formatHelpList(argumentList), '']; + } + if (command.#noBaseOptions === false) { + // Options + const optionList = helper + .visibleOptions(command) + .sort(sortOptions) + .map((option) => formatItem(helper.optionTerm(option), helper.optionDescription(option))); + if (optionList.length !== 0) { + output = [...output, chalk.bold('OPTIONS'), formatHelpList(optionList), '']; + } + } + // Description + if (commandDescription.length !== 0) { + output = [...output, chalk.bold('DESCRIPTION'), formatHelpList(commandDescription), '']; + } + // Aliases + // @ts-expect-error TS(2551) FIXME: Property '_aliases' does not exist on type 'Comman... Remove this comment to see the full error message + if (command._aliases.length !== 0) { + // @ts-expect-error TS(2551) FIXME: Property '_aliases' does not exist on type 'Comman... Remove this comment to see the full error message + const aliases = command._aliases.map((alias) => formatItem(`${parentCommand.name()} ${alias}`, null, true)); + output = [...output, chalk.bold('ALIASES'), formatHelpList(aliases), '']; + } + if (command.examples.length !== 0) { + output = [ + ...output, + chalk.bold('EXAMPLES'), + formatHelpList(command.examples.map((example) => `${HELP_$} ${example}`)), + '', + ]; + } + const commandList = getCommands(command).map((cmd) => formatItem(cmd.name(), helper.subcommandDescription(cmd).split('\n')[0], true)); + if (commandList.length !== 0) { + output = [...output, chalk.bold('COMMANDS'), formatHelpList(commandList), '']; + } + return [...output, ''].join('\n'); + }; + return help; + } + /** Will be called on the end of an action to track the metrics */ + async onEnd(error_) { + const { payload = {}, startTime } = this.analytics; + const duration = getDuration(startTime); + const status = error_ === undefined ? 'success' : 'error'; + const command = Array.isArray(this.args) ? this.args[0] : this.name(); + debug(`${this.name()}:onEnd`)(`Command: ${command}. Status: ${status}. Duration: ${duration}ms`); + try { + await track('command', { + ...payload, + command, + duration, + status, + }); + } + catch (err) { + debug(`${this.name()}:onEnd`)(`Command: ${command}. Telemetry tracking failed: ${err instanceof Error ? err.message : err?.toString()}`); + } + if (error_ !== undefined) { + logError(error_ instanceof Error ? error_ : format(error_)); + exit(1); + } + } + async authenticate(tokenFromFlag) { + const [token] = await getToken(tokenFromFlag); + if (token) { + return token; + } + return this.expensivelyAuthenticate(); + } + async expensivelyAuthenticate() { + const webUI = process.env.NETLIFY_WEB_UI || 'https://app.netlify.com'; + log(`Logging into your Netlify account...`); + // Create ticket for auth + const ticket = await this.netlify.api.createTicket({ + clientId: CLIENT_ID, + }); + // Open browser for authentication + const authLink = `${webUI}/authorize?response_type=ticket&ticket=${ticket.id}`; + log(`Opening ${authLink}`); + await openBrowser({ url: authLink }); + const accessToken = await pollForToken({ + api: this.netlify.api, + ticket, + }); + const { email, full_name: name, id: userId } = await this.netlify.api.getCurrentUser(); + const userData = merge(this.netlify.globalConfig.get(`users.${userId}`), { + id: userId, + name, + email, + auth: { + token: accessToken, + github: { + user: undefined, + token: undefined, + }, + }, + }); + // Set current userId + this.netlify.globalConfig.set('userId', userId); + // Set user data + this.netlify.globalConfig.set(`users.${userId}`, userData); + await identify({ + name, + email, + userId, + }); + await track('user_login', { + email, + }); + // Log success + log(); + log(chalk.greenBright('You are now logged into your Netlify account!')); + log(); + log(`Run ${chalk.cyanBright('netlify status')} for account details`); + log(); + log(`To see all available commands run: ${chalk.cyanBright('netlify help')}`); + log(); + return accessToken; + } + /** Adds some data to the analytics payload */ + setAnalyticsPayload(payload) { + this.analytics = { + ...this.analytics, + payload: { ...this.analytics.payload, ...payload }, + }; + } + /** + * Initializes the options and parses the configuration needs to be called on start of a command function + */ + async init(actionCommand) { + debug(`${actionCommand.name()}:init`)('start'); + const flags = actionCommand.opts(); + // here we actually want to use the process.cwd as we are setting the workingDir + // eslint-disable-next-line no-restricted-properties + this.workingDir = flags.cwd ? resolve(flags.cwd) : process.cwd(); + // ================================================== + // Create a Project and run the Heuristics to detect + // if we are running inside a monorepo or not. + // ================================================== + // retrieve the repository root + const rootDir = await getRepositoryRoot(); + // Get framework, add to analytics payload for every command, if a framework is set + const fs = new NodeFS(); + // disable logging inside the project and FS if not in debug mode + fs.logger = actionCommand.opts()?.debug ? new DefaultLogger('debug') : new NoopLogger(); + this.project = new Project(fs, this.workingDir, rootDir) + .setEnvironment(process.env) + .setNodeVersion(process.version) + .setReportFn((err, reportConfig) => { + reportError(err, { + severity: reportConfig?.severity || 'error', + metadata: reportConfig?.metadata, + }); + }); + const frameworks = await this.project.detectFrameworks(); + let packageConfig = flags.config ? resolve(flags.config) : undefined; + // check if we have detected multiple projects inside which one we have to perform our operations. + // only ask to select one if on the workspace root and no --cwd was provided + if (!flags.cwd && + !COMMANDS_WITHOUT_WORKSPACE_OPTIONS.has(actionCommand.name()) && + this.project.workspace?.packages.length && + this.project.workspace.isRoot) { + this.workspacePackage = await selectWorkspace(this.project, actionCommand.opts().filter); + this.workingDir = join(this.project.jsWorkspaceRoot, this.workspacePackage); + } + if (this.project.workspace?.packages.length && !this.project.workspace.isRoot) { + // set the package path even though we are not in the workspace root + // as the build command will set the process working directory to the workspace root + this.workspacePackage = this.project.relativeBaseDirectory; + } + this.jsWorkspaceRoot = this.project.jsWorkspaceRoot; + // detect if a toml exists in this package. + const tomlFile = join(this.workingDir, 'netlify.toml'); + if (!packageConfig && existsSync(tomlFile)) { + packageConfig = tomlFile; + } + // ================================================== + // Retrieve Site id and build state from the state.json + // ================================================== + const state = new CLIState(this.workingDir); + const [token] = await getToken(flags.auth); + const apiUrlOpts = { + userAgent: USER_AGENT, + }; + if (process.env.NETLIFY_API_URL) { + const apiUrl = new URL(process.env.NETLIFY_API_URL); + apiUrlOpts.scheme = apiUrl.protocol.slice(0, -1); + apiUrlOpts.host = apiUrl.host; + apiUrlOpts.pathPrefix = + process.env.NETLIFY_API_URL === `${apiUrl.protocol}//${apiUrl.host}` ? '/api/v1' : apiUrl.pathname; + } + const agent = await getAgent({ + httpProxy: flags.httpProxy, + certificateFile: flags.httpProxyCertificateFilename, + }); + const apiOpts = { ...apiUrlOpts, agent }; + const api = new NetlifyAPI(token ?? '', apiOpts); + actionCommand.siteId = flags.siteId || (typeof flags.site === 'string' && flags.site) || state.get('siteId'); + const needsFeatureFlagsToResolveConfig = COMMANDS_WITH_FEATURE_FLAGS.has(actionCommand.name()); + if (api.accessToken && !flags.offline && needsFeatureFlagsToResolveConfig && actionCommand.siteId) { + try { + // FIXME(serhalp): Remove `any` and fix errors. API types exist now. + const site = await api.getSite({ siteId: actionCommand.siteId, feature_flags: 'cli' }); + actionCommand.featureFlags = site.feature_flags; + actionCommand.accountId = site.account_id; + } + catch { + // if the site is not found, that could mean that the user passed a site name, not an ID + } + } + // ================================================== + // Start retrieving the configuration through the + // configuration file and the API + // ================================================== + const cachedConfig = await actionCommand.getConfig({ + cwd: flags.cwd ? this.workingDir : this.jsWorkspaceRoot || this.workingDir, + repositoryRoot: rootDir, + packagePath: this.workspacePackage, + // The config flag needs to be resolved from the actual process working directory + configFilePath: packageConfig, + token, + ...apiUrlOpts, + }); + const { accounts = [], buildDir, config, configPath, repositoryRoot, siteInfo } = cachedConfig; + let { env } = cachedConfig; + if (flags.offlineEnv) { + env = {}; + } + env.NETLIFY_CLI_VERSION = { sources: ['internal'], value: version }; + const normalizedConfig = normalizeConfig(config); + // If a user passes a site name as an option instead of a site ID to options.site, the siteInfo object + // will only have the property siteInfo.id. Checking for one of the other properties ensures that we can do + // a re-call of the api.getSite() that is done in @netlify/config so we have the proper site object in all + // commands. + // options.site as a site name (and not just site id) was introduced for the deploy command, so users could + // deploy by name along with by id + let siteData = siteInfo; + if (!siteData.url && flags.site) { + const result = await getSiteByName(api, flags.site); + if (result == null) { + return logAndThrowError(`Project with name "${flags.site}" not found`); + } + siteData = result; + } + const globalConfig = await getGlobalConfigStore(); + // ================================================== + // Perform analytics reporting + // ================================================== + const frameworkIDs = frameworks?.map((framework) => framework.id); + if (frameworkIDs?.length !== 0) { + this.setAnalyticsPayload({ frameworks: frameworkIDs }); + } + this.setAnalyticsPayload({ + monorepo: Boolean(this.project.workspace), + packageManager: this.project.packageManager?.name, + buildSystem: this.project.buildSystems.map(({ id }) => id), + opts: getScrubbedOptions(actionCommand), + args: actionCommand.args, + }); + // set the project and the netlify api object on the command, + // to be accessible inside each command. + actionCommand.project = this.project; + actionCommand.workingDir = this.workingDir; + actionCommand.workspacePackage = this.workspacePackage; + actionCommand.jsWorkspaceRoot = this.jsWorkspaceRoot; + // Either an existing configuration file from `@netlify/config` or a file path + // that should be used for creating it. + const configFilePath = configPath || join(this.workingDir, 'netlify.toml'); + actionCommand.netlify = { + accounts, + // api methods + api, + apiOpts, + // The absolute repository root (detected through @netlify/config) + repositoryRoot, + configFilePath, + relConfigFilePath: relative(repositoryRoot, configFilePath), + // current site context + site: { + root: buildDir, + configPath, + get id() { + return state.get('siteId'); + }, + set id(id) { + state.set('siteId', id); + }, + }, + // Site information retrieved using the API (api.getSite()) + siteInfo: siteData, + // Configuration from netlify.[toml/yml] + config: normalizedConfig, + // Used to avoid calling @netlify/config again + cachedConfig: { + ...cachedConfig, + env, + }, + // global cli config + // TODO(serhalp): Rename to `globalConfigStore` + globalConfig, + // state of current site dir + // TODO(serhalp): Rename to `cliState` + state, + frameworksAPIPaths: getFrameworksAPIPaths(buildDir, this.workspacePackage), + }; + debug(`${this.name()}:init`)('end'); + } + /** Find and resolve the Netlify configuration */ + async getConfig(opts) { + const { configFilePath, cwd, host, offline, packagePath, pathPrefix, repositoryRoot, scheme, token } = opts; + // the flags that are passed to the command like `--debug` or `--offline` + const flags = this.opts(); + try { + // FIXME(serhalp): Type this in `netlify/build`! This is blocking a ton of proper types across the CLI. + return await resolveConfig({ + accountId: this.accountId, + config: configFilePath, + packagePath: packagePath, + repositoryRoot: repositoryRoot, + cwd: cwd, + context: flags.context || process.env.CONTEXT || this.getDefaultContext(), + debug: flags.debug, + siteId: this.siteId, + token: token, + mode: 'cli', + host: host, + pathPrefix: pathPrefix, + scheme: scheme, + offline: offline ?? flags.offline, + siteFeatureFlagPrefix: 'cli', + featureFlags: this.featureFlags, + }); + } + catch (error_) { + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + const isUserError = error_.customErrorInfo !== undefined && error_.customErrorInfo.type === 'resolveConfig'; + // If we're failing due to an error thrown by us, it might be because the token we're using is invalid. + // To account for that, we try to retrieve the config again, this time without a token, to avoid making + // any API calls. + // + // @todo Replace this with a mechanism for calling `resolveConfig` with more granularity (i.e. having + // the option to say that we don't need API data.) + if (isUserError && !offline && token) { + if (flags.debug) { + logError(error_); + warn('Failed to resolve config, falling back to offline resolution'); + } + // recursive call with trying to resolve offline + return this.getConfig({ ...opts, offline: true }); + } + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + const message = isUserError ? error_.message : error_.stack; + return logAndThrowError(message); + } + } + /** + * get a path inside the `.netlify` project folder resolving with the workspace package + */ + getPathInProject(...paths) { + return join(this.workspacePackage || '', '.netlify', ...paths); + } + /** + * Returns the context that should be used in case one hasn't been explicitly + * set. The default context is `dev` most of the time, but some commands may + * wish to override that. + */ + getDefaultContext() { + return this.name() === 'serve' ? 'production' : 'dev'; + } + /** + * Retrieve feature flags for this site + */ + getFeatureFlag(flagName) { + // @ts-expect-error(serhalp) -- FIXME(serhalp): This probably isn't what we intend. + // We should return `false` feature flags as `false` and not `null`. Carefully fix. + return this.netlify.siteInfo.feature_flags?.[flagName] || null; + } +} +export const getBaseOptionValues = (options) => pick(options, ['auth', 'cwd', 'debug', 'filter', 'httpProxy', 'silent']); +//# sourceMappingURL=base-command.js.map \ No newline at end of file diff --git a/dist/commands/base-command.js.map b/dist/commands/base-command.js.map new file mode 100644 index 00000000000..5ae277a8562 --- /dev/null +++ b/dist/commands/base-command.js.map @@ -0,0 +1 @@ +{"version":3,"file":"base-command.js","sourceRoot":"","sources":["../../src/commands/base-command.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/blobs/blobs-delete.d.ts b/dist/commands/blobs/blobs-delete.d.ts new file mode 100644 index 00000000000..0d97984b660 --- /dev/null +++ b/dist/commands/blobs/blobs-delete.d.ts @@ -0,0 +1,5 @@ +/** + * The blobs:delete command + */ +export declare const blobsDelete: (storeName: string, key: string, _options: Record, command: any) => Promise; +//# sourceMappingURL=blobs-delete.d.ts.map \ No newline at end of file diff --git a/dist/commands/blobs/blobs-delete.d.ts.map b/dist/commands/blobs/blobs-delete.d.ts.map new file mode 100644 index 00000000000..8c2fe64164a --- /dev/null +++ b/dist/commands/blobs/blobs-delete.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"blobs-delete.d.ts","sourceRoot":"","sources":["../../../src/commands/blobs/blobs-delete.ts"],"names":[],"mappings":"AAKA;;GAEG;AACH,eAAO,MAAM,WAAW,GAAU,WAAW,MAAM,EAAE,KAAK,MAAM,EAAE,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,GAAG,uBAsBhH,CAAA"} \ No newline at end of file diff --git a/dist/commands/blobs/blobs-delete.js b/dist/commands/blobs/blobs-delete.js new file mode 100644 index 00000000000..98cead1e83b --- /dev/null +++ b/dist/commands/blobs/blobs-delete.js @@ -0,0 +1,27 @@ +import { getStore } from '@netlify/blobs'; +import { chalk, logAndThrowError, log } from '../../utils/command-helpers.js'; +import { promptBlobDelete } from '../../utils/prompts/blob-delete-prompts.js'; +/** + * The blobs:delete command + */ +export const blobsDelete = async (storeName, key, _options, command) => { + const { api, siteInfo } = command.netlify; + const { force } = _options; + const store = getStore({ + apiURL: `${api.scheme}://${api.host}`, + name: storeName, + siteID: siteInfo.id ?? '', + token: api.accessToken ?? '', + }); + if (force === undefined) { + await promptBlobDelete(key, storeName); + } + try { + await store.delete(key); + log(`${chalk.greenBright('Success')}: Blob ${chalk.yellow(key)} deleted from store ${chalk.yellow(storeName)}`); + } + catch { + return logAndThrowError(`Could not delete blob ${chalk.yellow(key)} from store ${chalk.yellow(storeName)}`); + } +}; +//# sourceMappingURL=blobs-delete.js.map \ No newline at end of file diff --git a/dist/commands/blobs/blobs-delete.js.map b/dist/commands/blobs/blobs-delete.js.map new file mode 100644 index 00000000000..b27c2b0b436 --- /dev/null +++ b/dist/commands/blobs/blobs-delete.js.map @@ -0,0 +1 @@ +{"version":3,"file":"blobs-delete.js","sourceRoot":"","sources":["../../../src/commands/blobs/blobs-delete.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEzC,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAA;AAC7E,OAAO,EAAE,gBAAgB,EAAE,MAAM,4CAA4C,CAAA;AAE7E;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,SAAiB,EAAE,GAAW,EAAE,QAAiC,EAAE,OAAY,EAAE,EAAE;IACnH,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IACzC,MAAM,EAAE,KAAK,EAAE,GAAG,QAAQ,CAAA;IAE1B,MAAM,KAAK,GAAG,QAAQ,CAAC;QACrB,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE;QACrC,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,EAAE;QACzB,KAAK,EAAE,GAAG,CAAC,WAAW,IAAI,EAAE;KAC7B,CAAC,CAAA;IAEF,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,gBAAgB,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;IACxC,CAAC;IAED,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAEvB,GAAG,CAAC,GAAG,KAAK,CAAC,WAAW,CAAC,SAAS,CAAC,UAAU,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,uBAAuB,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;IACjH,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,gBAAgB,CAAC,yBAAyB,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;IAC7G,CAAC;AACH,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/blobs/blobs-get.d.ts b/dist/commands/blobs/blobs-get.d.ts new file mode 100644 index 00000000000..fa06bdb2220 --- /dev/null +++ b/dist/commands/blobs/blobs-get.d.ts @@ -0,0 +1,8 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +interface Options extends OptionValues { + output?: string; +} +export declare const blobsGet: (storeName: string, key: string, options: Options, command: BaseCommand) => Promise; +export {}; +//# sourceMappingURL=blobs-get.d.ts.map \ No newline at end of file diff --git a/dist/commands/blobs/blobs-get.d.ts.map b/dist/commands/blobs/blobs-get.d.ts.map new file mode 100644 index 00000000000..404a9545c42 --- /dev/null +++ b/dist/commands/blobs/blobs-get.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"blobs-get.d.ts","sourceRoot":"","sources":["../../../src/commands/blobs/blobs-get.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAGxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,UAAU,OAAQ,SAAQ,YAAY;IACpC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,eAAO,MAAM,QAAQ,GAAU,WAAW,MAAM,EAAE,KAAK,MAAM,EAAE,SAAS,OAAO,EAAE,SAAS,WAAW,uBA6BpG,CAAA"} \ No newline at end of file diff --git a/dist/commands/blobs/blobs-get.js b/dist/commands/blobs/blobs-get.js new file mode 100644 index 00000000000..de97587930f --- /dev/null +++ b/dist/commands/blobs/blobs-get.js @@ -0,0 +1,32 @@ +import { promises as fs } from 'fs'; +import { resolve } from 'path'; +import { getStore } from '@netlify/blobs'; +import { chalk, logAndThrowError } from '../../utils/command-helpers.js'; +export const blobsGet = async (storeName, key, options, command) => { + const { api, siteInfo } = command.netlify; + const { output } = options; + const store = getStore({ + apiURL: `${api.scheme}://${api.host}`, + name: storeName, + siteID: siteInfo?.id ?? '', + token: api.accessToken ?? '', + }); + let blob; + try { + blob = await store.get(key); + } + catch { + return logAndThrowError(`Could not retrieve blob ${chalk.yellow(key)} from store ${chalk.yellow(storeName)}`); + } + if (blob === null) { + return logAndThrowError(`Blob ${chalk.yellow(key)} does not exist in store ${chalk.yellow(storeName)}`); + } + if (output) { + const path = resolve(output); + await fs.writeFile(path, blob); + } + else { + console.log(blob); + } +}; +//# sourceMappingURL=blobs-get.js.map \ No newline at end of file diff --git a/dist/commands/blobs/blobs-get.js.map b/dist/commands/blobs/blobs-get.js.map new file mode 100644 index 00000000000..bc42ce5c976 --- /dev/null +++ b/dist/commands/blobs/blobs-get.js.map @@ -0,0 +1 @@ +{"version":3,"file":"blobs-get.js","sourceRoot":"","sources":["../../../src/commands/blobs/blobs-get.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAA;AACnC,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAE9B,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAGzC,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AAOxE,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,EAAE,SAAiB,EAAE,GAAW,EAAE,OAAgB,EAAE,OAAoB,EAAE,EAAE;IACvG,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IACzC,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAA;IAC1B,MAAM,KAAK,GAAG,QAAQ,CAAC;QACrB,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE;QACrC,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,QAAQ,EAAE,EAAE,IAAI,EAAE;QAC1B,KAAK,EAAE,GAAG,CAAC,WAAW,IAAI,EAAE;KAC7B,CAAC,CAAA;IAEF,IAAI,IAAI,CAAA;IAER,IAAI,CAAC;QACH,IAAI,GAAG,MAAM,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;IAC7B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,gBAAgB,CAAC,2BAA2B,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;IAC/G,CAAC;IAED,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;QAClB,OAAO,gBAAgB,CAAC,QAAQ,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,4BAA4B,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;IACzG,CAAC;IAED,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,IAAI,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;QAE5B,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;IAChC,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAA;IACnB,CAAC;AACH,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/blobs/blobs-list.d.ts b/dist/commands/blobs/blobs-list.d.ts new file mode 100644 index 00000000000..320e92f9360 --- /dev/null +++ b/dist/commands/blobs/blobs-list.d.ts @@ -0,0 +1,10 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +interface Options extends OptionValues { + directories?: boolean; + json?: boolean; + prefix?: string; +} +export declare const blobsList: (storeName: string, options: Options, command: BaseCommand) => Promise; +export {}; +//# sourceMappingURL=blobs-list.d.ts.map \ No newline at end of file diff --git a/dist/commands/blobs/blobs-list.d.ts.map b/dist/commands/blobs/blobs-list.d.ts.map new file mode 100644 index 00000000000..1f74f34ade5 --- /dev/null +++ b/dist/commands/blobs/blobs-list.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"blobs-list.d.ts","sourceRoot":"","sources":["../../../src/commands/blobs/blobs-list.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAGxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,UAAU,OAAQ,SAAQ,YAAY;IACpC,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,eAAO,MAAM,SAAS,GAAU,WAAW,MAAM,EAAE,SAAS,OAAO,EAAE,SAAS,WAAW,uBAyCxF,CAAA"} \ No newline at end of file diff --git a/dist/commands/blobs/blobs-list.js b/dist/commands/blobs/blobs-list.js new file mode 100644 index 00000000000..88ca533f84b --- /dev/null +++ b/dist/commands/blobs/blobs-list.js @@ -0,0 +1,39 @@ +import { getStore } from '@netlify/blobs'; +import AsciiTable from 'ascii-table'; +import { chalk, logAndThrowError, log, logJson } from '../../utils/command-helpers.js'; +export const blobsList = async (storeName, options, command) => { + const { api, siteInfo } = command.netlify; + const store = getStore({ + apiURL: `${api.scheme}://${api.host}`, + name: storeName, + siteID: siteInfo.id, + token: api.accessToken ?? '', + }); + try { + const { blobs, directories } = await store.list({ + directories: Boolean(options.directories), + prefix: options.prefix, + }); + if (options.json) { + logJson({ blobs, directories }); + return; + } + if (blobs.length === 0 && directories.length === 0) { + log(`Netlify Blobs store ${chalk.yellow(storeName)} is empty`); + return; + } + const table = new AsciiTable(`Netlify Blobs (${storeName})`); + table.setHeading('Key', 'ETag'); + directories.forEach((directory) => { + table.addRow(directory, '(directory)'); + }); + blobs.forEach((blob) => { + table.addRow(blob.key, blob.etag); + }); + log(table.toString()); + } + catch { + return logAndThrowError(`Could not list blobs from store ${chalk.yellow(storeName)}`); + } +}; +//# sourceMappingURL=blobs-list.js.map \ No newline at end of file diff --git a/dist/commands/blobs/blobs-list.js.map b/dist/commands/blobs/blobs-list.js.map new file mode 100644 index 00000000000..75d379eedd9 --- /dev/null +++ b/dist/commands/blobs/blobs-list.js.map @@ -0,0 +1 @@ +{"version":3,"file":"blobs-list.js","sourceRoot":"","sources":["../../../src/commands/blobs/blobs-list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AACzC,OAAO,UAAU,MAAM,aAAa,CAAA;AAGpC,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AAStF,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,SAAiB,EAAE,OAAgB,EAAE,OAAoB,EAAE,EAAE;IAC3F,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IACzC,MAAM,KAAK,GAAG,QAAQ,CAAC;QACrB,MAAM,EAAE,GAAG,GAAG,CAAC,MAAM,MAAM,GAAG,CAAC,IAAI,EAAE;QACrC,IAAI,EAAE,SAAS;QACf,MAAM,EAAE,QAAQ,CAAC,EAAE;QACnB,KAAK,EAAE,GAAG,CAAC,WAAW,IAAI,EAAE;KAC7B,CAAC,CAAA;IAEF,IAAI,CAAC;QACH,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC;YAC9C,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC;YACzC,MAAM,EAAE,OAAO,CAAC,MAAM;SACvB,CAAC,CAAA;QAEF,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,OAAO,CAAC,EAAE,KAAK,EAAE,WAAW,EAAE,CAAC,CAAA;YAC/B,OAAM;QACR,CAAC;QAED,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACnD,GAAG,CAAC,uBAAuB,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;YAC9D,OAAM;QACR,CAAC;QAED,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,kBAAkB,SAAS,GAAG,CAAC,CAAA;QAE5D,KAAK,CAAC,UAAU,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;QAE/B,WAAW,CAAC,OAAO,CAAC,CAAC,SAAS,EAAE,EAAE;YAChC,KAAK,CAAC,MAAM,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;QACxC,CAAC,CAAC,CAAA;QAEF,KAAK,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;YACrB,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,EAAE,IAAI,CAAC,IAAI,CAAC,CAAA;QACnC,CAAC,CAAC,CAAA;QAEF,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAA;IACvB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,gBAAgB,CAAC,mCAAmC,KAAK,CAAC,MAAM,CAAC,SAAS,CAAC,EAAE,CAAC,CAAA;IACvF,CAAC;AACH,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/blobs/blobs-set.d.ts b/dist/commands/blobs/blobs-set.d.ts new file mode 100644 index 00000000000..4e50967e176 --- /dev/null +++ b/dist/commands/blobs/blobs-set.d.ts @@ -0,0 +1,9 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +interface Options extends OptionValues { + input?: string; + force?: string | boolean; +} +export declare const blobsSet: (storeName: string, key: string, valueParts: string[], options: Options, command: BaseCommand) => Promise; +export {}; +//# sourceMappingURL=blobs-set.d.ts.map \ No newline at end of file diff --git a/dist/commands/blobs/blobs-set.d.ts.map b/dist/commands/blobs/blobs-set.d.ts.map new file mode 100644 index 00000000000..4c5f0fb8a57 --- /dev/null +++ b/dist/commands/blobs/blobs-set.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"blobs-set.d.ts","sourceRoot":"","sources":["../../../src/commands/blobs/blobs-set.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAIxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,UAAU,OAAQ,SAAQ,YAAY;IACpC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACzB;AAED,eAAO,MAAM,QAAQ,GACnB,WAAW,MAAM,EACjB,KAAK,MAAM,EACX,YAAY,MAAM,EAAE,EACpB,SAAS,OAAO,EAChB,SAAS,WAAW,uBAqDrB,CAAA"} \ No newline at end of file diff --git a/dist/commands/blobs/blobs-set.js b/dist/commands/blobs/blobs-set.js new file mode 100644 index 00000000000..70590abed3d --- /dev/null +++ b/dist/commands/blobs/blobs-set.js @@ -0,0 +1,48 @@ +import { promises as fs } from 'fs'; +import { resolve } from 'path'; +import { getStore } from '@netlify/blobs'; +import { chalk, logAndThrowError, isNodeError, log } from '../../utils/command-helpers.js'; +import { promptBlobSetOverwrite } from '../../utils/prompts/blob-set-prompt.js'; +export const blobsSet = async (storeName, key, valueParts, options, command) => { + const { api, siteInfo } = command.netlify; + const { force, input } = options; + const store = getStore({ + apiURL: `${api.scheme}://${api.host}`, + name: storeName, + siteID: siteInfo.id, + token: api.accessToken ?? '', + }); + let value = valueParts.join(' '); + if (input) { + const inputPath = resolve(input); + try { + value = await fs.readFile(inputPath, 'utf8'); + } + catch (error) { + if (isNodeError(error) && error.code === 'ENOENT') { + return logAndThrowError(`Could not set blob ${chalk.yellow(key)} because the file ${chalk.underline(inputPath)} does not exist`); + } + if (isNodeError(error) && error.code === 'EISDIR') { + return logAndThrowError(`Could not set blob ${chalk.yellow(key)} because the path ${chalk.underline(inputPath)} is a directory`); + } + return logAndThrowError(`Could not set blob ${chalk.yellow(key)} because the path ${chalk.underline(inputPath)} could not be read`); + } + } + else if (!value) { + return logAndThrowError(`You must provide a value as a command-line parameter (e.g. 'netlify blobs:set my-store my-key my value') or specify the path to a file from where the value should be read (e.g. 'netlify blobs:set my-store my-key --input ./my-file.txt')`); + } + if (force === undefined) { + const existingValue = await store.get(key); + if (existingValue) { + await promptBlobSetOverwrite(key, storeName); + } + } + try { + await store.set(key, value); + log(`${chalk.greenBright('Success')}: Blob ${chalk.yellow(key)} set in store ${chalk.yellow(storeName)}`); + } + catch { + return logAndThrowError(`Could not set blob ${chalk.yellow(key)} in store ${chalk.yellow(storeName)}`); + } +}; +//# sourceMappingURL=blobs-set.js.map \ No newline at end of file diff --git a/dist/commands/blobs/blobs-set.js.map b/dist/commands/blobs/blobs-set.js.map new file mode 100644 index 00000000000..6f4c2c2bd07 --- /dev/null +++ b/dist/commands/blobs/blobs-set.js.map @@ -0,0 +1 @@ +{"version":3,"file":"blobs-set.js","sourceRoot":"","sources":["../../../src/commands/blobs/blobs-set.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/blobs/blobs.d.ts b/dist/commands/blobs/blobs.d.ts new file mode 100644 index 00000000000..7c121528a33 --- /dev/null +++ b/dist/commands/blobs/blobs.d.ts @@ -0,0 +1,6 @@ +import BaseCommand from '../base-command.js'; +/** + * Creates the `netlify blobs` command + */ +export declare const createBlobsCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=blobs.d.ts.map \ No newline at end of file diff --git a/dist/commands/blobs/blobs.d.ts.map b/dist/commands/blobs/blobs.d.ts.map new file mode 100644 index 00000000000..5356053e62e --- /dev/null +++ b/dist/commands/blobs/blobs.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"blobs.d.ts","sourceRoot":"","sources":["../../../src/commands/blobs/blobs.ts"],"names":[],"mappings":"AAIA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAS5C;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,WAAW,gBAsFtD,CAAA"} \ No newline at end of file diff --git a/dist/commands/blobs/blobs.js b/dist/commands/blobs/blobs.js new file mode 100644 index 00000000000..3ee4b32dfad --- /dev/null +++ b/dist/commands/blobs/blobs.js @@ -0,0 +1,82 @@ +import terminalLink from 'terminal-link'; +import requiresSiteInfo from '../../utils/hooks/requires-site-info.js'; +/** + * The blobs command + */ +const blobs = (_options, command) => { + command.help(); +}; +/** + * Creates the `netlify blobs` command + */ +export const createBlobsCommand = (program) => { + program + .command('blobs:delete') + .description(`Deletes an object with a given key, if it exists, from a Netlify Blobs store`) + .argument('', 'Name of the store') + .argument('', 'Object key') + .alias('blob:delete') + .hook('preAction', requiresSiteInfo) + .action(async (storeName, key, _options, command) => { + const { blobsDelete } = await import('./blobs-delete.js'); + await blobsDelete(storeName, key, _options, command); + }); + program + .command('blobs:get') + .description(`Reads an object with a given key from a Netlify Blobs store and, if it exists, prints the content to the terminal or saves it to a file`) + .argument('', 'Name of the store') + .argument('', 'Object key') + .option('-O, --output ', 'Defines the filesystem path where the blob data should be persisted') + .alias('blob:get') + .hook('preAction', requiresSiteInfo) + .action(async (storeName, key, options, command) => { + const { blobsGet } = await import('./blobs-get.js'); + await blobsGet(storeName, key, options, command); + }); + program + .command('blobs:list') + .description(`Lists objects in a Netlify Blobs store`) + .argument('', 'Name of the store') + .option('-d, --directories', `Indicates that keys with the '/' character should be treated as directories, returning a list of sub-directories at a given level rather than all the keys inside them`) + .option('-p, --prefix ', `A string for filtering down the entries; when specified, only the entries whose key starts with that prefix are returned`) + .option('--json', 'Output list contents as JSON') + .alias('blob:list') + .hook('preAction', requiresSiteInfo) + .action(async (storeName, options, command) => { + const { blobsList } = await import('./blobs-list.js'); + await blobsList(storeName, options, command); + }); + program + .command('blobs:set') + .description(`Writes to a Netlify Blobs store an object with the data provided in the command or the contents of a file defined by the 'input' parameter`) + .argument('', 'Name of the store') + .argument('', 'Object key') + .argument('[value...]', 'Object value') + .option('-i, --input ', 'Defines the filesystem path where the blob data should be read from') + .alias('blob:set') + .hook('preAction', requiresSiteInfo) + .action(async (storeName, key, valueParts, options, command) => { + const { blobsSet } = await import('./blobs-set.js'); + await blobsSet(storeName, key, valueParts, options, command); + }); + return program + .command('blobs') + .alias('blob') + .description(`Manage objects in Netlify Blobs`) + .addHelpText('after', () => { + const docsUrl = 'https://docs.netlify.com/blobs/overview/'; + return ` +For more information about Netlify Blobs, see ${terminalLink(docsUrl, docsUrl, { fallback: false })} +`; + }) + .addExamples([ + 'netlify blobs:get my-store my-key', + 'netlify blobs:set my-store my-key This will go in a blob', + 'netlify blobs:set my-store my-key --input ./some-file.txt', + 'netlify blobs:delete my-store my-key', + 'netlify blobs:list my-store', + 'netlify blobs:list my-store --json', + ]) + .action(blobs); +}; +//# sourceMappingURL=blobs.js.map \ No newline at end of file diff --git a/dist/commands/blobs/blobs.js.map b/dist/commands/blobs/blobs.js.map new file mode 100644 index 00000000000..54fb6ed0865 --- /dev/null +++ b/dist/commands/blobs/blobs.js.map @@ -0,0 +1 @@ +{"version":3,"file":"blobs.js","sourceRoot":"","sources":["../../../src/commands/blobs/blobs.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/build/build.d.ts b/dist/commands/build/build.d.ts new file mode 100644 index 00000000000..63209f9ac89 --- /dev/null +++ b/dist/commands/build/build.d.ts @@ -0,0 +1,6 @@ +import type { OptionValues } from 'commander'; +import { type RunBuildOptions } from '../../lib/build.js'; +import type BaseCommand from '../base-command.js'; +export declare const checkOptions: ({ cachedConfig: { siteInfo }, token }: RunBuildOptions) => undefined; +export declare const build: (options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=build.d.ts.map \ No newline at end of file diff --git a/dist/commands/build/build.d.ts.map b/dist/commands/build/build.d.ts.map new file mode 100644 index 00000000000..3ea2a1b31d7 --- /dev/null +++ b/dist/commands/build/build.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/commands/build/build.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAE7C,OAAO,EAAE,KAAK,eAAe,EAAgC,MAAM,oBAAoB,CAAA;AAIvF,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAEjD,eAAO,MAAM,YAAY,GAAI,uCAAuC,eAAe,cAUlF,CAAA;AAED,eAAO,MAAM,KAAK,GAAU,SAAS,YAAY,EAAE,SAAS,WAAW,kBA6BtE,CAAA"} \ No newline at end of file diff --git a/dist/commands/build/build.js b/dist/commands/build/build.js new file mode 100644 index 00000000000..bdd7c2e7ff0 --- /dev/null +++ b/dist/commands/build/build.js @@ -0,0 +1,39 @@ +import { getRunBuildOptions, runBuild } from '../../lib/build.js'; +import { detectFrameworkSettings, getDefaultConfig } from '../../utils/build-info.js'; +import { logAndThrowError, exit, getToken } from '../../utils/command-helpers.js'; +import { getEnvelopeEnv } from '../../utils/env/index.js'; +export const checkOptions = ({ cachedConfig: { siteInfo }, token }) => { + if (!siteInfo.id) { + return logAndThrowError('Could not find the project ID. If your project is not on Netlify, please run `netlify init` or `netlify deploy` first. If it is, please run `netlify link`.'); + } + if (!token) { + return logAndThrowError('Could not find the access token. Please run netlify login.'); + } +}; +export const build = async (options, command) => { + const { cachedConfig, siteInfo } = command.netlify; + command.setAnalyticsPayload({ dry: options.dry }); + // Retrieve Netlify Build options + const [token] = await getToken(); + const settings = await detectFrameworkSettings(command, 'build'); + const buildOptions = await getRunBuildOptions({ + cachedConfig, + defaultConfig: getDefaultConfig(settings), + packagePath: command.workspacePackage, + currentDir: command.workingDir, + token, + options, + }); + if (!options.offline) { + checkOptions(buildOptions); + buildOptions.cachedConfig.env = await getEnvelopeEnv({ + api: command.netlify.api, + context: options.context, + env: buildOptions.cachedConfig.env, + siteInfo, + }); + } + const { exitCode } = await runBuild(buildOptions); + exit(exitCode); +}; +//# sourceMappingURL=build.js.map \ No newline at end of file diff --git a/dist/commands/build/build.js.map b/dist/commands/build/build.js.map new file mode 100644 index 00000000000..6f196747c2f --- /dev/null +++ b/dist/commands/build/build.js.map @@ -0,0 +1 @@ +{"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/commands/build/build.ts"],"names":[],"mappings":"AAEA,OAAO,EAAwB,kBAAkB,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AACvF,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,2BAA2B,CAAA;AACrF,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAA;AACjF,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAGzD,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAAE,YAAY,EAAE,EAAE,QAAQ,EAAE,EAAE,KAAK,EAAmB,EAAE,EAAE;IACrF,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,OAAO,gBAAgB,CACrB,6JAA6J,CAC9J,CAAA;IACH,CAAC;IAED,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,gBAAgB,CAAC,4DAA4D,CAAC,CAAA;IACvF,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IACzE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IAClD,OAAO,CAAC,mBAAmB,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;IACjD,iCAAiC;IACjC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,QAAQ,EAAE,CAAA;IAChC,MAAM,QAAQ,GAAG,MAAM,uBAAuB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAEhE,MAAM,YAAY,GAAG,MAAM,kBAAkB,CAAC;QAC5C,YAAY;QACZ,aAAa,EAAE,gBAAgB,CAAC,QAAQ,CAAC;QACzC,WAAW,EAAE,OAAO,CAAC,gBAAgB;QACrC,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,KAAK;QACL,OAAO;KACR,CAAC,CAAA;IAEF,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACrB,YAAY,CAAC,YAAY,CAAC,CAAA;QAE1B,YAAY,CAAC,YAAY,CAAC,GAAG,GAAG,MAAM,cAAc,CAAC;YACnD,GAAG,EAAE,OAAO,CAAC,OAAO,CAAC,GAAG;YACxB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,GAAG,EAAE,YAAY,CAAC,YAAY,CAAC,GAAG;YAClC,QAAQ;SACT,CAAC,CAAA;IACJ,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,QAAQ,CAAC,YAAY,CAAC,CAAA;IACjD,IAAI,CAAC,QAAQ,CAAC,CAAA;AAChB,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/build/index.d.ts b/dist/commands/build/index.d.ts new file mode 100644 index 00000000000..02be57f6f19 --- /dev/null +++ b/dist/commands/build/index.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const createBuildCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/build/index.d.ts.map b/dist/commands/build/index.d.ts.map new file mode 100644 index 00000000000..9e1ce488c93 --- /dev/null +++ b/dist/commands/build/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/build/index.ts"],"names":[],"mappings":"AAKA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,kBAAkB,GAAI,SAAS,WAAW,gBA0BjD,CAAA"} \ No newline at end of file diff --git a/dist/commands/build/index.js b/dist/commands/build/index.js new file mode 100644 index 00000000000..149a443bc89 --- /dev/null +++ b/dist/commands/build/index.js @@ -0,0 +1,25 @@ +import process from 'process'; +import terminalLink from 'terminal-link'; +import { normalizeContext } from '../../utils/env/index.js'; +export const createBuildCommand = (program) => program + .command('build') + .description('Build on your local machine') + .option('--context ', 'Specify a deploy context for environment variables read during the build (ā€productionā€, ā€deploy-previewā€, ā€branch-deployā€, ā€devā€) or `branch:your-branch` where `your-branch` is the name of a branch (default: value of CONTEXT or ā€productionā€)', normalizeContext, process.env.CONTEXT || 'production') + .option('--dry', 'Dry run: show instructions without running them', false) + .option('-o, --offline', 'Disables any features that require network access') + .addExamples([ + 'netlify build', + 'netlify build --context deploy-preview # Build with env var values from deploy-preview context', + 'netlify build --context branch:feat/make-it-pop # Build with env var values from the feat/make-it-pop branch context or branch-deploy context', +]) + .addHelpText('after', () => { + const docsUrl = 'https://docs.netlify.com/configure-builds/overview/'; + return ` +For more information about Netlify builds, see ${terminalLink(docsUrl, docsUrl, { fallback: false })} +`; +}) + .action(async (options, command) => { + const { build } = await import('./build.js'); + await build(options, command); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/build/index.js.map b/dist/commands/build/index.js.map new file mode 100644 index 00000000000..acba7390616 --- /dev/null +++ b/dist/commands/build/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/build/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAA;AAE7B,OAAO,YAAY,MAAM,eAAe,CAAA;AAExC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAG3D,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAAoB,EAAE,EAAE,CACzD,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,6BAA6B,CAAC;KAC1C,MAAM,CACL,qBAAqB,EACrB,mPAAmP,EACnP,gBAAgB,EAChB,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,YAAY,CACpC;KACA,MAAM,CAAC,OAAO,EAAE,iDAAiD,EAAE,KAAK,CAAC;KACzE,MAAM,CAAC,eAAe,EAAE,mDAAmD,CAAC;KAC5E,WAAW,CAAC;IACX,eAAe;IACf,gGAAgG;IAChG,+IAA+I;CAChJ,CAAC;KACD,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE;IACzB,MAAM,OAAO,GAAG,qDAAqD,CAAA;IACrE,OAAO;iDACoC,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;CACnG,CAAA;AACG,CAAC,CAAC;KACD,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;IACjC,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAA;IAC5C,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAC/B,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/clone/clone.d.ts b/dist/commands/clone/clone.d.ts new file mode 100644 index 00000000000..5eea5a0e175 --- /dev/null +++ b/dist/commands/clone/clone.d.ts @@ -0,0 +1,7 @@ +import type BaseCommand from '../base-command.js'; +import type { CloneOptionValues } from './option_values.js'; +export declare const clone: (options: CloneOptionValues, command: BaseCommand, args: { + repo: string; + targetDir?: string; +}) => Promise; +//# sourceMappingURL=clone.d.ts.map \ No newline at end of file diff --git a/dist/commands/clone/clone.d.ts.map b/dist/commands/clone/clone.d.ts.map new file mode 100644 index 00000000000..b6b4f12b8d5 --- /dev/null +++ b/dist/commands/clone/clone.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"clone.d.ts","sourceRoot":"","sources":["../../../src/commands/clone/clone.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAEjD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAA;AAwB3D,eAAO,MAAM,KAAK,GAChB,SAAS,iBAAiB,EAC1B,SAAS,WAAW,EACpB,MAAM;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,uBA2C3C,CAAA"} \ No newline at end of file diff --git a/dist/commands/clone/clone.js b/dist/commands/clone/clone.js new file mode 100644 index 00000000000..e20c5b0a73a --- /dev/null +++ b/dist/commands/clone/clone.js @@ -0,0 +1,64 @@ +import inquirer from 'inquirer'; +import { normalizeRepoUrl } from '../../utils/normalize-repo-url.js'; +import { chalk, logAndThrowError, log } from '../../utils/command-helpers.js'; +import { runGit } from '../../utils/run-git.js'; +import { link } from '../link/link.js'; +import { startSpinner } from '../../lib/spinner.js'; +const getTargetDir = async (defaultDir) => { + const { selectedDir } = await inquirer.prompt([ + { + type: 'input', + name: 'selectedDir', + message: 'Where should we clone the repository?', + default: defaultDir, + }, + ]); + return selectedDir; +}; +const cloneRepo = async (repoUrl, targetDir, debug) => { + try { + await runGit(['clone', repoUrl, targetDir], !debug); + } + catch (error) { + throw new Error(`Failed to clone repository: ${error instanceof Error ? error.message : error?.toString() ?? ''}`); + } +}; +export const clone = async (options, command, args) => { + await command.authenticate(); + const { repoUrl, httpsUrl, repoName } = normalizeRepoUrl(args.repo); + const targetDir = args.targetDir ?? (await getTargetDir(`./${repoName}`)); + const cloneSpinner = startSpinner({ text: `Cloning repository to ${chalk.cyan(targetDir)}` }); + try { + await cloneRepo(repoUrl, targetDir, options.debug ?? false); + } + catch (error) { + return logAndThrowError(error); + } + cloneSpinner.success(`Cloned repository to ${chalk.cyan(targetDir)}`); + command.workingDir = targetDir; + // TODO(serhalp): This shouldn't be necessary but `getPathInProject` does not take + // `command.workingDir` into account. Carefully fix this and remove this line. + process.chdir(targetDir); + const { id, name, ...globalOptions } = options; + const linkOptions = { + ...globalOptions, + id, + name, + // Use the normalized HTTPS URL as the canonical git URL for linking to ensure + // we have a consistent URL format for looking up projects. + gitRemoteUrl: httpsUrl, + }; + await link(linkOptions, command); + log(); + log(chalk.green('āœ” Your project is ready to go!')); + log(`→ Next, enter your project directory using ${chalk.cyanBright(`cd ${targetDir}`)}`); + log(); + log(`→ You can now run other ${chalk.cyanBright('netlify')} CLI commands in this directory`); + log(`→ To build and deploy your project: ${chalk.cyanBright('netlify deploy')}`); + if (command.netlify.config.dev?.command) { + log(`→ To run your dev server: ${chalk.cyanBright(command.netlify.config.dev.command)}`); + } + log(`→ To see all available commands: ${chalk.cyanBright('netlify help')}`); + log(); +}; +//# sourceMappingURL=clone.js.map \ No newline at end of file diff --git a/dist/commands/clone/clone.js.map b/dist/commands/clone/clone.js.map new file mode 100644 index 00000000000..1d9999afdea --- /dev/null +++ b/dist/commands/clone/clone.js.map @@ -0,0 +1 @@ +{"version":3,"file":"clone.js","sourceRoot":"","sources":["../../../src/commands/clone/clone.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/clone/index.d.ts b/dist/commands/clone/index.d.ts new file mode 100644 index 00000000000..3638d1bf240 --- /dev/null +++ b/dist/commands/clone/index.d.ts @@ -0,0 +1,3 @@ +import type BaseCommand from '../base-command.js'; +export declare const createCloneCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/clone/index.d.ts.map b/dist/commands/clone/index.d.ts.map new file mode 100644 index 00000000000..7af3a2e0563 --- /dev/null +++ b/dist/commands/clone/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/clone/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAGjD,eAAO,MAAM,kBAAkB,GAAI,SAAS,WAAW,gBA8BjD,CAAA"} \ No newline at end of file diff --git a/dist/commands/clone/index.js b/dist/commands/clone/index.js new file mode 100644 index 00000000000..82ca79b136c --- /dev/null +++ b/dist/commands/clone/index.js @@ -0,0 +1,30 @@ +import terminalLink from 'terminal-link'; +export const createCloneCommand = (program) => program + .command('clone') + .description(`Clone a remote repository and link it to an existing project on Netlify +Use this command when the existing Netlify project is already configured to deploy from the existing repo. + +If you specify a target directory, the repo will be cloned into that directory. By default, a directory will be created with the name of the repo. + +To specify a project, use --id or --name. By default, the Netlify project to link will be automatically detected if exactly one project found is found with a matching git URL. If we cannot find such a project, you will be interactively prompted to select one.`) + .argument('', 'URL of the repository to clone or Github `owner/repo` (required)') + .argument('[targetDir]', 'directory in which to clone the repository - will be created if it does not exist') + .option('--id ', 'ID of existing Netlify project to link to') + .option('--name ', 'Name of existing Netlify project to link to') + .addExamples([ + 'netlify clone vibecoder/next-unicorn', + 'netlify clone https://github.com/vibecoder/next-unicorn.git', + 'netlify clone git@github.com:vibecoder/next-unicorn.git', + 'netlify clone vibecoder/next-unicorn ./next-unicorn-shh-secret', + 'netlify clone --id 123-123-123-123 vibecoder/next-unicorn', + 'netlify clone --name my-project-name vibecoder/next-unicorn', +]) + .addHelpText('after', () => { + const docsUrl = 'https://docs.netlify.com/cli/get-started/#link-and-unlink-sites'; + return `For more information about linking projects, see ${terminalLink(docsUrl, docsUrl, { fallback: false })}\n`; +}) + .action(async (repo, targetDir, options, command) => { + const { clone } = await import('./clone.js'); + await clone(options, command, { repo, targetDir }); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/clone/index.js.map b/dist/commands/clone/index.js.map new file mode 100644 index 00000000000..34efb6170d3 --- /dev/null +++ b/dist/commands/clone/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/clone/index.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAA;AAKxC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAAoB,EAAE,EAAE,CACzD,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CACV;;;;;oQAK8P,CAC/P;KACA,QAAQ,CAAC,QAAQ,EAAE,kEAAkE,CAAC;KACtF,QAAQ,CAAC,aAAa,EAAE,mFAAmF,CAAC;KAC5G,MAAM,CAAC,WAAW,EAAE,2CAA2C,CAAC;KAChE,MAAM,CAAC,eAAe,EAAE,6CAA6C,CAAC;KACtE,WAAW,CAAC;IACX,sCAAsC;IACtC,6DAA6D;IAC7D,yDAAyD;IACzD,gEAAgE;IAChE,2DAA2D;IAC3D,6DAA6D;CAC9D,CAAC;KACD,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE;IACzB,MAAM,OAAO,GAAG,iEAAiE,CAAA;IACjF,OAAO,oDAAoD,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,IAAI,CAAA;AACpH,CAAC,CAAC;KACD,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,SAA6B,EAAE,OAA0B,EAAE,OAAoB,EAAE,EAAE;IAC9G,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAA;IAC5C,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC,CAAA;AACpD,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/clone/option_values.d.ts b/dist/commands/clone/option_values.d.ts new file mode 100644 index 00000000000..cb4d4c68119 --- /dev/null +++ b/dist/commands/clone/option_values.d.ts @@ -0,0 +1,6 @@ +import type { BaseOptionValues } from '../base-command.js'; +export type CloneOptionValues = BaseOptionValues & { + id?: string | undefined; + name?: string | undefined; +}; +//# sourceMappingURL=option_values.d.ts.map \ No newline at end of file diff --git a/dist/commands/clone/option_values.d.ts.map b/dist/commands/clone/option_values.d.ts.map new file mode 100644 index 00000000000..e5336c8ddf2 --- /dev/null +++ b/dist/commands/clone/option_values.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"option_values.d.ts","sourceRoot":"","sources":["../../../src/commands/clone/option_values.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAE1D,MAAM,MAAM,iBAAiB,GAAG,gBAAgB,GAAG;IAIjD,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC1B,CAAA"} \ No newline at end of file diff --git a/dist/commands/clone/option_values.js b/dist/commands/clone/option_values.js new file mode 100644 index 00000000000..80d009caccc --- /dev/null +++ b/dist/commands/clone/option_values.js @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=option_values.js.map \ No newline at end of file diff --git a/dist/commands/clone/option_values.js.map b/dist/commands/clone/option_values.js.map new file mode 100644 index 00000000000..f3d1bfd893d --- /dev/null +++ b/dist/commands/clone/option_values.js.map @@ -0,0 +1 @@ +{"version":3,"file":"option_values.js","sourceRoot":"","sources":["../../../src/commands/clone/option_values.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/commands/completion/completion.d.ts b/dist/commands/completion/completion.d.ts new file mode 100644 index 00000000000..8661a3b10bb --- /dev/null +++ b/dist/commands/completion/completion.d.ts @@ -0,0 +1,5 @@ +import type { OptionValues } from 'commander'; +import type BaseCommand from '../base-command.js'; +export declare const completionGenerate: (_options: OptionValues, command: BaseCommand) => Promise; +export declare const completionUninstall: (_options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=completion.d.ts.map \ No newline at end of file diff --git a/dist/commands/completion/completion.d.ts.map b/dist/commands/completion/completion.d.ts.map new file mode 100644 index 00000000000..0b86948ef84 --- /dev/null +++ b/dist/commands/completion/completion.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../../src/commands/completion/completion.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAY7C,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAIjD,eAAO,MAAM,kBAAkB,GAAU,UAAU,YAAY,EAAE,SAAS,WAAW,uBAgEpF,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAU,UAAU,YAAY,EAAE,SAAS,WAAW,uBAOrF,CAAA"} \ No newline at end of file diff --git a/dist/commands/completion/completion.js b/dist/commands/completion/completion.js new file mode 100644 index 00000000000..635f62276e8 --- /dev/null +++ b/dist/commands/completion/completion.js @@ -0,0 +1,67 @@ +import fs from 'fs'; +import { homedir } from 'os'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; +import inquirer from 'inquirer'; +import { install, uninstall } from '@pnpm/tabtab'; +import { generateAutocompletion } from '../../lib/completion/index.js'; +import { logAndThrowError, log, chalk, checkFileForLine, TABTAB_CONFIG_LINE, AUTOLOAD_COMPINIT, } from '../../utils/command-helpers.js'; +const completer = join(dirname(fileURLToPath(import.meta.url)), '../../lib/completion/script.js'); +export const completionGenerate = async (_options, command) => { + const { parent } = command; + if (!parent) { + return logAndThrowError(`There has been an error generating the completion script.`); + } + generateAutocompletion(parent); + await install({ + name: parent.name(), + completer, + }); + const completionScriptPath = join(homedir(), `.config/tabtab/${parent.name()}.zsh`); + if (fs.existsSync(completionScriptPath)) { + let completionScript = fs.readFileSync(completionScriptPath, 'utf8'); + completionScript = completionScript.replace(/compdef _netlify_completion netlify/, 'compdef _netlify_completion netlify ntl'); + fs.writeFileSync(completionScriptPath, completionScript, 'utf8'); + log(`Added alias 'ntl' to completion script.`); + } + const zshConfigFilepath = join(process.env.HOME || homedir(), '.zshrc'); + if (fs.existsSync(zshConfigFilepath) && + checkFileForLine(zshConfigFilepath, TABTAB_CONFIG_LINE) && + !checkFileForLine(zshConfigFilepath, AUTOLOAD_COMPINIT)) { + log(`To enable Tabtab autocompletion with zsh, the following line may need to be added to your ~/.zshrc:`); + log(chalk.bold.cyan(`\n${AUTOLOAD_COMPINIT}\n`)); + const { compinitAdded } = await inquirer.prompt([ + { + type: 'confirm', + name: 'compinitAdded', + message: `Would you like to add it?`, + default: true, + }, + ]); + if (compinitAdded) { + fs.readFile(zshConfigFilepath, 'utf8', (_err, data) => { + const updatedZshFile = AUTOLOAD_COMPINIT + '\n' + data; + fs.writeFileSync(zshConfigFilepath, updatedZshFile, 'utf8'); + }); + log('Successfully added compinit line to .zshrc'); + } + } + log(`Completion for ${parent.name()} successfully installed!`); + if (process.platform !== 'win32') { + log("\nTo ensure proper functionality, you'll need to set appropriate file permissions."); + log(chalk.bold('Add executable permissions by running the following command:')); + log(chalk.bold.cyan(`\nchmod +x ${completer}\n`)); + } + else { + log(`\nTo ensure proper functionality, you may need to set appropriate file permissions to ${completer}.`); + } +}; +export const completionUninstall = async (_options, command) => { + if (!command.parent) { + return logAndThrowError(`There has been an error deleting the completion script.`); + } + await uninstall({ + name: command.parent.name(), + }); +}; +//# sourceMappingURL=completion.js.map \ No newline at end of file diff --git a/dist/commands/completion/completion.js.map b/dist/commands/completion/completion.js.map new file mode 100644 index 00000000000..4a97944e769 --- /dev/null +++ b/dist/commands/completion/completion.js.map @@ -0,0 +1 @@ +{"version":3,"file":"completion.js","sourceRoot":"","sources":["../../../src/commands/completion/completion.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/completion/index.d.ts b/dist/commands/completion/index.d.ts new file mode 100644 index 00000000000..1d4dea92876 --- /dev/null +++ b/dist/commands/completion/index.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const createCompletionCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/completion/index.d.ts.map b/dist/commands/completion/index.d.ts.map new file mode 100644 index 00000000000..3eceda38fb6 --- /dev/null +++ b/dist/commands/completion/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/completion/index.ts"],"names":[],"mappings":"AAEA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,uBAAuB,GAAI,SAAS,WAAW,gBA2B3D,CAAA"} \ No newline at end of file diff --git a/dist/commands/completion/index.js b/dist/commands/completion/index.js new file mode 100644 index 00000000000..1df6595fd53 --- /dev/null +++ b/dist/commands/completion/index.js @@ -0,0 +1,27 @@ +export const createCompletionCommand = (program) => { + program + .command('completion:install') + .alias('completion:generate') + .description('Generates completion script for your preferred shell') + .action(async (options, command) => { + const { completionGenerate } = await import('./completion.js'); + await completionGenerate(options, command); + }); + program + .command('completion:uninstall', { hidden: true }) + .alias('completion:remove') + .description('Uninstalls the installed completions') + .addExamples(['netlify completion:uninstall']) + .action(async (options, command) => { + const { completionUninstall } = await import('./completion.js'); + await completionUninstall(options, command); + }); + return program + .command('completion') + .description('Generate shell completion script\nRun this command to see instructions for your shell.') + .addExamples(['netlify completion:install']) + .action((_options, command) => { + command.help(); + }); +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/completion/index.js.map b/dist/commands/completion/index.js.map new file mode 100644 index 00000000000..c924bb16a3b --- /dev/null +++ b/dist/commands/completion/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/completion/index.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,uBAAuB,GAAG,CAAC,OAAoB,EAAE,EAAE;IAC9D,OAAO;SACJ,OAAO,CAAC,oBAAoB,CAAC;SAC7B,KAAK,CAAC,qBAAqB,CAAC;SAC5B,WAAW,CAAC,sDAAsD,CAAC;SACnE,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;QAC5D,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAA;QAC9D,MAAM,kBAAkB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAC5C,CAAC,CAAC,CAAA;IAEJ,OAAO;SACJ,OAAO,CAAC,sBAAsB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;SACjD,KAAK,CAAC,mBAAmB,CAAC;SAC1B,WAAW,CAAC,sCAAsC,CAAC;SACnD,WAAW,CAAC,CAAC,8BAA8B,CAAC,CAAC;SAC7C,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;QAC5D,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAA;QAC/D,MAAM,mBAAmB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAC7C,CAAC,CAAC,CAAA;IAEJ,OAAO,OAAO;SACX,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CAAC,wFAAwF,CAAC;SACrG,WAAW,CAAC,CAAC,4BAA4B,CAAC,CAAC;SAC3C,MAAM,CAAC,CAAC,QAAsB,EAAE,OAAoB,EAAE,EAAE;QACvD,OAAO,CAAC,IAAI,EAAE,CAAA;IAChB,CAAC,CAAC,CAAA;AACN,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/database/constants.d.ts b/dist/commands/database/constants.d.ts new file mode 100644 index 00000000000..9a776dc0861 --- /dev/null +++ b/dist/commands/database/constants.d.ts @@ -0,0 +1,4 @@ +export declare const NEON_DATABASE_EXTENSION_SLUG: string; +export declare const JIGSAW_URL: string; +export declare const NETLIFY_NEON_PACKAGE_NAME = "@netlify/neon"; +//# sourceMappingURL=constants.d.ts.map \ No newline at end of file diff --git a/dist/commands/database/constants.d.ts.map b/dist/commands/database/constants.d.ts.map new file mode 100644 index 00000000000..1ff28de52e8 --- /dev/null +++ b/dist/commands/database/constants.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/commands/database/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,4BAA4B,QAAqD,CAAA;AAC9F,eAAO,MAAM,UAAU,QAAqE,CAAA;AAC5F,eAAO,MAAM,yBAAyB,kBAAkB,CAAA"} \ No newline at end of file diff --git a/dist/commands/database/constants.js b/dist/commands/database/constants.js new file mode 100644 index 00000000000..0f975eb2782 --- /dev/null +++ b/dist/commands/database/constants.js @@ -0,0 +1,4 @@ +export const NEON_DATABASE_EXTENSION_SLUG = process.env.NEON_DATABASE_EXTENSION_SLUG ?? 'neon'; +export const JIGSAW_URL = process.env.JIGSAW_URL ?? 'https://jigsaw.services-prod.nsvcs.net'; +export const NETLIFY_NEON_PACKAGE_NAME = '@netlify/neon'; +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/dist/commands/database/constants.js.map b/dist/commands/database/constants.js.map new file mode 100644 index 00000000000..4cc6c2e1fd1 --- /dev/null +++ b/dist/commands/database/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/commands/database/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,4BAA4B,GAAG,OAAO,CAAC,GAAG,CAAC,4BAA4B,IAAI,MAAM,CAAA;AAC9F,MAAM,CAAC,MAAM,UAAU,GAAG,OAAO,CAAC,GAAG,CAAC,UAAU,IAAI,wCAAwC,CAAA;AAC5F,MAAM,CAAC,MAAM,yBAAyB,GAAG,eAAe,CAAA"} \ No newline at end of file diff --git a/dist/commands/database/database.d.ts b/dist/commands/database/database.d.ts new file mode 100644 index 00000000000..2bc66fabb8b --- /dev/null +++ b/dist/commands/database/database.d.ts @@ -0,0 +1,18 @@ +import BaseCommand from '../base-command.js'; +export type Extension = { + id: string; + name: string; + slug: string; + hostSiteUrl: string; + installedOnTeam: boolean; +}; +export type SiteInfo = { + id: string; + name: string; + account_id: string; + admin_url: string; + url: string; + ssl_url: string; +}; +export declare const createDatabaseCommand: (program: BaseCommand) => void; +//# sourceMappingURL=database.d.ts.map \ No newline at end of file diff --git a/dist/commands/database/database.d.ts.map b/dist/commands/database/database.d.ts.map new file mode 100644 index 00000000000..b110dd41c62 --- /dev/null +++ b/dist/commands/database/database.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../../src/commands/database/database.ts"],"names":[],"mappings":"AAEA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAG5C,MAAM,MAAM,SAAS,GAAG;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;IACnB,eAAe,EAAE,OAAO,CAAA;CACzB,CAAA;AAED,MAAM,MAAM,QAAQ,GAAG;IACrB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,UAAU,EAAE,MAAM,CAAA;IAClB,SAAS,EAAE,MAAM,CAAA;IACjB,GAAG,EAAE,MAAM,CAAA;IACX,OAAO,EAAE,MAAM,CAAA;CAChB,CAAA;AAID,eAAO,MAAM,qBAAqB,GAAI,SAAS,WAAW,SA0DzD,CAAA"} \ No newline at end of file diff --git a/dist/commands/database/database.js b/dist/commands/database/database.js new file mode 100644 index 00000000000..920effe0867 --- /dev/null +++ b/dist/commands/database/database.js @@ -0,0 +1,50 @@ +import { Option } from 'commander'; +import inquirer from 'inquirer'; +const supportedBoilerplates = new Set(['drizzle']); +export const createDatabaseCommand = (program) => { + const dbCommand = program + .command('db') + .alias('database') + .description(`Provision a production ready Postgres database with a single command`) + .addExamples(['netlify db status', 'netlify db init', 'netlify db init --help']); + dbCommand + .command('init') + .description(`Initialize a new database for the current site`) + .option('--assume-no', 'Non-interactive setup. Does not initialize any third-party tools/boilerplate. Ideal for CI environments or AI tools.', false) + .addOption(new Option('--boilerplate ', 'Type of boilerplate to add to your project.').choices(Array.from(supportedBoilerplates).sort())) + .option('--no-boilerplate', "Don't add any boilerplate to your project.") + .option('-o, --overwrite', 'Overwrites existing files that would be created when setting up boilerplate') + .action(async (_options, command) => { + const { init } = await import('./init.js'); + // Only prompt for drizzle if the user did not specify a boilerplate option, and if we're in + // interactive mode + if (_options.boilerplate === undefined && !_options.assumeNo) { + const answers = await inquirer.prompt([ + { + type: 'confirm', + name: 'useDrizzle', + message: 'Set up Drizzle boilerplate?', + }, + ]); + if (answers.useDrizzle) { + command.setOptionValue('boilerplate', 'drizzle'); + } + } + const options = _options; + if (options.assumeNo) { + options.boilerplate = false; + options.overwrite = false; + } + await init(options, command); + }) + .addExamples([`netlify db init --assume-no`, `netlify db init --boilerplate=drizzle --overwrite`]); + dbCommand + .command('status') + .description(`Check the status of the database`) + .action(async (options, command) => { + const { status } = await import('./status.js'); + // eslint-disable-next-line @typescript-eslint/no-unsafe-argument + await status(options, command); + }); +}; +//# sourceMappingURL=database.js.map \ No newline at end of file diff --git a/dist/commands/database/database.js.map b/dist/commands/database/database.js.map new file mode 100644 index 00000000000..aaa40831e47 --- /dev/null +++ b/dist/commands/database/database.js.map @@ -0,0 +1 @@ +{"version":3,"file":"database.js","sourceRoot":"","sources":["../../../src/commands/database/database.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAClC,OAAO,QAAQ,MAAM,UAAU,CAAA;AAqB/B,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAA0B,CAAC,SAAS,CAAC,CAAC,CAAA;AAE3E,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,OAAoB,EAAE,EAAE;IAC5D,MAAM,SAAS,GAAG,OAAO;SACtB,OAAO,CAAC,IAAI,CAAC;SACb,KAAK,CAAC,UAAU,CAAC;SACjB,WAAW,CAAC,sEAAsE,CAAC;SACnF,WAAW,CAAC,CAAC,mBAAmB,EAAE,iBAAiB,EAAE,wBAAwB,CAAC,CAAC,CAAA;IAElF,SAAS;SACN,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,gDAAgD,CAAC;SAC7D,MAAM,CACL,aAAa,EACb,sHAAsH,EACtH,KAAK,CACN;SACA,SAAS,CACR,IAAI,MAAM,CAAC,sBAAsB,EAAE,6CAA6C,CAAC,CAAC,OAAO,CACvF,KAAK,CAAC,IAAI,CAAC,qBAAqB,CAAC,CAAC,IAAI,EAAE,CACzC,CACF;SACA,MAAM,CAAC,kBAAkB,EAAE,4CAA4C,CAAC;SACxE,MAAM,CAAC,iBAAiB,EAAE,6EAA6E,CAAC;SACxG,MAAM,CAAC,KAAK,EAAE,QAAiC,EAAE,OAAoB,EAAE,EAAE;QACxE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAA;QAE1C,4FAA4F;QAC5F,mBAAmB;QACnB,IAAI,QAAQ,CAAC,WAAW,KAAK,SAAS,IAAI,CAAC,QAAQ,CAAC,QAAQ,EAAE,CAAC;YAC7D,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,MAAM,CAA0B;gBAC7D;oBACE,IAAI,EAAE,SAAS;oBACf,IAAI,EAAE,YAAY;oBAClB,OAAO,EAAE,6BAA6B;iBACvC;aACF,CAAC,CAAA;YACF,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;gBACvB,OAAO,CAAC,cAAc,CAAC,aAAa,EAAE,SAAS,CAAC,CAAA;YAClD,CAAC;QACH,CAAC;QAED,MAAM,OAAO,GAAG,QAA+B,CAAA;QAC/C,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;YACrB,OAAO,CAAC,WAAW,GAAG,KAAK,CAAA;YAC3B,OAAO,CAAC,SAAS,GAAG,KAAK,CAAA;QAC3B,CAAC;QAED,MAAM,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAC9B,CAAC,CAAC;SACD,WAAW,CAAC,CAAC,6BAA6B,EAAE,mDAAmD,CAAC,CAAC,CAAA;IAEpG,SAAS;SACN,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,kCAAkC,CAAC;SAC/C,MAAM,CAAC,KAAK,EAAE,OAAO,EAAE,OAAO,EAAE,EAAE;QACjC,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;QAC9C,iEAAiE;QACjE,MAAM,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAChC,CAAC,CAAC,CAAA;AACN,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/database/drizzle.d.ts b/dist/commands/database/drizzle.d.ts new file mode 100644 index 00000000000..fe4ad4a4445 --- /dev/null +++ b/dist/commands/database/drizzle.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const initDrizzle: (command: BaseCommand) => Promise; +//# sourceMappingURL=drizzle.d.ts.map \ No newline at end of file diff --git a/dist/commands/database/drizzle.d.ts.map b/dist/commands/database/drizzle.d.ts.map new file mode 100644 index 00000000000..8acf57416ea --- /dev/null +++ b/dist/commands/database/drizzle.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"drizzle.d.ts","sourceRoot":"","sources":["../../../src/commands/database/drizzle.ts"],"names":[],"mappings":"AACA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAM5C,eAAO,MAAM,WAAW,GAAU,SAAS,WAAW,kBAiErD,CAAA"} \ No newline at end of file diff --git a/dist/commands/database/drizzle.js b/dist/commands/database/drizzle.js new file mode 100644 index 00000000000..2a7852949e5 --- /dev/null +++ b/dist/commands/database/drizzle.js @@ -0,0 +1,96 @@ +import { carefullyWriteFile, getPackageJSON, spawnAsync } from './utils.js'; +import path from 'path'; +import fs from 'fs/promises'; +import inquirer from 'inquirer'; +import { NETLIFY_NEON_PACKAGE_NAME } from './constants.js'; +export const initDrizzle = async (command) => { + const workingDirectory = command.project.root ?? command.project.baseDirectory; + if (!workingDirectory) { + throw new Error('Failed to initialize Drizzle. Project root or base directory not found.'); + } + const opts = command.opts(); + const drizzleConfigFilePath = path.resolve(workingDirectory, 'drizzle.config.ts'); + const schemaFilePath = path.resolve(workingDirectory, 'db/schema.ts'); + const dbIndexFilePath = path.resolve(workingDirectory, 'db/index.ts'); + if (opts.overwrite) { + await fs.writeFile(drizzleConfigFilePath, drizzleConfig); + await fs.mkdir(path.resolve(workingDirectory, 'db'), { recursive: true }); + await fs.writeFile(schemaFilePath, drizzleSchema); + await fs.writeFile(dbIndexFilePath, dbIndex); + } + else { + await carefullyWriteFile(drizzleConfigFilePath, drizzleConfig, workingDirectory); + await fs.mkdir(path.resolve(workingDirectory, 'db'), { recursive: true }); + await carefullyWriteFile(schemaFilePath, drizzleSchema, workingDirectory); + await carefullyWriteFile(dbIndexFilePath, dbIndex, workingDirectory); + } + const packageJsonPath = path.resolve(command.workingDir, 'package.json'); + const packageJson = getPackageJSON(command.workingDir); + packageJson.scripts = { + ...(packageJson.scripts ?? {}), + ...packageJsonScripts, + }; + if (opts.overwrite) { + await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2)); + } + if (!opts.overwrite) { + const answers = await inquirer.prompt([ + { + type: 'confirm', + name: 'updatePackageJson', + message: `Add drizzle db commands to package.json?`, + }, + ]); + if (answers.updatePackageJson) { + await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2)); + } + } + if (!Object.keys(packageJson.devDependencies ?? {}).includes('drizzle-kit')) { + await spawnAsync(command.project.packageManager?.installCommand ?? 'npm install', ['drizzle-kit@latest', '-D'], { + stdio: 'inherit', + shell: true, + }); + } + if (!Object.keys(packageJson.dependencies ?? {}).includes('drizzle-orm')) { + await spawnAsync(command.project.packageManager?.installCommand ?? 'npm install', ['drizzle-orm@latest'], { + stdio: 'inherit', + shell: true, + }); + } +}; +const drizzleConfig = `import { defineConfig } from 'drizzle-kit'; + +export default defineConfig({ + dialect: 'postgresql', + dbCredentials: { + url: process.env.NETLIFY_DATABASE_URL! + }, + schema: './db/schema.ts', + /** + * Never edit the migrations directly, only use drizzle. + * There are scripts in the package.json "db:generate" and "db:migrate" to handle this. + */ + out: './migrations' +});`; +const drizzleSchema = `import { integer, pgTable, varchar, text } from 'drizzle-orm/pg-core'; + +export const posts = pgTable('posts', { + id: integer().primaryKey().generatedAlwaysAsIdentity(), + title: varchar({ length: 255 }).notNull(), + content: text().notNull().default('') +});`; +const dbIndex = `import { neon } from '${NETLIFY_NEON_PACKAGE_NAME}'; +import { drizzle } from 'drizzle-orm/neon-http'; + +import * as schema from './schema'; + +export const db = drizzle({ + schema, + client: neon() +});`; +const packageJsonScripts = { + 'db:generate': 'drizzle-kit generate', + 'db:migrate': 'netlify dev:exec drizzle-kit migrate', + 'db:studio': 'netlify dev:exec drizzle-kit studio', +}; +//# sourceMappingURL=drizzle.js.map \ No newline at end of file diff --git a/dist/commands/database/drizzle.js.map b/dist/commands/database/drizzle.js.map new file mode 100644 index 00000000000..fdfa297e670 --- /dev/null +++ b/dist/commands/database/drizzle.js.map @@ -0,0 +1 @@ +{"version":3,"file":"drizzle.js","sourceRoot":"","sources":["../../../src/commands/database/drizzle.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/database/index.d.ts b/dist/commands/database/index.d.ts new file mode 100644 index 00000000000..e6aef441249 --- /dev/null +++ b/dist/commands/database/index.d.ts @@ -0,0 +1,2 @@ +export { createDatabaseCommand } from './database.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/database/index.d.ts.map b/dist/commands/database/index.d.ts.map new file mode 100644 index 00000000000..5f5686d01f6 --- /dev/null +++ b/dist/commands/database/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/database/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA"} \ No newline at end of file diff --git a/dist/commands/database/index.js b/dist/commands/database/index.js new file mode 100644 index 00000000000..685da80a5e8 --- /dev/null +++ b/dist/commands/database/index.js @@ -0,0 +1,2 @@ +export { createDatabaseCommand } from './database.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/database/index.js.map b/dist/commands/database/index.js.map new file mode 100644 index 00000000000..3825d554dd7 --- /dev/null +++ b/dist/commands/database/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/database/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,MAAM,eAAe,CAAA"} \ No newline at end of file diff --git a/dist/commands/database/init.d.ts b/dist/commands/database/init.d.ts new file mode 100644 index 00000000000..f6d121bd86a --- /dev/null +++ b/dist/commands/database/init.d.ts @@ -0,0 +1,9 @@ +import BaseCommand from '../base-command.js'; +export type DatabaseInitOptions = { + assumeNo: boolean; + boilerplate: DatabaseBoilerplateType | false; + overwrite: boolean; +}; +export type DatabaseBoilerplateType = 'drizzle'; +export declare const init: (options: DatabaseInitOptions, command: BaseCommand) => Promise; +//# sourceMappingURL=init.d.ts.map \ No newline at end of file diff --git a/dist/commands/database/init.d.ts.map b/dist/commands/database/init.d.ts.map new file mode 100644 index 00000000000..a259866872a --- /dev/null +++ b/dist/commands/database/init.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/commands/database/init.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAQ5C,MAAM,MAAM,mBAAmB,GAAG;IAChC,QAAQ,EAAE,OAAO,CAAA;IACjB,WAAW,EAAE,uBAAuB,GAAG,KAAK,CAAA;IAC5C,SAAS,EAAE,OAAO,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,uBAAuB,GAAG,SAAS,CAAA;AAE/C,eAAO,MAAM,IAAI,GAAU,SAAS,mBAAmB,EAAE,SAAS,WAAW,kBA+I5E,CAAA"} \ No newline at end of file diff --git a/dist/commands/database/init.js b/dist/commands/database/init.js new file mode 100644 index 00000000000..2ff331e825b --- /dev/null +++ b/dist/commands/database/init.js @@ -0,0 +1,124 @@ +import { getAccount, getExtension, getJigsawToken, getPackageJSON, installExtension, spawnAsync } from './utils.js'; +import { initDrizzle } from './drizzle.js'; +import { NEON_DATABASE_EXTENSION_SLUG, NETLIFY_NEON_PACKAGE_NAME } from './constants.js'; +import prettyjson from 'prettyjson'; +import { log } from '../../utils/command-helpers.js'; +export const init = async (options, command) => { + const siteInfo = command.netlify.siteInfo; + if (!command.siteId) { + console.error(`The project must be linked with netlify link before initializing a database.`); + return; + } + if (!command.netlify.api.accessToken || !siteInfo.account_id || !siteInfo.name) { + throw new Error(`Please login with netlify login before running this command`); + } + const account = await getAccount(command, { accountId: siteInfo.account_id }); + const netlifyToken = command.netlify.api.accessToken.replace('Bearer ', ''); + const extension = await getExtension({ + accountId: siteInfo.account_id, + netlifyToken: netlifyToken, + slug: NEON_DATABASE_EXTENSION_SLUG, + }); + if (!extension?.hostSiteUrl) { + throw new Error(`Failed to get extension host site url when installing extension`); + } + const installNeonExtension = async () => { + if (!account.name) { + throw new Error(`Failed to install extension "${extension.name}"`); + } + const installed = await installExtension({ + accountId: siteInfo.account_id, + netlifyToken: netlifyToken, + slug: NEON_DATABASE_EXTENSION_SLUG, + hostSiteUrl: extension.hostSiteUrl, + }); + if (!installed) { + throw new Error(`Failed to install extension on team "${account.name}": "${extension.name}"`); + } + log(`Extension "${extension.name}" successfully installed on team "${account.name}"`); + }; + if (!extension.installedOnTeam) { + await installNeonExtension(); + } + if (typeof options.boilerplate === 'string') { + log(`Initializing ${options.boilerplate}...`); + await initDrizzle(command); + } + log(`Initializing a new database...`); + const hostSiteUrl = process.env.EXTENSION_HOST_SITE_URL ?? extension.hostSiteUrl; + const initEndpoint = new URL('/api/cli-db-init', hostSiteUrl).toString(); + const currentUser = await command.netlify.api.getCurrentUser(); + const { data: jigsawToken, error } = await getJigsawToken({ + netlifyToken: netlifyToken, + accountId: siteInfo.account_id, + integrationSlug: extension.slug, + }); + if (error || !jigsawToken) { + throw new Error(`Failed to get jigsaw token: ${error?.message ?? 'Unknown error'}`); + } + const headers = { + 'Content-Type': 'application/json', + 'Nf-UIExt-Netlify-Token': jigsawToken, + 'Nf-UIExt-Netlify-Token-Issuer': 'jigsaw', + 'Nf-UIExt-Extension-Id': extension.id, + 'Nf-UIExt-Extension-Slug': extension.slug, + 'Nf-UIExt-Site-Id': command.siteId ?? '', + 'Nf-UIExt-Team-Id': siteInfo.account_id, + 'Nf-UIExt-User-Id': currentUser.id ?? '', + }; + const req = await fetch(initEndpoint, { + method: 'POST', + headers, + }); + if (!req.ok) { + const error = (await req.json()); + if (error.code === 'CONFLICT') { + log(`Database already connected to this site. Skipping initialization.`); + } + else { + throw new Error(`Failed to initialize DB: ${error.message ?? 'Unknown error occurred'}`); + } + } + let status; + try { + const statusEndpoint = new URL('/api/cli-db-status', hostSiteUrl).toString(); + const statusRes = await fetch(statusEndpoint, { + headers, + }); + if (!statusRes.ok) { + throw new Error(`Failed to get database status`, { cause: statusRes }); + } + status = (await statusRes.json()); + } + catch (e) { + console.error('Failed to get database status', e); + } + try { + const packageJson = getPackageJSON(command.workingDir); + if ((packageJson.dependencies && !Object.keys(packageJson.dependencies).includes(NETLIFY_NEON_PACKAGE_NAME)) || + !packageJson.dependencies) { + await spawnAsync(command.project.packageManager?.installCommand ?? 'npm install', ['@netlify/neon@latest'], { + stdio: 'inherit', + shell: true, + }); + } + } + catch (e) { + console.error(`Failed to install @netlify/neon in ${command.workingDir}:`, e); + } + log(prettyjson.render({ + 'Current team': account.name, + 'Current site': siteInfo.name, + [`${extension.name} extension`]: 'installed on team', + ['Database status']: status?.siteConfiguration?.connectedDatabase?.isConnected + ? 'connected to site' + : 'not connected', + ['Environment variables']: '', + [' NETLIFY_DATABASE_URL']: status?.existingManagedEnvs?.includes('NETLIFY_DATABASE_URL') ? 'saved' : 'not set', + [' NETLIFY_DATABASE_URL_UNPOOLED']: status?.existingManagedEnvs?.includes('NETLIFY_DATABASE_URL_UNPOOLED') + ? 'saved' + : 'not set', + })); + return; +}; +//# sourceMappingURL=init.js.map \ No newline at end of file diff --git a/dist/commands/database/init.js.map b/dist/commands/database/init.js.map new file mode 100644 index 00000000000..585a9af2884 --- /dev/null +++ b/dist/commands/database/init.js.map @@ -0,0 +1 @@ +{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/commands/database/init.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/database/status.d.ts b/dist/commands/database/status.d.ts new file mode 100644 index 00000000000..eb9d6bb1493 --- /dev/null +++ b/dist/commands/database/status.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const status: (_options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=status.d.ts.map \ No newline at end of file diff --git a/dist/commands/database/status.d.ts.map b/dist/commands/database/status.d.ts.map new file mode 100644 index 00000000000..33aa3594d10 --- /dev/null +++ b/dist/commands/database/status.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/commands/database/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAExC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAM5C,eAAO,MAAM,MAAM,GAAU,UAAU,YAAY,EAAE,SAAS,WAAW,kBAsExE,CAAA"} \ No newline at end of file diff --git a/dist/commands/database/status.js b/dist/commands/database/status.js new file mode 100644 index 00000000000..8243172269c --- /dev/null +++ b/dist/commands/database/status.js @@ -0,0 +1,71 @@ +import { getAccount, getExtension, getSiteConfiguration } from './utils.js'; +import { NEON_DATABASE_EXTENSION_SLUG } from './constants.js'; +import prettyjson from 'prettyjson'; +import { chalk, log } from '../../utils/command-helpers.js'; +export const status = async (_options, command) => { + const siteInfo = command.netlify.siteInfo; + if (!command.siteId) { + throw new Error(`The project must be linked with netlify link before initializing a database.`); + } + if (!siteInfo.account_id) { + throw new Error(`No account id found for site ${command.siteId}`); + } + if (!command.netlify.api.accessToken) { + throw new Error(`You must be logged in with netlify login to check the status of the database`); + } + const netlifyToken = command.netlify.api.accessToken.replace('Bearer ', ''); + const account = await getAccount(command, { accountId: siteInfo.account_id }); + let databaseUrlEnv; + let unpooledDatabaseUrlEnv; + try { + databaseUrlEnv = await command.netlify.api.getEnvVar({ + accountId: siteInfo.account_id, + siteId: command.siteId, + key: 'NETLIFY_DATABASE_URL', + }); + } + catch { + // no-op, env var does not exist, so we just continue + } + try { + unpooledDatabaseUrlEnv = await command.netlify.api.getEnvVar({ + accountId: siteInfo.account_id, + siteId: command.siteId, + key: 'NETLIFY_DATABASE_URL_UNPOOLED', + }); + } + catch { + // no-op, env var does not exist, so we just continue + } + const extension = await getExtension({ + accountId: account.id, + netlifyToken: netlifyToken, + slug: NEON_DATABASE_EXTENSION_SLUG, + }); + let siteConfig; + try { + siteConfig = await getSiteConfiguration({ + siteId: command.siteId, + accountId: siteInfo.account_id, + slug: NEON_DATABASE_EXTENSION_SLUG, + netlifyToken: netlifyToken, + }); + } + catch { + // no-op, site config does not exist or extension not installed + } + log(prettyjson.render({ + 'Current team': account.name, + 'Current site': siteInfo.name, + [extension?.name ? `${extension.name} extension` : 'Database extension']: extension?.installedOnTeam + ? 'installed on team' + : chalk.red('not installed on team'), + // @ts-expect-error -- siteConfig is not typed + // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access + ['Database status']: siteConfig?.config?.connectedDatabase ? 'connected to site' : chalk.red('not connected'), + ['Environment variables']: '', + [' NETLIFY_DATABASE_URL']: databaseUrlEnv?.key === 'NETLIFY_DATABASE_URL' ? 'saved' : chalk.red('not set'), + [' NETLIFY_DATABASE_URL_UNPOOLED']: unpooledDatabaseUrlEnv?.key === 'NETLIFY_DATABASE_URL_UNPOOLED' ? 'saved' : chalk.red('not set'), + })); +}; +//# sourceMappingURL=status.js.map \ No newline at end of file diff --git a/dist/commands/database/status.js.map b/dist/commands/database/status.js.map new file mode 100644 index 00000000000..7f313f53b3c --- /dev/null +++ b/dist/commands/database/status.js.map @@ -0,0 +1 @@ +{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/commands/database/status.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/database/utils.d.ts b/dist/commands/database/utils.d.ts new file mode 100644 index 00000000000..ba08f48fee6 --- /dev/null +++ b/dist/commands/database/utils.d.ts @@ -0,0 +1,75 @@ +import BaseCommand from '../base-command.js'; +import { Extension } from './database.js'; +import { spawn } from 'child_process'; +type PackageJSON = { + dependencies?: Record; + devDependencies?: Record; + scripts?: Record; +}; +export declare function getPackageJSON(directory: string): PackageJSON; +export declare const spawnAsync: (command: string, args: string[], options: Parameters[2]) => Promise; +export declare const getExtension: ({ accountId, netlifyToken, slug, }: { + accountId: string; + netlifyToken: string; + slug: string; +}) => Promise; +export declare const installExtension: ({ netlifyToken, accountId, slug, hostSiteUrl, }: { + netlifyToken: string; + accountId: string; + slug: string; + hostSiteUrl: string; +}) => Promise; +export declare const getSiteConfiguration: ({ siteId, accountId, netlifyToken, slug, }: { + siteId: string; + accountId: string; + netlifyToken: string; + slug: string; +}) => Promise; +export declare const carefullyWriteFile: (filePath: string, data: string, projectRoot: string) => Promise; +export declare const getAccount: (command: BaseCommand, { accountId, }: { + accountId: string; +}) => Promise<{ + id: string; + name: string; +} & Omit<{ + id?: string; + name?: string; + slug?: string; + type?: string; + capabilities?: { + sites?: import("@netlify/open-api").components["schemas"]["accountUsageCapability"]; + collaborators?: import("@netlify/open-api").components["schemas"]["accountUsageCapability"]; + }; + billing_name?: string; + billing_email?: string; + billing_details?: string; + billing_period?: string; + payment_method_id?: string; + type_name?: string; + type_id?: string; + owner_ids?: string[]; + roles_allowed?: string[]; + created_at?: string; + updated_at?: string; +}, "name" | "id">>; +type JigsawTokenResult = { + data: string; + error: null; +} | { + data: null; + error: { + code: number; + message: string; + }; +}; +export declare const getJigsawToken: ({ netlifyToken, accountId, integrationSlug, isEnable, }: { + netlifyToken: string; + accountId: string; + integrationSlug?: string; + /** + * isEnable will make a token that can install the extension + */ + isEnable?: boolean; +}) => Promise; +export {}; +//# sourceMappingURL=utils.d.ts.map \ No newline at end of file diff --git a/dist/commands/database/utils.d.ts.map b/dist/commands/database/utils.d.ts.map new file mode 100644 index 00000000000..193dd3156a0 --- /dev/null +++ b/dist/commands/database/utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/commands/database/utils.ts"],"names":[],"mappings":"AAQA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAA;AACzC,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAA;AAErC,KAAK,WAAW,GAAG;IACjB,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACrC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CACjC,CAAA;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,GAexB,WAAW,CAClC;AAED,eAAO,MAAM,UAAU,GAAI,SAAS,MAAM,EAAE,MAAM,MAAM,EAAE,EAAE,SAAS,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,MAAM,CAYhH,CAAA;AAED,eAAO,MAAM,YAAY,GAAU,oCAIhC;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;CACb,mCAiBA,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAU,iDAKpC;IACD,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,IAAI,EAAE,MAAM,CAAA;IACZ,WAAW,EAAE,MAAM,CAAA;CACpB,qBA2BA,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAU,4CAKxC;IACD,MAAM,EAAE,MAAM,CAAA;IACd,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,MAAM,CAAA;CACb,qBAYA,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAU,UAAU,MAAM,EAAE,MAAM,MAAM,EAAE,aAAa,MAAM,kBAkB3F,CAAA;AAED,eAAO,MAAM,UAAU,GACrB,SAAS,WAAW,EACpB,gBAEG;IACD,SAAS,EAAE,MAAM,CAAA;CAClB;QAcuB,MAAM;UAAQ,MAAM;;;;;;;aAiFw8uC,CAAC,EAAC,iDAAsB;qBAAiD,CAAC,EAAC,iDAAsB;;;;;;;;;;;;;kBA7EtlvC,CAAA;AAED,KAAK,iBAAiB,GAClB;IACE,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,IAAI,CAAA;CACZ,GACD;IACE,IAAI,EAAE,IAAI,CAAA;IACV,KAAK,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAA;CACzC,CAAA;AAEL,eAAO,MAAM,cAAc,GAAU,yDAKlC;IACD,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB,KAAG,OAAO,CAAC,iBAAiB,CAmD5B,CAAA"} \ No newline at end of file diff --git a/dist/commands/database/utils.js b/dist/commands/database/utils.js new file mode 100644 index 00000000000..f3310a64a5f --- /dev/null +++ b/dist/commands/database/utils.js @@ -0,0 +1,173 @@ +import { createRequire } from 'module'; +import { join } from 'path'; +import fsPromises from 'fs/promises'; +import fs from 'fs'; +import inquirer from 'inquirer'; +import { JIGSAW_URL } from './constants.js'; +import { spawn } from 'child_process'; +export function getPackageJSON(directory) { + const require = createRequire(join(directory, 'package.json')); + const packageJson = require('./package.json'); + if (typeof packageJson !== 'object' || packageJson === null) { + throw new Error('Failed to load package.json'); + } + if ('dependencies' in packageJson && typeof packageJson.dependencies !== 'object') { + throw new Error(`Expected object at package.json#dependencies, got ${typeof packageJson.dependencies}`); + } + if ('devDependencies' in packageJson && typeof packageJson.devDependencies !== 'object') { + throw new Error(`Expected object at package.json#devDependencies, got ${typeof packageJson.devDependencies}`); + } + if ('scripts' in packageJson && typeof packageJson.scripts !== 'object') { + throw new Error(`Expected object at package.json#scripts, got ${typeof packageJson.scripts}`); + } + return packageJson; +} +export const spawnAsync = (command, args, options) => { + return new Promise((resolve, reject) => { + const child = spawn(command, args, options); + child.on('error', reject); + child.on('exit', (code) => { + if (code === 0) { + resolve(code); + } + const errorMessage = code ? `Process exited with code ${code.toString()}` : 'Process exited with no code'; + reject(new Error(errorMessage)); + }); + }); +}; +export const getExtension = async ({ accountId, netlifyToken, slug, }) => { + const extensionResponse = await fetch(`${JIGSAW_URL}/${encodeURIComponent(accountId)}/integrations/${encodeURIComponent(slug)}`, { + headers: { + 'netlify-token': netlifyToken, + 'Api-Version': '2', + }, + }); + if (!extensionResponse.ok) { + throw new Error(`Failed to fetch extension: ${slug}`); + } + const extension = (await extensionResponse.json()); + return extension; +}; +export const installExtension = async ({ netlifyToken, accountId, slug, hostSiteUrl, }) => { + const { data: jigsawToken, error } = await getJigsawToken({ + netlifyToken: netlifyToken, + accountId, + integrationSlug: slug, + isEnable: true, + }); + if (error || !jigsawToken) { + throw new Error(`Failed to get Jigsaw token: ${error?.message ?? 'Unknown error'}`); + } + const extensionOnInstallUrl = new URL('/.netlify/functions/handler/on-install', hostSiteUrl); + const installedResponse = await fetch(extensionOnInstallUrl, { + method: 'POST', + body: JSON.stringify({ + teamId: accountId, + }), + headers: { + 'netlify-token': jigsawToken, + }, + }); + if (!installedResponse.ok && installedResponse.status !== 409) { + const text = await installedResponse.text(); + throw new Error(`Failed to install extension '${slug}': ${text}`); + } + return true; +}; +export const getSiteConfiguration = async ({ siteId, accountId, netlifyToken, slug, }) => { + const url = new URL(`/team/${accountId}/integrations/${slug}/configuration/site/${siteId}`, JIGSAW_URL); + const siteConfigurationResponse = await fetch(url.toString(), { + headers: { + 'netlify-token': netlifyToken, + }, + }); + if (!siteConfigurationResponse.ok) { + throw new Error(`Failed to fetch extension site configuration for ${siteId}. Is the extension installed?`); + } + const siteConfiguration = await siteConfigurationResponse.json(); + return siteConfiguration; +}; +export const carefullyWriteFile = async (filePath, data, projectRoot) => { + if (fs.existsSync(filePath)) { + const answers = await inquirer.prompt([ + { + type: 'confirm', + name: 'overwrite', + message: `Overwrite existing file .${filePath.replace(projectRoot, '')}?`, + }, + ]); + if (answers.overwrite) { + await fsPromises.writeFile(filePath, data); + } + } + else { + await fsPromises.writeFile(filePath, data); + } +}; +export const getAccount = async (command, { accountId, }) => { + let account; + try { + // @ts-expect-error -- TODO: fix the getAccount type in the openapi spec. It should not be an array of accounts, just one account. + account = await command.netlify.api.getAccount({ accountId }); + } + catch (e) { + throw new Error(`Error getting account, make sure you are logged in with netlify login`, { + cause: e, + }); + } + if (!account.id || !account.name) { + throw new Error(`Error getting account, make sure you are logged in with netlify login`); + } + return account; +}; +export const getJigsawToken = async ({ netlifyToken, accountId, integrationSlug, isEnable, }) => { + try { + const tokenResponse = await fetch(`${JIGSAW_URL}/generate-token`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Cookie: `_nf-auth=${netlifyToken}`, + 'Api-Version': '2', + }, + body: JSON.stringify({ + ownerId: accountId, + integrationSlug, + isEnable, + }), + }); + if (!tokenResponse.ok) { + return { + data: null, + error: { + code: 401, + message: `Unauthorized`, + }, + }; + } + const tokenData = (await tokenResponse.json()); + if (!tokenData?.token) { + return { + data: null, + error: { + code: 401, + message: `Unauthorized`, + }, + }; + } + return { + data: tokenData.token, + error: null, + }; + } + catch (e) { + console.error('Failed to get Jigsaw token', e); + return { + data: null, + error: { + code: 401, + message: `Unauthorized`, + }, + }; + } +}; +//# sourceMappingURL=utils.js.map \ No newline at end of file diff --git a/dist/commands/database/utils.js.map b/dist/commands/database/utils.js.map new file mode 100644 index 00000000000..c9694fcb30a --- /dev/null +++ b/dist/commands/database/utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/commands/database/utils.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/deploy/deploy.d.ts b/dist/commands/deploy/deploy.d.ts new file mode 100644 index 00000000000..8d81d87855e --- /dev/null +++ b/dist/commands/deploy/deploy.d.ts @@ -0,0 +1,4 @@ +import type BaseCommand from '../base-command.js'; +import type { DeployOptionValues } from './option_values.js'; +export declare const deploy: (options: DeployOptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=deploy.d.ts.map \ No newline at end of file diff --git a/dist/commands/deploy/deploy.d.ts.map b/dist/commands/deploy/deploy.d.ts.map new file mode 100644 index 00000000000..1320cb560ea --- /dev/null +++ b/dist/commands/deploy/deploy.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../../src/commands/deploy/deploy.ts"],"names":[],"mappings":"AA6CA,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAKjD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AA0vB5D,eAAO,MAAM,MAAM,GAAU,SAAS,kBAAkB,EAAE,SAAS,WAAW,uBAyG7E,CAAA"} \ No newline at end of file diff --git a/dist/commands/deploy/deploy.js b/dist/commands/deploy/deploy.js new file mode 100644 index 00000000000..661b17f9bee --- /dev/null +++ b/dist/commands/deploy/deploy.js @@ -0,0 +1,687 @@ +import { stat } from 'fs/promises'; +import { basename, resolve } from 'path'; +import { runCoreSteps } from '@netlify/build'; +import inquirer from 'inquirer'; +import isEmpty from 'lodash/isEmpty.js'; +import isObject from 'lodash/isObject.js'; +import { parseAllHeaders } from '@netlify/headers-parser'; +import { parseAllRedirects } from '@netlify/redirect-parser'; +import prettyjson from 'prettyjson'; +import { cancelDeploy } from '../../lib/api.js'; +import { getRunBuildOptions, runBuild, } from '../../lib/build.js'; +import { getBootstrapURL } from '../../lib/edge-functions/bootstrap.js'; +import { featureFlags as edgeFunctionsFeatureFlags } from '../../lib/edge-functions/consts.js'; +import { normalizeFunctionsConfig } from '../../lib/functions/config.js'; +import { BACKGROUND_FUNCTIONS_WARNING } from '../../lib/log.js'; +import { startSpinner, stopSpinner } from '../../lib/spinner.js'; +import { detectFrameworkSettings, getDefaultConfig } from '../../utils/build-info.js'; +import { NETLIFY_CYAN_HEX, NETLIFYDEVERR, NETLIFYDEVLOG, chalk, logAndThrowError, exit, getToken, log, logJson, warn, } from '../../utils/command-helpers.js'; +import { DEFAULT_DEPLOY_TIMEOUT } from '../../utils/deploy/constants.js'; +import { deploySite } from '../../utils/deploy/deploy-site.js'; +import { getEnvelopeEnv } from '../../utils/env/index.js'; +import { getFunctionsManifestPath, getInternalFunctionsDir } from '../../utils/functions/index.js'; +import openBrowser from '../../utils/open-browser.js'; +import { link } from '../link/link.js'; +import { sitesCreate } from '../sites/sites-create.js'; +import boxen from 'boxen'; +import terminalLink from 'terminal-link'; +const triggerDeploy = async ({ api, options, siteData, siteId, }) => { + try { + const siteBuild = await api.createSiteBuild({ siteId }); + if (options.json) { + logJson({ + site_id: siteId, + site_name: siteData.name, + deploy_id: `${siteBuild.deploy_id}`, + logs: `https://app.netlify.com/projects/${siteData.name}/deploys/${siteBuild.deploy_id}`, + }); + } + else { + log(`${NETLIFYDEVLOG} A new deployment was triggered successfully. Visit https://app.netlify.com/projects/${siteData.name}/deploys/${siteBuild.deploy_id} to see the logs.`); + } + } + catch (error_) { + if (error_.status === 404) { + return logAndThrowError('Project not found. Please rerun "netlify link" and make sure that your project has CI configured.'); + } + else { + return logAndThrowError(error_.message); + } + } +}; +/** Retrieves the folder containing the static files that need to be deployed */ +const getDeployFolder = async ({ command, config, options, site, siteData, }) => { + let deployFolder; + // if the `--dir .` flag is provided we should resolve it to the working directory. + // - in regular sites this is the `process.cwd` + // - in mono repositories this will be the root of the jsWorkspace + if (options.dir) { + deployFolder = command.workspacePackage + ? resolve(command.jsWorkspaceRoot || site.root, options.dir) + : resolve(command.workingDir, options.dir); + } + else if (config?.build?.publish) { + deployFolder = resolve(site.root, config.build.publish); + } + else if (siteData?.build_settings?.dir) { + deployFolder = resolve(site.root, siteData.build_settings.dir); + } + if (!deployFolder) { + log('Please provide a publish directory (e.g. "public" or "dist" or "."):'); + const { promptPath } = await inquirer.prompt([ + { + type: 'input', + name: 'promptPath', + message: 'Publish directory', + default: '.', + filter: (input) => resolve(command.workingDir, input), + }, + ]); + deployFolder = promptPath; + } + return deployFolder; +}; +const validateDeployFolder = async (deployFolder) => { + let stats; + try { + stats = await stat(deployFolder); + } + catch (error_) { + if (error_ && typeof error_ === 'object' && 'code' in error_) { + if (error_.code === 'ENOENT') { + return logAndThrowError(`The deploy directory "${deployFolder}" has not been found. Did you forget to run 'netlify build'?`); + } + // Improve the message of permission errors + if (error_.code === 'EACCES') { + return logAndThrowError('Permission error when trying to access deploy folder'); + } + } + throw error_; + } + if (!stats.isDirectory()) { + return logAndThrowError('Deploy target must be a path to a directory'); + } + return stats; +}; +/** get the functions directory */ +const getFunctionsFolder = ({ config, options, site, siteData, workingDir, }) => { + let functionsFolder; + // Support "functions" and "Functions" + const funcConfig = config.functionsDirectory; + if (options.functions) { + functionsFolder = resolve(workingDir, options.functions); + } + else if (funcConfig) { + functionsFolder = resolve(site.root, funcConfig); + } + else if (siteData?.build_settings?.functions_dir) { + functionsFolder = resolve(site.root, siteData.build_settings.functions_dir); + } + return functionsFolder; +}; +const validateFunctionsFolder = async (functionsFolder) => { + let stats; + if (functionsFolder) { + // we used to hard error if functions folder is specified but doesn't exist + // but this was too strict for onboarding. we can just log a warning. + try { + stats = await stat(functionsFolder); + } + catch (error_) { + if (error_ && typeof error_ === 'object' && 'code' in error_) { + if (error_.code === 'ENOENT') { + log(`Functions folder "${functionsFolder}" specified but it doesn't exist! Will proceed without deploying functions`); + } + // Improve the message of permission errors + if (error_.code === 'EACCES') { + return logAndThrowError('Permission error when trying to access functions folder'); + } + } + } + } + if (stats && !stats.isDirectory()) { + return logAndThrowError('Functions folder must be a path to a directory'); + } + return stats; +}; +const validateFolders = async ({ deployFolder, functionsFolder, }) => { + const deployFolderStat = await validateDeployFolder(deployFolder); + const functionsFolderStat = await validateFunctionsFolder(functionsFolder); + return { deployFolderStat, functionsFolderStat }; +}; +/** + * @param {object} config + * @param {string} config.deployFolder + * @param {*} config.site + * @returns + */ +// @ts-expect-error TS(7031) FIXME: Binding element 'deployFolder' implicitly has an '... Remove this comment to see the full error message +const getDeployFilesFilter = ({ deployFolder, site }) => { + // site.root === deployFolder can happen when users run `netlify deploy --dir .` + // in that specific case we don't want to publish the repo node_modules + // when site.root !== deployFolder the behaviour matches our buildbot + const skipNodeModules = site.root === deployFolder; + return (filename) => { + if (filename == null) { + return false; + } + if (filename === deployFolder) { + return true; + } + const base = basename(filename); + const skipFile = (skipNodeModules && base === 'node_modules') || + (base.startsWith('.') && base !== '.well-known') || + base.startsWith('__MACOSX') || + base.includes('/.') || + // headers and redirects are bundled in the config + base === '_redirects' || + base === '_headers'; + return !skipFile; + }; +}; +const SEC_TO_MILLISEC = 1e3; +// 100 bytes +const SYNC_FILE_LIMIT = 1e2; +// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message +const prepareProductionDeploy = async ({ api, siteData }) => { + if (isObject(siteData.published_deploy) && siteData.published_deploy.locked) { + log(`\n${NETLIFYDEVERR} Deployments are "locked" for production context of this project\n`); + const { unlockChoice } = await inquirer.prompt([ + { + type: 'confirm', + name: 'unlockChoice', + message: 'Would you like to "unlock" deployments for production context to proceed?', + default: false, + }, + ]); + if (!unlockChoice) + exit(0); + await api.unlockDeploy({ deploy_id: siteData.published_deploy.id }); + log(`\n${NETLIFYDEVLOG} "Auto publishing" has been enabled for production context\n`); + } +}; +// @ts-expect-error TS(7006) FIXME: Parameter 'actual' implicitly has an 'any' type. +const hasErrorMessage = (actual, expected) => { + if (typeof actual === 'string') { + return actual.includes(expected); + } + return false; +}; +// @ts-expect-error TS(7031) FIXME: Binding element 'error_' implicitly has an 'any' t... Remove this comment to see the full error message +const reportDeployError = ({ error_, failAndExit }) => { + switch (true) { + case error_.name === 'JSONHTTPError': { + const message = error_?.json?.message ?? ''; + if (hasErrorMessage(message, 'Background Functions not allowed by team plan')) { + return failAndExit(`\n${BACKGROUND_FUNCTIONS_WARNING}`); + } + warn(`JSONHTTPError: ${message} ${error_.status}`); + warn(`\n${JSON.stringify(error_, null, ' ')}\n`); + failAndExit(error_); + return; + } + case error_.name === 'TextHTTPError': { + warn(`TextHTTPError: ${error_.status}`); + warn(`\n${error_}\n`); + failAndExit(error_); + return; + } + case hasErrorMessage(error_.message, 'Invalid filename'): { + warn(error_.message); + failAndExit(error_); + return; + } + default: { + warn(`\n${JSON.stringify(error_, null, ' ')}\n`); + failAndExit(error_); + } + } +}; +const deployProgressCb = function () { + const spinnersByType = {}; + return (event) => { + switch (event.phase) { + case 'start': { + spinnersByType[event.type] = startSpinner({ + text: event.msg, + }); + return; + } + case 'progress': { + const spinner = spinnersByType[event.type]; + if (spinner) { + spinner.update({ text: event.msg }); + } + return; + } + case 'error': + stopSpinner({ error: true, spinner: spinnersByType[event.type], text: event.msg }); + delete spinnersByType[event.type]; + return; + case 'stop': + default: { + spinnersByType[event.type].success(event.msg); + delete spinnersByType[event.type]; + } + } + }; +}; +const uploadDeployBlobs = async ({ cachedConfig, deployId, options, packagePath, silent, siteId, }) => { + const statusCb = silent ? () => { } : deployProgressCb(); + statusCb({ + type: 'blobs-uploading', + msg: 'Uploading blobs to deploy store...\n', + phase: 'start', + }); + const [token] = await getToken(); + const blobsToken = token || undefined; + const { success } = await runCoreSteps(['blobs_upload'], { + ...options, + // We log our own progress so we don't want this as well. Plus, this logs much of the same + // information as the build that (likely) came before this as part of the deploy build. + quiet: options.debug ?? true, + // @ts-expect-error(serhalp) -- Untyped in `@netlify/build` + cachedConfig, + packagePath, + deployId, + siteId, + token: blobsToken, + }); + if (!success) { + statusCb({ + type: 'blobs-uploading', + msg: 'Deploy aborted due to error while uploading blobs to deploy store', + phase: 'error', + }); + return logAndThrowError('Error while uploading blobs to deploy store'); + } + statusCb({ + type: 'blobs-uploading', + msg: 'Finished uploading blobs to deploy store', + phase: 'stop', + }); +}; +const runDeploy = async ({ +// @ts-expect-error TS(7031) FIXME: Binding element 'alias' implicitly has an 'any' ty... Remove this comment to see the full error message +alias, +// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message +api, command, +// @ts-expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message +config, +// @ts-expect-error TS(7031) FIXME: Binding element 'deployFolder' implicitly has an '... Remove this comment to see the full error message +deployFolder, +// @ts-expect-error TS(7031) FIXME: Binding element 'deployTimeout' implicitly has an ... Remove this comment to see the full error message +deployTimeout, +// @ts-expect-error TS(7031) FIXME: Binding element 'deployToProduction' implicitly ha... Remove this comment to see the full error message +deployToProduction, +// @ts-expect-error TS(7031) FIXME: Binding element 'functionsConfig' implicitly has a... Remove this comment to see the full error message +functionsConfig, functionsFolder, +// @ts-expect-error TS(7031) FIXME: Binding element 'options' implicitly has an 'a... Remove this comment to see the full error message +options, +// @ts-expect-error TS(7031) FIXME: Binding element 'packagePath' implicitly has an 'a... Remove this comment to see the full error message +packagePath, +// @ts-expect-error TS(7031) FIXME: Binding element 'silent' implicitly has an 'any' t... Remove this comment to see the full error message +silent, +// @ts-expect-error TS(7031) FIXME: Binding element 'site' implicitly has an 'any' typ... Remove this comment to see the full error message +site, +// @ts-expect-error TS(7031) FIXME: Binding element 'siteData' implicitly has an 'any'... Remove this comment to see the full error message +siteData, +// @ts-expect-error TS(7031) FIXME: Binding element 'siteId' implicitly has an 'any' t... Remove this comment to see the full error message +siteId, +// @ts-expect-error TS(7031) FIXME: Binding element 'skipFunctionsCache' implicitly ha... Remove this comment to see the full error message +skipFunctionsCache, +// @ts-expect-error TS(7031) FIXME: Binding element 'title' implicitly has an 'any' ty... Remove this comment to see the full error message +title, }) => { + let results; + let deployId; + try { + if (deployToProduction) { + await prepareProductionDeploy({ siteData, api }); + } + const draft = !deployToProduction && !alias; + results = await api.createSiteDeploy({ siteId, title, body: { draft, branch: alias } }); + deployId = results.id; + const internalFunctionsFolder = await getInternalFunctionsDir({ base: site.root, packagePath, ensureExists: true }); + await command.netlify.frameworksAPIPaths.functions.ensureExists(); + // The order of the directories matter: zip-it-and-ship-it will prioritize + // functions from the rightmost directories. In this case, we want user + // functions to take precedence over internal functions. + const functionDirectories = [ + internalFunctionsFolder, + command.netlify.frameworksAPIPaths.functions.path, + functionsFolder, + ].filter((folder) => Boolean(folder)); + const manifestPath = skipFunctionsCache ? null : await getFunctionsManifestPath({ base: site.root, packagePath }); + const redirectsPath = `${deployFolder}/_redirects`; + const headersPath = `${deployFolder}/_headers`; + const { redirects } = await parseAllRedirects({ + configRedirects: config.redirects, + redirectsFiles: [redirectsPath], + minimal: true, + }); + config.redirects = redirects; + const { headers } = await parseAllHeaders({ + configHeaders: config.headers, + headersFiles: [headersPath], + minimal: true, + }); + config.headers = headers; + await uploadDeployBlobs({ + deployId, + siteId, + silent, + options, + cachedConfig: command.netlify.cachedConfig, + packagePath: command.workspacePackage, + }); + results = await deploySite(command, api, siteId, deployFolder, { + // @ts-expect-error FIXME + config, + fnDir: functionDirectories, + functionsConfig, + statusCb: silent ? () => { } : deployProgressCb(), + deployTimeout, + syncFileLimit: SYNC_FILE_LIMIT, + // pass an existing deployId to update + deployId, + filter: getDeployFilesFilter({ site, deployFolder }), + workingDir: command.workingDir, + manifestPath, + skipFunctionsCache, + siteRoot: site.root, + }); + } + catch (error_) { + if (deployId) { + await cancelDeploy({ api, deployId }); + } + reportDeployError({ error_, failAndExit: logAndThrowError }); + } + const siteUrl = results.deploy.ssl_url || results.deploy.url; + const deployUrl = results.deploy.deploy_ssl_url || results.deploy.deploy_url; + const logsUrl = `${results.deploy.admin_url}/deploys/${results.deploy.id}`; + let functionLogsUrl = `${results.deploy.admin_url}/logs/functions`; + let edgeFunctionLogsUrl = `${results.deploy.admin_url}/logs/edge-functions`; + if (!deployToProduction) { + functionLogsUrl += `?scope=deploy:${deployId}`; + edgeFunctionLogsUrl += `?scope=deployid:${deployId}`; + } + return { + siteId: results.deploy.site_id, + siteName: results.deploy.name, + deployId: results.deployId, + siteUrl, + deployUrl, + logsUrl, + functionLogsUrl, + edgeFunctionLogsUrl, + }; +}; +const handleBuild = async ({ cachedConfig, currentDir, defaultConfig, deployHandler, options, packagePath, }) => { + if (!options.build) { + return {}; + } + const [token] = await getToken(); + const resolvedOptions = await getRunBuildOptions({ + cachedConfig, + defaultConfig, + packagePath, + token, + options, + currentDir, + deployHandler, + }); + const { configMutations, exitCode, newConfig } = await runBuild(resolvedOptions); + if (exitCode !== 0) { + exit(exitCode); + } + return { newConfig, configMutations }; +}; +const bundleEdgeFunctions = async (options, command) => { + const argv = process.argv.slice(2); + const statusCb = options.silent || argv.includes('--json') || argv.includes('--silent') ? () => { } : deployProgressCb(); + statusCb({ + type: 'edge-functions-bundling', + msg: 'Bundling edge functions...\n', + phase: 'start', + }); + const { severityCode, success } = await runCoreSteps(['edge_functions_bundling'], { + ...options, + packagePath: command.workspacePackage, + buffer: true, + featureFlags: edgeFunctionsFeatureFlags, + // We log our own progress so we don't want this as well. Plus, this logs much of the same + // information as the build that (likely) came before this as part of the deploy build. + quiet: options.debug ?? true, + // @ts-expect-error FIXME(serhalp): This is missing from the `runCoreSteps` type in @netlify/build + edgeFunctionsBootstrapURL: await getBootstrapURL(), + }); + if (!success) { + statusCb({ + type: 'edge-functions-bundling', + msg: 'Deploy aborted due to error while bundling edge functions', + phase: 'error', + }); + exit(severityCode); + } + statusCb({ + type: 'edge-functions-bundling', + msg: 'Finished bundling edge functions', + phase: 'stop', + }); +}; +const printResults = ({ deployToProduction, json, results, runBuildCommand, }) => { + const msgData = { + 'Build logs': terminalLink(results.logsUrl, results.logsUrl, { fallback: false }), + 'Function logs': terminalLink(results.functionLogsUrl, results.functionLogsUrl, { fallback: false }), + 'Edge function Logs': terminalLink(results.edgeFunctionLogsUrl, results.edgeFunctionLogsUrl, { fallback: false }), + }; + log(''); + // Note: this is leakily mimicking the @netlify/build heading style + log(chalk.cyanBright.bold(`šŸš€ Deploy complete\n${'─'.repeat(64)}`)); + // Json response for piping commands + if (json) { + const jsonData = { + site_id: results.siteId, + site_name: results.siteName, + deploy_id: results.deployId, + deploy_url: results.deployUrl, + logs: results.logsUrl, + function_logs: results.functionLogsUrl, + edge_function_logs: results.edgeFunctionLogsUrl, + }; + if (deployToProduction) { + jsonData.url = results.siteUrl; + } + logJson(jsonData); + exit(0); + } + else { + const message = deployToProduction + ? `Deployed to production URL: ${terminalLink(results.siteUrl, results.siteUrl, { fallback: false })}\n + Unique deploy URL: ${terminalLink(results.deployUrl, results.deployUrl, { fallback: false })}` + : `Deployed draft to ${terminalLink(results.deployUrl, results.deployUrl, { fallback: false })}`; + log(boxen(message, { + padding: 1, + margin: 1, + textAlignment: 'center', + borderStyle: 'round', + borderColor: NETLIFY_CYAN_HEX, + // This is an intentional half-width space to work around a unicode padding math bug in boxen + // eslint-disable-next-line no-irregular-whitespace + title: `⬄ ${deployToProduction ? 'Production deploy' : 'Draft deploy'} is live ⬄ `, + titleAlignment: 'center', + })); + log(prettyjson.render(msgData)); + if (!deployToProduction) { + log(); + log('If everything looks good on your draft URL, deploy it to your main project URL with the --prod flag:'); + log(chalk.cyanBright.bold(`netlify deploy${runBuildCommand ? '' : ' --no-build'} --prod`)); + log(); + } + } +}; +const prepAndRunDeploy = async ({ api, command, config, deployToProduction, options, site, siteData, siteId, workingDir, }) => { + const alias = options.alias || options.branch; + // if a context is passed besides dev, we need to pull env vars from that specific context + if (options.context && options.context !== 'dev') { + command.netlify.cachedConfig.env = await getEnvelopeEnv({ + api, + context: options.context, + env: command.netlify.cachedConfig.env, + siteInfo: siteData, + }); + } + const deployFolder = await getDeployFolder({ command, options, config, site, siteData }); + const functionsFolder = getFunctionsFolder({ workingDir, options, config, site, siteData }); + const { configPath } = site; + const edgeFunctionsConfig = command.netlify.config.edge_functions; + // build flag wasn't used and edge functions exist + if (!options.build && edgeFunctionsConfig && edgeFunctionsConfig.length !== 0) { + await bundleEdgeFunctions(options, command); + } + log(''); + // Note: this is leakily mimicking the @netlify/build heading style + log(chalk.cyanBright.bold(`Deploying to Netlify\n${'─'.repeat(64)}`)); + log(''); + log(prettyjson.render({ + 'Deploy path': deployFolder, + 'Functions path': functionsFolder, + 'Configuration path': configPath, + })); + log(); + const { functionsFolderStat } = await validateFolders({ + deployFolder, + functionsFolder, + }); + const siteEnv = await getEnvelopeEnv({ + api, + context: options.context, + env: command.netlify.cachedConfig.env, + raw: true, + scope: 'functions', + siteInfo: siteData, + }); + const functionsConfig = normalizeFunctionsConfig({ + functionsConfig: config.functions, + projectRoot: site.root, + siteEnv, + }); + const results = await runDeploy({ + // @ts-expect-error FIXME + alias, + api, + command, + config, + deployFolder, + deployTimeout: options.timeout ? options.timeout * SEC_TO_MILLISEC : DEFAULT_DEPLOY_TIMEOUT, + deployToProduction, + functionsConfig, + // pass undefined functionsFolder if doesn't exist + functionsFolder: functionsFolderStat && functionsFolder, + options, + packagePath: command.workspacePackage, + silent: options.json || options.silent, + site, + siteData, + siteId, + skipFunctionsCache: options.skipFunctionsCache, + title: options.message, + }); + return results; +}; +export const deploy = async (options, command) => { + const { workingDir } = command; + const { api, site, siteInfo } = command.netlify; + const alias = options.alias || options.branch; + command.setAnalyticsPayload({ open: options.open, prod: options.prod, json: options.json, alias: Boolean(alias) }); + await command.authenticate(options.auth); + let initialSiteData; + let newSiteData; + const hasSiteData = (site.id || options.site) && !isEmpty(siteInfo); + if (hasSiteData) { + initialSiteData = siteInfo; + } + else { + log("This folder isn't linked to a project yet"); + const NEW_SITE = '+ Create & configure a new project'; + const EXISTING_SITE = 'Link this directory to an existing project'; + const initializeOpts = [EXISTING_SITE, NEW_SITE]; + const { initChoice } = await inquirer.prompt([ + { + type: 'list', + name: 'initChoice', + message: 'What would you like to do?', + choices: initializeOpts, + }, + ]); + // create site or search for one + switch (initChoice) { + case NEW_SITE: + newSiteData = await sitesCreate({}, command); + site.id = newSiteData.id; + break; + case EXISTING_SITE: + newSiteData = await link({}, command); + site.id = newSiteData.id; + break; + } + } + // This is the best I could come up with to make TS happy with the complexities above. + const siteData = initialSiteData ?? newSiteData; + const siteId = siteData.id; + if (options.trigger) { + return triggerDeploy({ api, options, siteData, siteId }); + } + const deployToProduction = options.prod || (options.prodIfUnlocked && !(siteData.published_deploy?.locked ?? false)); + let results = {}; + if (options.build) { + const settings = await detectFrameworkSettings(command, 'build'); + await handleBuild({ + packagePath: command.workspacePackage, + cachedConfig: command.netlify.cachedConfig, + defaultConfig: getDefaultConfig(settings), + currentDir: command.workingDir, + options, + deployHandler: async ({ netlifyConfig }) => { + results = await prepAndRunDeploy({ + command, + options, + workingDir, + api, + site, + config: netlifyConfig, + siteData, + siteId, + deployToProduction, + }); + return { newEnvChanges: { DEPLOY_ID: results.deployId, DEPLOY_URL: results.deployUrl } }; + }, + }); + } + else { + results = await prepAndRunDeploy({ + command, + options, + workingDir, + api, + site, + config: command.netlify.config, + siteData, + siteId, + deployToProduction, + }); + } + printResults({ + runBuildCommand: options.build, + json: options.json, + results, + deployToProduction, + }); + if (options.open) { + const urlToOpen = deployToProduction ? results.siteUrl : results.deployUrl; + await openBrowser({ url: urlToOpen }); + exit(); + } +}; +//# sourceMappingURL=deploy.js.map \ No newline at end of file diff --git a/dist/commands/deploy/deploy.js.map b/dist/commands/deploy/deploy.js.map new file mode 100644 index 00000000000..ee839d9541a --- /dev/null +++ b/dist/commands/deploy/deploy.js.map @@ -0,0 +1 @@ +{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../../src/commands/deploy/deploy.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/deploy/index.d.ts b/dist/commands/deploy/index.d.ts new file mode 100644 index 00000000000..7d304fa32ad --- /dev/null +++ b/dist/commands/deploy/index.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const createDeployCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/deploy/index.d.ts.map b/dist/commands/deploy/index.d.ts.map new file mode 100644 index 00000000000..0ae4ed87af6 --- /dev/null +++ b/dist/commands/deploy/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/deploy/index.ts"],"names":[],"mappings":"AAKA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAI5C,eAAO,MAAM,mBAAmB,GAAI,SAAS,WAAW,gBA2JlD,CAAA"} \ No newline at end of file diff --git a/dist/commands/deploy/index.js b/dist/commands/deploy/index.js new file mode 100644 index 00000000000..a1c308da270 --- /dev/null +++ b/dist/commands/deploy/index.js @@ -0,0 +1,132 @@ +import { env } from 'process'; +import { Option } from 'commander'; +import terminalLink from 'terminal-link'; +import { chalk, logAndThrowError, warn } from '../../utils/command-helpers.js'; +export const createDeployCommand = (program) => program + .command('deploy') + .description(`Create a new deploy from the contents of a folder +Deploys from the build settings found in the netlify.toml file, or settings from the API. + +The following environment variables can be used to override configuration file lookups and prompts: + +- \`NETLIFY_AUTH_TOKEN\` - an access token to use when authenticating commands. Keep this value private. +- \`NETLIFY_SITE_ID\` - override any linked project in the current working directory. + +Lambda functions in the function folder can be in the following configurations for deployment: + + +Built Go binaries: +------------------ + +\`\`\` +functions/ +└── nameOfGoFunction +\`\`\` + +Build binaries of your Go language functions into the functions folder as part of your build process. + + +Single file Node.js functions: +----------------------------- + +Build dependency bundled Node.js lambda functions with tools like webpack or browserify into the function folder as part of your build process. + +\`\`\` +functions/ +└── nameOfBundledNodeJSFunction.js +\`\`\` + +Unbundled Node.js functions that have dependencies outside or inside of the functions folder: +--------------------------------------------------------------------------------------------- + +You can ship unbundled Node.js functions with the CLI, utilizing top level project dependencies, or a nested package.json. +If you use nested dependencies, be sure to populate the nested node_modules as part of your build process before deploying using npm or yarn. + +\`\`\` +project/ +ā”œā”€ā”€ functions +│ ā”œā”€ā”€ functionName/ +│ │ ā”œā”€ā”€ functionName.js (Note the folder and the function name need to match) +│ │ ā”œā”€ā”€ package.json +│ │ └── node_modules/ +│ └── unbundledFunction.js +ā”œā”€ā”€ package.json +ā”œā”€ā”€ netlify.toml +└── node_modules/ +\`\`\` + +Any mix of these configurations works as well. + + +Node.js function entry points +----------------------------- + +Function entry points are determined by the file name and name of the folder they are in: + +\`\`\` +functions/ +ā”œā”€ā”€ aFolderlessFunctionEntrypoint.js +└── functionName/ + ā”œā”€ā”€ notTheEntryPoint.js + └── functionName.js +\`\`\` + +Support for package.json's main field, and intrinsic index.js entrypoints are coming soon.`) + .option('-d, --dir ', 'Specify a folder to deploy') + .option('-f, --functions ', 'Specify a functions folder to deploy') + .addOption(new Option('-p, --prod', 'Deploy to production') + .default(false) + .conflicts(['alias', 'branch', 'prod-if-unlocked'])) + .addOption(new Option('--prod-if-unlocked', 'Deploy to production if unlocked, create a draft otherwise') + .default(false) + .conflicts(['alias', 'branch', 'prod'])) + .option('--alias ', 'Specifies the alias for deployment, the string at the beginning of the deploy subdomain. Useful for creating predictable deployment URLs. Avoid setting an alias string to the same value as a deployed branch. `alias` doesn’t create a branch deploy and can’t be used in conjunction with the branch subdomain feature. Maximum 37 characters.') + .addOption(new Option('-b, --branch ', 'Do not use - renamed to --alias.').hideHelp(true)) + .option('-O, --open', 'Open project after deploy', false) + .option('-m, --message ', 'A short message to include in the deploy log') + .option('-s, --site ', 'A project name or ID to deploy to', env.NETLIFY_SITE_ID) + .option('--json', 'Output deployment data as JSON') + .option('--timeout ', 'Timeout to wait for deployment to finish', (value) => Number.parseInt(value)) + .addOption(new Option('--trigger', 'Trigger a new build of your project on Netlify without uploading local files').conflicts('build')) + .addOption(new Option('--build', 'Do not use - this is now the default. Will be removed in future versions.') + .default(true) + .hideHelp(true)) + /** + * Note that this has special meaning to commander. It negates the above `build` option. + * @see https://github.com/tj/commander.js/tree/83c3f4e391754d2f80b179acc4bccc2d4d0c863d?tab=readme-ov-file#other-option-types-negatable-boolean-and-booleanvalue + */ + .option('--no-build', 'Do not run build command before deploying. Only use this if you have no need for a build or your project has already been built.') + .option('--context ', 'Specify a deploy context for environment variables read during the build (ā€productionā€, ā€deploy-previewā€, ā€branch-deployā€, ā€devā€) or `branch:your-branch` where `your-branch` is the name of a branch (default: dev)') + .option('--skip-functions-cache', 'Ignore any functions created as part of a previous `build` or `deploy` commands, forcing them to be bundled again as part of the deployment', false) + .addExamples([ + 'netlify deploy', + 'netlify deploy --site my-first-project', + 'netlify deploy --no-build # Deploy without running a build first', + 'netlify deploy --prod', + 'netlify deploy --prod --open', + 'netlify deploy --prod-if-unlocked', + 'netlify deploy --message "A message with an $ENV_VAR"', + 'netlify deploy --auth $NETLIFY_AUTH_TOKEN', + 'netlify deploy --trigger', + 'netlify deploy --context deploy-preview', +]) + .addHelpText('after', () => { + const docsUrl = 'https://docs.netlify.com/site-deploys/overview/'; + return ` +For more information about Netlify deploys, see ${terminalLink(docsUrl, docsUrl, { fallback: false })} +`; +}) + .action(async (options, command) => { + if (options.build && command.getOptionValueSource('build') === 'cli') { + warn(`${chalk.cyanBright('--build')} is now the default and can safely be omitted.`); + } + if (options.branch) { + warn('--branch flag has been renamed to --alias'); + } + if (options.context && !options.build) { + return logAndThrowError('--context flag is only available when using the --build flag'); + } + const { deploy } = await import('./deploy.js'); + await deploy(options, command); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/deploy/index.js.map b/dist/commands/deploy/index.js.map new file mode 100644 index 00000000000..5989c5cdcb8 --- /dev/null +++ b/dist/commands/deploy/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/deploy/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/deploy/option_values.d.ts b/dist/commands/deploy/option_values.d.ts new file mode 100644 index 00000000000..77fbdb4ae86 --- /dev/null +++ b/dist/commands/deploy/option_values.d.ts @@ -0,0 +1,19 @@ +import type { BaseOptionValues } from '../base-command.js'; +export type DeployOptionValues = BaseOptionValues & { + alias?: string; + build: boolean; + branch?: string; + context?: string; + dir?: string; + functions?: string; + json: boolean; + message?: string; + open: boolean; + prod: boolean; + prodIfUnlocked: boolean; + site?: string; + skipFunctionsCache: boolean; + timeout?: number; + trigger?: boolean; +}; +//# sourceMappingURL=option_values.d.ts.map \ No newline at end of file diff --git a/dist/commands/deploy/option_values.d.ts.map b/dist/commands/deploy/option_values.d.ts.map new file mode 100644 index 00000000000..da548871f01 --- /dev/null +++ b/dist/commands/deploy/option_values.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"option_values.d.ts","sourceRoot":"","sources":["../../../src/commands/deploy/option_values.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAE1D,MAAM,MAAM,kBAAkB,GAAG,gBAAgB,GAAG;IAClD,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,OAAO,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,IAAI,EAAE,OAAO,CAAA;IACb,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,OAAO,CAAA;IACb,IAAI,EAAE,OAAO,CAAA;IACb,cAAc,EAAE,OAAO,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,kBAAkB,EAAE,OAAO,CAAA;IAC3B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,OAAO,CAAC,EAAE,OAAO,CAAA;CAClB,CAAA"} \ No newline at end of file diff --git a/dist/commands/deploy/option_values.js b/dist/commands/deploy/option_values.js new file mode 100644 index 00000000000..91337fa021d --- /dev/null +++ b/dist/commands/deploy/option_values.js @@ -0,0 +1,3 @@ +// This type lives in a separate file to prevent import cycles. +export {}; +//# sourceMappingURL=option_values.js.map \ No newline at end of file diff --git a/dist/commands/deploy/option_values.js.map b/dist/commands/deploy/option_values.js.map new file mode 100644 index 00000000000..e061cd83e4d --- /dev/null +++ b/dist/commands/deploy/option_values.js.map @@ -0,0 +1 @@ +{"version":3,"file":"option_values.js","sourceRoot":"","sources":["../../../src/commands/deploy/option_values.ts"],"names":[],"mappings":"AAAA,+DAA+D"} \ No newline at end of file diff --git a/dist/commands/dev-exec/dev-exec.d.ts b/dist/commands/dev-exec/dev-exec.d.ts new file mode 100644 index 00000000000..2c39d6620fd --- /dev/null +++ b/dist/commands/dev-exec/dev-exec.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const devExec: (cmd: string, options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=dev-exec.d.ts.map \ No newline at end of file diff --git a/dist/commands/dev-exec/dev-exec.d.ts.map b/dist/commands/dev-exec/dev-exec.d.ts.map new file mode 100644 index 00000000000..aec4e306324 --- /dev/null +++ b/dist/commands/dev-exec/dev-exec.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dev-exec.d.ts","sourceRoot":"","sources":["../../../src/commands/dev-exec/dev-exec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAKxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,OAAO,GAAU,KAAK,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,kBAYrF,CAAA"} \ No newline at end of file diff --git a/dist/commands/dev-exec/dev-exec.js b/dist/commands/dev-exec/dev-exec.js new file mode 100644 index 00000000000..082a0f1e7e8 --- /dev/null +++ b/dist/commands/dev-exec/dev-exec.js @@ -0,0 +1,14 @@ +import execa from 'execa'; +import { getDotEnvVariables, injectEnvVariables } from '../../utils/dev.js'; +import { getEnvelopeEnv } from '../../utils/env/index.js'; +export const devExec = async (cmd, options, command) => { + const { api, cachedConfig, config, site, siteInfo } = command.netlify; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + const withEnvelopeEnvVars = await getEnvelopeEnv({ api, context: options.context, env: cachedConfig.env, siteInfo }); + const withDotEnvVars = await getDotEnvVariables({ devConfig: { ...config.dev }, env: withEnvelopeEnvVars, site }); + injectEnvVariables(withDotEnvVars); + await execa(cmd, command.args.slice(1), { + stdio: 'inherit', + }); +}; +//# sourceMappingURL=dev-exec.js.map \ No newline at end of file diff --git a/dist/commands/dev-exec/dev-exec.js.map b/dist/commands/dev-exec/dev-exec.js.map new file mode 100644 index 00000000000..aa786364ff1 --- /dev/null +++ b/dist/commands/dev-exec/dev-exec.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dev-exec.js","sourceRoot":"","sources":["../../../src/commands/dev-exec/dev-exec.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAGzD,MAAM,CAAC,MAAM,OAAO,GAAG,KAAK,EAAE,GAAW,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IACxF,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IAErE,mEAAmE;IACnE,MAAM,mBAAmB,GAAG,MAAM,cAAc,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,YAAY,CAAC,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAA;IACpH,MAAM,cAAc,GAAG,MAAM,kBAAkB,CAAC,EAAE,SAAS,EAAE,EAAE,GAAG,MAAM,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,mBAAmB,EAAE,IAAI,EAAE,CAAC,CAAA;IAEjH,kBAAkB,CAAC,cAAc,CAAC,CAAA;IAElC,MAAM,KAAK,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;QACtC,KAAK,EAAE,SAAS;KACjB,CAAC,CAAA;AACJ,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/dev-exec/index.d.ts b/dist/commands/dev-exec/index.d.ts new file mode 100644 index 00000000000..2dde065951b --- /dev/null +++ b/dist/commands/dev-exec/index.d.ts @@ -0,0 +1,3 @@ +import type BaseCommand from '../base-command.js'; +export declare const createDevExecCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/dev-exec/index.d.ts.map b/dist/commands/dev-exec/index.d.ts.map new file mode 100644 index 00000000000..8f076879470 --- /dev/null +++ b/dist/commands/dev-exec/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/dev-exec/index.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAGjD,eAAO,MAAM,oBAAoB,GAAI,SAAS,WAAW,gBAsBnD,CAAA"} \ No newline at end of file diff --git a/dist/commands/dev-exec/index.js b/dist/commands/dev-exec/index.js new file mode 100644 index 00000000000..e50bf9f2462 --- /dev/null +++ b/dist/commands/dev-exec/index.js @@ -0,0 +1,17 @@ +import { normalizeContext } from '../../utils/env/index.js'; +export const createDevExecCommand = (program) => program + .command('dev:exec') + .argument('<...cmd>', `the command that should be executed`) + .option('--context ', 'Specify a deploy context for environment variables (ā€productionā€, ā€deploy-previewā€, ā€branch-deployā€, ā€devā€) or `branch:your-branch` where `your-branch` is the name of a branch (default: dev)', normalizeContext, 'dev') + .description('Runs a command within the netlify dev environment. For example, with environment variables from any installed add-ons') + .allowExcessArguments(true) + .addExamples([ + 'netlify dev:exec npm run bootstrap', + 'netlify dev:exec --context deploy-preview npm run bootstrap # Run with env var values from deploy-preview context', + 'netlify dev:exec --context branch:feat/make-it-pop npm run bootstrap # Run with env var values from the feat/make-it-pop branch context or branch-deploy context', +]) + .action(async (cmd, options, command) => { + const { devExec } = await import('./dev-exec.js'); + await devExec(cmd, options, command); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/dev-exec/index.js.map b/dist/commands/dev-exec/index.js.map new file mode 100644 index 00000000000..3d7972f8082 --- /dev/null +++ b/dist/commands/dev-exec/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/dev-exec/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAE3D,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,OAAoB,EAAE,EAAE,CAC3D,OAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,QAAQ,CAAC,UAAU,EAAE,qCAAqC,CAAC;KAC3D,MAAM,CACL,qBAAqB,EACrB,gMAAgM,EAChM,gBAAgB,EAChB,KAAK,CACN;KACA,WAAW,CACV,uHAAuH,CACxH;KACA,oBAAoB,CAAC,IAAI,CAAC;KAC1B,WAAW,CAAC;IACX,oCAAoC;IACpC,mHAAmH;IACnH,kKAAkK;CACnK,CAAC;KACD,MAAM,CAAC,KAAK,EAAE,GAAW,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IACzE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAA;IACjD,MAAM,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;AACtC,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/dev/dev.d.ts b/dist/commands/dev/dev.d.ts new file mode 100644 index 00000000000..0803f02e3fc --- /dev/null +++ b/dist/commands/dev/dev.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import type BaseCommand from '../base-command.js'; +export declare const dev: (options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=dev.d.ts.map \ No newline at end of file diff --git a/dist/commands/dev/dev.d.ts.map b/dist/commands/dev/dev.d.ts.map new file mode 100644 index 00000000000..11aa9be7bd3 --- /dev/null +++ b/dist/commands/dev/dev.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../../src/commands/dev/dev.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AA0BxC,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AA+CjD,eAAO,MAAM,GAAG,GAAU,SAAS,YAAY,EAAE,SAAS,WAAW,kBAoMpE,CAAA"} \ No newline at end of file diff --git a/dist/commands/dev/dev.js b/dist/commands/dev/dev.js new file mode 100644 index 00000000000..534f880e5c6 --- /dev/null +++ b/dist/commands/dev/dev.js @@ -0,0 +1,200 @@ +import process from 'process'; +import { applyMutations } from '@netlify/config'; +import { BLOBS_CONTEXT_VARIABLE, encodeBlobsContext, getBlobsContextWithEdgeAccess } from '../../lib/blobs/blobs.js'; +import { promptEditorHelper } from '../../lib/edge-functions/editor-helper.js'; +import { startFunctionsServer } from '../../lib/functions/server.js'; +import { printBanner } from '../../utils/dev-server-banner.js'; +import { NETLIFYDEVERR, NETLIFYDEVLOG, NETLIFYDEVWARN, chalk, log, normalizeConfig, netlifyCommand, } from '../../utils/command-helpers.js'; +import detectServerSettings, { getConfigWithPlugins } from '../../utils/detect-server-settings.js'; +import { UNLINKED_SITE_MOCK_ID, getDotEnvVariables, getSiteInformation, injectEnvVariables } from '../../utils/dev.js'; +import { getEnvelopeEnv } from '../../utils/env/index.js'; +import { ensureNetlifyIgnore } from '../../utils/gitignore.js'; +import { getLiveTunnelSlug, startLiveTunnel } from '../../utils/live-tunnel.js'; +import openBrowser from '../../utils/open-browser.js'; +import { generateInspectSettings, startProxyServer } from '../../utils/proxy-server.js'; +import { getProxyUrl } from '../../utils/proxy.js'; +import { runDevTimeline } from '../../utils/run-build.js'; +import { getBaseOptionValues } from '../base-command.js'; +import { doesProjectRequireLinkedSite } from '../../lib/extensions.js'; +const handleLiveTunnel = async ({ api, options, settings, site, state, }) => { + const { live } = options; + if (live) { + const customSlug = typeof live === 'string' && live.length !== 0 ? live : undefined; + const slug = getLiveTunnelSlug(state, customSlug); + let message = `${NETLIFYDEVWARN} Creating live URL with ID ${chalk.yellow(slug)}`; + if (!customSlug) { + message += ` (to generate a custom URL, use ${chalk.magenta('--live=')})`; + } + log(message); + const sessionUrl = await startLiveTunnel({ + siteId: site.id, + netlifyApiToken: api.accessToken, + localPort: settings.port, + slug, + }); + process.env.BASE_URL = sessionUrl; + return sessionUrl; + } +}; +export const dev = async (options, command) => { + const { api, cachedConfig, config, repositoryRoot, site, siteInfo, state } = command.netlify; + config.dev = config.dev != null ? { ...config.dev } : undefined; + config.build = { ...config.build }; + const devConfig = { + framework: '#auto', + autoLaunch: Boolean(options.open), + ...(cachedConfig.siteInfo.dev_server_settings && { + command: cachedConfig.siteInfo.dev_server_settings.cmd, + targetPort: cachedConfig.siteInfo.dev_server_settings.target_port, + }), + ...(config.functionsDirectory && { functions: config.functionsDirectory }), + ...('publish' in config.build && config.build.publish && { publish: config.build.publish }), + ...(config.build.base && { base: config.build.base }), + ...config.dev, + ...options, + }; + let { env } = cachedConfig; + env.NETLIFY_DEV = { sources: ['internal'], value: 'true' }; + const [needsLinkedSite, packagesRequiringLinkedSite] = await doesProjectRequireLinkedSite({ + options, + project: command.project, + site: command.netlify.site, + siteInfo: command.netlify.siteInfo, + }); + if (needsLinkedSite) { + log(`Dependenc${packagesRequiringLinkedSite.length > 1 ? 'ies' : 'y'} ${packagesRequiringLinkedSite.join(', ')} require${packagesRequiringLinkedSite.length > 1 ? '' : 's'} a linked project, but you don't have one linked yet. Let's do that first.`); + const { init } = await import('../init/init.js'); + const { LINKED_NEW_SITE_EXIT_CODE, LINKED_EXISTING_SITE_EXIT_CODE } = await import('../init/constants.js'); + await init(getBaseOptionValues(options), command, { + customizeExitMessage: (code, defaultMessage) => { + switch (code) { + case LINKED_NEW_SITE_EXIT_CODE: + // fallthrough + case LINKED_EXISTING_SITE_EXIT_CODE: + return `${defaultMessage !== '' ? `${defaultMessage}\n` : ''}You can run ${chalk.cyanBright.bold(`${netlifyCommand()} dev`)} again to start the local development server.`; + } + }, + exitAfterConfiguringRepo: true, + }); + } + const blobsContext = await getBlobsContextWithEdgeAccess({ + debug: options.debug, + projectRoot: command.workingDir, + siteID: site.id ?? UNLINKED_SITE_MOCK_ID, + }); + env[BLOBS_CONTEXT_VARIABLE] = { sources: ['internal'], value: encodeBlobsContext(blobsContext) }; + if (!options.offline && !options.offlineEnv) { + env = await getEnvelopeEnv({ api, context: options.context, env, siteInfo }); + log(`${NETLIFYDEVLOG} Injecting environment variable values for ${chalk.yellow('all scopes')}`); + } + env = await getDotEnvVariables({ devConfig, env, site }); + injectEnvVariables(env); + await promptEditorHelper({ chalk, config, log, NETLIFYDEVLOG, repositoryRoot, state }); + const { accountId, addonsUrls, capabilities, siteUrl, timeouts } = await getSiteInformation({ + // inherited from base command --offline + offline: options.offline, + api, + site, + siteInfo, + }); + let settings; + try { + settings = await detectServerSettings(devConfig, options, command); + const { NETLIFY_INCLUDE_DEV_SERVER_PLUGIN } = process.env; + if (NETLIFY_INCLUDE_DEV_SERVER_PLUGIN) { + const plugins = NETLIFY_INCLUDE_DEV_SERVER_PLUGIN.split(','); + if (options.debug) { + log(`${NETLIFYDEVLOG} Including dev server plugins: ${NETLIFY_INCLUDE_DEV_SERVER_PLUGIN}`); + } + settings.plugins = [...(settings.plugins ?? []), ...plugins]; + } + // TODO(serhalp): Doing this as a side effect inside `BaseCommand` like this is WILD. + // Refactor this to be more explicit and less brittle. + cachedConfig.config = getConfigWithPlugins(cachedConfig.config, settings); + } + catch (error) { + if (error instanceof Error) { + log(NETLIFYDEVERR, error.message); + } + process.exit(1); + } + command.setAnalyticsPayload({ live: options.live }); + const liveTunnelUrl = await handleLiveTunnel({ options, site, api, settings, state }); + const url = liveTunnelUrl || getProxyUrl(settings); + process.env.URL = url; + process.env.DEPLOY_URL = url; + log(`${NETLIFYDEVLOG} Setting up local dev server`); + const { configMutations, configPath: configPathOverride } = await runDevTimeline({ + command, + options, + settings, + env: { + URL: url, + DEPLOY_URL: url, + }, + }); + // FIXME(serhalp): `applyMutations` is `(any, any) => any)`. Add types in `@netlify/config`. + const mutatedConfig = applyMutations(config, configMutations); + const functionsRegistry = await startFunctionsServer({ + blobsContext, + command, + config: mutatedConfig, + debug: options.debug, + settings, + site, + siteInfo, + siteUrl, + capabilities, + timeouts, + geolocationMode: options.geo, + geoCountry: options.country, + offline: options.offline, + state, + accountId, + }); + // Try to add `.netlify` to `.gitignore`. + try { + await ensureNetlifyIgnore(repositoryRoot); + } + catch { + // no-op + } + // TODO: We should consolidate this with the existing config watcher. + const getUpdatedConfig = async () => { + const { config: newConfig } = await command.getConfig({ + cwd: command.workingDir, + offline: true, + }); + return normalizeConfig(newConfig); + }; + const inspectSettings = generateInspectSettings(options.edgeInspect, options.edgeInspectBrk); + await startProxyServer({ + addonsUrls, + api, + blobsContext, + command, + config: mutatedConfig, + configPath: configPathOverride, + debug: options.debug, + disableEdgeFunctions: options.internalDisableEdgeFunctions, + projectDir: command.workingDir, + env, + getUpdatedConfig, + inspectSettings, + offline: options.offline, + settings, + site, + siteInfo, + state, + geolocationMode: options.geo, + geoCountry: options.country, + accountId, + functionsRegistry, + repositoryRoot, + }); + if (devConfig.autoLaunch !== false) { + await openBrowser({ url, silentBrowserNoneError: true }); + } + printBanner({ url }); +}; +//# sourceMappingURL=dev.js.map \ No newline at end of file diff --git a/dist/commands/dev/dev.js.map b/dist/commands/dev/dev.js.map new file mode 100644 index 00000000000..658d5380090 --- /dev/null +++ b/dist/commands/dev/dev.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../../src/commands/dev/dev.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/dev/index.d.ts b/dist/commands/dev/index.d.ts new file mode 100644 index 00000000000..2a1d6cc8ce6 --- /dev/null +++ b/dist/commands/dev/index.d.ts @@ -0,0 +1,3 @@ +import type BaseCommand from '../base-command.js'; +export declare const createDevCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/dev/index.d.ts.map b/dist/commands/dev/index.d.ts.map new file mode 100644 index 00000000000..9b6aac2073a --- /dev/null +++ b/dist/commands/dev/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/dev/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAkBjD,eAAO,MAAM,gBAAgB,GAAI,SAAS,WAAW,gBA8FpD,CAAA"} \ No newline at end of file diff --git a/dist/commands/dev/index.js b/dist/commands/dev/index.js new file mode 100644 index 00000000000..599a5f5ee71 --- /dev/null +++ b/dist/commands/dev/index.js @@ -0,0 +1,75 @@ +import { Option } from 'commander'; +import terminalLink from 'terminal-link'; +import { BANG, chalk } from '../../utils/command-helpers.js'; +import { normalizeContext } from '../../utils/env/index.js'; +import { getGeoCountryArgParser } from '../../utils/validation.js'; +const validateShortFlagArgs = (args) => { + if (args.startsWith('=')) { + throw new Error(`Short flag options like -e or -E don't support the '=' sign + ${chalk.red(BANG)} Supported formats: + netlify dev -e + netlify dev -e 127.0.0.1:9229 + netlify dev -e127.0.0.1:9229 + netlify dev -E + netlify dev -E 127.0.0.1:9229 + netlify dev -E127.0.0.1:9229`); + } + return args; +}; +export const createDevCommand = (program) => { + return program + .command('dev') + .alias('develop') + .description(`Local dev server\nThe dev command will run a local dev server with Netlify's proxy and redirect rules`) + .option('-c ,--command ', 'command to run') + .option('--context ', 'Specify a deploy context for environment variables (ā€productionā€, ā€deploy-previewā€, ā€branch-deployā€, ā€devā€) or `branch:your-branch` where `your-branch` is the name of a branch (default: dev)', normalizeContext) + .option('-p ,--port ', 'port of netlify dev', (value) => Number.parseInt(value)) + .addOption(new Option('--skip-wait-port', 'disables waiting for target port to become available').hideHelp(true)) + .addOption(new Option('--no-open', 'disables the automatic opening of a browser window')) + .option('--target-port ', 'port of target app server', (value) => Number.parseInt(value)) + .option('--framework ', 'framework to use. Defaults to #auto which automatically detects a framework') + .option('-d ,--dir ', 'dir with static files') + .option('-f ,--functions ', 'specify a functions folder to serve') + .option('-o, --offline', 'Disables any features that require network access') + .addOption(new Option('--offline-env', 'disables fetching environment variables from the Netlify API').hideHelp(true)) + .addOption(new Option('--internal-disable-edge-functions', "disables edge functions. use this if your environment doesn't support Deno. This option is internal and should not be used by end users.").hideHelp(true)) + .option('-l, --live [subdomain]', 'start a public live session; optionally, supply a subdomain to generate a custom URL', false) + .option('--functions-port ', 'port of functions server', (value) => Number.parseInt(value)) + .addOption(new Option('--geo ', 'force geolocation data to be updated, use cached data from the last 24h if found, or use a mock location') + .choices(['cache', 'mock', 'update']) + .default('cache')) + .addOption(new Option('--country ', 'Two-letter country code (https://ntl.fyi/country-codes) to use as mock geolocation (enables --geo=mock automatically)').argParser(getGeoCountryArgParser('netlify dev --geo=mock --country=FR'))) + .addOption(new Option('--staticServerPort ', 'port of the static app server used when no framework is detected') + .argParser((value) => Number.parseInt(value)) + .hideHelp()) + .addOption(new Option('-e, --edge-inspect [address]', 'enable the V8 Inspector Protocol for Edge Functions, with an optional address in the host:port format') + .conflicts('edgeInspectBrk') + .argParser(validateShortFlagArgs)) + .addOption(new Option('-E, --edge-inspect-brk [address]', 'enable the V8 Inspector Protocol for Edge Functions and pause execution on the first line of code, with an optional address in the host:port format') + .conflicts('edgeInspect') + .argParser(validateShortFlagArgs)) + .addExamples([ + 'netlify dev', + 'netlify dev -d public', + 'netlify dev -c "hugo server -w" --target-port 1313', + 'netlify dev --context production # Use env var values from production context', + 'netlify dev --context deploy-preview # Use env var values from deploy-preview context', + 'netlify dev --context branch:feat/make-it-pop # Use env var values from the feat/make-it-pop branch context or branch-deploy context', + 'netlify dev --edge-inspect', + 'netlify dev --edge-inspect=127.0.0.1:9229', + 'netlify dev --edge-inspect-brk', + 'netlify dev --edge-inspect-brk=127.0.0.1:9229', + 'BROWSER=none netlify dev # disable browser auto opening', + ]) + .addHelpText('after', () => { + const docsUrl = 'https://docs.netlify.com/cli/local-development/'; + return ` +For more information about Netlify local development, see ${terminalLink(docsUrl, docsUrl, { fallback: false })} +`; + }) + .action(async (options, command) => { + const { dev } = await import('./dev.js'); + await dev(options, command); + }); +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/dev/index.js.map b/dist/commands/dev/index.js.map new file mode 100644 index 00000000000..3a7f0f3ba2b --- /dev/null +++ b/dist/commands/dev/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/dev/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/env/env-clone.d.ts b/dist/commands/env/env-clone.d.ts new file mode 100644 index 00000000000..d06106ae0c8 --- /dev/null +++ b/dist/commands/env/env-clone.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const envClone: (options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=env-clone.d.ts.map \ No newline at end of file diff --git a/dist/commands/env/env-clone.d.ts.map b/dist/commands/env/env-clone.d.ts.map new file mode 100644 index 00000000000..bcf97762bbc --- /dev/null +++ b/dist/commands/env/env-clone.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"env-clone.d.ts","sourceRoot":"","sources":["../../../src/commands/env/env-clone.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAIxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAqD5C,eAAO,MAAM,QAAQ,GAAU,SAAS,YAAY,EAAE,SAAS,WAAW,qBAgDzE,CAAA"} \ No newline at end of file diff --git a/dist/commands/env/env-clone.js b/dist/commands/env/env-clone.js new file mode 100644 index 00000000000..85788695b58 --- /dev/null +++ b/dist/commands/env/env-clone.js @@ -0,0 +1,81 @@ +import { chalk, log, logAndThrowError } from '../../utils/command-helpers.js'; +import { promptEnvCloneOverwrite } from '../../utils/prompts/env-clone-prompt.js'; +// @ts-expect-error TS(7006) FIXME: Parameter 'api' implicitly has an 'any' type. +const safeGetSite = async (api, siteId) => { + try { + const data = await api.getSite({ siteId }); + return { data }; + } + catch (error) { + return { error }; + } +}; +/** + * Copies the env from a project configured with Envelope to a different project configured with Envelope + * @returns {Promise} + */ +// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message +const cloneEnvVars = async ({ api, force, siteFrom, siteTo }) => { + const [envelopeFrom, envelopeTo] = await Promise.all([ + api.getEnvVars({ accountId: siteFrom.account_slug, siteId: siteFrom.id }), + api.getEnvVars({ accountId: siteTo.account_slug, siteId: siteTo.id }), + ]); + // @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message + const keysFrom = envelopeFrom.map(({ key }) => key); + if (keysFrom.length === 0) { + log(`${chalk.green(siteFrom.name)} has no environment variables, nothing to clone`); + return false; + } + const accountId = siteTo.account_slug; + const siteId = siteTo.id; + // @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message + const envVarsToDelete = envelopeTo.filter(({ key }) => keysFrom.includes(key)); + if (envVarsToDelete.length !== 0 && Boolean(force) === false) { + await promptEnvCloneOverwrite(siteTo.id, envVarsToDelete); + } + // delete marked env vars in parallel + // @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message + await Promise.all(envVarsToDelete.map(({ key }) => api.deleteEnvVar({ accountId, siteId, key }))); + // hit create endpoint + try { + await api.createEnvVars({ accountId, siteId, body: envelopeFrom }); + } + catch (error) { + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + throw error.json ? error.json.msg : error; + } + return true; +}; +export const envClone = async (options, command) => { + const { api, site } = command.netlify; + const { force } = options; + if (!site.id && !options.from) { + log('Please include the source project ID as the `--from` option, or run `netlify link` to link this folder to a Netlify project'); + return false; + } + const sourceId = options.from || site.id; + if (!sourceId) { + log('Please include the source project ID as the `--from` option, or run `netlify link` to link this folder to a Netlify project'); + } + const siteId = { + from: sourceId, + to: options.to, + }; + const [{ data: siteFrom, error: errorFrom }, { data: siteTo, error: errorTo }] = await Promise.all([ + safeGetSite(api, siteId.from), + safeGetSite(api, siteId.to), + ]); + if (errorFrom) { + return logAndThrowError(`Can't find project with id ${chalk.bold(siteId.from)}. Please make sure the project exists.`); + } + if (errorTo) { + return logAndThrowError(`Can't find project with id ${chalk.bold(siteId.to)}. Please make sure the project exists.`); + } + const success = await cloneEnvVars({ api, siteFrom, siteTo, force }); + if (!success) { + return false; + } + log(`Successfully cloned environment variables from ${chalk.green(siteFrom.name)} to ${chalk.green(siteTo.name)}`); + return true; +}; +//# sourceMappingURL=env-clone.js.map \ No newline at end of file diff --git a/dist/commands/env/env-clone.js.map b/dist/commands/env/env-clone.js.map new file mode 100644 index 00000000000..4b20f353591 --- /dev/null +++ b/dist/commands/env/env-clone.js.map @@ -0,0 +1 @@ +{"version":3,"file":"env-clone.js","sourceRoot":"","sources":["../../../src/commands/env/env-clone.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/env/env-get.d.ts b/dist/commands/env/env-get.d.ts new file mode 100644 index 00000000000..5099816cfa2 --- /dev/null +++ b/dist/commands/env/env-get.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const envGet: (name: string, options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=env-get.d.ts.map \ No newline at end of file diff --git a/dist/commands/env/env-get.d.ts.map b/dist/commands/env/env-get.d.ts.map new file mode 100644 index 00000000000..96e3d155b7a --- /dev/null +++ b/dist/commands/env/env-get.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"env-get.d.ts","sourceRoot":"","sources":["../../../src/commands/env/env-get.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAIxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,MAAM,GAAU,MAAM,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,+BA+BrF,CAAA"} \ No newline at end of file diff --git a/dist/commands/env/env-get.js b/dist/commands/env/env-get.js new file mode 100644 index 00000000000..36c38e1e816 --- /dev/null +++ b/dist/commands/env/env-get.js @@ -0,0 +1,29 @@ +import { chalk, log, logJson } from '../../utils/command-helpers.js'; +import { SUPPORTED_CONTEXTS, getEnvelopeEnv } from '../../utils/env/index.js'; +export const envGet = async (name, options, command) => { + const { context, scope } = options; + const { api, cachedConfig, site } = command.netlify; + const siteId = site.id; + if (!siteId) { + log('No project id found, please run inside a project folder or `netlify link`'); + return false; + } + const { siteInfo } = cachedConfig; + const env = await getEnvelopeEnv({ api, context, env: cachedConfig.env, key: name, scope, siteInfo }); + // @ts-expect-error FIXME(ndhoule) + const { value } = env[name] || {}; + // Return json response for piping commands + if (options.json) { + logJson(value ? { [name]: value } : {}); + return false; + } + if (!value) { + const contextType = SUPPORTED_CONTEXTS.includes(context) ? 'context' : 'branch'; + const withContext = `in the ${chalk.magenta(context)} ${contextType}`; + const withScope = scope === 'any' ? '' : ` and the ${chalk.magenta(scope)} scope`; + log(`No value set ${withContext}${withScope} for environment variable ${chalk.yellow(name)}`); + return false; + } + log(value); +}; +//# sourceMappingURL=env-get.js.map \ No newline at end of file diff --git a/dist/commands/env/env-get.js.map b/dist/commands/env/env-get.js.map new file mode 100644 index 00000000000..e194b9d0325 --- /dev/null +++ b/dist/commands/env/env-get.js.map @@ -0,0 +1 @@ +{"version":3,"file":"env-get.js","sourceRoot":"","sources":["../../../src/commands/env/env-get.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AAG7E,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,EAAE,IAAY,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IACxF,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,OAAO,CAAA;IAClC,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IACnD,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAA;IAEtB,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,2EAA2E,CAAC,CAAA;QAChF,OAAO,KAAK,CAAA;IACd,CAAC;IAED,MAAM,EAAE,QAAQ,EAAE,GAAG,YAAY,CAAA;IACjC,MAAM,GAAG,GAAG,MAAM,cAAc,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,YAAY,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAA;IAErG,kCAAkC;IAClC,MAAM,EAAE,KAAK,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,EAAE,CAAA;IAEjC,2CAA2C;IAC3C,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAA;QACvC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,WAAW,GAAG,kBAAkB,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAA;QAC/E,MAAM,WAAW,GAAG,UAAU,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,WAAW,EAAE,CAAA;QACrE,MAAM,SAAS,GAAG,KAAK,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAA;QACjF,GAAG,CAAC,gBAAgB,WAAW,GAAG,SAAS,6BAA6B,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;QAC7F,OAAO,KAAK,CAAA;IACd,CAAC;IAED,GAAG,CAAC,KAAK,CAAC,CAAA;AACZ,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/env/env-import.d.ts b/dist/commands/env/env-import.d.ts new file mode 100644 index 00000000000..369be71851e --- /dev/null +++ b/dist/commands/env/env-import.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const envImport: (fileName: string, options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=env-import.d.ts.map \ No newline at end of file diff --git a/dist/commands/env/env-import.d.ts.map b/dist/commands/env/env-import.d.ts.map new file mode 100644 index 00000000000..fc3d5be140a --- /dev/null +++ b/dist/commands/env/env-import.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"env-import.d.ts","sourceRoot":"","sources":["../../../src/commands/env/env-import.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAKxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AA2C5C,eAAO,MAAM,SAAS,GAAU,UAAU,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,+BAyC5F,CAAA"} \ No newline at end of file diff --git a/dist/commands/env/env-import.js b/dist/commands/env/env-import.js new file mode 100644 index 00000000000..177cb92fb16 --- /dev/null +++ b/dist/commands/env/env-import.js @@ -0,0 +1,78 @@ +import { readFile } from 'fs/promises'; +import AsciiTable from 'ascii-table'; +import dotenv from 'dotenv'; +import { exit, log, logJson } from '../../utils/command-helpers.js'; +import { translateFromEnvelopeToMongo, translateFromMongoToEnvelope } from '../../utils/env/index.js'; +/** + * Saves the imported env in the Envelope service + * @returns {Promise} + */ +// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message +const importDotEnv = async ({ api, importedEnv, options, siteInfo }) => { + // fetch env vars + const accountId = siteInfo.account_slug; + const siteId = siteInfo.id; + const dotEnvKeys = Object.keys(importedEnv); + const envelopeVariables = await api.getEnvVars({ accountId, siteId }); + // @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message + const envelopeKeys = envelopeVariables.map(({ key }) => key); + // if user intends to replace all existing env vars + // either replace; delete all existing env vars on the site + // or, merge; delete only the existing env vars that would collide with new .env entries + // @ts-expect-error TS(7006) FIXME: Parameter 'key' implicitly has an 'any' type. + const keysToDelete = options.replaceExisting ? envelopeKeys : envelopeKeys.filter((key) => dotEnvKeys.includes(key)); + // delete marked env vars in parallel + // @ts-expect-error TS(7006) FIXME: Parameter 'key' implicitly has an 'any' type. + await Promise.all(keysToDelete.map((key) => api.deleteEnvVar({ accountId, siteId, key }))); + // hit create endpoint + const body = translateFromMongoToEnvelope(importedEnv); + try { + await api.createEnvVars({ accountId, siteId, body }); + } + catch (error) { + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + throw error.json ? error.json.msg : error; + } + // return final env to aid in --json output (for testing) + return { + // @ts-expect-error TS(7031) FIXME: Binding element 'key' implicitly has an 'any' type... Remove this comment to see the full error message + ...translateFromEnvelopeToMongo(envelopeVariables.filter(({ key }) => !keysToDelete.includes(key))), + ...importedEnv, + }; +}; +export const envImport = async (fileName, options, command) => { + const { api, cachedConfig, site } = command.netlify; + const siteId = site.id; + if (!siteId) { + log('No project id found, please run inside a project folder or `netlify link`'); + return false; + } + let importedEnv = {}; + try { + const envFileContents = await readFile(fileName, 'utf-8'); + importedEnv = dotenv.parse(envFileContents); + } + catch (error) { + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + log(error.message); + exit(1); + } + if (Object.keys(importedEnv).length === 0) { + log(`No environment variables found in file ${fileName} to import`); + return false; + } + const { siteInfo } = cachedConfig; + const finalEnv = await importDotEnv({ api, importedEnv, options, siteInfo }); + // Return new environment variables of site if using json flag + if (options.json) { + logJson(finalEnv); + return false; + } + // List newly imported environment variables in a table + log(`site: ${siteInfo.name}`); + const table = new AsciiTable(`Imported environment variables`); + table.setHeading('Key', 'Value'); + table.addRowMatrix(Object.entries(importedEnv)); + log(table.toString()); +}; +//# sourceMappingURL=env-import.js.map \ No newline at end of file diff --git a/dist/commands/env/env-import.js.map b/dist/commands/env/env-import.js.map new file mode 100644 index 00000000000..ed0d98155cf --- /dev/null +++ b/dist/commands/env/env-import.js.map @@ -0,0 +1 @@ +{"version":3,"file":"env-import.js","sourceRoot":"","sources":["../../../src/commands/env/env-import.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/env/env-list.d.ts b/dist/commands/env/env-list.d.ts new file mode 100644 index 00000000000..89b60ea45dd --- /dev/null +++ b/dist/commands/env/env-list.d.ts @@ -0,0 +1,4 @@ +import type { OptionValues } from 'commander'; +import type BaseCommand from '../base-command.js'; +export declare const envList: (options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=env-list.d.ts.map \ No newline at end of file diff --git a/dist/commands/env/env-list.d.ts.map b/dist/commands/env/env-list.d.ts.map new file mode 100644 index 00000000000..a4069b26e5c --- /dev/null +++ b/dist/commands/env/env-list.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"env-list.d.ts","sourceRoot":"","sources":["../../../src/commands/env/env-list.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAM7C,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAiCjD,eAAO,MAAM,OAAO,GAAU,SAAS,YAAY,EAAE,SAAS,WAAW,+BA0ExE,CAAA"} \ No newline at end of file diff --git a/dist/commands/env/env-list.js b/dist/commands/env/env-list.js new file mode 100644 index 00000000000..a48ff3e698e --- /dev/null +++ b/dist/commands/env/env-list.js @@ -0,0 +1,85 @@ +import ansiEscapes from 'ansi-escapes'; +import AsciiTable from 'ascii-table'; +import { isCI } from 'ci-info'; +import inquirer from 'inquirer'; +import logUpdate from 'log-update'; +import { chalk, log, logJson } from '../../utils/command-helpers.js'; +import { SUPPORTED_CONTEXTS, getEnvelopeEnv, getHumanReadableScopes } from '../../utils/env/index.js'; +const MASK_LENGTH = 50; +const MASK = '*'.repeat(MASK_LENGTH); +const getTable = ({ environment, hideValues, scopesColumn, }) => { + const table = new AsciiTable(`Environment variables`); + const headings = ['Key', 'Value', scopesColumn && 'Scope'].filter(Boolean); + table.setHeading(...headings); + table.addRowMatrix(Object.entries(environment).map(([key, variable]) => [ + // Key + key, + // Value + hideValues ? MASK : variable.value || ' ', + // Scope + scopesColumn && getHumanReadableScopes(variable.scopes), + ].filter(Boolean))); + return table.toString(); +}; +export const envList = async (options, command) => { + const { context, scope } = options; + const { api, cachedConfig, site } = command.netlify; + const siteId = site.id; + if (!siteId) { + log('No project id found, please run inside a project folder or `netlify link`'); + return false; + } + const { env, siteInfo } = cachedConfig; + let environment = await getEnvelopeEnv({ api, context, env, scope, siteInfo }); + // filter out general sources + environment = Object.fromEntries(Object.entries(environment).filter( + // @ts-expect-error TS(18046) - 'variable' is of type 'unknown' + ([, variable]) => variable.sources[0] !== 'general' && variable.sources[0] !== 'internal')); + // Return json response for piping commands + if (options.json) { + const envDictionary = Object.fromEntries( + // @ts-expect-error TS(18046) - 'variable' is of type 'unknown' + Object.entries(environment).map(([key, variable]) => [key, variable.value])); + logJson(envDictionary); + return false; + } + if (options.plain) { + const plaintext = Object.entries(environment) + // @ts-expect-error TS(18046) - 'variable' is of type 'unknown' + .map(([key, variable]) => `${key}=${variable.value}`) + .join('\n'); + log(plaintext); + return false; + } + const forSite = `for project ${chalk.green(siteInfo.name)}`; + const contextType = SUPPORTED_CONTEXTS.includes(context) ? 'context' : 'branch'; + const withContext = `in the ${chalk.magenta(options.context)} ${contextType}`; + const withScope = scope === 'any' ? '' : `and ${chalk.yellow(options.scope)} scope`; + if (Object.keys(environment).length === 0) { + log(`No environment variables set ${forSite} ${withContext} ${withScope}`); + return false; + } + // List environment in a table + const count = Object.keys(environment).length; + log(`${count} environment variable${count === 1 ? '' : 's'} ${forSite} ${withContext} ${withScope}`); + if (isCI) { + log(getTable({ environment, hideValues: false, scopesColumn: true })); + return false; + } + logUpdate(getTable({ environment, hideValues: true, scopesColumn: true })); + const { showValues } = await inquirer.prompt([ + { + type: 'confirm', + name: 'showValues', + message: 'Show values?', + default: false, + }, + ]); + if (showValues) { + // since inquirer adds a prompt, we need to account for it when printing the table again + log(ansiEscapes.eraseLines(3)); + logUpdate(getTable({ environment, hideValues: false, scopesColumn: true })); + log(`${chalk.cyan('?')} Show values? ${chalk.cyan('Yes')}`); + } +}; +//# sourceMappingURL=env-list.js.map \ No newline at end of file diff --git a/dist/commands/env/env-list.js.map b/dist/commands/env/env-list.js.map new file mode 100644 index 00000000000..a35b8570934 --- /dev/null +++ b/dist/commands/env/env-list.js.map @@ -0,0 +1 @@ +{"version":3,"file":"env-list.js","sourceRoot":"","sources":["../../../src/commands/env/env-list.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/env/env-set.d.ts b/dist/commands/env/env-set.d.ts new file mode 100644 index 00000000000..aabe3e13ced --- /dev/null +++ b/dist/commands/env/env-set.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const envSet: (key: string, value: string, options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=env-set.d.ts.map \ No newline at end of file diff --git a/dist/commands/env/env-set.d.ts.map b/dist/commands/env/env-set.d.ts.map new file mode 100644 index 00000000000..8d73b0472c7 --- /dev/null +++ b/dist/commands/env/env-set.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"env-set.d.ts","sourceRoot":"","sources":["../../../src/commands/env/env-set.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAKxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAwG5C,eAAO,MAAM,MAAM,GAAU,KAAK,MAAM,EAAE,OAAO,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,+BA+BnG,CAAA"} \ No newline at end of file diff --git a/dist/commands/env/env-set.js b/dist/commands/env/env-set.js new file mode 100644 index 00000000000..a4bcd7e64c9 --- /dev/null +++ b/dist/commands/env/env-set.js @@ -0,0 +1,118 @@ +import { chalk, logAndThrowError, log, logJson } from '../../utils/command-helpers.js'; +import { SUPPORTED_CONTEXTS, ALL_ENVELOPE_SCOPES, translateFromEnvelopeToMongo } from '../../utils/env/index.js'; +import { promptOverwriteEnvVariable } from '../../utils/prompts/env-set-prompts.js'; +/** + * Updates the env for a site configured with Envelope with a new key/value pair + * @returns {Promise} + */ +// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message +const setInEnvelope = async ({ api, context, force, key, scope, secret, siteInfo, value }) => { + const accountId = siteInfo.account_slug; + const siteId = siteInfo.id; + // secret values may not be used in the post-processing scope + // @ts-expect-error TS(7006) FIXME: Parameter 'sco' implicitly has an 'any' type. + if (secret && scope?.some((sco) => /post[-_]processing/.test(sco))) { + return logAndThrowError(`Secret values cannot be used within the post-processing scope.`); + } + // secret values must specify deploy contexts. `all` or `dev` are not allowed + if (secret && value && (!context || context.includes('dev'))) { + return logAndThrowError(`To set a secret environment variable value, please specify a non-development context with the \`--context\` flag.`); + } + // fetch envelope env vars + const envelopeVariables = await api.getEnvVars({ accountId, siteId }); + const contexts = context || ['all']; + let scopes = scope || ALL_ENVELOPE_SCOPES; + if (secret) { + // post_processing (aka post-processing) scope is not allowed with secrets + // @ts-expect-error TS(7006) FIXME: Parameter 'sco' implicitly has an 'any' type. + scopes = scopes.filter((sco) => !/post[-_]processing/.test(sco)); + } + // if the passed context is unknown, it is actually a branch name + // @ts-expect-error TS(7006) FIXME: Parameter 'ctx' implicitly has an 'any' type. + let values = contexts.map((ctx) => SUPPORTED_CONTEXTS.includes(ctx) ? { context: ctx, value } : { context: 'branch', context_parameter: ctx, value }); + // @ts-expect-error TS(7006) FIXME: Parameter 'envVar' implicitly has an 'any' type. + const existing = envelopeVariables.find((envVar) => envVar.key === key); + // Checks if --force is passed and if it is an existing variaible, then we need to prompt the user + if (Boolean(force) === false && existing) { + await promptOverwriteEnvVariable(key); + } + const params = { accountId, siteId, key }; + try { + if (existing) { + if (!value) { + values = existing.values; + if (!scope) { + scopes = existing.scopes; + } + } + if (context && scope) { + return logAndThrowError('Setting the context and scope at the same time on an existing env var is not allowed. Run the set command separately for each update.'); + } + if (context) { + // update individual value(s) + // @ts-expect-error TS(7006) FIXME: Parameter 'val' implicitly has an 'any' type. + await Promise.all(values.map((val) => api.setEnvVarValue({ ...params, body: val }))); + } + else { + // otherwise update whole env var + if (secret) { + // @ts-expect-error TS(7006) FIXME: Parameter 'sco' implicitly has an 'any' type. + scopes = scopes.filter((sco) => !/post[-_]processing/.test(sco)); + // @ts-expect-error TS(7006) FIXME: Parameter 'val' implicitly has an 'any' type. + if (values.some((val) => val.context === 'all')) { + log(`This secret's value will be empty in the dev context.`); + log(`Run \`netlify env:set ${key} --context dev\` to set a new value for the dev context.`); + values = SUPPORTED_CONTEXTS.filter((ctx) => ctx !== 'all').map((ctx) => ({ + context: ctx, + // empty out dev value so that secret is indeed secret + // @ts-expect-error TS(7006) FIXME: Parameter 'val' implicitly has an 'any' type. + value: ctx === 'dev' ? '' : values.find((val) => val.context === 'all').value, + })); + } + } + const body = { key, is_secret: secret, scopes, values }; + await api.updateEnvVar({ ...params, body }); + } + } + else { + // create whole env var + const body = [{ key, is_secret: secret, scopes, values }]; + await api.createEnvVars({ ...params, body }); + } + } + catch (error_) { + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + throw error_.json ? error_.json.msg : error_; + } + const env = translateFromEnvelopeToMongo(envelopeVariables, context ? context[0] : 'dev'); + return { + ...env, + // @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message + [key]: value || env[key], + }; +}; +export const envSet = async (key, value, options, command) => { + const { context, force, scope, secret } = options; + const { api, cachedConfig, site } = command.netlify; + const siteId = site.id; + if (!siteId) { + log('No project id found, please run inside a project folder or `netlify link`'); + return false; + } + const { siteInfo } = cachedConfig; + // Get current environment variables set in the UI + const finalEnv = await setInEnvelope({ api, siteInfo, force, key, value, context, scope, secret }); + if (!finalEnv) { + return false; + } + // Return new environment variables of site if using json flag + if (options.json) { + logJson(finalEnv); + return false; + } + const withScope = scope ? ` scoped to ${chalk.white(scope)}` : ''; + const withSecret = secret ? ` as a ${chalk.blue('secret')}` : ''; + const contextType = SUPPORTED_CONTEXTS.includes(context || 'all') ? 'context' : 'branch'; + log(`Set environment variable ${chalk.yellow(`${key}${value && !secret ? `=${value}` : ''}`)}${withScope}${withSecret} in the ${chalk.magenta(context || 'all')} ${contextType}`); +}; +//# sourceMappingURL=env-set.js.map \ No newline at end of file diff --git a/dist/commands/env/env-set.js.map b/dist/commands/env/env-set.js.map new file mode 100644 index 00000000000..d83c930e055 --- /dev/null +++ b/dist/commands/env/env-set.js.map @@ -0,0 +1 @@ +{"version":3,"file":"env-set.js","sourceRoot":"","sources":["../../../src/commands/env/env-set.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/env/env-unset.d.ts b/dist/commands/env/env-unset.d.ts new file mode 100644 index 00000000000..19a274b6e33 --- /dev/null +++ b/dist/commands/env/env-unset.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const envUnset: (key: string, options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=env-unset.d.ts.map \ No newline at end of file diff --git a/dist/commands/env/env-unset.d.ts.map b/dist/commands/env/env-unset.d.ts.map new file mode 100644 index 00000000000..3b0e8d42f0f --- /dev/null +++ b/dist/commands/env/env-unset.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"env-unset.d.ts","sourceRoot":"","sources":["../../../src/commands/env/env-unset.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAKxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAgE5C,eAAO,MAAM,QAAQ,GAAU,KAAK,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,+BAsBtF,CAAA"} \ No newline at end of file diff --git a/dist/commands/env/env-unset.js b/dist/commands/env/env-unset.js new file mode 100644 index 00000000000..f791f19cdff --- /dev/null +++ b/dist/commands/env/env-unset.js @@ -0,0 +1,76 @@ +import { chalk, log, logJson } from '../../utils/command-helpers.js'; +import { SUPPORTED_CONTEXTS, translateFromEnvelopeToMongo } from '../../utils/env/index.js'; +import { promptOverwriteEnvVariable } from '../../utils/prompts/env-unset-prompts.js'; +/** + * Deletes a given key from the env of a site configured with Envelope + * @returns {Promise} + */ +// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message +const unsetInEnvelope = async ({ api, context, force, key, siteInfo }) => { + const accountId = siteInfo.account_slug; + const siteId = siteInfo.id; + // fetch envelope env vars + const envelopeVariables = await api.getEnvVars({ accountId, siteId }); + const contexts = context || ['all']; + const env = translateFromEnvelopeToMongo(envelopeVariables, context ? context[0] : 'dev'); + // check if the given key exists + // @ts-expect-error TS(7006) FIXME: Parameter 'envVar' implicitly has an 'any' type. + const variable = envelopeVariables.find((envVar) => envVar.key === key); + if (!variable) { + // if not, no need to call delete; return early + return env; + } + if (Boolean(force) === false) { + await promptOverwriteEnvVariable(key); + } + const params = { accountId, siteId, key }; + try { + if (context) { + // if context(s) are passed, delete the matching contexts / branches, and the `all` context + // @ts-expect-error TS(7006) FIXME: Parameter 'val' implicitly has an 'any' type. + const values = variable.values.filter((val) => [...contexts, 'all'].includes(val.context_parameter || val.context)); + if (values) { + // @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. + await Promise.all(values.map((value) => api.deleteEnvVarValue({ ...params, id: value.id }))); + // if this was the `all` context, we need to create 3 values in the other contexts + if (values.length === 1 && values[0].context === 'all') { + const newContexts = SUPPORTED_CONTEXTS.filter((ctx) => !context.includes(ctx)); + const allValue = values[0].value; + await Promise.all(newContexts + .filter((ctx) => ctx !== 'all') + .map((ctx) => api.setEnvVarValue({ ...params, body: { context: ctx, value: allValue } }))); + } + } + } + else { + // otherwise, if no context passed, delete the whole key + await api.deleteEnvVar({ accountId, siteId, key }); + } + } + catch (error_) { + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + throw error_.json ? error_.json.msg : error_; + } + // @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message + delete env[key]; + return env; +}; +export const envUnset = async (key, options, command) => { + const { context, force } = options; + const { api, cachedConfig, site } = command.netlify; + const siteId = site.id; + if (!siteId) { + log('No project id found, please run inside a project folder or `netlify link`'); + return false; + } + const { siteInfo } = cachedConfig; + const finalEnv = await unsetInEnvelope({ api, context, force, siteInfo, key }); + // Return new environment variables of site if using json flag + if (options.json) { + logJson(finalEnv); + return false; + } + const contextType = SUPPORTED_CONTEXTS.includes(context || 'all') ? 'context' : 'branch'; + log(`Unset environment variable ${chalk.yellow(key)} in the ${chalk.magenta(context || 'all')} ${contextType}`); +}; +//# sourceMappingURL=env-unset.js.map \ No newline at end of file diff --git a/dist/commands/env/env-unset.js.map b/dist/commands/env/env-unset.js.map new file mode 100644 index 00000000000..eea03310539 --- /dev/null +++ b/dist/commands/env/env-unset.js.map @@ -0,0 +1 @@ +{"version":3,"file":"env-unset.js","sourceRoot":"","sources":["../../../src/commands/env/env-unset.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/env/env.d.ts b/dist/commands/env/env.d.ts new file mode 100644 index 00000000000..6262c3c6add --- /dev/null +++ b/dist/commands/env/env.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const createEnvCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=env.d.ts.map \ No newline at end of file diff --git a/dist/commands/env/env.d.ts.map b/dist/commands/env/env.d.ts.map new file mode 100644 index 00000000000..0d4997aaef4 --- /dev/null +++ b/dist/commands/env/env.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../../src/commands/env/env.ts"],"names":[],"mappings":"AAIA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAM5C,eAAO,MAAM,gBAAgB,GAAI,SAAS,WAAW,gBAmKpD,CAAA"} \ No newline at end of file diff --git a/dist/commands/env/env.js b/dist/commands/env/env.js new file mode 100644 index 00000000000..1d2d7869454 --- /dev/null +++ b/dist/commands/env/env.js @@ -0,0 +1,139 @@ +import { Option } from 'commander'; +import terminalLink from 'terminal-link'; +import { normalizeContext } from '../../utils/env/index.js'; +const env = (_options, command) => { + command.help(); +}; +export const createEnvCommand = (program) => { + program + .command('env:get') + .argument('', 'Environment variable name') + .option('-c, --context ', 'Specify a deploy context for environment variables (ā€productionā€, ā€deploy-previewā€, ā€branch-deployā€, ā€devā€) or `branch:your-branch` where `your-branch` is the name of a branch', normalizeContext, 'dev') + .option('--json', 'Output environment variables as JSON') + .addOption(new Option('-s, --scope ', 'Specify a scope') + .choices(['builds', 'functions', 'post-processing', 'runtime', 'any']) + .default('any')) + .addExamples([ + 'netlify env:get MY_VAR # get value for MY_VAR in dev context', + 'netlify env:get MY_VAR --context production', + 'netlify env:get MY_VAR --context branch:feat/make-it-pop # get value in the feat/make-it-pop branch context or branch-deploy context', + 'netlify env:get MY_VAR --scope functions', + ]) + .description('Get resolved value of specified environment variable (includes netlify.toml)') + .action(async (name, options, command) => { + const { envGet } = await import('./env-get.js'); + await envGet(name, options, command); + }); + program + .command('env:import') + .argument('', '.env file to import') + .option('-r, --replace-existing', 'Replace all existing variables instead of merging them with the current ones', false) + .option('--json', 'Output environment variables as JSON') + .description('Import and set environment variables from .env file') + .action(async (fileName, options, command) => { + const { envImport } = await import('./env-import.js'); + await envImport(fileName, options, command); + }); + program + .command('env:list') + .option('-c, --context ', 'Specify a deploy context for environment variables (ā€productionā€, ā€deploy-previewā€, ā€branch-deployā€, ā€devā€) or `branch:your-branch` where `your-branch` is the name of a branch (default: all contexts)', normalizeContext, 'dev') + .option('--json', 'Output environment variables as JSON') + .addOption(new Option('--plain', 'Output environment variables as plaintext').conflicts('json')) + .addOption(new Option('-s, --scope ', 'Specify a scope') + .choices(['builds', 'functions', 'post-processing', 'runtime', 'any']) + .default('any')) + .addExamples([ + 'netlify env:list # list variables with values in the dev context and with any scope', + 'netlify env:list --context production', + 'netlify env:list --context branch:feat/make-it-pop # list variables with values in the feat/make-it-pop branch context or branch-deploy context', + 'netlify env:list --scope functions', + 'netlify env:list --plain', + ]) + .description('Lists resolved environment variables for project (includes netlify.toml)') + .action(async (options, command) => { + const { envList } = await import('./env-list.js'); + await envList(options, command); + }); + program + .command('env:set') + .argument('', 'Environment variable key') + .argument('[value]', 'Value to set to', '') + .option('-c, --context ', 'Specify a deploy context for environment variables (ā€productionā€, ā€deploy-previewā€, ā€branch-deployā€, ā€devā€) or `branch:your-branch` where `your-branch` is the name of a branch (default: all contexts)', + // spread over an array for variadic options + (context, previous = []) => [...previous, normalizeContext(context)]) + .option('--json', 'Output environment variables as JSON') + .addOption(new Option('-s, --scope ', 'Specify a scope (default: all scopes)').choices([ + 'builds', + 'functions', + 'post-processing', + 'runtime', + ])) + .option('--secret', 'Indicate whether the environment variable value can be read again.') + .description('Set value of environment variable') + .addExamples([ + 'netlify env:set VAR_NAME value # set in all contexts and scopes', + 'netlify env:set VAR_NAME value --context production', + 'netlify env:set VAR_NAME value --context production deploy-preview # set in the production and deploy-preview contexts', + 'netlify env:set VAR_NAME value --context branch:feat/make-it-pop # set in the feat/make-it-pop branch context', + 'netlify env:set VAR_NAME value --context production --secret', + 'netlify env:set VAR_NAME value --scope builds', + 'netlify env:set VAR_NAME value --scope builds functions', + 'netlify env:set VAR_NAME --secret # convert existing variable to secret', + ]) + .action(async (key, value, options, command) => { + const { envSet } = await import('./env-set.js'); + await envSet(key, value, options, command); + }); + program + .command('env:unset') + .aliases(['env:delete', 'env:remove']) + .argument('', 'Environment variable key') + .option('-c, --context ', 'Specify a deploy context for environment variables (ā€productionā€, ā€deploy-previewā€, ā€branch-deployā€, ā€devā€) or `branch:your-branch` where `your-branch` is the name of a branch (default: all contexts)', + // spread over an array for variadic options + (context, previous = []) => [...previous, normalizeContext(context)]) + .option('--json', 'Output environment variables as JSON') + .addExamples([ + 'netlify env:unset VAR_NAME # unset in all contexts', + 'netlify env:unset VAR_NAME --context production', + 'netlify env:unset VAR_NAME --context production deploy-preview', + 'netlify env:unset VAR_NAME --context branch:feat/make-it-pop # unset in the feat/make-it-pop branch context', + ]) + .description('Unset an environment variable which removes it from the UI') + .action(async (key, options, command) => { + const { envUnset } = await import('./env-unset.js'); + await envUnset(key, options, command); + }); + program + .command('env:clone') + .alias('env:migrate') + .option('-f, --from ', 'Project ID (From)') + .requiredOption('-t, --to ', 'Project ID (To)') + .description(`Clone environment variables from one project to another`) + .addExamples([ + 'netlify env:clone --to ', + 'netlify env:clone --to --from ', + ]) + .action(async (options, command) => { + const { envClone } = await import('./env-clone.js'); + await envClone(options, command); + }); + return program + .command('env') + .description('Control environment variables for the current project') + .addExamples([ + 'netlify env:list', + 'netlify env:get VAR_NAME', + 'netlify env:set VAR_NAME value', + 'netlify env:unset VAR_NAME', + 'netlify env:import fileName', + 'netlify env:clone --to ', + ]) + .addHelpText('afterAll', () => { + const docsUrl = 'https://docs.netlify.com/configure-builds/environment-variables/'; + return ` +For more information about environment variables on Netlify, see ${terminalLink(docsUrl, docsUrl, { fallback: false })} +`; + }) + .action(env); +}; +//# sourceMappingURL=env.js.map \ No newline at end of file diff --git a/dist/commands/env/env.js.map b/dist/commands/env/env.js.map new file mode 100644 index 00000000000..6000d08889a --- /dev/null +++ b/dist/commands/env/env.js.map @@ -0,0 +1 @@ +{"version":3,"file":"env.js","sourceRoot":"","sources":["../../../src/commands/env/env.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/env/index.d.ts b/dist/commands/env/index.d.ts new file mode 100644 index 00000000000..18c39d1f5ec --- /dev/null +++ b/dist/commands/env/index.d.ts @@ -0,0 +1,2 @@ +export { createEnvCommand } from './env.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/env/index.d.ts.map b/dist/commands/env/index.d.ts.map new file mode 100644 index 00000000000..ffb93ab1458 --- /dev/null +++ b/dist/commands/env/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/env/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA"} \ No newline at end of file diff --git a/dist/commands/env/index.js b/dist/commands/env/index.js new file mode 100644 index 00000000000..b2d12512a78 --- /dev/null +++ b/dist/commands/env/index.js @@ -0,0 +1,2 @@ +export { createEnvCommand } from './env.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/env/index.js.map b/dist/commands/env/index.js.map new file mode 100644 index 00000000000..fa7cfef87f8 --- /dev/null +++ b/dist/commands/env/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/env/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,UAAU,CAAA"} \ No newline at end of file diff --git a/dist/commands/functions/functions-build.d.ts b/dist/commands/functions/functions-build.d.ts new file mode 100644 index 00000000000..a4004bc23f6 --- /dev/null +++ b/dist/commands/functions/functions-build.d.ts @@ -0,0 +1,4 @@ +import type { OptionValues } from 'commander'; +import type BaseCommand from '../base-command.js'; +export declare const functionsBuild: (options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=functions-build.d.ts.map \ No newline at end of file diff --git a/dist/commands/functions/functions-build.d.ts.map b/dist/commands/functions/functions-build.d.ts.map new file mode 100644 index 00000000000..4f7ed8aa05e --- /dev/null +++ b/dist/commands/functions/functions-build.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"functions-build.d.ts","sourceRoot":"","sources":["../../../src/commands/functions/functions-build.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAI7C,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAEjD,eAAO,MAAM,cAAc,GAAU,SAAS,YAAY,EAAE,SAAS,WAAW,uBA+B/E,CAAA"} \ No newline at end of file diff --git a/dist/commands/functions/functions-build.js b/dist/commands/functions/functions-build.js new file mode 100644 index 00000000000..fb1895a29be --- /dev/null +++ b/dist/commands/functions/functions-build.js @@ -0,0 +1,26 @@ +import { mkdir } from 'fs/promises'; +import { zipFunctions } from '@netlify/zip-it-and-ship-it'; +import { NETLIFYDEVERR, NETLIFYDEVLOG, exit, log } from '../../utils/command-helpers.js'; +import { getFunctionsDir } from '../../utils/functions/index.js'; +export const functionsBuild = async (options, command) => { + const { config } = command.netlify; + const src = ('src' in options && typeof options.src === 'string' && options.src.trim().length > 0 ? options.src : null) ?? + config.build.functionsSource; + const dst = getFunctionsDir({ options, config }); + if (src === dst) { + log(`${NETLIFYDEVERR} Source and destination for function build can't be the same`); + exit(1); + } + if (!src || !dst) { + if (!src) + log(`${NETLIFYDEVERR} Error: You must specify a source folder with a --src flag or a functionsSource field in your config`); + if (!dst) + log(`${NETLIFYDEVERR} Error: You must specify a destination functions folder with a --functions flag or a functions field in your config`); + return exit(1); + } + await mkdir(dst, { recursive: true }); + log(`${NETLIFYDEVLOG} Building functions`); + await zipFunctions(src, dst); + log(`${NETLIFYDEVLOG} Functions built to `, dst); +}; +//# sourceMappingURL=functions-build.js.map \ No newline at end of file diff --git a/dist/commands/functions/functions-build.js.map b/dist/commands/functions/functions-build.js.map new file mode 100644 index 00000000000..c46c84b9848 --- /dev/null +++ b/dist/commands/functions/functions-build.js.map @@ -0,0 +1 @@ +{"version":3,"file":"functions-build.js","sourceRoot":"","sources":["../../../src/commands/functions/functions-build.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAEnC,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAA;AAG1D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAA;AACxF,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAGhE,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IAClF,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IAElC,MAAM,GAAG,GACP,CAAC,KAAK,IAAI,OAAO,IAAI,OAAO,OAAO,CAAC,GAAG,KAAK,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QAC3G,MAAM,CAAC,KAAK,CAAC,eAAe,CAAA;IAC9B,MAAM,GAAG,GAAG,eAAe,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAA;IAEhD,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC;QAChB,GAAG,CAAC,GAAG,aAAa,8DAA8D,CAAC,CAAA;QACnF,IAAI,CAAC,CAAC,CAAC,CAAA;IACT,CAAC;IAED,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QACjB,IAAI,CAAC,GAAG;YACN,GAAG,CACD,GAAG,aAAa,sGAAsG,CACvH,CAAA;QACH,IAAI,CAAC,GAAG;YACN,GAAG,CACD,GAAG,aAAa,qHAAqH,CACtI,CAAA;QACH,OAAO,IAAI,CAAC,CAAC,CAAC,CAAA;IAChB,CAAC;IAED,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAErC,GAAG,CAAC,GAAG,aAAa,qBAAqB,CAAC,CAAA;IAE1C,MAAM,YAAY,CAAC,GAAG,EAAE,GAAG,CAAC,CAAA;IAC5B,GAAG,CAAC,GAAG,aAAa,sBAAsB,EAAE,GAAG,CAAC,CAAA;AAClD,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/functions/functions-create.d.ts b/dist/commands/functions/functions-create.d.ts new file mode 100644 index 00000000000..71ef27589b7 --- /dev/null +++ b/dist/commands/functions/functions-create.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const functionsCreate: (name: string, options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=functions-create.d.ts.map \ No newline at end of file diff --git a/dist/commands/functions/functions-create.d.ts.map b/dist/commands/functions/functions-create.d.ts.map new file mode 100644 index 00000000000..cd4d51605e2 --- /dev/null +++ b/dist/commands/functions/functions-create.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"functions-create.d.ts","sourceRoot":"","sources":["../../../src/commands/functions/functions-create.ts"],"names":[],"mappings":"AAQA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAsBxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAmtB5C,eAAO,MAAM,eAAe,GAAU,MAAM,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,kBAQ9F,CAAA"} \ No newline at end of file diff --git a/dist/commands/functions/functions-create.js b/dist/commands/functions/functions-create.js new file mode 100644 index 00000000000..b0fc693ace1 --- /dev/null +++ b/dist/commands/functions/functions-create.js @@ -0,0 +1,629 @@ +import cp from 'child_process'; +import fs from 'fs'; +import { mkdir, readdir, unlink } from 'fs/promises'; +import { createRequire } from 'module'; +import path, { dirname, join, relative } from 'path'; +import process from 'process'; +import { fileURLToPath, pathToFileURL } from 'url'; +import { findUp } from 'find-up'; +import fuzzy from 'fuzzy'; +import inquirer from 'inquirer'; +import fetch from 'node-fetch'; +import { createSpinner } from 'nanospinner'; +import { fileExistsAsync } from '../../lib/fs.js'; +import { getAddons, getCurrentAddon, getSiteData } from '../../utils/addons/prepare.js'; +import { NETLIFYDEVERR, NETLIFYDEVLOG, NETLIFYDEVWARN, chalk, logAndThrowError, log, } from '../../utils/command-helpers.js'; +import { copyTemplateDir } from '../../utils/copy-template-dir/copy-template-dir.js'; +import { getDotEnvVariables, injectEnvVariables } from '../../utils/dev.js'; +import execa from '../../utils/execa.js'; +import { readRepoURL, validateRepoURL } from '../../utils/read-repo-url.js'; +const require = createRequire(import.meta.url); +const templatesDir = path.resolve(dirname(fileURLToPath(import.meta.url)), '../../../functions-templates'); +/** + * Ensure that there's a sub-directory in `/functions-templates` named after + * each `value` property in this list. + */ +const languages = [ + { name: 'JavaScript', value: 'javascript' }, + { name: 'TypeScript', value: 'typescript' }, + { name: 'Go', value: 'go' }, + { name: 'Rust', value: 'rust' }, +]; +const MOON_SPINNER = { + interval: 80, + frames: ['šŸŒ‘ ', 'šŸŒ’ ', 'šŸŒ“ ', 'šŸŒ” ', 'šŸŒ• ', 'šŸŒ– ', 'šŸŒ— ', '🌘 '], +}; +/** + * prompt for a name if name not supplied + * @param {string} argumentName + * @param {import('commander').OptionValues} options + * @param {string} [defaultName] + * @returns + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'argumentName' implicitly has an 'any' t... Remove this comment to see the full error message +const getNameFromArgs = async function (argumentName, options, defaultName) { + if (options.name) { + if (argumentName) { + throw new Error('function name specified in both flag and arg format, pick one'); + } + return options.name; + } + if (argumentName) { + return argumentName; + } + const { name } = await inquirer.prompt([ + { + name: 'name', + message: 'Name your function:', + default: defaultName, + type: 'input', + validate: (val) => Boolean(val) && /^[\w.-]+$/i.test(val), + // make sure it is not undefined and is a valid filename. + // this has some nuance i have ignored, eg crossenv and i18n concerns + }, + ]); + return name; +}; +// @ts-expect-error TS(7006) FIXME: Parameter 'registry' implicitly has an 'any' type. +const filterRegistry = function (registry, input) { + // @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. + const temp = registry.map((value) => value.name + value.description); + const filteredTemplates = fuzzy.filter(input, temp); + const filteredTemplateNames = new Set(filteredTemplates.map((filteredTemplate) => (input ? filteredTemplate.string : filteredTemplate))); + return (registry + // @ts-expect-error TS(7006) FIXME: Parameter 't' implicitly has an 'any' type. + .filter((t) => filteredTemplateNames.has(t.name + t.description)) + // @ts-expect-error TS(7006) FIXME: Parameter 't' implicitly has an 'any' type. + .map((t) => { + // add the score + // @ts-expect-error TS(2339) FIXME: Property 'score' does not exist on type 'FilterRes... Remove this comment to see the full error message + const { score } = filteredTemplates.find((filteredTemplate) => filteredTemplate.string === t.name + t.description); + t.score = score; + return t; + })); +}; +/** + * @param {string} lang + * @param {'edge' | 'serverless'} funcType + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'lang' implicitly has an 'any' type. +const formatRegistryArrayForInquirer = async function (lang, funcType) { + const folders = await readdir(path.join(templatesDir, lang), { withFileTypes: true }); + const imports = await Promise.all(folders + .filter((folder) => Boolean(folder?.isDirectory())) + .map(async ({ name }) => { + try { + const templatePath = path.join(templatesDir, lang, name, '.netlify-function-template.mjs'); + // @ts-expect-error TS(7036) FIXME: Dynamic import's specifier must be of type 'string... Remove this comment to see the full error message + const template = await import(pathToFileURL(templatePath)); + return template.default; + } + catch { + // noop if import fails we don't break the whole inquirer + } + })); + const registry = imports + .filter((template) => template?.functionType === funcType) + .sort((templateA, templateB) => { + const priorityDiff = (templateA.priority || DEFAULT_PRIORITY) - (templateB.priority || DEFAULT_PRIORITY); + if (priorityDiff !== 0) { + return priorityDiff; + } + // This branch is needed because `Array.prototype.sort` was not stable + // until Node 11, so the original sorting order from `fs.readdirSync` + // was not respected. We can simplify this once we drop support for + // Node 10. + return templateA - templateB; + }) + .map((t) => { + t.lang = lang; + return { + // confusing but this is the format inquirer wants + name: `[${t.name}] ${t.description}`, + value: t, + short: `${lang}-${t.name}`, + }; + }); + return registry; +}; +/** + * pick template from our existing templates + * @param {import('commander').OptionValues} config + * @param {'edge' | 'serverless'} funcType + */ +// @ts-expect-error TS(7031) FIXME: Binding element 'languageFromFlag' implicitly has ... Remove this comment to see the full error message +const pickTemplate = async function ({ language: languageFromFlag }, funcType) { + const specialCommands = [ + new inquirer.Separator(), + { + name: `Clone template from GitHub URL`, + value: 'url', + short: 'gh-url', + }, + { + name: `Report issue with, or suggest a new template`, + value: 'report', + short: 'gh-report', + }, + new inquirer.Separator(), + ]; + let language = languageFromFlag; + if (language === undefined) { + const langs = funcType === 'edge' + ? languages.filter((lang) => lang.value === 'javascript' || lang.value === 'typescript') + : languages.filter(Boolean); + const { language: languageFromPrompt } = await inquirer.prompt({ + choices: langs, + message: 'Select the language of your function', + name: 'language', + type: 'list', + }); + language = languageFromPrompt; + } + let templatesForLanguage; + try { + templatesForLanguage = await formatRegistryArrayForInquirer(language, funcType); + } + catch { + return logAndThrowError(`Invalid language: ${language}`); + } + const { chosenTemplate } = await inquirer.prompt({ + name: 'chosenTemplate', + message: 'Pick a template', + // @ts-expect-error TS(2769) FIXME: No overload matches this call. + type: 'autocomplete', + source(_answersSoFar, input) { + // if Edge Functions template, don't show url option + // @ts-expect-error TS(2339) FIXME: Property 'value' does not exist on type 'Separator... Remove this comment to see the full error message + const edgeCommands = specialCommands.filter((val) => val.value !== 'url'); + const parsedSpecialCommands = funcType === 'edge' ? edgeCommands : specialCommands; + if (!input || input === '') { + // show separators + return [...templatesForLanguage, ...parsedSpecialCommands]; + } + // only show filtered results sorted by score + const answers = [...filterRegistry(templatesForLanguage, input), ...parsedSpecialCommands].sort((answerA, answerB) => answerB.score - answerA.score); + return answers; + }, + }); + return chosenTemplate; +}; +const DEFAULT_PRIORITY = 999; +const selectTypeOfFunc = async () => { + const functionTypes = [ + { name: 'Edge function (Deno)', value: 'edge' }, + { name: 'Serverless function (Node/Go/Rust)', value: 'serverless' }, + ]; + const { functionType } = await inquirer.prompt([ + { + name: 'functionType', + message: "Select the type of function you'd like to create", + type: 'list', + choices: functionTypes, + }, + ]); + return functionType; +}; +/** + * @param {import('../base-command.js').default} command + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'command' implicitly has an 'any' type. +const ensureEdgeFuncDirExists = function (command) { + const { config, site } = command.netlify; + const siteId = site.id; + if (!siteId) { + return logAndThrowError(`${NETLIFYDEVERR} No project id found, please run inside a project directory or \`netlify link\``); + } + const functionsDir = config.build?.edge_functions ?? join(command.workingDir, 'netlify/edge-functions'); + const relFunctionsDir = relative(command.workingDir, functionsDir); + if (!fs.existsSync(functionsDir)) { + log(`${NETLIFYDEVLOG} Edge Functions directory ${chalk.magenta.inverse(relFunctionsDir)} does not exist yet, creating it...`); + fs.mkdirSync(functionsDir, { recursive: true }); + log(`${NETLIFYDEVLOG} Edge Functions directory ${chalk.magenta.inverse(relFunctionsDir)} created.`); + } + return functionsDir; +}; +/** + * Prompts the user to choose a functions directory + * @param {import('../base-command.js').default} command + * @returns {Promise} - functions directory or throws an error + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'command' implicitly has an 'any' type. +const promptFunctionsDirectory = async (command) => { + const { api, relConfigFilePath, site } = command.netlify; + log(`\n${NETLIFYDEVLOG} functions directory not specified in ${relConfigFilePath} or UI settings`); + if (!site.id) { + return logAndThrowError(`${NETLIFYDEVERR} No project id found, please run inside a project directory or \`netlify link\``); + } + const { functionsDir } = await inquirer.prompt([ + { + type: 'input', + name: 'functionsDir', + message: 'Enter the path, relative to your project, where your functions should live:', + default: 'netlify/functions', + }, + ]); + try { + log(`${NETLIFYDEVLOG} updating project settings with ${chalk.magenta.inverse(functionsDir)}`); + await api.updateSite({ + siteId: site.id, + body: { + build_settings: { + functions_dir: functionsDir, + }, + }, + }); + log(`${NETLIFYDEVLOG} functions directory ${chalk.magenta.inverse(functionsDir)} updated in project settings`); + } + catch { + return logAndThrowError('Error updating project settings'); + } + return functionsDir; +}; +/** + * Get functions directory (and make it if necessary) + * @param {import('../base-command.js').default} command + * @returns {Promise} - functions directory or throws an error + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'command' implicitly has an 'any' type. +const ensureFunctionDirExists = async function (command) { + const { config } = command.netlify; + const functionsDirHolder = config.functionsDirectory || join(command.workingDir, await promptFunctionsDirectory(command)); + const relFunctionsDirHolder = relative(command.workingDir, functionsDirHolder); + if (!fs.existsSync(functionsDirHolder)) { + log(`${NETLIFYDEVLOG} functions directory ${chalk.magenta.inverse(relFunctionsDirHolder)} does not exist yet, creating it...`); + await mkdir(functionsDirHolder, { recursive: true }); + log(`${NETLIFYDEVLOG} functions directory ${chalk.magenta.inverse(relFunctionsDirHolder)} created`); + } + return functionsDirHolder; +}; +/** + * Download files from a given GitHub URL + * @param {import('../base-command.js').default} command + * @param {import('commander').OptionValues} options + * @param {string} argumentName + * @param {string} functionsDir + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'command' implicitly has an 'any' type. +const downloadFromURL = async function (command, options, argumentName, functionsDir) { + const folderContents = await readRepoURL(options.url); + const [functionName] = options.url.split('/').slice(-1); + const nameToUse = await getNameFromArgs(argumentName, options, functionName); + const fnFolder = path.join(functionsDir, nameToUse); + if (fs.existsSync(`${fnFolder}.js`) && fs.lstatSync(`${fnFolder}.js`).isFile()) { + log(`${NETLIFYDEVWARN}: A single file version of the function ${nameToUse} already exists at ${fnFolder}.js. Terminating without further action.`); + process.exit(1); + } + try { + await mkdir(fnFolder, { recursive: true }); + } + catch { + // Ignore + } + await Promise.all( + // @ts-expect-error TS(7031) FIXME: Binding element 'downloadUrl' implicitly has an 'a... Remove this comment to see the full error message + folderContents.map(async ({ download_url: downloadUrl, name }) => { + try { + const res = await fetch(downloadUrl); + const finalName = path.basename(name, '.js') === functionName ? `${nameToUse}.js` : name; + const dest = fs.createWriteStream(path.join(fnFolder, finalName)); + res.body?.pipe(dest); + } + catch (error_) { + throw new Error(`Error while retrieving ${downloadUrl} ${error_}`); + } + })); + log(`${NETLIFYDEVLOG} Installing dependencies for ${nameToUse}...`); + cp.exec('npm i', { cwd: path.join(functionsDir, nameToUse) }, () => { + log(`${NETLIFYDEVLOG} Installing dependencies for ${nameToUse} complete `); + }); + // read, execute, and delete function template file if exists + const fnTemplateFile = path.join(fnFolder, '.netlify-function-template.mjs'); + if (await fileExistsAsync(fnTemplateFile)) { + const { default: { addons = [], onComplete }, } = await import(pathToFileURL(fnTemplateFile).href); + await installAddons(command, addons, path.resolve(fnFolder)); + await handleOnComplete({ command, onComplete }); + // delete + await unlink(fnTemplateFile); + } +}; +/** + * Takes a list of existing packages and a list of packages required by a + * function, and returns the packages from the latter that aren't present + * in the former. The packages are returned as an array of strings with the + * name and version range (e.g. '@netlify/functions@0.1.0'). + */ +const getNpmInstallPackages = (existingPackages = {}, neededPackages = {}) => Object.entries(neededPackages) + // @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message + .filter(([name]) => existingPackages[name] === undefined) + .map(([name, version]) => `${name}@${version}`); +/** + * When installing a function's dependencies, we first try to find a project-level + * `package.json` file. If we find one, we identify the function's dependencies + * that aren't already listed as dependencies of the project and install them. If + * we don't do this check, we may be upgrading the version of a module used in + * another part of the project, which we don't want to do. + */ +// @ts-expect-error TS(7031) FIXME: Binding element 'functionPackageJson' implicitly h... Remove this comment to see the full error message +const installDeps = async ({ functionPackageJson, functionPath, functionsDir }) => { + const { dependencies: functionDependencies, devDependencies: functionDevDependencies } = require(functionPackageJson); + const sitePackageJson = await findUp('package.json', { cwd: functionsDir }); + const npmInstallFlags = ['--no-audit', '--no-fund']; + // If there is no project-level `package.json`, we fall back to the old behavior + // of keeping that file in the function directory and running `npm install` + // from there. + if (!sitePackageJson) { + await execa('npm', ['i', ...npmInstallFlags], { cwd: functionPath }); + return; + } + const { dependencies: siteDependencies, devDependencies: siteDevDependencies } = require(sitePackageJson); + const dependencies = getNpmInstallPackages(siteDependencies, functionDependencies); + const devDependencies = getNpmInstallPackages(siteDevDependencies, functionDevDependencies); + const npmInstallPath = path.dirname(sitePackageJson); + if (dependencies.length !== 0) { + await execa('npm', ['i', ...dependencies, '--save', ...npmInstallFlags], { cwd: npmInstallPath }); + } + if (devDependencies.length !== 0) { + await execa('npm', ['i', ...devDependencies, '--save-dev', ...npmInstallFlags], { cwd: npmInstallPath }); + } + // We installed the function's dependencies in the project-level `package.json`, + // so there's no reason to keep the one copied over from the template. + fs.unlinkSync(functionPackageJson); + // Similarly, if the template has a `package-lock.json` file, we delete it. + try { + const functionPackageLock = path.join(functionPath, 'package-lock.json'); + fs.unlinkSync(functionPackageLock); + } + catch { + // no-op + } +}; +/** + * no --url flag specified, pick from a provided template + * @param {import('../base-command.js').default} command + * @param {import('commander').OptionValues} options + * @param {string} argumentName + * @param {string} functionsDir Absolute path of the functions directory + * @param {'edge' | 'serverless'} funcType + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'command' implicitly has an 'any' type. +const scaffoldFromTemplate = async function (command, options, argumentName, functionsDir, funcType) { + // pull the rest of the metadata from the template + const chosenTemplate = await pickTemplate(options, funcType); + if (chosenTemplate === 'url') { + const { chosenUrl } = await inquirer.prompt([ + { + name: 'chosenUrl', + message: 'URL to clone: ', + type: 'input', + validate: (/** @type {string} */ val) => Boolean(validateRepoURL(val)), + // make sure it is not undefined and is a valid filename. + // this has some nuance i have ignored, eg crossenv and i18n concerns + }, + ]); + options.url = chosenUrl.trim(); + try { + await downloadFromURL(command, options, argumentName, functionsDir); + } + catch { + return logAndThrowError(`$${NETLIFYDEVERR} Error downloading from URL: ${options.url}`); + } + } + else if (chosenTemplate === 'report') { + log(`${NETLIFYDEVLOG} Open in browser: https://github.com/netlify/cli/issues/new`); + } + else { + const { addons = [], lang, name: templateName, onComplete } = chosenTemplate; + const pathToTemplate = path.join(templatesDir, lang, templateName); + if (!fs.existsSync(pathToTemplate)) { + throw new Error(`There isn't a corresponding directory to the selected name. Template '${templateName}' is misconfigured`); + } + const name = await getNameFromArgs(argumentName, options, templateName); + log(`${NETLIFYDEVLOG} Creating function ${chalk.cyan.inverse(name)}`); + const functionPath = ensureFunctionPathIsOk(functionsDir, name); + const vars = { name }; + let functionPackageJson; + // These files will not be part of the log message because they'll likely + // be removed before the command finishes. + const omittedFromOutput = new Set(['.netlify-function-template.mjs', 'package.json', 'package-lock.json']); + const createdFiles = await copyTemplateDir(pathToTemplate, functionPath, vars); + createdFiles.forEach((filePath) => { + const filename = path.basename(filePath); + if (!omittedFromOutput.has(filename)) { + log(`${NETLIFYDEVLOG} ${chalk.greenBright('Created')} ${filePath}`); + } + fs.chmodSync(path.resolve(filePath), TEMPLATE_PERMISSIONS); + if (filePath.includes('package.json')) { + functionPackageJson = path.resolve(filePath); + } + }); + // delete function template file that was copied over by copydir + await unlink(path.join(functionPath, '.netlify-function-template.mjs')); + // npm install + if (functionPackageJson !== undefined) { + const spinner = createSpinner(`Installing dependencies for ${name}`, MOON_SPINNER).start(); + await installDeps({ functionPackageJson, functionPath, functionsDir }); + spinner.success(`Installed dependencies for ${name}`); + } + if (funcType === 'edge') { + await registerEFInToml(name, command.netlify); + } + await installAddons(command, addons, path.resolve(functionPath)); + await handleOnComplete({ command, onComplete }); + log(); + log(chalk.greenBright(`Function created!`)); + if (lang == 'rust') { + log(chalk.green(`Please note that Rust functions require setting the NETLIFY_EXPERIMENTAL_BUILD_RUST_SOURCE environment variable to 'true' on your project.`)); + } + } +}; +const TEMPLATE_PERMISSIONS = 0o777; +// @ts-expect-error TS(7031) FIXME: Binding element 'addonName' implicitly has an 'any... Remove this comment to see the full error message +const createFunctionAddon = async function ({ addonName, addons, api, siteData, siteId }) { + try { + const addon = getCurrentAddon({ addons, addonName }); + if (addon && addon.id) { + log(`The "${addonName} add-on" already exists for ${siteData.name}`); + return false; + } + await api.createServiceInstance({ + siteId, + addon: addonName, + body: { config: {} }, + }); + log(`Add-on "${addonName}" created for ${siteData.name}`); + return true; + } + catch (error_) { + return logAndThrowError(error_.message); + } +}; +/** + * + * @param {object} config + * @param {import('../base-command.js').default} config.command + * @param {(command: import('../base-command.js').default) => any} config.onComplete + */ +// @ts-expect-error TS(7031) FIXME: Binding element 'command' implicitly has an 'any' ... Remove this comment to see the full error message +const handleOnComplete = async ({ command, onComplete }) => { + const { config } = command.netlify; + if (onComplete) { + const env = await getDotEnvVariables({ + devConfig: { ...config.dev }, + env: command.netlify.cachedConfig.env, + site: command.netlify.site, + }); + injectEnvVariables(env); + await onComplete.call(command); + } +}; +/** + * + * @param {object} config + * @param {*} config.addonCreated + * @param {*} config.addonDidInstall + * @param {import('../base-command.js').default} config.command + * @param {string} config.fnPath + */ +// @ts-expect-error TS(7031) FIXME: Binding element 'addonCreated' implicitly has an '... Remove this comment to see the full error message +const handleAddonDidInstall = async ({ addonCreated, addonDidInstall, command, fnPath }) => { + const { config } = command.netlify; + if (!addonCreated || !addonDidInstall) { + return; + } + const { confirmPostInstall } = await inquirer.prompt([ + { + type: 'confirm', + name: 'confirmPostInstall', + message: `This template has an optional setup script that runs after addon install. This can be helpful for first time users to try out templates. Run the script?`, + default: false, + }, + ]); + if (!confirmPostInstall) { + return; + } + await injectEnvVariables({ + devConfig: { ...config.dev }, + env: command.netlify.cachedConfig.env, + site: command.netlify.site, + }); + addonDidInstall(fnPath); +}; +/** + * + * @param {import('../base-command.js').default} command + * @param {*} functionAddons + * @param {*} fnPath + * @returns + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'command' implicitly has an 'any' type. +const installAddons = async function (command, functionAddons, fnPath) { + if (functionAddons.length === 0) { + return; + } + const { api, site } = command.netlify; + const siteId = site.id; + if (!siteId) { + log('No project id found, please run inside a project directory or `netlify link`'); + return false; + } + log(`${NETLIFYDEVLOG} checking Netlify APIs...`); + const [siteData, siteAddons] = await Promise.all([getSiteData({ api, siteId }), getAddons({ api, siteId })]); + // @ts-expect-error TS(7031) FIXME: Binding element 'addonDidInstall' implicitly has a... Remove this comment to see the full error message + const arr = functionAddons.map(async ({ addonDidInstall, addonName }) => { + log(`${NETLIFYDEVLOG} installing addon: ${chalk.yellow.inverse(addonName)}`); + try { + const addonCreated = await createFunctionAddon({ + api, + addons: siteAddons, + siteId, + addonName, + siteData, + }); + await handleAddonDidInstall({ addonCreated, addonDidInstall, command, fnPath }); + } + catch (error_) { + return logAndThrowError(`${NETLIFYDEVERR} Error installing addon: ${error_}`); + } + }); + return Promise.all(arr); +}; +/** + * + * @param {string} funcName + * @param {import('../types.js').NetlifyOptions} options + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'funcName' implicitly has an 'any' type. +const registerEFInToml = async (funcName, options) => { + const { configFilePath, relConfigFilePath } = options; + if (!fs.existsSync(configFilePath)) { + log(`${NETLIFYDEVLOG} \`${relConfigFilePath}\` file does not exist yet. Creating it...`); + } + let { funcPath } = await inquirer.prompt([ + { + type: 'input', + name: 'funcPath', + message: `What route do you want your edge function to be invoked on?`, + default: '/test', + validate: (val) => Boolean(val), + // Make sure route isn't undefined and is valid + // Todo: add more validation? + }, + ]); + // Make sure path begins with a '/' + if (funcPath[0] !== '/') { + funcPath = `/${funcPath}`; + } + const functionRegister = `\n\n[[edge_functions]]\nfunction = "${funcName}"\npath = "${funcPath}"`; + try { + fs.promises.appendFile(configFilePath, functionRegister); + log(`${NETLIFYDEVLOG} Function '${funcName}' registered for route \`${funcPath}\`. To change, edit your \`${relConfigFilePath}\` file.`); + } + catch { + return logAndThrowError(`${NETLIFYDEVERR} Unable to register function. Please check your \`${relConfigFilePath}\` file.`); + } +}; +/** + * we used to allow for a --dir command, + * but have retired that to force every scaffolded function to be a directory + * @param {string} functionsDir + * @param {string} name + * @returns + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'functionsDir' implicitly has an 'any' t... Remove this comment to see the full error message +const ensureFunctionPathIsOk = function (functionsDir, name) { + const functionPath = path.join(functionsDir, name); + if (fs.existsSync(functionPath)) { + log(`${NETLIFYDEVLOG} Function ${functionPath} already exists, cancelling...`); + process.exit(1); + } + return functionPath; +}; +export const functionsCreate = async (name, options, command) => { + const functionType = await selectTypeOfFunc(); + const functionsDir = functionType === 'edge' ? await ensureEdgeFuncDirExists(command) : await ensureFunctionDirExists(command); + /* either download from URL or scaffold from template */ + const mainFunc = options.url ? downloadFromURL : scaffoldFromTemplate; + await mainFunc(command, options, name, functionsDir, functionType); +}; +//# sourceMappingURL=functions-create.js.map \ No newline at end of file diff --git a/dist/commands/functions/functions-create.js.map b/dist/commands/functions/functions-create.js.map new file mode 100644 index 00000000000..af96a4d0664 --- /dev/null +++ b/dist/commands/functions/functions-create.js.map @@ -0,0 +1 @@ +{"version":3,"file":"functions-create.js","sourceRoot":"","sources":["../../../src/commands/functions/functions-create.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/functions/functions-invoke.d.ts b/dist/commands/functions/functions-invoke.d.ts new file mode 100644 index 00000000000..50b68c39fe2 --- /dev/null +++ b/dist/commands/functions/functions-invoke.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const functionsInvoke: (nameArgument: string, options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=functions-invoke.d.ts.map \ No newline at end of file diff --git a/dist/commands/functions/functions-invoke.d.ts.map b/dist/commands/functions/functions-invoke.d.ts.map new file mode 100644 index 00000000000..ed4cda1c49c --- /dev/null +++ b/dist/commands/functions/functions-invoke.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"functions-invoke.d.ts","sourceRoot":"","sources":["../../../src/commands/functions/functions-invoke.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAMxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAwI5C,eAAO,MAAM,eAAe,GAAU,cAAc,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,uBA4FtG,CAAA"} \ No newline at end of file diff --git a/dist/commands/functions/functions-invoke.js b/dist/commands/functions/functions-invoke.js new file mode 100644 index 00000000000..010efd03689 --- /dev/null +++ b/dist/commands/functions/functions-invoke.js @@ -0,0 +1,210 @@ +import fs from 'fs'; +import { createRequire } from 'module'; +import path from 'path'; +import inquirer from 'inquirer'; +import fetch from 'node-fetch'; +import { NETLIFYDEVWARN, chalk, logAndThrowError, exit } from '../../utils/command-helpers.js'; +import { BACKGROUND, CLOCKWORK_USERAGENT, getFunctions } from '../../utils/functions/index.js'; +const require = createRequire(import.meta.url); +// https://docs.netlify.com/functions/trigger-on-events/ +const events = [ + 'deploy-building', + 'deploy-succeeded', + 'deploy-failed', + 'deploy-locked', + 'deploy-unlocked', + 'split-test-activated', + 'split-test-deactivated', + 'split-test-modified', + 'submission-created', + 'identity-validate', + 'identity-signup', + 'identity-login', +]; +const eventTriggeredFunctions = new Set([...events, ...events.map((name) => `${name}${BACKGROUND}`)]); +const DEFAULT_PORT = 8888; +// https://stackoverflow.com/questions/3710204/how-to-check-if-a-string-is-a-valid-json-string-in-javascript-without-using-try +// @ts-expect-error TS(7006) FIXME: Parameter 'jsonString' implicitly has an 'any' typ... Remove this comment to see the full error message +const tryParseJSON = function (jsonString) { + try { + const parsedValue = JSON.parse(jsonString); + // Handle non-exception-throwing cases: + // Neither JSON.parse(false) or JSON.parse(1234) throw errors, hence the type-checking, + // but... JSON.parse(null) returns null, and typeof null === "object", + // so we must check for that, too. Thankfully, null is falsey, so this suffices: + if (parsedValue && typeof parsedValue === 'object') { + return parsedValue; + } + } + catch { } + return false; +}; +// @ts-expect-error TS(7006) FIXME: Parameter 'querystring' implicitly has an 'any' ty... Remove this comment to see the full error message +const formatQstring = function (querystring) { + if (querystring) { + return `?${querystring}`; + } + return ''; +}; +/** + * process payloads from flag + * @param {string} payloadString + * @param {string} workingDir + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'payloadString' implicitly has an 'any' ... Remove this comment to see the full error message +const processPayloadFromFlag = function (payloadString, workingDir) { + if (payloadString) { + // case 1: jsonstring + let payload = tryParseJSON(payloadString); + if (payload) + return payload; + // case 2: jsonpath + const payloadpath = path.join(workingDir, payloadString); + const pathexists = fs.existsSync(payloadpath); + if (pathexists) { + try { + // there is code execution potential here + payload = require(payloadpath); + return payload; + } + catch (error_) { + console.error(error_); + } + } + // case 3: invalid string, invalid path + return false; + } +}; +/** + * prompt for a name if name not supplied + * also used in functions:create + * @param {*} functions + * @param {import('commander').OptionValues} options + * @param {string} [argumentName] The name that might be provided as argument (optional argument) + * @returns {Promise} + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'functions' implicitly has an 'any' type... Remove this comment to see the full error message +const getNameFromArgs = async function (functions, options, argumentName) { + const functionToTrigger = getFunctionToTrigger(options, argumentName); + // @ts-expect-error TS(7031) FIXME: Binding element 'name' implicitly has an 'any' typ... Remove this comment to see the full error message + const functionNames = functions.map(({ name }) => name); + if (functionToTrigger) { + if (functionNames.includes(functionToTrigger)) { + return functionToTrigger; + } + console.warn(`Function name ${chalk.yellow(functionToTrigger)} supplied but no matching function found in your functions folder, forcing you to pick a valid one...`); + } + const { trigger } = await inquirer.prompt([ + { + type: 'list', + message: 'Pick a function to trigger', + name: 'trigger', + choices: functionNames, + }, + ]); + return trigger; +}; +/** + * get the function name out of the argument or options + * @param {import('commander').OptionValues} options + * @param {string} [argumentName] The name that might be provided as argument (optional argument) + * @returns {string} + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. +const getFunctionToTrigger = function (options, argumentName) { + if (options.name) { + if (argumentName) { + console.error('function name specified in both flag and arg format, pick one'); + exit(1); + } + return options.name; + } + return argumentName; +}; +export const functionsInvoke = async (nameArgument, options, command) => { + const { config, relConfigFilePath } = command.netlify; + const functionsDir = options.functions || config.dev?.functions || config.functionsDirectory; + if (typeof functionsDir === 'undefined') { + return logAndThrowError(`Functions directory is undefined, did you forget to set it in ${relConfigFilePath}?`); + } + if (!options.port) + console.warn(`${NETLIFYDEVWARN} "port" flag was not specified. Attempting to connect to localhost:8888 by default`); + const port = options.port || DEFAULT_PORT; + const functions = await getFunctions(functionsDir, config); + const functionToTrigger = await getNameFromArgs(functions, options, nameArgument); + const functionObj = functions.find((func) => func.name === functionToTrigger); + let headers = {}; + let body = {}; + // @ts-expect-error TS(2532) FIXME: Object is possibly 'undefined'. + if (functionObj.schedule) { + headers = { + 'user-agent': CLOCKWORK_USERAGENT, + }; + } + else if (eventTriggeredFunctions.has(functionToTrigger)) { + /** handle event triggered fns */ + // https://docs.netlify.com/functions/trigger-on-events/ + const [name, event] = functionToTrigger.split('-'); + if (name === 'identity') { + // https://docs.netlify.com/functions/functions-and-identity/#trigger-functions-on-identity-events + // @ts-expect-error TS(2339) FIXME: Property 'event' does not exist on type '{}'. + body.event = event; + // @ts-expect-error TS(2339) FIXME: Property 'user' does not exist on type '{}'. + body.user = { + id: '1111a1a1-a11a-1111-aa11-aaa11111a11a', + aud: '', + role: '', + email: 'foo@trust-this-company.com', + app_metadata: { + provider: 'email', + }, + user_metadata: { + full_name: 'Test Person', + }, + created_at: new Date(Date.now()).toISOString(), + update_at: new Date(Date.now()).toISOString(), + }; + } + else { + // non identity functions seem to have a different shape + // https://docs.netlify.com/functions/trigger-on-events/#payload + // @ts-expect-error TS(2339) FIXME: Property 'payload' does not exist on type '{}'. + body.payload = { + TODO: 'mock up payload data better', + }; + // @ts-expect-error TS(2339) FIXME: Property 'site' does not exist on type '{}'. + body.site = { + TODO: 'mock up site data better', + }; + } + } + else { + // NOT an event triggered function, but may still want to simulate authentication locally + const isAuthenticated = Boolean(options.identity); + if (isAuthenticated) { + headers = { + authorization: 'Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb3VyY2UiOiJuZXRsaWZ5IGZ1bmN0aW9uczp0cmlnZ2VyIiwidGVzdERhdGEiOiJORVRMSUZZX0RFVl9MT0NBTExZX0VNVUxBVEVEX0pXVCJ9.Xb6vOFrfLUZmyUkXBbCvU4bM7q8tPilF0F03Wupap_c', + }; + // you can decode this https://jwt.io/ + // { + // "source": "netlify functions:trigger", + // "testData": "NETLIFY_DEV_LOCALLY_EMULATED_JWT" + // } + } + } + const payload = processPayloadFromFlag(options.payload, command.workingDir); + body = { ...body, ...payload }; + try { + const response = await fetch(`http://localhost:${port}/.netlify/functions/${functionToTrigger}${formatQstring(options.querystring)}`, { + method: 'post', + headers, + body: JSON.stringify(body), + }); + const data = await response.text(); + console.log(data); + } + catch (error_) { + return logAndThrowError(`Ran into an error invoking your function: ${error_.message}`); + } +}; +//# sourceMappingURL=functions-invoke.js.map \ No newline at end of file diff --git a/dist/commands/functions/functions-invoke.js.map b/dist/commands/functions/functions-invoke.js.map new file mode 100644 index 00000000000..d3aeca22557 --- /dev/null +++ b/dist/commands/functions/functions-invoke.js.map @@ -0,0 +1 @@ +{"version":3,"file":"functions-invoke.js","sourceRoot":"","sources":["../../../src/commands/functions/functions-invoke.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/functions/functions-list.d.ts b/dist/commands/functions/functions-list.d.ts new file mode 100644 index 00000000000..8331ccb51ce --- /dev/null +++ b/dist/commands/functions/functions-list.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const functionsList: (options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=functions-list.d.ts.map \ No newline at end of file diff --git a/dist/commands/functions/functions-list.d.ts.map b/dist/commands/functions/functions-list.d.ts.map new file mode 100644 index 00000000000..e549ebdbcff --- /dev/null +++ b/dist/commands/functions/functions-list.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"functions-list.d.ts","sourceRoot":"","sources":["../../../src/commands/functions/functions-list.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAIxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAoB5C,eAAO,MAAM,aAAa,GAAU,SAAS,YAAY,EAAE,SAAS,WAAW,uBAoC9E,CAAA"} \ No newline at end of file diff --git a/dist/commands/functions/functions-list.js b/dist/commands/functions/functions-list.js new file mode 100644 index 00000000000..7be1f015e34 --- /dev/null +++ b/dist/commands/functions/functions-list.js @@ -0,0 +1,38 @@ +import AsciiTable from 'ascii-table'; +import { exit, log, logJson } from '../../utils/command-helpers.js'; +import { getFunctions, getFunctionsDir } from '../../utils/functions/index.js'; +const normalizeFunction = function (deployedFunctions, { name, urlPath: url, }) { + const isDeployed = deployedFunctions.some((deployedFunction) => deployedFunction.n === name); + return { name, url, isDeployed }; +}; +export const functionsList = async (options, command) => { + const { config, relConfigFilePath, siteInfo } = command.netlify; + // @ts-expect-error FIXME(serhalp): Investigate. This is either dead code or a type error in the API client package. + const deployedFunctions = siteInfo.published_deploy?.available_functions ?? []; + const functionsDir = getFunctionsDir({ options, config }); + if (typeof functionsDir === 'undefined') { + log('Functions directory is undefined'); + log(`Please verify that 'functions.directory' is set in your Netlify configuration file ${relConfigFilePath}`); + log('Refer to https://ntl.fyi/file-based-build-config for more information'); + return exit(1); + } + const functions = await getFunctions(functionsDir); + const normalizedFunctions = functions.map(normalizeFunction.bind(null, deployedFunctions)); + if (normalizedFunctions.length === 0) { + log(`No functions found in ${functionsDir}`); + return exit(); + } + if (options.json) { + logJson(normalizedFunctions); + return exit(); + } + // Make table + log(`Based on local functions folder ${functionsDir}, these are the functions detected`); + const table = new AsciiTable(`Netlify Functions (in local functions folder)`); + table.setHeading('Name', 'URL', 'deployed'); + normalizedFunctions.forEach(({ isDeployed, name, url }) => { + table.addRow(name, url, isDeployed ? 'yes' : 'no'); + }); + log(table.toString()); +}; +//# sourceMappingURL=functions-list.js.map \ No newline at end of file diff --git a/dist/commands/functions/functions-list.js.map b/dist/commands/functions/functions-list.js.map new file mode 100644 index 00000000000..b87a095fe60 --- /dev/null +++ b/dist/commands/functions/functions-list.js.map @@ -0,0 +1 @@ +{"version":3,"file":"functions-list.js","sourceRoot":"","sources":["../../../src/commands/functions/functions-list.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,aAAa,CAAA;AAGpC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,OAAO,EAAE,MAAM,gCAAgC,CAAA;AACnE,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAO9E,MAAM,iBAAiB,GAAG,UACxB,iBAAqC,EACrC,EACE,IAAI,EACJ,OAAO,EAAE,GAAG,GAIb;IAED,MAAM,UAAU,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAC,gBAAgB,EAAE,EAAE,CAAC,gBAAgB,CAAC,CAAC,KAAK,IAAI,CAAC,CAAA;IAC5F,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,UAAU,EAAE,CAAA;AAClC,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IACjF,MAAM,EAAE,MAAM,EAAE,iBAAiB,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IAE/D,oHAAoH;IACpH,MAAM,iBAAiB,GAAI,QAAQ,CAAC,gBAAgB,EAAE,mBAAsD,IAAI,EAAE,CAAA;IAElH,MAAM,YAAY,GAAG,eAAe,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAA;IAEzD,IAAI,OAAO,YAAY,KAAK,WAAW,EAAE,CAAC;QACxC,GAAG,CAAC,kCAAkC,CAAC,CAAA;QACvC,GAAG,CAAC,sFAAsF,iBAAiB,EAAE,CAAC,CAAA;QAC9G,GAAG,CAAC,uEAAuE,CAAC,CAAA;QAC5E,OAAO,IAAI,CAAC,CAAC,CAAC,CAAA;IAChB,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,YAAY,CAAC,YAAY,CAAC,CAAA;IAClD,MAAM,mBAAmB,GAAG,SAAS,CAAC,GAAG,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,iBAAiB,CAAC,CAAC,CAAA;IAE1F,IAAI,mBAAmB,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrC,GAAG,CAAC,yBAAyB,YAAY,EAAE,CAAC,CAAA;QAC5C,OAAO,IAAI,EAAE,CAAA;IACf,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,CAAC,mBAAmB,CAAC,CAAA;QAC5B,OAAO,IAAI,EAAE,CAAA;IACf,CAAC;IAED,aAAa;IACb,GAAG,CAAC,mCAAmC,YAAY,oCAAoC,CAAC,CAAA;IACxF,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,+CAA+C,CAAC,CAAA;IAC7E,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,UAAU,CAAC,CAAA;IAC3C,mBAAmB,CAAC,OAAO,CAAC,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,GAAG,EAAE,EAAE,EAAE;QACxD,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE,UAAU,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IACF,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAA;AACvB,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/functions/functions-serve.d.ts b/dist/commands/functions/functions-serve.d.ts new file mode 100644 index 00000000000..9094f4e252e --- /dev/null +++ b/dist/commands/functions/functions-serve.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const functionsServe: (options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=functions-serve.d.ts.map \ No newline at end of file diff --git a/dist/commands/functions/functions-serve.d.ts.map b/dist/commands/functions/functions-serve.d.ts.map new file mode 100644 index 00000000000..94b660fb86f --- /dev/null +++ b/dist/commands/functions/functions-serve.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"functions-serve.d.ts","sourceRoot":"","sources":["../../../src/commands/functions/functions-serve.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAcxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAK5C,eAAO,MAAM,cAAc,GAAU,SAAS,YAAY,EAAE,SAAS,WAAW,kBAkD/E,CAAA"} \ No newline at end of file diff --git a/dist/commands/functions/functions-serve.js b/dist/commands/functions/functions-serve.js new file mode 100644 index 00000000000..d98cb43d02d --- /dev/null +++ b/dist/commands/functions/functions-serve.js @@ -0,0 +1,53 @@ +import { join } from 'path'; +import { getBlobsContextWithEdgeAccess } from '../../lib/blobs/blobs.js'; +import { startFunctionsServer } from '../../lib/functions/server.js'; +import { printBanner } from '../../utils/dev-server-banner.js'; +import { UNLINKED_SITE_MOCK_ID, acquirePort, getDotEnvVariables, getSiteInformation, injectEnvVariables, } from '../../utils/dev.js'; +import { getFunctionsDir } from '../../utils/functions/index.js'; +import { getProxyUrl } from '../../utils/proxy.js'; +const DEFAULT_PORT = 9999; +// FIXME(serhalp): Replace `OptionValues` with more specific type. This is full of implicit `any`s. +export const functionsServe = async (options, command) => { + const { api, config, site, siteInfo, state } = command.netlify; + const functionsDir = getFunctionsDir({ options, config }, join('netlify', 'functions')); + let { env } = command.netlify.cachedConfig; + env.NETLIFY_DEV = { sources: ['internal'], value: 'true' }; + env = await getDotEnvVariables({ devConfig: { ...config.dev }, env, site }); + injectEnvVariables(env); + const { accountId, capabilities, siteUrl, timeouts } = await getSiteInformation({ + offline: options.offline, + api, + site, + siteInfo, + }); + const functionsPort = await acquirePort({ + configuredPort: options.port || config.dev?.functionsPort, + defaultPort: DEFAULT_PORT, + errorMessage: 'Could not acquire configured functions port', + }); + const blobsContext = await getBlobsContextWithEdgeAccess({ + debug: options.debug, + projectRoot: command.workingDir, + siteID: site.id ?? UNLINKED_SITE_MOCK_ID, + }); + await startFunctionsServer({ + blobsContext, + config, + debug: options.debug, + command, + settings: { functions: functionsDir, functionsPort }, + site, + siteInfo, + siteUrl, + capabilities, + timeouts, + geolocationMode: options.geo, + geoCountry: options.country, + offline: options.offline, + state, + accountId, + }); + const url = getProxyUrl({ port: functionsPort }); + printBanner({ url }); +}; +//# sourceMappingURL=functions-serve.js.map \ No newline at end of file diff --git a/dist/commands/functions/functions-serve.js.map b/dist/commands/functions/functions-serve.js.map new file mode 100644 index 00000000000..5146341b5ef --- /dev/null +++ b/dist/commands/functions/functions-serve.js.map @@ -0,0 +1 @@ +{"version":3,"file":"functions-serve.js","sourceRoot":"","sources":["../../../src/commands/functions/functions-serve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAI3B,OAAO,EAAE,6BAA6B,EAAE,MAAM,0BAA0B,CAAA;AACxE,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AAC9D,OAAO,EACL,qBAAqB,EACrB,WAAW,EACX,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,eAAe,EAAE,MAAM,gCAAgC,CAAA;AAChE,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAGlD,MAAM,YAAY,GAAG,IAAI,CAAA;AAEzB,mGAAmG;AACnG,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IAClF,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IAE9D,MAAM,YAAY,GAAG,eAAe,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,CAAA;IACvF,IAAI,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,YAAY,CAAA;IAE1C,GAAG,CAAC,WAAW,GAAG,EAAE,OAAO,EAAE,CAAC,UAAU,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAA;IAE1D,GAAG,GAAG,MAAM,kBAAkB,CAAC,EAAE,SAAS,EAAE,EAAE,GAAG,MAAM,CAAC,GAAG,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAA;IAC3E,kBAAkB,CAAC,GAAG,CAAC,CAAA;IAEvB,MAAM,EAAE,SAAS,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,kBAAkB,CAAC;QAC9E,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,GAAG;QACH,IAAI;QACJ,QAAQ;KACT,CAAC,CAAA;IAEF,MAAM,aAAa,GAAG,MAAM,WAAW,CAAC;QACtC,cAAc,EAAE,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,GAAG,EAAE,aAAa;QACzD,WAAW,EAAE,YAAY;QACzB,YAAY,EAAE,6CAA6C;KAC5D,CAAC,CAAA;IAEF,MAAM,YAAY,GAAG,MAAM,6BAA6B,CAAC;QACvD,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,WAAW,EAAE,OAAO,CAAC,UAAU;QAC/B,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,qBAAqB;KACzC,CAAC,CAAA;IAEF,MAAM,oBAAoB,CAAC;QACzB,YAAY;QACZ,MAAM;QACN,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,OAAO;QACP,QAAQ,EAAE,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE;QACpD,IAAI;QACJ,QAAQ;QACR,OAAO;QACP,YAAY;QACZ,QAAQ;QACR,eAAe,EAAE,OAAO,CAAC,GAAG;QAC5B,UAAU,EAAE,OAAO,CAAC,OAAO;QAC3B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,KAAK;QACL,SAAS;KACV,CAAC,CAAA;IAEF,MAAM,GAAG,GAAG,WAAW,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,CAAC,CAAA;IAChD,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;AACtB,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/functions/functions.d.ts b/dist/commands/functions/functions.d.ts new file mode 100644 index 00000000000..da32cdd5b38 --- /dev/null +++ b/dist/commands/functions/functions.d.ts @@ -0,0 +1,3 @@ +import type BaseCommand from '../base-command.js'; +export declare const createFunctionsCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=functions.d.ts.map \ No newline at end of file diff --git a/dist/commands/functions/functions.d.ts.map b/dist/commands/functions/functions.d.ts.map new file mode 100644 index 00000000000..18b503c4fdf --- /dev/null +++ b/dist/commands/functions/functions.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../../../src/commands/functions/functions.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAMjD,eAAO,MAAM,sBAAsB,GAAI,SAAS,WAAW,gBAsH1D,CAAA"} \ No newline at end of file diff --git a/dist/commands/functions/functions.js b/dist/commands/functions/functions.js new file mode 100644 index 00000000000..110b82c2d28 --- /dev/null +++ b/dist/commands/functions/functions.js @@ -0,0 +1,108 @@ +import terminalLink from 'terminal-link'; +import { chalk } from '../../utils/command-helpers.js'; +import requiresSiteInfo from '../../utils/hooks/requires-site-info.js'; +const functions = (_options, command) => { + command.help(); +}; +export const createFunctionsCommand = (program) => { + program + .command('functions:build') + .alias('function:build') + .description('Build functions locally') + .option('-f, --functions ', 'Specify a functions directory to build to') + .option('-s, --src ', 'Specify the source directory for the functions') + .action(async (options, command) => { + const { functionsBuild } = await import('./functions-build.js'); + await functionsBuild(options, command); + }); + program + .command('functions:create') + .alias('function:create') + .argument('[name]', 'name of your new function file inside your functions directory') + .description('Create a new function locally') + .option('-n, --name ', 'function name') + .option('-u, --url ', 'pull template from URL') + .option('-l, --language ', 'function language') + .option('-o, --offline', 'Disables any features that require network access') + .addExamples([ + 'netlify functions:create', + 'netlify functions:create hello-world', + 'netlify functions:create --name hello-world', + ]) + .action(async (name, options, command) => { + const { functionsCreate } = await import('./functions-create.js'); + await functionsCreate(name, options, command); + }); + program + .command('functions:invoke') + .alias('function:trigger') + .argument('[name]', 'function name to invoke') + .description(`Trigger a function while in netlify dev with simulated data, good for testing function calls including Netlify's Event Triggered Functions`) + .option('-n, --name ', 'function name to invoke') + .option('-f, --functions ', 'Specify a functions folder to parse, overriding netlify.toml') + .option('-q, --querystring ', 'Querystring to add to your function invocation') + .option('-p, --payload ', 'Supply POST payload in stringified json, or a path to a json file') + // TODO: refactor to not need the `undefined` state by removing the --identity flag (value `identity` will be then always defined to true or false) + .option('--identity', 'simulate Netlify Identity authentication JWT. pass --identity to affirm unauthenticated request') + .option('--no-identity', 'simulate Netlify Identity authentication JWT. pass --no-identity to affirm unauthenticated request') + .option('--port ', 'Port where netlify dev is accessible. e.g. 8888', (value) => Number.parseInt(value)) + .option('-o, --offline', 'Disables any features that require network access') + .addExamples([ + 'netlify functions:invoke', + 'netlify functions:invoke myfunction', + 'netlify functions:invoke --name myfunction', + 'netlify functions:invoke --name myfunction --identity', + 'netlify functions:invoke --name myfunction --no-identity', + `netlify functions:invoke myfunction --payload '{"foo": 1}'`, + 'netlify functions:invoke myfunction --querystring "foo=1', + 'netlify functions:invoke myfunction --payload "./pathTo.json"', + ]) + .action(async (name, options, command) => { + const { functionsInvoke } = await import('./functions-invoke.js'); + await functionsInvoke(name, options, command); + }); + program + .command('functions:list') + .alias('function:list') + .description(`List functions that exist locally +Helpful for making sure that you have formatted your functions correctly + +NOT the same as listing the functions that have been deployed. For that info you need to go to your Netlify deploy log.`) + .option('-f, --functions ', 'Specify a functions directory to list') + .option('--json', 'Output function data as JSON') + .hook('preAction', requiresSiteInfo) + .action(async (options, command) => { + const { functionsList } = await import('./functions-list.js'); + await functionsList(options, command); + }); + program + .command('functions:serve') + .alias('function:serve') + .description('Serve functions locally') + .option('-f, --functions ', 'Specify a functions directory to serve') + .option('-p, --port ', 'Specify a port for the functions server', (value) => Number.parseInt(value)) + .option('-o, --offline', 'Disables any features that require network access') + .addHelpText('after', 'Helpful for debugging functions.') + .action(async (options, command) => { + const { functionsServe } = await import('./functions-serve.js'); + await functionsServe(options, command); + }); + const name = chalk.greenBright('`functions`'); + return program + .command('functions') + .alias('function') + .description(`Manage netlify functions +The ${name} command will help you manage the functions in this project`) + .addExamples([ + 'netlify functions:create --name function-xyz', + 'netlify functions:build --functions build/to/directory --src source/directory', + ]) + .addHelpText('afterAll', () => { + const docsUrl = 'https://docs.netlify.com/functions/overview/'; + return ` +For more information about Netlify Functions, see ${terminalLink(docsUrl, docsUrl, { fallback: false })} +`; + }) + .action(functions); +}; +//# sourceMappingURL=functions.js.map \ No newline at end of file diff --git a/dist/commands/functions/functions.js.map b/dist/commands/functions/functions.js.map new file mode 100644 index 00000000000..9799cc2b9b3 --- /dev/null +++ b/dist/commands/functions/functions.js.map @@ -0,0 +1 @@ +{"version":3,"file":"functions.js","sourceRoot":"","sources":["../../../src/commands/functions/functions.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/functions/index.d.ts b/dist/commands/functions/index.d.ts new file mode 100644 index 00000000000..6895723d77a --- /dev/null +++ b/dist/commands/functions/index.d.ts @@ -0,0 +1,2 @@ +export { createFunctionsCommand } from './functions.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/functions/index.d.ts.map b/dist/commands/functions/index.d.ts.map new file mode 100644 index 00000000000..6dba173c199 --- /dev/null +++ b/dist/commands/functions/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/functions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA"} \ No newline at end of file diff --git a/dist/commands/functions/index.js b/dist/commands/functions/index.js new file mode 100644 index 00000000000..067a5e0d7c0 --- /dev/null +++ b/dist/commands/functions/index.js @@ -0,0 +1,2 @@ +export { createFunctionsCommand } from './functions.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/functions/index.js.map b/dist/commands/functions/index.js.map new file mode 100644 index 00000000000..4bc8ca77451 --- /dev/null +++ b/dist/commands/functions/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/functions/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,gBAAgB,CAAA"} \ No newline at end of file diff --git a/dist/commands/index.d.ts b/dist/commands/index.d.ts new file mode 100644 index 00000000000..bc3bfa394be --- /dev/null +++ b/dist/commands/index.d.ts @@ -0,0 +1,3 @@ +export { default as BaseCommand } from './base-command.js'; +export { createMainCommand } from './main.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/index.d.ts.map b/dist/commands/index.d.ts.map new file mode 100644 index 00000000000..4d71b49c150 --- /dev/null +++ b/dist/commands/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA"} \ No newline at end of file diff --git a/dist/commands/index.js b/dist/commands/index.js new file mode 100644 index 00000000000..e3f46a0d834 --- /dev/null +++ b/dist/commands/index.js @@ -0,0 +1,3 @@ +export { default as BaseCommand } from './base-command.js'; +export { createMainCommand } from './main.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/index.js.map b/dist/commands/index.js.map new file mode 100644 index 00000000000..342d9801f43 --- /dev/null +++ b/dist/commands/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/commands/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC1D,OAAO,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAA"} \ No newline at end of file diff --git a/dist/commands/init/ai-rules.d.ts b/dist/commands/init/ai-rules.d.ts new file mode 100644 index 00000000000..e80fa7b0463 --- /dev/null +++ b/dist/commands/init/ai-rules.d.ts @@ -0,0 +1,7 @@ +import type BaseCommand from '../base-command.js'; +/** + * Handles AI rules initialization workflow + * This is the experimental --ai-rules functionality for the init command + */ +export declare const initWithAiRules: (hash: string, command: BaseCommand) => Promise; +//# sourceMappingURL=ai-rules.d.ts.map \ No newline at end of file diff --git a/dist/commands/init/ai-rules.d.ts.map b/dist/commands/init/ai-rules.d.ts.map new file mode 100644 index 00000000000..3bb0ff1dd40 --- /dev/null +++ b/dist/commands/init/ai-rules.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"ai-rules.d.ts","sourceRoot":"","sources":["../../../src/commands/init/ai-rules.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAyHjD;;;GAGG;AACH,eAAO,MAAM,eAAe,GAAU,MAAM,MAAM,EAAE,SAAS,WAAW,KAAG,OAAO,CAAC,IAAI,CAuGtF,CAAA"} \ No newline at end of file diff --git a/dist/commands/init/ai-rules.js b/dist/commands/init/ai-rules.js new file mode 100644 index 00000000000..15d7f0f9df3 --- /dev/null +++ b/dist/commands/init/ai-rules.js @@ -0,0 +1,200 @@ +import { resolve } from 'node:path'; +import { promises as fs } from 'node:fs'; +import { chalk, log, logAndThrowError } from '../../utils/command-helpers.js'; +import { normalizeRepoUrl } from '../../utils/normalize-repo-url.js'; +import { runGit } from '../../utils/run-git.js'; +import { startSpinner } from '../../lib/spinner.js'; +import { detectIDE } from '../../recipes/ai-context/index.js'; +import { generateMcpConfig, configureMcpForVSCode, configureMcpForCursor, configureMcpForWindsurf, showGenericMcpConfig } from '../../utils/mcp-utils.js'; +import inquirer from 'inquirer'; +// Trigger IDE-specific MCP configuration +const triggerMcpConfiguration = async (ide, projectPath) => { + log(`\n${chalk.blue('šŸ”§ MCP Configuration for')} ${chalk.cyan(ide.presentedName)}`); + const { shouldConfigure } = await inquirer.prompt([ + { + type: 'confirm', + name: 'shouldConfigure', + message: `Would you like to automatically configure the MCP server for ${ide.presentedName}?`, + default: true, + }, + ]); + if (!shouldConfigure) { + log(chalk.gray('Skipped MCP configuration. You can set it up manually later by changing MCP settings in your editor')); + return false; + } + try { + const config = generateMcpConfig(ide); + // IDE-specific configuration actions + switch (ide.key) { + case 'vscode': + await configureMcpForVSCode(config, projectPath); + break; + case 'cursor': + await configureMcpForCursor(config, projectPath); + break; + case 'windsurf': + await configureMcpForWindsurf(config, projectPath); + break; + default: + showGenericMcpConfig(config, ide.presentedName); + } + log(`${chalk.green('āœ…')} MCP configuration completed for ${chalk.cyan(ide.presentedName)}`); + return true; + } + catch (error) { + log(`${chalk.red('āŒ')} Failed to configure MCP: ${error instanceof Error ? error.message : 'Unknown error'}`); + return false; + } +}; +// Helper functions reused from ai-start.ts +const decodeHash = (hash) => { + try { + return atob(hash); + } + catch (error) { + throw new Error(`Failed to decode hash: ${error instanceof Error ? error.message : 'Invalid base64 or URL'}`); + } +}; +const fetchProjectInfo = async (url) => { + try { + const response = await fetch(url, { + headers: { + 'content-type': 'text/plain', + }, + }); + const data = (await response.text()); + const parsedData = JSON.parse(data); + return parsedData; + } + catch (error) { + throw new Error(`Failed to fetch project information: ${error instanceof Error ? error.message : 'Unknown error'}`); + } +}; +const getRepoUrlFromProjectId = async (api, projectId) => { + try { + const siteInfo = (await api.getSite({ siteId: projectId })); + const repoUrl = siteInfo.build_settings?.repo_url; + if (!repoUrl) { + throw new Error(`No repository URL found for project ID: ${projectId}`); + } + return repoUrl; + } + catch (error) { + if (error.status === 404) { + throw new Error(`Project with ID ${projectId} not found`); + } + throw new Error(`Failed to fetch project data: ${error.message}`); + } +}; +const savePrompt = async (instructions, ntlContext, targetDir) => { + try { + const filePath = resolve(targetDir, 'AI-instructions.md'); + await fs.writeFile(filePath, `Context: ${ntlContext ?? ''}\n\n${instructions}`, 'utf-8'); + log(`${chalk.green('āœ…')} AI instructions saved to ${chalk.cyan('AI-instructions.md')}`); + } + catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unknown error'; + log(`${chalk.yellow('āš ļø')} Warning: Failed to save AI instructions: ${errorMessage}`); + } +}; +const cloneRepo = async (repoUrl, targetDir, debug) => { + try { + await runGit(['clone', repoUrl, targetDir], !debug); + } + catch (error) { + throw new Error(`Failed to clone repository: ${error instanceof Error ? error.message : error?.toString() ?? ''}`); + } +}; +/** + * Handles AI rules initialization workflow + * This is the experimental --ai-rules functionality for the init command + */ +export const initWithAiRules = async (hash, command) => { + // Authenticate first before any API operations + await command.authenticate(); + const { api } = command.netlify; + log(`${chalk.blue('šŸ¤– Initializing AI project')} with rules...`); + log(`${chalk.gray('User:')} ${api.accessToken ? 'Authenticated āœ…' : 'Not authenticated āŒ'}`); + try { + // Step 1: Decode hash and fetch project information + log('\nšŸ“‹ Extracting project details...'); + const decodedUrl = decodeHash(hash); + log(`${chalk.cyan('Decoded URL:')} ${decodedUrl}`); + log('\nšŸ” Fetching project information...'); + const projectInfo = await fetchProjectInfo(decodedUrl); + log(`${chalk.cyan('Project ID:')} ${projectInfo.projectId}`); + // Step 2: Get repository URL from project ID via Netlify site API + log('\nšŸ”— Linking to Netlify project and fetching repository...'); + const repositoryUrl = await getRepoUrlFromProjectId(api, projectInfo.projectId); + log(`${chalk.cyan('Repository:')} ${repositoryUrl}`); + // Step 3: Clone repository + const { repoUrl, repoName } = normalizeRepoUrl(repositoryUrl); + const targetDir = `ai-project-${repoName}-${hash.substring(0, 8)}`; + const cloneSpinner = startSpinner({ text: `Cloning repository to ${chalk.cyan(targetDir)}` }); + await cloneRepo(repoUrl, targetDir, false); + cloneSpinner.success({ text: `Cloned repository to ${chalk.cyan(targetDir)}` }); + // Step 4: Save AI instructions to file + if (projectInfo.prompt) { + const ntlContext = await fetch('https://docs.netlify.com/ai-context/scoped-context?scopes=serverless,blobs,forms', { + method: 'GET', + headers: { + 'Content-Type': 'text/plain', + }, + }) + .then((res) => res.text()) + .catch(() => { + return null; + }); + log('\nšŸ“ Saving AI instructions...'); + await savePrompt(projectInfo.prompt, ntlContext, targetDir); + } + // Step 5: Detect IDE and configure MCP server + log('\nšŸ” Detecting development environment...'); + const detectedIDE = await detectIDE(); + let mcpConfigured = false; + if (detectedIDE) { + log(`${chalk.green('āœ…')} Detected development environment: ${chalk.cyan(detectedIDE.presentedName)}`); + mcpConfigured = await triggerMcpConfiguration(detectedIDE, targetDir); + } + // Update working directory to cloned repo + process.chdir(targetDir); + command.workingDir = targetDir; + // Success message with next steps + log(); + log(chalk.green('āœ” Your AI project is ready to go!')); + log(`→ Project ID: ${chalk.cyanBright(projectInfo.projectId)}`); + log(`→ Project cloned to: ${chalk.cyanBright(targetDir)}`); + if (projectInfo.prompt) { + log(`→ AI instructions saved: ${chalk.cyanBright('AI-instructions.md')}`); + } + log(); + log(chalk.yellowBright(`šŸ“ Step 1: Enter your project directory`)); + log(` ${chalk.cyanBright(`cd ${targetDir}`)}`); + if (detectedIDE) { + if (mcpConfigured) { + log(chalk.yellowBright(`šŸ”§ Step 2: MCP Server Configured`)); + log(` ${chalk.green('āœ…')} ${chalk.cyan(detectedIDE.key)} is ready with Netlify MCP server`); + log(` ${chalk.gray('šŸ’” MCP will activate when you reload/restart your development environment')}`); + } + else { + log(chalk.yellowBright(`šŸ”§ Step 2: Manual MCP Configuration`)); + log(` ${chalk.cyan(detectedIDE.key)} detected - MCP setup was skipped`); + log(` ${chalk.gray('You can configure MCP manually later for enhanced AI capabilities')}`); + } + log(); + } + if (projectInfo.prompt) { + const stepNumber = detectedIDE ? '3' : '2'; + log(chalk.yellowBright(`šŸ¤– Step ${stepNumber}: Ask your AI assistant to process the instructions`)); + log(); + log(chalk.gray('*'.repeat(60))); + log(chalk.cyan(`Follow ${targetDir}/AI-instructions.md and create a new site`)); + log(chalk.gray('*'.repeat(60))); + log(); + } + } + catch (error) { + return logAndThrowError(error); + } +}; +//# sourceMappingURL=ai-rules.js.map \ No newline at end of file diff --git a/dist/commands/init/ai-rules.js.map b/dist/commands/init/ai-rules.js.map new file mode 100644 index 00000000000..d3f137059ad --- /dev/null +++ b/dist/commands/init/ai-rules.js.map @@ -0,0 +1 @@ +{"version":3,"file":"ai-rules.js","sourceRoot":"","sources":["../../../src/commands/init/ai-rules.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/init/constants.d.ts b/dist/commands/init/constants.d.ts new file mode 100644 index 00000000000..896af9aa4e6 --- /dev/null +++ b/dist/commands/init/constants.d.ts @@ -0,0 +1,4 @@ +export declare const LINKED_NEW_SITE_EXIT_CODE = "LINKED_NEW_SITE"; +export declare const LINKED_EXISTING_SITE_EXIT_CODE = "LINKED_EXISTING_SITE"; +export type InitExitCode = typeof LINKED_NEW_SITE_EXIT_CODE | typeof LINKED_EXISTING_SITE_EXIT_CODE; +//# sourceMappingURL=constants.d.ts.map \ No newline at end of file diff --git a/dist/commands/init/constants.d.ts.map b/dist/commands/init/constants.d.ts.map new file mode 100644 index 00000000000..10018821e42 --- /dev/null +++ b/dist/commands/init/constants.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/commands/init/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,yBAAyB,oBAAoB,CAAA;AAE1D,eAAO,MAAM,8BAA8B,yBAAyB,CAAA;AAEpE,MAAM,MAAM,YAAY,GAAG,OAAO,yBAAyB,GAAG,OAAO,8BAA8B,CAAA"} \ No newline at end of file diff --git a/dist/commands/init/constants.js b/dist/commands/init/constants.js new file mode 100644 index 00000000000..5a3a6dbcde0 --- /dev/null +++ b/dist/commands/init/constants.js @@ -0,0 +1,3 @@ +export const LINKED_NEW_SITE_EXIT_CODE = 'LINKED_NEW_SITE'; +export const LINKED_EXISTING_SITE_EXIT_CODE = 'LINKED_EXISTING_SITE'; +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/dist/commands/init/constants.js.map b/dist/commands/init/constants.js.map new file mode 100644 index 00000000000..dcf550d01c7 --- /dev/null +++ b/dist/commands/init/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/commands/init/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,yBAAyB,GAAG,iBAAiB,CAAA;AAE1D,MAAM,CAAC,MAAM,8BAA8B,GAAG,sBAAsB,CAAA"} \ No newline at end of file diff --git a/dist/commands/init/index.d.ts b/dist/commands/init/index.d.ts new file mode 100644 index 00000000000..804ee38e6d2 --- /dev/null +++ b/dist/commands/init/index.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const createInitCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/init/index.d.ts.map b/dist/commands/init/index.d.ts.map new file mode 100644 index 00000000000..5cdf133d608 --- /dev/null +++ b/dist/commands/init/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/init/index.ts"],"names":[],"mappings":"AAGA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,iBAAiB,GAAI,SAAS,WAAW,gBA0BhD,CAAA"} \ No newline at end of file diff --git a/dist/commands/init/index.js b/dist/commands/init/index.js new file mode 100644 index 00000000000..4c0c6442a73 --- /dev/null +++ b/dist/commands/init/index.js @@ -0,0 +1,26 @@ +import { Option } from 'commander'; +import terminalLink from 'terminal-link'; +export const createInitCommand = (program) => program + .command('init') + .description('Configure continuous deployment for a new or existing project. To create a new project without continuous deployment, use `netlify sites:create`') + .option('-m, --manual', 'Manually configure a git remote for CI') + .option('--git-remote-name ', 'Name of Git remote to use. e.g. "origin"') + .addOption(new Option('--ai-rules ', 'Initialize with AI project configuration (experimental)').hideHelp()) + .addHelpText('after', () => { + const docsUrl = 'https://docs.netlify.com/cli/get-started/'; + return ` +For more information about getting started with Netlify CLI, see ${terminalLink(docsUrl, docsUrl, { fallback: false })} +`; +}) + .action(async (options, command) => { + // Check for experimental AI rules flag + if (options.aiRules) { + const { initWithAiRules } = await import('./ai-rules.js'); + await initWithAiRules(options.aiRules, command); + return; + } + // Standard init flow + const { init } = await import('./init.js'); + await init(options, command); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/init/index.js.map b/dist/commands/init/index.js.map new file mode 100644 index 00000000000..3e4fcb85982 --- /dev/null +++ b/dist/commands/init/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/init/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,MAAM,EAAE,MAAM,WAAW,CAAA;AAChD,OAAO,YAAY,MAAM,eAAe,CAAA;AAIxC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,OAAoB,EAAE,EAAE,CACxD,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CACV,kJAAkJ,CACnJ;KACA,MAAM,CAAC,cAAc,EAAE,wCAAwC,CAAC;KAChE,MAAM,CAAC,0BAA0B,EAAE,0CAA0C,CAAC;KAC9E,SAAS,CAAC,IAAI,MAAM,CAAC,mBAAmB,EAAE,yDAAyD,CAAC,CAAC,QAAQ,EAAE,CAAC;KAChH,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE;IACzB,MAAM,OAAO,GAAG,2CAA2C,CAAA;IAC3D,OAAO;mEACsD,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;CACrH,CAAA;AACG,CAAC,CAAC;KACD,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IAC5D,uCAAuC;IACvC,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACpB,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAA;QACzD,MAAM,eAAe,CAAC,OAAO,CAAC,OAAiB,EAAE,OAAO,CAAC,CAAA;QACzD,OAAM;IACR,CAAC;IAED,qBAAqB;IACrB,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAA;IAC1C,MAAM,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAC9B,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/init/init.d.ts b/dist/commands/init/init.d.ts new file mode 100644 index 00000000000..e55f1f9167e --- /dev/null +++ b/dist/commands/init/init.d.ts @@ -0,0 +1,12 @@ +import { OptionValues } from 'commander'; +import type BaseCommand from '../base-command.js'; +import type { SiteInfo } from '../../utils/types.js'; +import { type InitExitCode } from './constants.js'; +type InitExitMessageCustomizer = (code: InitExitCode, defaultMessage: string) => string | undefined; +type InitExtraOptions = { + customizeExitMessage?: InitExitMessageCustomizer | undefined; + exitAfterConfiguringRepo?: boolean | undefined; +}; +export declare const init: (options: OptionValues, command: BaseCommand, { customizeExitMessage, exitAfterConfiguringRepo }?: InitExtraOptions) => Promise; +export {}; +//# sourceMappingURL=init.d.ts.map \ No newline at end of file diff --git a/dist/commands/init/init.d.ts.map b/dist/commands/init/init.d.ts.map new file mode 100644 index 00000000000..78f9c142c7a --- /dev/null +++ b/dist/commands/init/init.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../../src/commands/init/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AASxC,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAGjD,OAAO,KAAK,EAAY,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAE9D,OAAO,EAAE,KAAK,YAAY,EAA6D,MAAM,gBAAgB,CAAA;AA8M7G,KAAK,yBAAyB,GAAG,CAAC,IAAI,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAA;AAEnG,KAAK,gBAAgB,GAAG;IACtB,oBAAoB,CAAC,EAAE,yBAAyB,GAAG,SAAS,CAAA;IAC5D,wBAAwB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;CAC/C,CAAA;AAED,eAAO,MAAM,IAAI,GACf,SAAS,YAAY,EACrB,SAAS,WAAW,EACpB,qDAA4D,gBAAqB,KAChF,OAAO,CAAC,QAAQ,CAoDlB,CAAA"} \ No newline at end of file diff --git a/dist/commands/init/init.js b/dist/commands/init/init.js new file mode 100644 index 00000000000..048ec94bd7b --- /dev/null +++ b/dist/commands/init/init.js @@ -0,0 +1,205 @@ +import inquirer from 'inquirer'; +import isEmpty from 'lodash/isEmpty.js'; +import { chalk, exit, log, netlifyCommand } from '../../utils/command-helpers.js'; +import getRepoData from '../../utils/get-repo-data.js'; +import { ensureNetlifyIgnore } from '../../utils/gitignore.js'; +import { configureRepo } from '../../utils/init/config.js'; +import { track } from '../../utils/telemetry/index.js'; +import { link } from '../link/link.js'; +import { sitesCreate } from '../sites/sites-create.js'; +import { getBuildSettings, saveNetlifyToml } from '../../utils/init/utils.js'; +import { LINKED_EXISTING_SITE_EXIT_CODE, LINKED_NEW_SITE_EXIT_CODE } from './constants.js'; +const persistState = ({ siteInfo, state }) => { + // Save to .netlify/state.json file + state.set('siteId', siteInfo.id); +}; +const getRepoUrl = (siteInfo) => siteInfo.build_settings?.repo_url ?? ''; +const logExistingAndExit = ({ siteInfo }) => { + log(); + log(`This project has been initialized`); + log(); + log(`Project Name: ${chalk.cyan(siteInfo.name)}`); + log(`Project Url: ${chalk.cyan(siteInfo.ssl_url || siteInfo.url)}`); + log(`Project Repo: ${chalk.cyan(getRepoUrl(siteInfo))}`); + log(`Project Id: ${chalk.cyan(siteInfo.id)}`); + log(`Admin URL: ${chalk.cyan(siteInfo.admin_url)}`); + log(); + log(`To disconnect this directory and create a new project (or link to another project ID)`); + log(`1. Run ${chalk.cyanBright.bold(`${netlifyCommand()} unlink`)}`); + log(`2. Then run ${chalk.cyanBright.bold(`${netlifyCommand()} init`)} again`); + return exit(); +}; +/** + * Creates and new site and exits the process + */ +const createNewSiteAndExit = async ({ command, state, disableLinking, customizeExitMessage, }) => { + const siteInfo = await sitesCreate({}, command); + log(`"${siteInfo.name}" project was created`); + log(); + persistState({ state, siteInfo }); + if (!disableLinking) { + const { shouldConfigureBuild } = await inquirer.prompt([ + { + type: 'confirm', + name: 'shouldConfigureBuild', + message: `Do you want to configure build settings? We'll suggest settings for your project automatically`, + }, + ]); + if (shouldConfigureBuild) { + const { cachedConfig: { configPath }, config, repositoryRoot, } = command.netlify; + const { baseDir, buildCmd, buildDir, functionsDir } = await getBuildSettings({ + config, + command, + }); + await saveNetlifyToml({ repositoryRoot, config, configPath, baseDir, buildCmd, buildDir, functionsDir }); + } + } + log(); + const defaultExitMesage = `To deploy to this project, run ${chalk.cyanBright.bold(`${netlifyCommand()} deploy`)}.`; + log(customizeExitMessage?.(LINKED_NEW_SITE_EXIT_CODE, defaultExitMesage) ?? defaultExitMesage); + return exit(); +}; +const logGitSetupInstructionsAndExit = () => { + log(); + log(`${chalk.bold('To initialize a new git repo follow the steps below.')} + +1. Initialize a new repo: + + ${chalk.cyanBright.bold('git init')} + +2. Add your files + + ${chalk.cyanBright.bold('git add .')} + +3. Commit your files + + ${chalk.cyanBright.bold("git commit -m 'initial commit'")} + +4. Create a new repo in GitHub ${chalk.cyanBright.bold('https://github.com/new')} + +5. Link the remote repo with this local directory + + ${chalk.cyanBright.bold('git remote add origin git@github.com:YourGithubName/your-repo-slug.git')} + +6. Push up your files + + ${chalk.cyanBright.bold('git push -u origin main')} + +7. Initialize your Netlify Site + + ${chalk.cyanBright.bold(`${netlifyCommand()} init`)} +`); + return exit(); +}; +/** + * Handles the case where no git remote was found. + */ +const handleNoGitRemoteAndExit = async ({ command, error, state, disableLinking, customizeExitMessage, }) => { + log(); + log(chalk.yellow('No git remote was found, would you like to set one up?')); + log(` +It is recommended that you initialize a project that has a remote repository in GitHub. + +This will allow for Netlify Continuous deployment to build branch & PR previews. + +For more details on Netlify CI check out the docs: http://bit.ly/2N0Jhy5 +`); + if (error === "Couldn't find origin url") { + log(`Unable to find a remote origin URL. Please add a git remote. + +git remote add origin https://github.com/YourUserName/RepoName.git +`); + } + const NEW_SITE_NO_GIT = 'Yes, create and deploy project manually'; + const NO_ABORT = 'No, I will connect this directory with GitHub first'; + const { noGitRemoteChoice } = await inquirer.prompt([ + { + type: 'list', + name: 'noGitRemoteChoice', + message: 'Do you want to create a Netlify project without a git repository?', + choices: [NEW_SITE_NO_GIT, NO_ABORT], + }, + ]); + if (noGitRemoteChoice === NEW_SITE_NO_GIT) { + // TODO(ndhoule): Shove a custom error message in here + return createNewSiteAndExit({ state, command, disableLinking, customizeExitMessage }); + } + return logGitSetupInstructionsAndExit(); +}; +/** + * Creates a new site or links an existing one to the repository + */ +const createOrLinkSiteToRepo = async (command) => { + const NEW_SITE = '+ Create & configure a new project'; + const EXISTING_SITE = '⇄ Connect this directory to an existing Netlify project'; + const initializeOpts = [EXISTING_SITE, NEW_SITE]; + // TODO(serhalp): inquirer should infer the choice type here, but doesn't. Fix. + const { initChoice } = await inquirer.prompt([ + { + type: 'list', + name: 'initChoice', + message: 'What would you like to do?', + choices: initializeOpts, + }, + ]); + // create site or search for one + if (initChoice === NEW_SITE) { + await track('sites_initStarted', { + type: 'new site', + }); + return await sitesCreate({}, command); + } + // run link command + return await link({}, command); +}; +const logExistingRepoSetupAndExit = ({ repoUrl, siteName, customizeExitMessage, }) => { + log(); + log(chalk.underline.bold(`Success`)); + const defaultExitMessage = `This project "${siteName}" is configured to automatically deploy via ${repoUrl}.`; + log(customizeExitMessage?.(LINKED_EXISTING_SITE_EXIT_CODE, defaultExitMessage) ?? defaultExitMessage); + // TODO add support for changing GitHub repo in site:config command + exit(); +}; +export const init = async (options, command, { customizeExitMessage, exitAfterConfiguringRepo = false } = {}) => { + command.setAnalyticsPayload({ manual: options.manual, force: options.force }); + const { repositoryRoot, state } = command.netlify; + const { siteInfo: existingSiteInfo } = command.netlify; + // Check logged in status + await command.authenticate(); + // Add .netlify to .gitignore file + await ensureNetlifyIgnore(repositoryRoot); + const repoUrl = getRepoUrl(existingSiteInfo); + if (repoUrl && !options.force) { + logExistingAndExit({ siteInfo: existingSiteInfo }); + } + // Look for local repo + const repoData = await getRepoData({ workingDir: command.workingDir, remoteName: options.gitRemoteName }); + if ('error' in repoData) { + // TODO(ndhoule): Custom error messaage here + return await handleNoGitRemoteAndExit({ + command, + error: repoData.error, + state, + disableLinking: options.disableLinking, + customizeExitMessage, + }); + } + const siteInfo = isEmpty(existingSiteInfo) ? await createOrLinkSiteToRepo(command) : existingSiteInfo; + log(); + // Check for existing CI setup + const remoteBuildRepo = getRepoUrl(siteInfo); + if (remoteBuildRepo && !options.force) { + logExistingRepoSetupAndExit({ siteName: siteInfo.name, repoUrl: remoteBuildRepo, customizeExitMessage }); + } + persistState({ state, siteInfo }); + await configureRepo({ command, siteId: siteInfo.id, repoData, manual: options.manual }); + if (exitAfterConfiguringRepo) { + const customErrorMessage = customizeExitMessage?.(LINKED_EXISTING_SITE_EXIT_CODE, ''); + if (customErrorMessage) { + log(customErrorMessage); + } + return exit(); + } + return siteInfo; +}; +//# sourceMappingURL=init.js.map \ No newline at end of file diff --git a/dist/commands/init/init.js.map b/dist/commands/init/init.js.map new file mode 100644 index 00000000000..89cb485e442 --- /dev/null +++ b/dist/commands/init/init.js.map @@ -0,0 +1 @@ +{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../src/commands/init/init.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/link/index.d.ts b/dist/commands/link/index.d.ts new file mode 100644 index 00000000000..c70297db191 --- /dev/null +++ b/dist/commands/link/index.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const createLinkCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/link/index.d.ts.map b/dist/commands/link/index.d.ts.map new file mode 100644 index 00000000000..74d84f1a902 --- /dev/null +++ b/dist/commands/link/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/link/index.ts"],"names":[],"mappings":"AAEA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAG5C,eAAO,MAAM,iBAAiB,GAAI,SAAS,WAAW,gBAuBhD,CAAA"} \ No newline at end of file diff --git a/dist/commands/link/index.js b/dist/commands/link/index.js new file mode 100644 index 00000000000..672ef74a245 --- /dev/null +++ b/dist/commands/link/index.js @@ -0,0 +1,25 @@ +import terminalLink from 'terminal-link'; +export const createLinkCommand = (program) => program + .command('link') + .description('Link a local repo or project folder to an existing project on Netlify') + .option('--id ', 'ID of project to link to') + .option('--name ', 'Name of project to link to') + .option('--git-remote-name ', 'Name of Git remote to use. e.g. "origin"') + .option('--git-remote-url ', 'URL of the repository (or Github `owner/repo`) to link to') + .addExamples([ + 'netlify link', + 'netlify link --id 123-123-123-123', + 'netlify link --name my-project-name', + 'netlify link --git-remote-url https://github.com/vibecoder/my-unicorn.git', +]) + .addHelpText('after', () => { + const docsUrl = 'https://docs.netlify.com/cli/get-started/#link-and-unlink-sites'; + return ` +For more information about linking projects, see ${terminalLink(docsUrl, docsUrl, { fallback: false })} +`; +}) + .action(async (options, command) => { + const { link } = await import('./link.js'); + await link(options, command); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/link/index.js.map b/dist/commands/link/index.js.map new file mode 100644 index 00000000000..802d9e43876 --- /dev/null +++ b/dist/commands/link/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/link/index.ts"],"names":[],"mappings":"AAAA,OAAO,YAAY,MAAM,eAAe,CAAA;AAKxC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,OAAoB,EAAE,EAAE,CACxD,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,uEAAuE,CAAC;KACpF,MAAM,CAAC,WAAW,EAAE,0BAA0B,CAAC;KAC/C,MAAM,CAAC,eAAe,EAAE,4BAA4B,CAAC;KACrD,MAAM,CAAC,0BAA0B,EAAE,0CAA0C,CAAC;KAC9E,MAAM,CAAC,yBAAyB,EAAE,2DAA2D,CAAC;KAC9F,WAAW,CAAC;IACX,cAAc;IACd,mCAAmC;IACnC,qCAAqC;IACrC,2EAA2E;CAC5E,CAAC;KACD,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE;IACzB,MAAM,OAAO,GAAG,iEAAiE,CAAA;IACjF,OAAO;mDACsC,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;CACrG,CAAA;AACG,CAAC,CAAC;KACD,MAAM,CAAC,KAAK,EAAE,OAAyB,EAAE,OAAoB,EAAE,EAAE;IAChE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAA;IAC1C,MAAM,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAC9B,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/link/link.d.ts b/dist/commands/link/link.d.ts new file mode 100644 index 00000000000..3fb44337173 --- /dev/null +++ b/dist/commands/link/link.d.ts @@ -0,0 +1,5 @@ +import type { SiteInfo } from '../../utils/types.js'; +import BaseCommand from '../base-command.js'; +import type { LinkOptionValues } from './option_values.js'; +export declare const link: (options: LinkOptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=link.d.ts.map \ No newline at end of file diff --git a/dist/commands/link/link.d.ts.map b/dist/commands/link/link.d.ts.map new file mode 100644 index 00000000000..fcb90556a63 --- /dev/null +++ b/dist/commands/link/link.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"link.d.ts","sourceRoot":"","sources":["../../../src/commands/link/link.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAC5C,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAmP1D,eAAO,MAAM,IAAI,GAAU,SAAS,gBAAgB,EAAE,SAAS,WAAW,sBAoGzE,CAAA"} \ No newline at end of file diff --git a/dist/commands/link/link.js b/dist/commands/link/link.js new file mode 100644 index 00000000000..4e3db383065 --- /dev/null +++ b/dist/commands/link/link.js @@ -0,0 +1,305 @@ +import assert from 'node:assert'; +import inquirer from 'inquirer'; +import isEmpty from 'lodash/isEmpty.js'; +import { listSites } from '../../lib/api.js'; +import { startSpinner } from '../../lib/spinner.js'; +import { chalk, logAndThrowError, exit, log, netlifyCommand } from '../../utils/command-helpers.js'; +import getRepoData from '../../utils/get-repo-data.js'; +import { ensureNetlifyIgnore } from '../../utils/gitignore.js'; +import { track } from '../../utils/telemetry/index.js'; +const findSiteByRepoUrl = async (api, repoUrl) => { + log(); + const spinner = startSpinner({ text: `Looking for projects connected to '${repoUrl}'` }); + const sites = await listSites({ api, options: { filter: 'all' } }); + if (sites.length === 0) { + spinner.error(); + return logAndThrowError(`You don't have any projects yet. Run ${chalk.cyanBright(`${netlifyCommand()} sites:create`)} to create a project.`); + } + const matchingSites = sites.filter(({ build_settings: buildSettings = {} }) => repoUrl === buildSettings.repo_url); + if (matchingSites.length === 0) { + spinner.error(); + log(chalk.redBright.bold.underline(`No matching project found`)); + log(); + log(`No project found with the remote ${repoUrl}. + +Double check you are in the correct working directory and a remote origin repo is configured. + +Run ${chalk.cyanBright('git remote -v')} to see a list of your git remotes.`); + return exit(1); + } + if (matchingSites.length === 1) { + spinner.success({ text: `Found 1 project connected to ${repoUrl}` }); + const [firstSite] = matchingSites; + return firstSite; + } + spinner.warn({ text: `Found ${matchingSites.length} projects connected to ${repoUrl}` }); + const { selectedSite } = await inquirer.prompt([ + { + type: 'list', + name: 'selectedSite', + message: 'Which project do you want to link?', + choices: matchingSites.map((matchingSite) => ({ + name: `${matchingSite.name} - ${matchingSite.ssl_url}`, + value: matchingSite, + })), + }, + ]); + if (!selectedSite) { + return logAndThrowError('No project selected'); + } + return selectedSite; +}; +const linkPrompt = async (command, options) => { + const { api, state } = command.netlify; + const SITE_NAME_PROMPT = 'Search by full or partial project name'; + const SITE_LIST_PROMPT = 'Choose from a list of your recently updated projects'; + const SITE_ID_PROMPT = 'Enter a project ID'; + let GIT_REMOTE_PROMPT = 'Use the current git remote origin URL'; + let site; + // Get git remote data if exists + const repoData = await getRepoData({ workingDir: command.workingDir, remoteName: options.gitRemoteName }); + let linkChoices = [SITE_NAME_PROMPT, SITE_LIST_PROMPT, SITE_ID_PROMPT]; + if (!('error' in repoData)) { + // Add git GIT_REMOTE_PROMPT if in a repo + GIT_REMOTE_PROMPT = `Use current git remote origin (${repoData.httpsUrl})`; + linkChoices = [GIT_REMOTE_PROMPT, ...linkChoices]; + } + log(); + log(`${chalk.cyanBright(`${netlifyCommand()} link`)} will connect this folder to a project on Netlify`); + log(); + const { linkType } = await inquirer.prompt([ + { + type: 'list', + name: 'linkType', + message: 'How do you want to link this folder to a project?', + choices: linkChoices, + }, + ]); + let kind; + switch (linkType) { + case GIT_REMOTE_PROMPT: { + // TODO(serhalp): Refactor function to avoid this. We can only be here if `repoData` is not an error. + assert(!('error' in repoData)); + kind = 'gitRemote'; + site = await findSiteByRepoUrl(api, repoData.httpsUrl); + break; + } + case SITE_NAME_PROMPT: { + kind = 'byName'; + const { searchTerm } = await inquirer.prompt([ + { + type: 'input', + name: 'searchTerm', + message: 'Enter the project name (or just part of it):', + }, + ]); + log(`Looking for projects with names containing '${searchTerm}'...`); + log(); + let matchingSites = []; + try { + matchingSites = await listSites({ + api, + options: { name: searchTerm, filter: 'all' }, + }); + } + catch (error_) { + if (error_.status === 404) { + return logAndThrowError(`'${searchTerm}' not found`); + } + else { + return logAndThrowError(error_); + } + } + if (!matchingSites || matchingSites.length === 0) { + return logAndThrowError(`No project names found containing '${searchTerm}'. + +Run ${chalk.cyanBright(`${netlifyCommand()} link`)} again to try a new search, +or run ${chalk.cyanBright(`npx ${netlifyCommand()} sites:create`)} to create a project.`); + } + if (matchingSites.length > 1) { + log(`Found ${matchingSites.length} matching projects!`); + const { selectedSite } = await inquirer.prompt([ + { + type: 'list', + name: 'selectedSite', + message: 'Which project do you want to link?', + paginated: true, + choices: matchingSites.map((matchingSite) => ({ name: matchingSite.name, value: matchingSite })), + }, + ]); + if (!selectedSite) { + return logAndThrowError('No project selected'); + } + site = selectedSite; + } + else { + const [firstSite] = matchingSites; + site = firstSite; + } + break; + } + case SITE_LIST_PROMPT: { + kind = 'fromList'; + log(`Fetching recently updated projects...`); + log(); + let sites; + try { + sites = await listSites({ api, options: { maxPages: 1, filter: 'all' } }); + } + catch (error_) { + return logAndThrowError(error_); + } + if (!sites || sites.length === 0) { + return logAndThrowError(`You don't have any projects yet. Run ${chalk.cyanBright(`${netlifyCommand()} sites:create`)} to create a project.`); + } + const { selectedSite } = await inquirer.prompt([ + { + type: 'list', + name: 'selectedSite', + message: 'Which project do you want to link?', + paginated: true, + choices: sites.map((matchingSite) => ({ name: matchingSite.name, value: matchingSite })), + }, + ]); + if (!selectedSite) { + return logAndThrowError('No project selected'); + } + site = selectedSite; + break; + } + case SITE_ID_PROMPT: { + kind = 'bySiteId'; + const { siteId } = await inquirer.prompt([ + { + type: 'input', + name: 'siteId', + message: 'What is the project ID?', + }, + ]); + try { + site = await api.getSite({ siteId }); + } + catch (error_) { + if (error_.status === 404) { + return logAndThrowError(`Project ID '${siteId}' not found`); + } + else { + return logAndThrowError(error_); + } + } + break; + } + } + if (!site) { + return logAndThrowError(new Error(`No project found`)); + } + // Save site ID to config + state.set('siteId', site.id); + await track('sites_linked', { + siteId: site.id, + linkType: 'prompt', + kind, + }); + // Log output + log(); + log(chalk.greenBright.bold.underline(`Directory Linked`)); + log(); + log(`Admin url: ${chalk.magentaBright(site.admin_url)}`); + log(`Project url: ${chalk.cyanBright(site.ssl_url || site.url)}`); + log(); + log(`You can now run other \`netlify\` cli commands in this directory`); + // FIXME(serhalp): Mismatch between hardcoded `SiteInfo` and generated Netlify API types. + return site; +}; +export const link = async (options, command) => { + await command.authenticate(); + const { api, repositoryRoot, site: { id: siteId }, siteInfo, state, } = command.netlify; + let initialSiteData; + let newSiteData; + // Add .netlify to .gitignore file + await ensureNetlifyIgnore(repositoryRoot); + // Site id is incorrect + if (siteId && isEmpty(siteInfo)) { + log(`"${siteId}" was not found in your Netlify account.`); + log(`Please double check your project ID and which account you are logged into via \`${netlifyCommand()} status\`.`); + return exit(); + } + if (!isEmpty(siteInfo)) { + // If already linked to project, exit and prompt for unlink + initialSiteData = siteInfo; + log(`Project already linked to "${initialSiteData.name}"`); + log(`Admin url: ${initialSiteData.admin_url}`); + log(); + log(`To unlink this project, run: ${chalk.cyanBright(`${netlifyCommand()} unlink`)}`); + } + else if (options.id) { + try { + // @ts-expect-error FIXME(serhalp): Mismatch between hardcoded `SiteInfo` and new generated Netlify API types. + newSiteData = await api.getSite({ site_id: options.id }); + } + catch (error_) { + if (error_.status === 404) { + return logAndThrowError(new Error(`Project id ${options.id} not found`)); + } + else { + return logAndThrowError(error_); + } + } + // Save site ID + state.set('siteId', newSiteData.id); + log(`${chalk.green('āœ”')} Linked to ${newSiteData.name}`); + await track('sites_linked', { + siteId: newSiteData.id, + linkType: 'manual', + kind: 'byId', + }); + } + else if (options.name) { + let results = []; + try { + results = await listSites({ + api, + options: { + name: options.name, + filter: 'all', + }, + }); + } + catch (error_) { + if (error_.status === 404) { + return logAndThrowError(new Error(`${options.name} not found`)); + } + else { + return logAndThrowError(error_); + } + } + if (results.length === 0) { + return logAndThrowError(new Error(`No projects found named ${options.name}`)); + } + const matchingSiteData = results.find((site) => site.name === options.name) || results[0]; + state.set('siteId', matchingSiteData.id); + log(`${chalk.green('āœ”')} Linked to ${matchingSiteData.name}`); + await track('sites_linked', { + siteId: (matchingSiteData && matchingSiteData.id) || siteId, + linkType: 'manual', + kind: 'byName', + }); + } + else if (options.gitRemoteUrl) { + newSiteData = await findSiteByRepoUrl(api, options.gitRemoteUrl); + state.set('siteId', newSiteData.id); + log(`${chalk.green('āœ”')} Linked to ${newSiteData.name}`); + await track('sites_linked', { + siteId: newSiteData.id, + linkType: 'clone', + kind: 'byRepoUrl', + }); + } + else { + newSiteData = await linkPrompt(command, options); + } + // FIXME(serhalp): All the cases above except one (look up by site name) end up *returning* + // the site data. This is probably not intentional and may result in bugs in deploy/init. Investigate. + return initialSiteData || newSiteData; +}; +//# sourceMappingURL=link.js.map \ No newline at end of file diff --git a/dist/commands/link/link.js.map b/dist/commands/link/link.js.map new file mode 100644 index 00000000000..e82608db0d4 --- /dev/null +++ b/dist/commands/link/link.js.map @@ -0,0 +1 @@ +{"version":3,"file":"link.js","sourceRoot":"","sources":["../../../src/commands/link/link.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/link/option_values.d.ts b/dist/commands/link/option_values.d.ts new file mode 100644 index 00000000000..a86ed21f464 --- /dev/null +++ b/dist/commands/link/option_values.d.ts @@ -0,0 +1,8 @@ +import type { BaseOptionValues } from '../base-command.js'; +export type LinkOptionValues = BaseOptionValues & { + id?: string | undefined; + name?: string | undefined; + gitRemoteUrl?: string | undefined; + gitRemoteName?: string | undefined; +}; +//# sourceMappingURL=option_values.d.ts.map \ No newline at end of file diff --git a/dist/commands/link/option_values.d.ts.map b/dist/commands/link/option_values.d.ts.map new file mode 100644 index 00000000000..3659840a3a5 --- /dev/null +++ b/dist/commands/link/option_values.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"option_values.d.ts","sourceRoot":"","sources":["../../../src/commands/link/option_values.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAE1D,MAAM,MAAM,gBAAgB,GAAG,gBAAgB,GAAG;IAChD,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACvB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACzB,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACnC,CAAA"} \ No newline at end of file diff --git a/dist/commands/link/option_values.js b/dist/commands/link/option_values.js new file mode 100644 index 00000000000..91337fa021d --- /dev/null +++ b/dist/commands/link/option_values.js @@ -0,0 +1,3 @@ +// This type lives in a separate file to prevent import cycles. +export {}; +//# sourceMappingURL=option_values.js.map \ No newline at end of file diff --git a/dist/commands/link/option_values.js.map b/dist/commands/link/option_values.js.map new file mode 100644 index 00000000000..905a7089413 --- /dev/null +++ b/dist/commands/link/option_values.js.map @@ -0,0 +1 @@ +{"version":3,"file":"option_values.js","sourceRoot":"","sources":["../../../src/commands/link/option_values.ts"],"names":[],"mappings":"AAAA,+DAA+D"} \ No newline at end of file diff --git a/dist/commands/login/index.d.ts b/dist/commands/login/index.d.ts new file mode 100644 index 00000000000..da9f7dbf906 --- /dev/null +++ b/dist/commands/login/index.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const createLoginCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/login/index.d.ts.map b/dist/commands/login/index.d.ts.map new file mode 100644 index 00000000000..f9b8d5f95f2 --- /dev/null +++ b/dist/commands/login/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/login/index.ts"],"names":[],"mappings":"AAGA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,kBAAkB,GAAI,SAAS,WAAW,gBAiBjD,CAAA"} \ No newline at end of file diff --git a/dist/commands/login/index.js b/dist/commands/login/index.js new file mode 100644 index 00000000000..532fe025a44 --- /dev/null +++ b/dist/commands/login/index.js @@ -0,0 +1,17 @@ +import terminalLink from 'terminal-link'; +export const createLoginCommand = (program) => program + .command('login') + .description(`Login to your Netlify account +Opens a web browser to acquire an OAuth token.`) + .option('--new', 'Login to new Netlify account') + .addHelpText('after', () => { + const docsUrl = 'https://docs.netlify.com/cli/get-started/#authentication'; + return ` +For more information about Netlify authentication, see ${terminalLink(docsUrl, docsUrl, { fallback: false })} +`; +}) + .action(async (options, command) => { + const { login } = await import('./login.js'); + await login(options, command); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/login/index.js.map b/dist/commands/login/index.js.map new file mode 100644 index 00000000000..ad88a69291b --- /dev/null +++ b/dist/commands/login/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/login/index.ts"],"names":[],"mappings":"AACA,OAAO,YAAY,MAAM,eAAe,CAAA;AAIxC,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAAoB,EAAE,EAAE,CACzD,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CACV;+CACyC,CAC1C;KACA,MAAM,CAAC,OAAO,EAAE,8BAA8B,CAAC;KAC/C,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE;IACzB,MAAM,OAAO,GAAG,0DAA0D,CAAA;IAC1E,OAAO;yDAC4C,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;CAC3G,CAAA;AACG,CAAC,CAAC;KACD,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IAC5D,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAA;IAC5C,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAC/B,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/login/login.d.ts b/dist/commands/login/login.d.ts new file mode 100644 index 00000000000..75ba827aa45 --- /dev/null +++ b/dist/commands/login/login.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const login: (options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=login.d.ts.map \ No newline at end of file diff --git a/dist/commands/login/login.d.ts.map b/dist/commands/login/login.d.ts.map new file mode 100644 index 00000000000..ca2754ee08d --- /dev/null +++ b/dist/commands/login/login.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"login.d.ts","sourceRoot":"","sources":["../../../src/commands/login/login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAIxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAe5C,eAAO,MAAM,KAAK,GAAU,SAAS,YAAY,EAAE,SAAS,WAAW,uBAkBtE,CAAA"} \ No newline at end of file diff --git a/dist/commands/login/login.js b/dist/commands/login/login.js new file mode 100644 index 00000000000..216e9ca52ce --- /dev/null +++ b/dist/commands/login/login.js @@ -0,0 +1,30 @@ +import { chalk, exit, getToken, log } from '../../utils/command-helpers.js'; +const msg = function (location) { + switch (location) { + case 'env': + return 'via process.env.NETLIFY_AUTH_TOKEN set in your terminal session'; + case 'flag': + return 'via CLI --auth flag'; + case 'config': + return 'via netlify config on your machine'; + default: + return ''; + } +}; +export const login = async (options, command) => { + const [accessToken, location] = await getToken(); + command.setAnalyticsPayload({ new: options.new }); + if (accessToken && !options.new) { + log(`Already logged in ${msg(location)}`); + log(); + log(`Run ${chalk.cyanBright('netlify status')} for account details`); + log(); + log(`or run ${chalk.cyanBright('netlify switch')} to switch accounts`); + log(); + log(`To see all available commands run: ${chalk.cyanBright('netlify help')}`); + log(); + return exit(); + } + await command.expensivelyAuthenticate(); +}; +//# sourceMappingURL=login.js.map \ No newline at end of file diff --git a/dist/commands/login/login.js.map b/dist/commands/login/login.js.map new file mode 100644 index 00000000000..805596785c9 --- /dev/null +++ b/dist/commands/login/login.js.map @@ -0,0 +1 @@ +{"version":3,"file":"login.js","sourceRoot":"","sources":["../../../src/commands/login/login.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAA;AAI3E,MAAM,GAAG,GAAG,UAAU,QAAuB;IAC3C,QAAQ,QAAQ,EAAE,CAAC;QACjB,KAAK,KAAK;YACR,OAAO,iEAAiE,CAAA;QAC1E,KAAK,MAAM;YACT,OAAO,qBAAqB,CAAA;QAC9B,KAAK,QAAQ;YACX,OAAO,oCAAoC,CAAA;QAC7C;YACE,OAAO,EAAE,CAAA;IACb,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IACzE,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,GAAG,MAAM,QAAQ,EAAE,CAAA;IAEhD,OAAO,CAAC,mBAAmB,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAA;IAEjD,IAAI,WAAW,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QAChC,GAAG,CAAC,qBAAqB,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAA;QACzC,GAAG,EAAE,CAAA;QACL,GAAG,CAAC,OAAO,KAAK,CAAC,UAAU,CAAC,gBAAgB,CAAC,sBAAsB,CAAC,CAAA;QACpE,GAAG,EAAE,CAAA;QACL,GAAG,CAAC,UAAU,KAAK,CAAC,UAAU,CAAC,gBAAgB,CAAC,qBAAqB,CAAC,CAAA;QACtE,GAAG,EAAE,CAAA;QACL,GAAG,CAAC,sCAAsC,KAAK,CAAC,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC,CAAA;QAC7E,GAAG,EAAE,CAAA;QACL,OAAO,IAAI,EAAE,CAAA;IACf,CAAC;IAED,MAAM,OAAO,CAAC,uBAAuB,EAAE,CAAA;AACzC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/logout/index.d.ts b/dist/commands/logout/index.d.ts new file mode 100644 index 00000000000..7e7a1b81572 --- /dev/null +++ b/dist/commands/logout/index.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const createLogoutCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/logout/index.d.ts.map b/dist/commands/logout/index.d.ts.map new file mode 100644 index 00000000000..ce971f36858 --- /dev/null +++ b/dist/commands/logout/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/logout/index.ts"],"names":[],"mappings":"AAEA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,mBAAmB,GAAI,SAAS,WAAW,gBAOlD,CAAA"} \ No newline at end of file diff --git a/dist/commands/logout/index.js b/dist/commands/logout/index.js new file mode 100644 index 00000000000..d2a4256c213 --- /dev/null +++ b/dist/commands/logout/index.js @@ -0,0 +1,8 @@ +export const createLogoutCommand = (program) => program + .command('logout', { hidden: true }) + .description('Logout of your Netlify account') + .action(async (options, command) => { + const { logout } = await import('./logout.js'); + await logout(options, command); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/logout/index.js.map b/dist/commands/logout/index.js.map new file mode 100644 index 00000000000..c38f6986529 --- /dev/null +++ b/dist/commands/logout/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/logout/index.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAAoB,EAAE,EAAE,CAC1D,OAAO;KACJ,OAAO,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;KACnC,WAAW,CAAC,gCAAgC,CAAC;KAC7C,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IAC5D,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;IAC9C,MAAM,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAChC,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/logout/logout.d.ts b/dist/commands/logout/logout.d.ts new file mode 100644 index 00000000000..dda6a8363b7 --- /dev/null +++ b/dist/commands/logout/logout.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const logout: (_options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=logout.d.ts.map \ No newline at end of file diff --git a/dist/commands/logout/logout.d.ts.map b/dist/commands/logout/logout.d.ts.map new file mode 100644 index 00000000000..fdf48f63a23 --- /dev/null +++ b/dist/commands/logout/logout.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../../src/commands/logout/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAIxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,MAAM,GAAU,UAAU,YAAY,EAAE,SAAS,WAAW,kBAwBxE,CAAA"} \ No newline at end of file diff --git a/dist/commands/logout/logout.js b/dist/commands/logout/logout.js new file mode 100644 index 00000000000..34296b3feb2 --- /dev/null +++ b/dist/commands/logout/logout.js @@ -0,0 +1,23 @@ +import { exit, getToken, log } from '../../utils/command-helpers.js'; +import { track } from '../../utils/telemetry/index.js'; +export const logout = async (_options, command) => { + const [accessToken, location] = await getToken(); + if (!accessToken) { + log(`Already logged out`); + log(); + log('To login run "netlify login"'); + exit(); + } + await track('user_logout'); + // unset userID without deleting key + command.netlify.globalConfig.set('userId', null); + if (location === 'env') { + log('The "process.env.NETLIFY_AUTH_TOKEN" is still set in your terminal session'); + log(); + log('To logout completely, unset the environment variable'); + log(); + exit(); + } + log(`Logging you out of Netlify. Come back soon!`); +}; +//# sourceMappingURL=logout.js.map \ No newline at end of file diff --git a/dist/commands/logout/logout.js.map b/dist/commands/logout/logout.js.map new file mode 100644 index 00000000000..2968f4e9b82 --- /dev/null +++ b/dist/commands/logout/logout.js.map @@ -0,0 +1 @@ +{"version":3,"file":"logout.js","sourceRoot":"","sources":["../../../src/commands/logout/logout.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAA;AAGtD,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,EAAE,QAAsB,EAAE,OAAoB,EAAE,EAAE;IAC3E,MAAM,CAAC,WAAW,EAAE,QAAQ,CAAC,GAAG,MAAM,QAAQ,EAAE,CAAA;IAEhD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,GAAG,CAAC,oBAAoB,CAAC,CAAA;QACzB,GAAG,EAAE,CAAA;QACL,GAAG,CAAC,8BAA8B,CAAC,CAAA;QACnC,IAAI,EAAE,CAAA;IACR,CAAC;IAED,MAAM,KAAK,CAAC,aAAa,CAAC,CAAA;IAE1B,oCAAoC;IACpC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;IAEhD,IAAI,QAAQ,KAAK,KAAK,EAAE,CAAC;QACvB,GAAG,CAAC,4EAA4E,CAAC,CAAA;QACjF,GAAG,EAAE,CAAA;QACL,GAAG,CAAC,sDAAsD,CAAC,CAAA;QAC3D,GAAG,EAAE,CAAA;QACL,IAAI,EAAE,CAAA;IACR,CAAC;IAED,GAAG,CAAC,6CAA6C,CAAC,CAAA;AACpD,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/logs/build.d.ts b/dist/commands/logs/build.d.ts new file mode 100644 index 00000000000..65a4239284f --- /dev/null +++ b/dist/commands/logs/build.d.ts @@ -0,0 +1,8 @@ +import type { OptionValues } from 'commander'; +import type BaseCommand from '../base-command.js'; +export declare function getName({ deploy, userId }: { + deploy: any; + userId: string; +}): string; +export declare const logsBuild: (_options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=build.d.ts.map \ No newline at end of file diff --git a/dist/commands/logs/build.d.ts.map b/dist/commands/logs/build.d.ts.map new file mode 100644 index 00000000000..27dbcf639f6 --- /dev/null +++ b/dist/commands/logs/build.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../../src/commands/logs/build.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAK7C,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAEjD,wBAAgB,OAAO,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,EAAE,GAAG,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,UAyB1E;AAED,eAAO,MAAM,SAAS,GAAU,UAAU,YAAY,EAAE,SAAS,WAAW,kBAuD3E,CAAA"} \ No newline at end of file diff --git a/dist/commands/logs/build.js b/dist/commands/logs/build.js new file mode 100644 index 00000000000..2650140854a --- /dev/null +++ b/dist/commands/logs/build.js @@ -0,0 +1,72 @@ +import inquirer from 'inquirer'; +import { log, chalk } from '../../utils/command-helpers.js'; +import { getWebSocket } from '../../utils/websockets/index.js'; +export function getName({ deploy, userId }) { + let normalisedName = ''; + const isUserDeploy = deploy.user_id === userId; + switch (deploy.context) { + case 'branch-deploy': + normalisedName = 'Branch Deploy'; + break; + case 'deploy-preview': { + // Deploys via the CLI can have the `deploy-preview` context + // but no review id because they don't come from a PR. + // + const id = deploy.review_id; + normalisedName = id ? `Deploy Preview #${id}` : 'Deploy Preview'; + break; + } + default: + normalisedName = 'Production'; + } + if (isUserDeploy) { + normalisedName += chalk.yellow('*'); + } + return `(${deploy.id.slice(0, 7)}) ${normalisedName}`; +} +export const logsBuild = async (_options, command) => { + await command.authenticate(); + const client = command.netlify.api; + const { site } = command.netlify; + const { id: siteId } = site; + const userId = command.netlify.globalConfig.get('userId'); + if (!siteId) { + log('You must link a project before attempting to view deploy logs'); + return; + } + const deploys = await client.listSiteDeploys({ siteId, state: 'building' }); + if (deploys.length === 0) { + log('No active builds'); + return; + } + let [deploy] = deploys; + if (deploys.length > 1) { + const { result } = await inquirer.prompt({ + name: 'result', + type: 'list', + message: `Select a deploy\n\n${chalk.yellow('*')} indicates a deploy created by you`, + choices: deploys.map((dep) => ({ + name: getName({ deploy: dep, userId }), + value: dep.id, + })), + }); + deploy = deploys.find((dep) => dep.id === result) || deploy; + } + const { id } = deploy; + const ws = getWebSocket(`wss://socketeer.services.netlify.com/build/logs`); + ws.on('open', function open() { + ws.send(JSON.stringify({ deploy_id: id, site_id: siteId, access_token: client.accessToken })); + }); + ws.on('message', (data) => { + const { message, section, type } = JSON.parse(data); + log(message); + if (type === 'report' && section === 'building') { + // end of build + ws.close(); + } + }); + ws.on('close', () => { + log('---'); + }); +}; +//# sourceMappingURL=build.js.map \ No newline at end of file diff --git a/dist/commands/logs/build.js.map b/dist/commands/logs/build.js.map new file mode 100644 index 00000000000..416131b32a0 --- /dev/null +++ b/dist/commands/logs/build.js.map @@ -0,0 +1 @@ +{"version":3,"file":"build.js","sourceRoot":"","sources":["../../../src/commands/logs/build.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/logs/functions.d.ts b/dist/commands/logs/functions.d.ts new file mode 100644 index 00000000000..0e93ce96671 --- /dev/null +++ b/dist/commands/logs/functions.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import type BaseCommand from '../base-command.js'; +export declare const logsFunction: (functionName: string | undefined, options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=functions.d.ts.map \ No newline at end of file diff --git a/dist/commands/logs/functions.d.ts.map b/dist/commands/logs/functions.d.ts.map new file mode 100644 index 00000000000..a3adcf12b2c --- /dev/null +++ b/dist/commands/logs/functions.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../../../src/commands/logs/functions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAKxC,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAwBjD,eAAO,MAAM,YAAY,GAAU,cAAc,MAAM,GAAG,SAAS,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,kBAqE/G,CAAA"} \ No newline at end of file diff --git a/dist/commands/logs/functions.js b/dist/commands/logs/functions.js new file mode 100644 index 00000000000..a56f10c5684 --- /dev/null +++ b/dist/commands/logs/functions.js @@ -0,0 +1,79 @@ +import inquirer from 'inquirer'; +import { chalk, log } from '../../utils/command-helpers.js'; +import { getWebSocket } from '../../utils/websockets/index.js'; +import { CLI_LOG_LEVEL_CHOICES_STRING, LOG_LEVELS, LOG_LEVELS_LIST } from './log-levels.js'; +function getLog(logData) { + let logString = ''; + switch (logData.level) { + case LOG_LEVELS.INFO: + logString += chalk.blueBright(logData.level); + break; + case LOG_LEVELS.WARN: + logString += chalk.yellowBright(logData.level); + break; + case LOG_LEVELS.ERROR: + logString += chalk.redBright(logData.level); + break; + default: + logString += logData.level; + break; + } + return `${logString} ${logData.message}`; +} +export const logsFunction = async (functionName, options, command) => { + const client = command.netlify.api; + const { site } = command.netlify; + const { id: siteId } = site; + if (options.level && !options.level.every((level) => LOG_LEVELS_LIST.includes(level))) { + log(`Invalid log level. Choices are:${CLI_LOG_LEVEL_CHOICES_STRING}`); + } + const levelsToPrint = options.level || LOG_LEVELS_LIST; + // TODO: Update type once the open api spec is updated https://open-api.netlify.com/#tag/function/operation/searchSiteFunctions + const { functions = [] } = (await client.searchSiteFunctions({ siteId: siteId })); + if (functions.length === 0) { + log(`No functions found for the project`); + return; + } + let selectedFunction; + if (functionName) { + selectedFunction = functions.find((fn) => fn.n === functionName); + } + else { + const { result } = await inquirer.prompt({ + name: 'result', + type: 'list', + message: 'Select a function', + choices: functions.map((fn) => fn.n), + }); + selectedFunction = functions.find((fn) => fn.n === result); + } + if (!selectedFunction) { + log(`Could not find function ${functionName}`); + return; + } + const { a: accountId, oid: functionId } = selectedFunction; + const ws = getWebSocket('wss://socketeer.services.netlify.com/function/logs'); + ws.on('open', () => { + ws.send(JSON.stringify({ + function_id: functionId, + site_id: siteId, + access_token: client.accessToken, + account_id: accountId, + })); + }); + ws.on('message', (data) => { + const logData = JSON.parse(data); + if (!levelsToPrint.includes(logData.level.toLowerCase())) { + return; + } + log(getLog(logData)); + }); + ws.on('close', () => { + log('Connection closed'); + }); + ws.on('error', (err) => { + log('Connection error'); + log(err); + }); +}; +//# sourceMappingURL=functions.js.map \ No newline at end of file diff --git a/dist/commands/logs/functions.js.map b/dist/commands/logs/functions.js.map new file mode 100644 index 00000000000..606fde3cc41 --- /dev/null +++ b/dist/commands/logs/functions.js.map @@ -0,0 +1 @@ +{"version":3,"file":"functions.js","sourceRoot":"","sources":["../../../src/commands/logs/functions.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/logs/index.d.ts b/dist/commands/logs/index.d.ts new file mode 100644 index 00000000000..dbc5fba6ef7 --- /dev/null +++ b/dist/commands/logs/index.d.ts @@ -0,0 +1,5 @@ +import BaseCommand from '../base-command.js'; +export declare const createLogsBuildCommand: (program: BaseCommand) => void; +export declare const createLogsFunctionCommand: (program: BaseCommand) => void; +export declare const createLogsCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/logs/index.d.ts.map b/dist/commands/logs/index.d.ts.map new file mode 100644 index 00000000000..2aeb8871c4e --- /dev/null +++ b/dist/commands/logs/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/logs/index.ts"],"names":[],"mappings":"AAEA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAI5C,eAAO,MAAM,sBAAsB,GAAI,SAAS,WAAW,SAS1D,CAAA;AAED,eAAO,MAAM,yBAAyB,GAAI,SAAS,WAAW,SAkB7D,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,SAAS,WAAW,gBAWrD,CAAA"} \ No newline at end of file diff --git a/dist/commands/logs/index.js b/dist/commands/logs/index.js new file mode 100644 index 00000000000..6f5922beb5e --- /dev/null +++ b/dist/commands/logs/index.js @@ -0,0 +1,40 @@ +import { Option, Argument } from 'commander'; +import { CLI_LOG_LEVEL_CHOICES_STRING } from './log-levels.js'; +export const createLogsBuildCommand = (program) => { + program + .command('logs:deploy') + .alias('logs:build') + .description('Stream the logs of deploys currently being built to the console') + .action(async (options, command) => { + const { logsBuild } = await import('./build.js'); + await logsBuild(options, command); + }); +}; +export const createLogsFunctionCommand = (program) => { + program + .command('logs:function') + .alias('logs:functions') + .addOption(new Option('-l, --level ', `Log levels to stream. Choices are:${CLI_LOG_LEVEL_CHOICES_STRING}`)) + .addArgument(new Argument('[functionName]', 'Name of the function to stream logs for')) + .addExamples([ + 'netlify logs:function', + 'netlify logs:function my-function', + 'netlify logs:function my-function -l info warn', + ]) + .description('Stream netlify function logs to the console') + .action(async (functionName, options, command) => { + const { logsFunction } = await import('./functions.js'); + await logsFunction(functionName, options, command); + }); +}; +export const createLogsCommand = (program) => { + createLogsBuildCommand(program); + createLogsFunctionCommand(program); + return program + .command('logs') + .alias('log') + .description('Stream logs from your project') + .addExamples(['netlify logs:deploy', 'netlify logs:function', 'netlify logs:function my-function']) + .action((_, command) => command.help()); +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/logs/index.js.map b/dist/commands/logs/index.js.map new file mode 100644 index 00000000000..7df3e57e9af --- /dev/null +++ b/dist/commands/logs/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/logs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAgB,QAAQ,EAAE,MAAM,WAAW,CAAA;AAI1D,OAAO,EAAE,4BAA4B,EAAE,MAAM,iBAAiB,CAAA;AAE9D,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,OAAoB,EAAE,EAAE;IAC7D,OAAO;SACJ,OAAO,CAAC,aAAa,CAAC;SACtB,KAAK,CAAC,YAAY,CAAC;SACnB,WAAW,CAAC,iEAAiE,CAAC;SAC9E,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;QAC5D,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAA;QAChD,MAAM,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACnC,CAAC,CAAC,CAAA;AACN,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,OAAoB,EAAE,EAAE;IAChE,OAAO;SACJ,OAAO,CAAC,eAAe,CAAC;SACxB,KAAK,CAAC,gBAAgB,CAAC;SACvB,SAAS,CACR,IAAI,MAAM,CAAC,yBAAyB,EAAE,qCAAqC,4BAA4B,EAAE,CAAC,CAC3G;SACA,WAAW,CAAC,IAAI,QAAQ,CAAC,gBAAgB,EAAE,yCAAyC,CAAC,CAAC;SACtF,WAAW,CAAC;QACX,uBAAuB;QACvB,mCAAmC;QACnC,gDAAgD;KACjD,CAAC;SACD,WAAW,CAAC,6CAA6C,CAAC;SAC1D,MAAM,CAAC,KAAK,EAAE,YAAgC,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;QAC9F,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAA;QACvD,MAAM,YAAY,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;AACN,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,OAAoB,EAAE,EAAE;IACxD,sBAAsB,CAAC,OAAO,CAAC,CAAA;IAE/B,yBAAyB,CAAC,OAAO,CAAC,CAAA;IAElC,OAAO,OAAO;SACX,OAAO,CAAC,MAAM,CAAC;SACf,KAAK,CAAC,KAAK,CAAC;SACZ,WAAW,CAAC,+BAA+B,CAAC;SAC5C,WAAW,CAAC,CAAC,qBAAqB,EAAE,uBAAuB,EAAE,mCAAmC,CAAC,CAAC;SAClG,MAAM,CAAC,CAAC,CAAC,EAAE,OAAoB,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;AACxD,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/logs/log-levels.d.ts b/dist/commands/logs/log-levels.d.ts new file mode 100644 index 00000000000..9521124722e --- /dev/null +++ b/dist/commands/logs/log-levels.d.ts @@ -0,0 +1,11 @@ +export declare const LOG_LEVELS: { + TRACE: string; + DEBUG: string; + INFO: string; + WARN: string; + ERROR: string; + FATAL: string; +}; +export declare const LOG_LEVELS_LIST: string[]; +export declare const CLI_LOG_LEVEL_CHOICES_STRING: string[]; +//# sourceMappingURL=log-levels.d.ts.map \ No newline at end of file diff --git a/dist/commands/logs/log-levels.d.ts.map b/dist/commands/logs/log-levels.d.ts.map new file mode 100644 index 00000000000..666504cd80a --- /dev/null +++ b/dist/commands/logs/log-levels.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"log-levels.d.ts","sourceRoot":"","sources":["../../../src/commands/logs/log-levels.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,UAAU;;;;;;;CAOtB,CAAA;AACD,eAAO,MAAM,eAAe,UAAgE,CAAA;AAC5F,eAAO,MAAM,4BAA4B,UAA8C,CAAA"} \ No newline at end of file diff --git a/dist/commands/logs/log-levels.js b/dist/commands/logs/log-levels.js new file mode 100644 index 00000000000..74e98806e8a --- /dev/null +++ b/dist/commands/logs/log-levels.js @@ -0,0 +1,12 @@ +// Source: Source: https://docs.aws.amazon.com/lambda/latest/dg/monitoring-cloudwatchlogs.html#monitoring-cloudwatchlogs-advanced +export const LOG_LEVELS = { + TRACE: 'TRACE', + DEBUG: 'DEBUG', + INFO: 'INFO', + WARN: 'WARN', + ERROR: 'ERROR', + FATAL: 'FATAL', +}; +export const LOG_LEVELS_LIST = Object.values(LOG_LEVELS).map((level) => level.toLowerCase()); +export const CLI_LOG_LEVEL_CHOICES_STRING = LOG_LEVELS_LIST.map((level) => ` ${level}`); +//# sourceMappingURL=log-levels.js.map \ No newline at end of file diff --git a/dist/commands/logs/log-levels.js.map b/dist/commands/logs/log-levels.js.map new file mode 100644 index 00000000000..21a6a1eba0a --- /dev/null +++ b/dist/commands/logs/log-levels.js.map @@ -0,0 +1 @@ +{"version":3,"file":"log-levels.js","sourceRoot":"","sources":["../../../src/commands/logs/log-levels.ts"],"names":[],"mappings":"AAAA,iIAAiI;AACjI,MAAM,CAAC,MAAM,UAAU,GAAG;IACxB,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;IACd,IAAI,EAAE,MAAM;IACZ,IAAI,EAAE,MAAM;IACZ,KAAK,EAAE,OAAO;IACd,KAAK,EAAE,OAAO;CACf,CAAA;AACD,MAAM,CAAC,MAAM,eAAe,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAA;AAC5F,MAAM,CAAC,MAAM,4BAA4B,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,KAAK,EAAE,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/main.d.ts b/dist/commands/main.d.ts new file mode 100644 index 00000000000..cd3e7ebd6cb --- /dev/null +++ b/dist/commands/main.d.ts @@ -0,0 +1,36 @@ +import BaseCommand from './base-command.js'; +export declare const CI_FORCED_COMMANDS: { + 'env:set': { + options: string; + description: string; + }; + 'env:unset': { + options: string; + description: string; + }; + 'env:clone': { + options: string; + description: string; + }; + 'blobs:set': { + options: string; + description: string; + }; + 'blobs:delete': { + options: string; + description: string; + }; + init: { + options: string; + description: string; + }; + 'sites:delete': { + options: string; + description: string; + }; +}; +/** + * Creates the `netlify-cli` command + */ +export declare const createMainCommand: () => BaseCommand; +//# sourceMappingURL=main.d.ts.map \ No newline at end of file diff --git a/dist/commands/main.d.ts.map b/dist/commands/main.d.ts.map new file mode 100644 index 00000000000..517b98d469b --- /dev/null +++ b/dist/commands/main.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"main.d.ts","sourceRoot":"","sources":["../../src/commands/main.ts"],"names":[],"mappings":"AAyBA,OAAO,WAAW,MAAM,mBAAmB,CAAA;AA8B3C,eAAO,MAAM,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAW9B,CAAA;AA+ID;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAAO,WAqEpC,CAAA"} \ No newline at end of file diff --git a/dist/commands/main.js b/dist/commands/main.js new file mode 100644 index 00000000000..6ad8934b1ea --- /dev/null +++ b/dist/commands/main.js @@ -0,0 +1,227 @@ +import process from 'process'; +import { Option } from 'commander'; +import envinfo from 'envinfo'; +import { closest } from 'fastest-levenshtein'; +import inquirer from 'inquirer'; +import { BANG, chalk, logAndThrowError, exit, log, NETLIFY_CYAN, USER_AGENT, warn, logError, } from '../utils/command-helpers.js'; +import execa from '../utils/execa.js'; +import getGlobalConfigStore from '../utils/get-global-config-store.js'; +import getCLIPackageJson from '../utils/get-cli-package-json.js'; +import { didEnableCompileCache } from '../utils/nodejs-compile-cache.js'; +import { track, reportError } from '../utils/telemetry/index.js'; +import { createApiCommand } from './api/index.js'; +import BaseCommand from './base-command.js'; +import { createBlobsCommand } from './blobs/blobs.js'; +import { createBuildCommand } from './build/index.js'; +import { createCloneCommand } from './clone/index.js'; +import { createCompletionCommand } from './completion/index.js'; +import { createDeployCommand } from './deploy/index.js'; +import { createDevCommand } from './dev/index.js'; +import { createDevExecCommand } from './dev-exec/index.js'; +import { createEnvCommand } from './env/index.js'; +import { createFunctionsCommand } from './functions/index.js'; +import { createInitCommand } from './init/index.js'; +import { createLinkCommand } from './link/index.js'; +import { createLoginCommand } from './login/index.js'; +import { createLogoutCommand } from './logout/index.js'; +import { createLogsCommand } from './logs/index.js'; +import { createOpenCommand } from './open/index.js'; +import { createRecipesCommand } from './recipes/index.js'; +import { createServeCommand } from './serve/index.js'; +import { createSitesCommand } from './sites/index.js'; +import { createStatusCommand } from './status/index.js'; +import { createSwitchCommand } from './switch/index.js'; +import { createUnlinkCommand } from './unlink/index.js'; +import { createWatchCommand } from './watch/index.js'; +import terminalLink from 'terminal-link'; +import { createDatabaseCommand } from './database/index.js'; +const SUGGESTION_TIMEOUT = 1e4; +// These commands run with the --force flag in non-interactive and CI environments +export const CI_FORCED_COMMANDS = { + 'env:set': { options: '--force', description: 'Bypasses prompts & Force the command to run.' }, + 'env:unset': { options: '--force', description: 'Bypasses prompts & Force the command to run.' }, + 'env:clone': { options: '--force', description: 'Bypasses prompts & Force the command to run.' }, + 'blobs:set': { options: '--force', description: 'Bypasses prompts & Force the command to run.' }, + 'blobs:delete': { options: '--force', description: 'Bypasses prompts & Force the command to run.' }, + init: { + options: '--force', + description: 'Reinitialize CI hooks if the linked project is already configured to use CI', + }, + 'sites:delete': { options: '-f, --force', description: 'Delete without prompting (useful for CI).' }, +}; +process.on('uncaughtException', async (err) => { + if ('code' in err && err.code === 'EADDRINUSE') { + logError(`${chalk.red(`Port ${err.port} is already in use`)}\n\n` + + `Your serverless functions might be initializing a server\n` + + `to listen on specific port without properly closing it.\n\n` + + `This behavior is generally not advised\n` + + `To resolve this issue, try the following:\n` + + `1. If you NEED your serverless function to listen on a specific port,\n` + + `use a randomly assigned port as we do not officially support this.\n` + + `2. Review your serverless functions for lingering server connections, close them\n` + + `3. Check if any other applications are using port ${err.port}\n`); + } + else { + logError(`${chalk.red('Netlify CLI has terminated unexpectedly')}\nThis is a problem with the Netlify CLI, not with your application.\nIf you recently updated the CLI, consider reverting to an older version by running:\n\n${chalk.bold('npm install -g netlify-cli@VERSION')}\n\nYou can use any version from ${chalk.underline('https://ntl.fyi/cli-versions')}.\n\nPlease report this problem at ${chalk.underline('https://ntl.fyi/cli-error')} including the error details below.\n`); + const systemInfo = await getSystemInfo(); + console.log(chalk.dim(err.stack || err)); + console.log(chalk.dim(systemInfo)); + reportError(err, { severity: 'error' }); + } + process.exit(1); +}); +const pkg = await getCLIPackageJson(); +const getSystemInfo = () => envinfo.run({ + System: ['OS', 'CPU'], + Binaries: ['Node', 'Yarn', 'npm'], + Browsers: ['Chrome', 'Edge', 'Firefox', 'Safari'], + npmGlobalPackages: ['netlify-cli'], +}); +const getVersionPage = async () => { + const data = await getSystemInfo(); + return ` +────────────────────┐ + Environment Info │ +ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ +${data} +${USER_AGENT} +`; +}; +/** + * The main CLI command without any command (root action) + * @param {import('commander').OptionValues} options + * @param {import('./base-command.js').default} command + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'options' implicitly has an 'any' type. +const mainCommand = async function (options, command) { + const globalConfig = await getGlobalConfigStore(); + if (options.telemetryDisable) { + globalConfig.set('telemetryDisabled', true); + console.log('Netlify telemetry has been disabled'); + console.log('You can re-enable it anytime with the --telemetry-enable flag'); + exit(); + } + if (options.telemetryEnable) { + globalConfig.set('telemetryDisabled', false); + console.log('Netlify telemetry has been enabled'); + console.log('You can disable it anytime with the --telemetry-disable flag'); + await track('user_telemetryEnabled'); + exit(); + } + if (command.args[0] === 'version' || options.version) { + if (options.verbose) { + const versionPage = await getVersionPage(); + log(versionPage); + } + log(USER_AGENT); + exit(); + } + // if no command show help + if (command.args.length === 0) { + command.help(); + } + if (command.args[0] === 'help') { + if (command.args[1]) { + // @ts-expect-error TS(7006) FIXME: Parameter 'cmd' implicitly has an 'any' type. + const subCommand = command.commands.find((cmd) => cmd.name() === command.args[1]); + if (!subCommand) { + return logAndThrowError(`command ${command.args[1]} not found`); + } + subCommand.help(); + } + command.help(); + } + warn(`${chalk.yellow(command.args[0])} is not a ${command.name()} command.`); + // @ts-expect-error TS(7006) FIXME: Parameter 'cmd' implicitly has an 'any' type. + const allCommands = command.commands.map((cmd) => cmd.name()); + const suggestion = closest(command.args[0], allCommands); + const applySuggestion = await new Promise((resolve) => { + const prompt = inquirer.prompt({ + type: 'confirm', + name: 'suggestion', + message: `Did you mean ${chalk.blue(suggestion)}`, + default: false, + }); + setTimeout(() => { + // @ts-expect-error TS(2445) FIXME: Property 'close' is protected and only accessible ... Remove this comment to see the full error message + prompt.ui.close(); + resolve(false); + }, SUGGESTION_TIMEOUT); + prompt.then((value) => { + resolve(value.suggestion); + }); + }); + // create new log line + log(); + if (!applySuggestion) { + return logAndThrowError(`Run ${NETLIFY_CYAN(`${command.name()} help`)} for a list of available commands.`); + } + await execa(process.argv[0], [process.argv[1], suggestion], { stdio: 'inherit' }); +}; +/** + * Creates the `netlify-cli` command + */ +export const createMainCommand = () => { + const program = new BaseCommand('netlify'); + // register all the commands + createApiCommand(program); + createBlobsCommand(program); + createBuildCommand(program); + createCompletionCommand(program); + createDeployCommand(program); + createDevExecCommand(program); + createDevCommand(program); + createEnvCommand(program); + createFunctionsCommand(program); + createRecipesCommand(program); + createInitCommand(program); + createCloneCommand(program); + createLinkCommand(program); + createLoginCommand(program); + createLogoutCommand(program); + createOpenCommand(program); + createServeCommand(program); + createSitesCommand(program); + createStatusCommand(program); + createSwitchCommand(program); + createUnlinkCommand(program); + createWatchCommand(program); + createLogsCommand(program); + createDatabaseCommand(program); + program.setAnalyticsPayload({ didEnableCompileCache }); + program + .version(USER_AGENT, '-V') + .showSuggestionAfterError(true) + .option('--telemetry-disable', 'Disable telemetry') + .option('--telemetry-enable', 'Enables telemetry') + // needed for custom version output as we display further environment information + // commanders version output is set to uppercase -V + .addOption(new Option('-v, --version').hideHelp()) + .addOption(new Option('--verbose').hideHelp()) + .noHelpOptions() + .addHelpText('before', () => NETLIFY_CYAN('\n⬄ Netlify CLI\n')) + .addHelpText('after', () => { + const cliDocsEntrypointUrl = 'https://developers.netlify.com/cli'; + const docsUrl = 'https://docs.netlify.com'; + const bugsUrl = pkg.bugs?.url ?? ''; + return `→ For more help with the CLI, visit ${NETLIFY_CYAN(terminalLink(cliDocsEntrypointUrl, cliDocsEntrypointUrl, { fallback: false }))} +→ For help with Netlify, visit ${NETLIFY_CYAN(terminalLink(docsUrl, docsUrl, { fallback: false }))} +→ To report a CLI bug, visit ${NETLIFY_CYAN(terminalLink(bugsUrl, bugsUrl, { fallback: false }))}\n`; + }) + .configureOutput({ + outputError: (message, write) => { + write(` ${chalk.red(BANG)} Error: ${message.replace(/^error:\s/g, '')}`); + write(` ${chalk.red(BANG)} See more help with --help\n`); + }, + }) + .action(mainCommand); + program.commands.forEach((cmd) => { + const cmdName = cmd.name(); + if (cmdName in CI_FORCED_COMMANDS) { + const { description, options } = CI_FORCED_COMMANDS[cmdName]; + cmd.option(options, description); + } + }); + return program; +}; +//# sourceMappingURL=main.js.map \ No newline at end of file diff --git a/dist/commands/main.js.map b/dist/commands/main.js.map new file mode 100644 index 00000000000..552d93a95dd --- /dev/null +++ b/dist/commands/main.js.map @@ -0,0 +1 @@ +{"version":3,"file":"main.js","sourceRoot":"","sources":["../../src/commands/main.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAA;AAE7B,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAClC,OAAO,OAAO,MAAM,SAAS,CAAA;AAC7B,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAC7C,OAAO,QAAQ,MAAM,UAAU,CAAA;AAE/B,OAAO,EACL,IAAI,EACJ,KAAK,EACL,gBAAgB,EAChB,IAAI,EACJ,GAAG,EACH,YAAY,EACZ,UAAU,EACV,IAAI,EACJ,QAAQ,GACT,MAAM,6BAA6B,CAAA;AACpC,OAAO,KAAK,MAAM,mBAAmB,CAAA;AACrC,OAAO,oBAAoB,MAAM,qCAAqC,CAAA;AACtE,OAAO,iBAAiB,MAAM,kCAAkC,CAAA;AAChE,OAAO,EAAE,qBAAqB,EAAE,MAAM,kCAAkC,CAAA;AACxE,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAEhE,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,WAAW,MAAM,mBAAmB,CAAA;AAC3C,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAC/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAA;AAC1D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AACjD,OAAO,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAA;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAA;AACnD,OAAO,EAAE,oBAAoB,EAAE,MAAM,oBAAoB,CAAA;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAEvD,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AACvD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAA;AACrD,OAAO,YAAY,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAE3D,MAAM,kBAAkB,GAAG,GAAG,CAAA;AAE9B,kFAAkF;AAClF,MAAM,CAAC,MAAM,kBAAkB,GAAG;IAChC,SAAS,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,8CAA8C,EAAE;IAC9F,WAAW,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,8CAA8C,EAAE;IAChG,WAAW,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,8CAA8C,EAAE;IAChG,WAAW,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,8CAA8C,EAAE;IAChG,cAAc,EAAE,EAAE,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,8CAA8C,EAAE;IACnG,IAAI,EAAE;QACJ,OAAO,EAAE,SAAS;QAClB,WAAW,EAAE,6EAA6E;KAC3F;IACD,cAAc,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,2CAA2C,EAAE;CACrG,CAAA;AAED,OAAO,CAAC,EAAE,CAAC,mBAAmB,EAAE,KAAK,EAAE,GAA8B,EAAE,EAAE;IACvE,IAAI,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QAC/C,QAAQ,CACN,GAAG,KAAK,CAAC,GAAG,CAAC,QAAQ,GAAG,CAAC,IAAI,oBAAoB,CAAC,MAAM;YACtD,4DAA4D;YAC5D,6DAA6D;YAC7D,0CAA0C;YAC1C,6CAA6C;YAC7C,yEAAyE;YACzE,sEAAsE;YACtE,oFAAoF;YACpF,qDAAqD,GAAG,CAAC,IAAI,IAAI,CACpE,CAAA;IACH,CAAC;SAAM,CAAC;QACN,QAAQ,CACN,GAAG,KAAK,CAAC,GAAG,CACV,yCAAyC,CAC1C,gKAAgK,KAAK,CAAC,IAAI,CACzK,oCAAoC,CACrC,oCAAoC,KAAK,CAAC,SAAS,CAClD,8BAA8B,CAC/B,sCAAsC,KAAK,CAAC,SAAS,CACpD,2BAA2B,CAC5B,uCAAuC,CACzC,CAAA;QAED,MAAM,UAAU,GAAG,MAAM,aAAa,EAAE,CAAA;QAExC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,KAAK,IAAI,GAAG,CAAC,CAAC,CAAA;QACxC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,CAAA;QAClC,WAAW,CAAC,GAAG,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAA;IACzC,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;AACjB,CAAC,CAAC,CAAA;AAEF,MAAM,GAAG,GAAG,MAAM,iBAAiB,EAAE,CAAA;AAErC,MAAM,aAAa,GAAG,GAAG,EAAE,CACzB,OAAO,CAAC,GAAG,CAAC;IACV,MAAM,EAAE,CAAC,IAAI,EAAE,KAAK,CAAC;IACrB,QAAQ,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC;IACjC,QAAQ,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,CAAC;IACjD,iBAAiB,EAAE,CAAC,aAAa,CAAC;CACnC,CAAC,CAAA;AAEJ,MAAM,cAAc,GAAG,KAAK,IAAI,EAAE;IAChC,MAAM,IAAI,GAAG,MAAM,aAAa,EAAE,CAAA;IAElC,OAAO;;;;EAIP,IAAI;EACJ,UAAU;CACX,CAAA;AACD,CAAC,CAAA;AAED;;;;GAIG;AACH,qFAAqF;AACrF,MAAM,WAAW,GAAG,KAAK,WAAW,OAAO,EAAE,OAAO;IAClD,MAAM,YAAY,GAAG,MAAM,oBAAoB,EAAE,CAAA;IAEjD,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;QAC7B,YAAY,CAAC,GAAG,CAAC,mBAAmB,EAAE,IAAI,CAAC,CAAA;QAC3C,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAA;QAClD,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAA;QAC5E,IAAI,EAAE,CAAA;IACR,CAAC;IACD,IAAI,OAAO,CAAC,eAAe,EAAE,CAAC;QAC5B,YAAY,CAAC,GAAG,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAA;QAC5C,OAAO,CAAC,GAAG,CAAC,oCAAoC,CAAC,CAAA;QACjD,OAAO,CAAC,GAAG,CAAC,8DAA8D,CAAC,CAAA;QAC3E,MAAM,KAAK,CAAC,uBAAuB,CAAC,CAAA;QACpC,IAAI,EAAE,CAAA;IACR,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;QACrD,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;YACpB,MAAM,WAAW,GAAG,MAAM,cAAc,EAAE,CAAA;YAC1C,GAAG,CAAC,WAAW,CAAC,CAAA;QAClB,CAAC;QACD,GAAG,CAAC,UAAU,CAAC,CAAA;QACf,IAAI,EAAE,CAAA;IACR,CAAC;IAED,0BAA0B;IAC1B,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9B,OAAO,CAAC,IAAI,EAAE,CAAA;IAChB,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC;QAC/B,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;YACpB,iFAAiF;YACjF,MAAM,UAAU,GAAG,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;YACjF,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChB,OAAO,gBAAgB,CAAC,WAAW,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAA;YACjE,CAAC;YACD,UAAU,CAAC,IAAI,EAAE,CAAA;QACnB,CAAC;QACD,OAAO,CAAC,IAAI,EAAE,CAAA;IAChB,CAAC;IAED,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,aAAa,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;IAE5E,iFAAiF;IACjF,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAA;IAC7D,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW,CAAC,CAAA;IAExD,MAAM,eAAe,GAAG,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;QACpD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;YAC7B,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,YAAY;YAClB,OAAO,EAAE,gBAAgB,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE;YACjD,OAAO,EAAE,KAAK;SACf,CAAC,CAAA;QAEF,UAAU,CAAC,GAAG,EAAE;YACd,2IAA2I;YAC3I,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,CAAA;YACjB,OAAO,CAAC,KAAK,CAAC,CAAA;QAChB,CAAC,EAAE,kBAAkB,CAAC,CAAA;QAEtB,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;YACpB,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,CAAA;QAC3B,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IACF,sBAAsB;IACtB,GAAG,EAAE,CAAA;IAEL,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,OAAO,gBAAgB,CAAC,OAAO,YAAY,CAAC,GAAG,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,oCAAoC,CAAC,CAAA;IAC5G,CAAC;IAED,MAAM,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAA;AACnF,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAgB,EAAE;IACjD,MAAM,OAAO,GAAG,IAAI,WAAW,CAAC,SAAS,CAAC,CAAA;IAE1C,4BAA4B;IAC5B,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACzB,kBAAkB,CAAC,OAAO,CAAC,CAAA;IAC3B,kBAAkB,CAAC,OAAO,CAAC,CAAA;IAC3B,uBAAuB,CAAC,OAAO,CAAC,CAAA;IAChC,mBAAmB,CAAC,OAAO,CAAC,CAAA;IAC5B,oBAAoB,CAAC,OAAO,CAAC,CAAA;IAC7B,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACzB,gBAAgB,CAAC,OAAO,CAAC,CAAA;IACzB,sBAAsB,CAAC,OAAO,CAAC,CAAA;IAC/B,oBAAoB,CAAC,OAAO,CAAC,CAAA;IAC7B,iBAAiB,CAAC,OAAO,CAAC,CAAA;IAC1B,kBAAkB,CAAC,OAAO,CAAC,CAAA;IAC3B,iBAAiB,CAAC,OAAO,CAAC,CAAA;IAC1B,kBAAkB,CAAC,OAAO,CAAC,CAAA;IAC3B,mBAAmB,CAAC,OAAO,CAAC,CAAA;IAC5B,iBAAiB,CAAC,OAAO,CAAC,CAAA;IAC1B,kBAAkB,CAAC,OAAO,CAAC,CAAA;IAC3B,kBAAkB,CAAC,OAAO,CAAC,CAAA;IAC3B,mBAAmB,CAAC,OAAO,CAAC,CAAA;IAC5B,mBAAmB,CAAC,OAAO,CAAC,CAAA;IAC5B,mBAAmB,CAAC,OAAO,CAAC,CAAA;IAC5B,kBAAkB,CAAC,OAAO,CAAC,CAAA;IAC3B,iBAAiB,CAAC,OAAO,CAAC,CAAA;IAC1B,qBAAqB,CAAC,OAAO,CAAC,CAAA;IAE9B,OAAO,CAAC,mBAAmB,CAAC,EAAE,qBAAqB,EAAE,CAAC,CAAA;IAEtD,OAAO;SACJ,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC;SACzB,wBAAwB,CAAC,IAAI,CAAC;SAC9B,MAAM,CAAC,qBAAqB,EAAE,mBAAmB,CAAC;SAClD,MAAM,CAAC,oBAAoB,EAAE,mBAAmB,CAAC;QAClD,iFAAiF;QACjF,mDAAmD;SAClD,SAAS,CAAC,IAAI,MAAM,CAAC,eAAe,CAAC,CAAC,QAAQ,EAAE,CAAC;SACjD,SAAS,CAAC,IAAI,MAAM,CAAC,WAAW,CAAC,CAAC,QAAQ,EAAE,CAAC;SAC7C,aAAa,EAAE;SACf,WAAW,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,YAAY,CAAC,mBAAmB,CAAC,CAAC;SAC9D,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE;QACzB,MAAM,oBAAoB,GAAG,oCAAoC,CAAA;QACjE,MAAM,OAAO,GAAG,0BAA0B,CAAA;QAC1C,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,GAAG,IAAI,EAAE,CAAA;QACnC,OAAO,uCAAuC,YAAY,CACxD,YAAY,CAAC,oBAAoB,EAAE,oBAAoB,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAC9E;iCAC0B,YAAY,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;+BACnE,YAAY,CAAC,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC,IAAI,CAAA;IAChG,CAAC,CAAC;SACD,eAAe,CAAC;QACf,WAAW,EAAE,CAAC,OAAO,EAAE,KAAK,EAAE,EAAE;YAC9B,KAAK,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,aAAa,OAAO,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,EAAE,CAAC,CAAA;YAC1E,KAAK,CAAC,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAA;QAC5D,CAAC;KACF,CAAC;SACD,MAAM,CAAC,WAAW,CAAC,CAAA;IAEtB,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE;QAC/B,MAAM,OAAO,GAAG,GAAG,CAAC,IAAI,EAAE,CAAA;QAC1B,IAAI,OAAO,IAAI,kBAAkB,EAAE,CAAC;YAClC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,kBAAkB,CAAC,OAA0C,CAAC,CAAA;YAC/F,GAAG,CAAC,MAAM,CAAC,OAAO,EAAE,WAAW,CAAC,CAAA;QAClC,CAAC;IACH,CAAC,CAAC,CAAA;IAEF,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/open/index.d.ts b/dist/commands/open/index.d.ts new file mode 100644 index 00000000000..74e8d1e6f0d --- /dev/null +++ b/dist/commands/open/index.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const createOpenCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/open/index.d.ts.map b/dist/commands/open/index.d.ts.map new file mode 100644 index 00000000000..cb502932a4d --- /dev/null +++ b/dist/commands/open/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/open/index.ts"],"names":[],"mappings":"AAGA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,iBAAiB,GAAI,SAAS,WAAW,gBA+BrD,CAAA"} \ No newline at end of file diff --git a/dist/commands/open/index.js b/dist/commands/open/index.js new file mode 100644 index 00000000000..321b20b450d --- /dev/null +++ b/dist/commands/open/index.js @@ -0,0 +1,32 @@ +import requiresSiteInfo from '../../utils/hooks/requires-site-info.js'; +export const createOpenCommand = (program) => { + program + .command('open:admin') + .description('Opens current project admin UI in Netlify') + .addExamples(['netlify open:admin']) + .hook('preAction', requiresSiteInfo) + .action(async (options, command) => { + const { openAdmin } = await import('./open-admin.js'); + await openAdmin(options, command); + }); + program + .command('open:site') + .description('Opens current project url in browser') + .addExamples(['netlify open:site']) + .hook('preAction', requiresSiteInfo) + .action(async (options, command) => { + const { openSite } = await import('./open-site.js'); + await openSite(options, command); + }); + return program + .command('open') + .description(`Open settings for the project linked to the current folder`) + .option('--site', 'Open project') + .option('--admin', 'Open Netlify project') + .addExamples(['netlify open --site', 'netlify open --admin', 'netlify open:admin', 'netlify open:site']) + .action(async (options, command) => { + const { open } = await import('./open.js'); + await open(options, command); + }); +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/open/index.js.map b/dist/commands/open/index.js.map new file mode 100644 index 00000000000..f7d4eab0cc2 --- /dev/null +++ b/dist/commands/open/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/open/index.ts"],"names":[],"mappings":"AAEA,OAAO,gBAAgB,MAAM,yCAAyC,CAAA;AAGtE,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,OAAoB,EAAE,EAAE;IACxD,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CAAC,2CAA2C,CAAC;SACxD,WAAW,CAAC,CAAC,oBAAoB,CAAC,CAAC;SACnC,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC;SACnC,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;QAC5D,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAA;QACrD,MAAM,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACnC,CAAC,CAAC,CAAA;IAEJ,OAAO;SACJ,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CAAC,sCAAsC,CAAC;SACnD,WAAW,CAAC,CAAC,mBAAmB,CAAC,CAAC;SAClC,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC;SACnC,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;QAC5D,MAAM,EAAE,QAAQ,EAAE,GAAG,MAAM,MAAM,CAAC,gBAAgB,CAAC,CAAA;QACnD,MAAM,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAClC,CAAC,CAAC,CAAA;IAEJ,OAAO,OAAO;SACX,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,4DAA4D,CAAC;SACzE,MAAM,CAAC,QAAQ,EAAE,cAAc,CAAC;SAChC,MAAM,CAAC,SAAS,EAAE,sBAAsB,CAAC;SACzC,WAAW,CAAC,CAAC,qBAAqB,EAAE,sBAAsB,EAAE,oBAAoB,EAAE,mBAAmB,CAAC,CAAC;SACvG,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;QAC5D,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,WAAW,CAAC,CAAA;QAC1C,MAAM,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAC9B,CAAC,CAAC,CAAA;AACN,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/open/open-admin.d.ts b/dist/commands/open/open-admin.d.ts new file mode 100644 index 00000000000..18546bc2dd5 --- /dev/null +++ b/dist/commands/open/open-admin.d.ts @@ -0,0 +1,3 @@ +import type BaseCommand from '../base-command.js'; +export declare const openAdmin: (_options: unknown, command: BaseCommand) => Promise; +//# sourceMappingURL=open-admin.d.ts.map \ No newline at end of file diff --git a/dist/commands/open/open-admin.d.ts.map b/dist/commands/open/open-admin.d.ts.map new file mode 100644 index 00000000000..9e0cef8218e --- /dev/null +++ b/dist/commands/open/open-admin.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"open-admin.d.ts","sourceRoot":"","sources":["../../../src/commands/open/open-admin.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAEjD,eAAO,MAAM,SAAS,GAAU,UAAU,OAAO,EAAE,SAAS,WAAW,kBAUtE,CAAA"} \ No newline at end of file diff --git a/dist/commands/open/open-admin.js b/dist/commands/open/open-admin.js new file mode 100644 index 00000000000..d3f46370706 --- /dev/null +++ b/dist/commands/open/open-admin.js @@ -0,0 +1,11 @@ +import { exit, log } from '../../utils/command-helpers.js'; +import openBrowser from '../../utils/open-browser.js'; +export const openAdmin = async (_options, command) => { + const { siteInfo } = command.netlify; + await command.authenticate(); + log(`Opening "${siteInfo.name}" project admin UI:`); + log(`> ${siteInfo.admin_url}`); + await openBrowser({ url: siteInfo.admin_url }); + exit(); +}; +//# sourceMappingURL=open-admin.js.map \ No newline at end of file diff --git a/dist/commands/open/open-admin.js.map b/dist/commands/open/open-admin.js.map new file mode 100644 index 00000000000..6cefd4b1276 --- /dev/null +++ b/dist/commands/open/open-admin.js.map @@ -0,0 +1 @@ +{"version":3,"file":"open-admin.js","sourceRoot":"","sources":["../../../src/commands/open/open-admin.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAA;AAC1D,OAAO,WAAW,MAAM,6BAA6B,CAAA;AAGrD,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,QAAiB,EAAE,OAAoB,EAAE,EAAE;IACzE,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IAEpC,MAAM,OAAO,CAAC,YAAY,EAAE,CAAA;IAE5B,GAAG,CAAC,YAAY,QAAQ,CAAC,IAAI,qBAAqB,CAAC,CAAA;IACnD,GAAG,CAAC,KAAK,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAA;IAE9B,MAAM,WAAW,CAAC,EAAE,GAAG,EAAE,QAAQ,CAAC,SAAS,EAAE,CAAC,CAAA;IAC9C,IAAI,EAAE,CAAA;AACR,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/open/open-site.d.ts b/dist/commands/open/open-site.d.ts new file mode 100644 index 00000000000..7642ab389e1 --- /dev/null +++ b/dist/commands/open/open-site.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const openSite: (_options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=open-site.d.ts.map \ No newline at end of file diff --git a/dist/commands/open/open-site.d.ts.map b/dist/commands/open/open-site.d.ts.map new file mode 100644 index 00000000000..6738763d206 --- /dev/null +++ b/dist/commands/open/open-site.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"open-site.d.ts","sourceRoot":"","sources":["../../../src/commands/open/open-site.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAIxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,QAAQ,GAAU,UAAU,YAAY,EAAE,SAAS,WAAW,kBAW1E,CAAA"} \ No newline at end of file diff --git a/dist/commands/open/open-site.js b/dist/commands/open/open-site.js new file mode 100644 index 00000000000..0c079b5af5f --- /dev/null +++ b/dist/commands/open/open-site.js @@ -0,0 +1,12 @@ +import { exit, log } from '../../utils/command-helpers.js'; +import openBrowser from '../../utils/open-browser.js'; +export const openSite = async (_options, command) => { + const { siteInfo } = command.netlify; + await command.authenticate(); + const url = siteInfo.ssl_url || siteInfo.url; + log(`Opening "${siteInfo.name}" project url:`); + log(`> ${url}`); + await openBrowser({ url }); + exit(); +}; +//# sourceMappingURL=open-site.js.map \ No newline at end of file diff --git a/dist/commands/open/open-site.js.map b/dist/commands/open/open-site.js.map new file mode 100644 index 00000000000..2d8c7ae50b5 --- /dev/null +++ b/dist/commands/open/open-site.js.map @@ -0,0 +1 @@ +{"version":3,"file":"open-site.js","sourceRoot":"","sources":["../../../src/commands/open/open-site.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAA;AAC1D,OAAO,WAAW,MAAM,6BAA6B,CAAA;AAGrD,MAAM,CAAC,MAAM,QAAQ,GAAG,KAAK,EAAE,QAAsB,EAAE,OAAoB,EAAE,EAAE;IAC7E,MAAM,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IAEpC,MAAM,OAAO,CAAC,YAAY,EAAE,CAAA;IAE5B,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,IAAI,QAAQ,CAAC,GAAG,CAAA;IAC5C,GAAG,CAAC,YAAY,QAAQ,CAAC,IAAI,gBAAgB,CAAC,CAAA;IAC9C,GAAG,CAAC,KAAK,GAAG,EAAE,CAAC,CAAA;IAEf,MAAM,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;IAC1B,IAAI,EAAE,CAAA;AACR,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/open/open.d.ts b/dist/commands/open/open.d.ts new file mode 100644 index 00000000000..a411c9c6f78 --- /dev/null +++ b/dist/commands/open/open.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const open: (options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=open.d.ts.map \ No newline at end of file diff --git a/dist/commands/open/open.d.ts.map b/dist/commands/open/open.d.ts.map new file mode 100644 index 00000000000..1c23724422d --- /dev/null +++ b/dist/commands/open/open.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"open.d.ts","sourceRoot":"","sources":["../../../src/commands/open/open.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAGxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAK5C,eAAO,MAAM,IAAI,GAAU,SAAS,YAAY,EAAE,SAAS,WAAW,kBAUrE,CAAA"} \ No newline at end of file diff --git a/dist/commands/open/open.js b/dist/commands/open/open.js new file mode 100644 index 00000000000..fa0f54992e8 --- /dev/null +++ b/dist/commands/open/open.js @@ -0,0 +1,14 @@ +import { log } from '../../utils/command-helpers.js'; +import { openAdmin } from './open-admin.js'; +import { openSite } from './open-site.js'; +export const open = async (options, command) => { + if (!options.site || !options.admin) { + log(command.helpInformation()); + } + if (options.site) { + await openSite(options, command); + } + // Default open netlify admin + await openAdmin(options, command); +}; +//# sourceMappingURL=open.js.map \ No newline at end of file diff --git a/dist/commands/open/open.js.map b/dist/commands/open/open.js.map new file mode 100644 index 00000000000..fce2457d611 --- /dev/null +++ b/dist/commands/open/open.js.map @@ -0,0 +1 @@ +{"version":3,"file":"open.js","sourceRoot":"","sources":["../../../src/commands/open/open.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAA;AAGpD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAC3C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAEzC,MAAM,CAAC,MAAM,IAAI,GAAG,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IACxE,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QACpC,GAAG,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,CAAA;IAChC,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAClC,CAAC;IACD,6BAA6B;IAC7B,MAAM,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AACnC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/recipes/common.d.ts b/dist/commands/recipes/common.d.ts new file mode 100644 index 00000000000..3351de4270a --- /dev/null +++ b/dist/commands/recipes/common.d.ts @@ -0,0 +1,3 @@ +export declare const getRecipe: (name: any) => Promise; +export declare const listRecipes: () => Promise; +//# sourceMappingURL=common.d.ts.map \ No newline at end of file diff --git a/dist/commands/recipes/common.d.ts.map b/dist/commands/recipes/common.d.ts.map new file mode 100644 index 00000000000..cd63f339f05 --- /dev/null +++ b/dist/commands/recipes/common.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"common.d.ts","sourceRoot":"","sources":["../../../src/commands/recipes/common.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,SAAS,GAAU,SAAI,iBAQnC,CAAA;AAED,eAAO,MAAM,WAAW,sBAmBvB,CAAA"} \ No newline at end of file diff --git a/dist/commands/recipes/common.js b/dist/commands/recipes/common.js new file mode 100644 index 00000000000..346548aa31a --- /dev/null +++ b/dist/commands/recipes/common.js @@ -0,0 +1,26 @@ +import fs from 'fs/promises'; +import { dirname, join, resolve } from 'path'; +import { fileURLToPath, pathToFileURL } from 'url'; +const directoryPath = dirname(fileURLToPath(import.meta.url)); +// @ts-expect-error TS(7006) FIXME: Parameter 'name' implicitly has an 'any' type. +export const getRecipe = async (name) => { + const recipePath = resolve(directoryPath, '../../recipes', name, 'index.js'); + // windows needs a URL for absolute paths + const recipe = await import(pathToFileURL(recipePath).href); + return recipe; +}; +export const listRecipes = async () => { + const recipesPath = resolve(directoryPath, '../../recipes'); + const recipeNames = await fs.readdir(recipesPath); + const recipes = await Promise.all(recipeNames.map(async (name) => { + const recipePath = join(recipesPath, name, 'index.js'); + // windows needs a URL for absolute paths + const recipe = await import(pathToFileURL(recipePath).href); + return { + ...recipe, + name, + }; + })); + return recipes; +}; +//# sourceMappingURL=common.js.map \ No newline at end of file diff --git a/dist/commands/recipes/common.js.map b/dist/commands/recipes/common.js.map new file mode 100644 index 00000000000..cd8745f6ed2 --- /dev/null +++ b/dist/commands/recipes/common.js.map @@ -0,0 +1 @@ +{"version":3,"file":"common.js","sourceRoot":"","sources":["../../../src/commands/recipes/common.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAA;AAC5B,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAC7C,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AAElD,MAAM,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAE7D,kFAAkF;AAClF,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,IAAI,EAAE,EAAE;IACtC,MAAM,UAAU,GAAG,OAAO,CAAC,aAAa,EAAE,eAAe,EAAE,IAAI,EAAE,UAAU,CAAC,CAAA;IAE5E,yCAAyC;IAEzC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAA;IAE3D,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,IAAI,EAAE;IACpC,MAAM,WAAW,GAAG,OAAO,CAAC,aAAa,EAAE,eAAe,CAAC,CAAA;IAC3D,MAAM,WAAW,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,CAAC,CAAA;IACjD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QAC7B,MAAM,UAAU,GAAG,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,UAAU,CAAC,CAAA;QAEtD,yCAAyC;QAEzC,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,CAAA;QAE3D,OAAO;YACL,GAAG,MAAM;YACT,IAAI;SACL,CAAA;IACH,CAAC,CAAC,CACH,CAAA;IAED,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/recipes/index.d.ts b/dist/commands/recipes/index.d.ts new file mode 100644 index 00000000000..5b1d8a0cabe --- /dev/null +++ b/dist/commands/recipes/index.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const createRecipesCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/recipes/index.d.ts.map b/dist/commands/recipes/index.d.ts.map new file mode 100644 index 00000000000..05d3aca20ec --- /dev/null +++ b/dist/commands/recipes/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/recipes/index.ts"],"names":[],"mappings":"AAEA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,oBAAoB,GAAI,SAAS,WAAW,gBAoBxD,CAAA"} \ No newline at end of file diff --git a/dist/commands/recipes/index.js b/dist/commands/recipes/index.js new file mode 100644 index 00000000000..bdf15eca322 --- /dev/null +++ b/dist/commands/recipes/index.js @@ -0,0 +1,21 @@ +export const createRecipesCommand = (program) => { + program + .command('recipes:list') + .description(`List the recipes available to create and modify files in a project`) + .addExamples(['netlify recipes:list']) + .action(async () => { + const { recipesListCommand } = await import('./recipes-list.js'); + await recipesListCommand(); + }); + return program + .command('recipes') + .argument('[name]', 'name of the recipe') + .description(`Create and modify files in a project using pre-defined recipes`) + .option('-n, --name ', 'recipe name to use') + .addExamples(['netlify recipes my-recipe', 'netlify recipes --name my-recipe']) + .action(async (recipeName, options, command) => { + const { recipesCommand } = await import('./recipes.js'); + await recipesCommand(recipeName, options, command); + }); +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/recipes/index.js.map b/dist/commands/recipes/index.js.map new file mode 100644 index 00000000000..022c3dfd964 --- /dev/null +++ b/dist/commands/recipes/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/recipes/index.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,OAAoB,EAAE,EAAE;IAC3D,OAAO;SACJ,OAAO,CAAC,cAAc,CAAC;SACvB,WAAW,CAAC,oEAAoE,CAAC;SACjF,WAAW,CAAC,CAAC,sBAAsB,CAAC,CAAC;SACrC,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAA;QAChE,MAAM,kBAAkB,EAAE,CAAA;IAC5B,CAAC,CAAC,CAAA;IAEJ,OAAO,OAAO;SACX,OAAO,CAAC,SAAS,CAAC;SAClB,QAAQ,CAAC,QAAQ,EAAE,oBAAoB,CAAC;SACxC,WAAW,CAAC,gEAAgE,CAAC;SAC7E,MAAM,CAAC,mBAAmB,EAAE,oBAAoB,CAAC;SACjD,WAAW,CAAC,CAAC,2BAA2B,EAAE,kCAAkC,CAAC,CAAC;SAC9E,MAAM,CAAC,KAAK,EAAE,UAAkB,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;QAChF,MAAM,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CAAC,cAAc,CAAC,CAAA;QACvD,MAAM,cAAc,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;AACN,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/recipes/recipes-list.d.ts b/dist/commands/recipes/recipes-list.d.ts new file mode 100644 index 00000000000..7bc71964fce --- /dev/null +++ b/dist/commands/recipes/recipes-list.d.ts @@ -0,0 +1,5 @@ +/** + * The recipes:list command + */ +export declare const recipesListCommand: () => Promise; +//# sourceMappingURL=recipes-list.d.ts.map \ No newline at end of file diff --git a/dist/commands/recipes/recipes-list.d.ts.map b/dist/commands/recipes/recipes-list.d.ts.map new file mode 100644 index 00000000000..6874abe0291 --- /dev/null +++ b/dist/commands/recipes/recipes-list.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"recipes-list.d.ts","sourceRoot":"","sources":["../../../src/commands/recipes/recipes-list.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,eAAO,MAAM,kBAAkB,qBAW9B,CAAA"} \ No newline at end of file diff --git a/dist/commands/recipes/recipes-list.js b/dist/commands/recipes/recipes-list.js new file mode 100644 index 00000000000..01fedf93738 --- /dev/null +++ b/dist/commands/recipes/recipes-list.js @@ -0,0 +1,15 @@ +import AsciiTable from 'ascii-table'; +import { listRecipes } from './common.js'; +/** + * The recipes:list command + */ +export const recipesListCommand = async () => { + const recipes = await listRecipes(); + const table = new AsciiTable(`Usage: netlify recipes `); + table.setHeading('Name', 'Description'); + recipes.forEach(({ description, name }) => { + table.addRow(name, description); + }); + console.log(table.toString()); +}; +//# sourceMappingURL=recipes-list.js.map \ No newline at end of file diff --git a/dist/commands/recipes/recipes-list.js.map b/dist/commands/recipes/recipes-list.js.map new file mode 100644 index 00000000000..770ed5463e1 --- /dev/null +++ b/dist/commands/recipes/recipes-list.js.map @@ -0,0 +1 @@ +{"version":3,"file":"recipes-list.js","sourceRoot":"","sources":["../../../src/commands/recipes/recipes-list.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,aAAa,CAAA;AAEpC,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAEzC;;GAEG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,IAAI,EAAE;IAC3C,MAAM,OAAO,GAAG,MAAM,WAAW,EAAE,CAAA;IACnC,MAAM,KAAK,GAAG,IAAI,UAAU,CAAC,+BAA+B,CAAC,CAAA;IAE7D,KAAK,CAAC,UAAU,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IAEvC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,EAAE;QACxC,KAAK,CAAC,MAAM,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;IACjC,CAAC,CAAC,CAAA;IAEF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,CAAA;AAC/B,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/recipes/recipes.d.ts b/dist/commands/recipes/recipes.d.ts new file mode 100644 index 00000000000..cb21e56e942 --- /dev/null +++ b/dist/commands/recipes/recipes.d.ts @@ -0,0 +1,12 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export interface RunRecipeOptions { + args: string[]; + command?: BaseCommand; + config: unknown; + recipeName: string; + repositoryRoot: string; +} +export declare const runRecipe: ({ args, command, config, recipeName, repositoryRoot }: RunRecipeOptions) => Promise; +export declare const recipesCommand: (recipeName: string, options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=recipes.d.ts.map \ No newline at end of file diff --git a/dist/commands/recipes/recipes.d.ts.map b/dist/commands/recipes/recipes.d.ts.map new file mode 100644 index 00000000000..d22940473c5 --- /dev/null +++ b/dist/commands/recipes/recipes.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"recipes.d.ts","sourceRoot":"","sources":["../../../src/commands/recipes/recipes.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAKxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAM5C,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,OAAO,CAAC,EAAE,WAAW,CAAA;IACrB,MAAM,EAAE,OAAO,CAAA;IACf,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;CACvB;AAED,eAAO,MAAM,SAAS,GAAU,uDAAuD,gBAAgB,iBAItG,CAAA;AAED,eAAO,MAAM,cAAc,GAAU,YAAY,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,KAAG,OAAO,CAAC,GAAG,CAiDjH,CAAA"} \ No newline at end of file diff --git a/dist/commands/recipes/recipes.js b/dist/commands/recipes/recipes.js new file mode 100644 index 00000000000..ca1750c4551 --- /dev/null +++ b/dist/commands/recipes/recipes.js @@ -0,0 +1,53 @@ +import { basename } from 'path'; +import { closest } from 'fastest-levenshtein'; +import inquirer from 'inquirer'; +import { NETLIFYDEVERR, chalk, log } from '../../utils/command-helpers.js'; +import { getRecipe, listRecipes } from './common.js'; +const SUGGESTION_TIMEOUT = 1e4; +export const runRecipe = async ({ args, command, config, recipeName, repositoryRoot }) => { + const recipe = await getRecipe(recipeName); + return recipe.run({ args, command, config, repositoryRoot }); +}; +export const recipesCommand = async (recipeName, options, command) => { + const { config, repositoryRoot } = command.netlify; + const sanitizedRecipeName = basename(recipeName || '').toLowerCase(); + if (sanitizedRecipeName.length === 0) { + return command.help(); + } + const args = command.args.slice(1); + try { + return await runRecipe({ args, command, config, recipeName: sanitizedRecipeName, repositoryRoot }); + } + catch (error) { + if ( + // The ESM loader throws this instead of MODULE_NOT_FOUND + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + error.code !== 'ERR_MODULE_NOT_FOUND') { + throw error; + } + log(`${NETLIFYDEVERR} ${chalk.yellow(recipeName)} is not a valid recipe name.`); + const recipes = await listRecipes(); + const recipeNames = recipes.map(({ name }) => name); + const suggestion = closest(recipeName, recipeNames); + const applySuggestion = await new Promise((resolve) => { + const prompt = inquirer.prompt({ + type: 'confirm', + name: 'suggestion', + message: `Did you mean ${chalk.blue(suggestion)}`, + default: false, + }); + setTimeout(() => { + // @ts-expect-error TS(2445) FIXME: Property 'close' is protected and only accessible ... Remove this comment to see the full error message + prompt.ui.close(); + resolve(false); + }, SUGGESTION_TIMEOUT); + prompt.then((value) => { + resolve(value.suggestion); + }); + }); + if (applySuggestion) { + return recipesCommand(suggestion, options, command); + } + } +}; +//# sourceMappingURL=recipes.js.map \ No newline at end of file diff --git a/dist/commands/recipes/recipes.js.map b/dist/commands/recipes/recipes.js.map new file mode 100644 index 00000000000..a9bc7c5f4e4 --- /dev/null +++ b/dist/commands/recipes/recipes.js.map @@ -0,0 +1 @@ +{"version":3,"file":"recipes.js","sourceRoot":"","sources":["../../../src/commands/recipes/recipes.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/serve/index.d.ts b/dist/commands/serve/index.d.ts new file mode 100644 index 00000000000..1225062fb71 --- /dev/null +++ b/dist/commands/serve/index.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const createServeCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/serve/index.d.ts.map b/dist/commands/serve/index.d.ts.map new file mode 100644 index 00000000000..8414d2185a5 --- /dev/null +++ b/dist/commands/serve/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/serve/index.ts"],"names":[],"mappings":"AAIA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,kBAAkB,GAAI,SAAS,WAAW,gBAmDjD,CAAA"} \ No newline at end of file diff --git a/dist/commands/serve/index.js b/dist/commands/serve/index.js new file mode 100644 index 00000000000..69cc3cf5beb --- /dev/null +++ b/dist/commands/serve/index.js @@ -0,0 +1,32 @@ +import { Option } from 'commander'; +import { normalizeContext } from '../../utils/env/index.js'; +import { getGeoCountryArgParser } from '../../utils/validation.js'; +export const createServeCommand = (program) => program + .command('serve') + .description('Build the project for production and serve locally. This does not watch the code for changes, so if you need to rebuild your project then you must exit and run `serve` again.') + .option('--context ', 'Specify a deploy context for environment variables (ā€productionā€, ā€deploy-previewā€, ā€branch-deployā€, ā€devā€) or `branch:your-branch` where `your-branch` is the name of a branch (default: dev)', normalizeContext) + .option('-p ,--port ', 'port of netlify dev', (value) => Number.parseInt(value)) + .option('-d ,--dir ', 'dir with static files') + .option('-f ,--functions ', 'specify a functions folder to serve') + .option('-o, --offline', 'Disables any features that require network access') + .addOption(new Option('--internal-disable-edge-functions', "disables edge functions. use this if your environment doesn't support Deno. This option is internal and should not be used by end users.").hideHelp(true)) + .option('--functions-port ', 'port of functions server', (value) => Number.parseInt(value)) + .addOption(new Option('--geo ', 'force geolocation data to be updated, use cached data from the last 24h if found, or use a mock location') + .choices(['cache', 'mock', 'update']) + .default('cache')) + .addOption(new Option('--country ', 'Two-letter country code (https://ntl.fyi/country-codes) to use as mock geolocation (enables --geo=mock automatically)').argParser(getGeoCountryArgParser('netlify dev --geo=mock --country=FR'))) + .addOption(new Option('--staticServerPort ', 'port of the static app server used when no framework is detected') + .argParser((value) => Number.parseInt(value)) + .hideHelp()) + .addExamples([ + 'netlify serve', + 'BROWSER=none netlify serve # disable browser auto opening', + 'netlify serve --context production # Use env var values from production context', + 'netlify serve --context deploy-preview # Use env var values from deploy-preview context', + 'netlify serve --context branch:feat/make-it-pop # Use env var values from the feat/make-it-pop branch context or branch-deploy context', +]) + .action(async (options, command) => { + const { serve } = await import('./serve.js'); + await serve(options, command); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/serve/index.js.map b/dist/commands/serve/index.js.map new file mode 100644 index 00000000000..e3a14d2bba2 --- /dev/null +++ b/dist/commands/serve/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/serve/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAA;AAElC,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAA;AAGlE,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAAoB,EAAE,EAAE,CACzD,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CACV,gLAAgL,CACjL;KACA,MAAM,CACL,qBAAqB,EACrB,gMAAgM,EAChM,gBAAgB,CACjB;KACA,MAAM,CAAC,mBAAmB,EAAE,qBAAqB,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;KACrF,MAAM,CAAC,kBAAkB,EAAE,uBAAuB,CAAC;KACnD,MAAM,CAAC,0BAA0B,EAAE,qCAAqC,CAAC;KACzE,MAAM,CAAC,eAAe,EAAE,mDAAmD,CAAC;KAC5E,SAAS,CACR,IAAI,MAAM,CACR,mCAAmC,EACnC,0IAA0I,CAC3I,CAAC,QAAQ,CAAC,IAAI,CAAC,CACjB;KACA,MAAM,CAAC,yBAAyB,EAAE,0BAA0B,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;KAChG,SAAS,CACR,IAAI,MAAM,CACR,cAAc,EACd,0GAA0G,CAC3G;KACE,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;KACpC,OAAO,CAAC,OAAO,CAAC,CACpB;KACA,SAAS,CACR,IAAI,MAAM,CACR,wBAAwB,EACxB,uHAAuH,CACxH,CAAC,SAAS,CAAC,sBAAsB,CAAC,qCAAqC,CAAC,CAAC,CAC3E;KACA,SAAS,CACR,IAAI,MAAM,CAAC,2BAA2B,EAAE,kEAAkE,CAAC;KACxG,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;KAC5C,QAAQ,EAAE,CACd;KACA,WAAW,CAAC;IACX,eAAe;IACf,2DAA2D;IAC3D,iFAAiF;IACjF,yFAAyF;IACzF,wIAAwI;CACzI,CAAC;KACD,MAAM,CAAC,KAAK,EAAE,OAAe,EAAE,OAAoB,EAAE,EAAE;IACtD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAA;IAC5C,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAC/B,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/serve/serve.d.ts b/dist/commands/serve/serve.d.ts new file mode 100644 index 00000000000..b71b44bc901 --- /dev/null +++ b/dist/commands/serve/serve.d.ts @@ -0,0 +1,4 @@ +import type { OptionValues } from 'commander'; +import type BaseCommand from '../base-command.js'; +export declare const serve: (options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=serve.d.ts.map \ No newline at end of file diff --git a/dist/commands/serve/serve.d.ts.map b/dist/commands/serve/serve.d.ts.map new file mode 100644 index 00000000000..9a2bd8d1ee2 --- /dev/null +++ b/dist/commands/serve/serve.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../../../src/commands/serve/serve.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AA8B7C,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAGjD,eAAO,MAAM,KAAK,GAAU,SAAS,YAAY,EAAE,SAAS,WAAW,uBA8JtE,CAAA"} \ No newline at end of file diff --git a/dist/commands/serve/serve.js b/dist/commands/serve/serve.js new file mode 100644 index 00000000000..921f5282f33 --- /dev/null +++ b/dist/commands/serve/serve.js @@ -0,0 +1,149 @@ +import process from 'process'; +import { BLOBS_CONTEXT_VARIABLE, encodeBlobsContext, getBlobsContextWithAPIAccess, getBlobsContextWithEdgeAccess, } from '../../lib/blobs/blobs.js'; +import { promptEditorHelper } from '../../lib/edge-functions/editor-helper.js'; +import { startFunctionsServer } from '../../lib/functions/server.js'; +import { printBanner } from '../../utils/dev-server-banner.js'; +import { NETLIFYDEVERR, NETLIFYDEVLOG, NETLIFYDEVWARN, chalk, exit, log, normalizeConfig, } from '../../utils/command-helpers.js'; +import detectServerSettings, { getConfigWithPlugins } from '../../utils/detect-server-settings.js'; +import { UNLINKED_SITE_MOCK_ID, getDotEnvVariables, getSiteInformation, injectEnvVariables } from '../../utils/dev.js'; +import { getEnvelopeEnv } from '../../utils/env/index.js'; +import { getFrameworksAPIConfig } from '../../utils/frameworks-api.js'; +import { getInternalFunctionsDir } from '../../utils/functions/functions.js'; +import { ensureNetlifyIgnore } from '../../utils/gitignore.js'; +import openBrowser from '../../utils/open-browser.js'; +import { generateInspectSettings, startProxyServer } from '../../utils/proxy-server.js'; +import { runBuildTimeline } from '../../utils/run-build.js'; +export const serve = async (options, command) => { + const { api, cachedConfig, config, frameworksAPIPaths, repositoryRoot, site, siteInfo, state } = command.netlify; + config.dev = config.dev != null ? { ...config.dev } : undefined; + config.build = { ...config.build }; + const devConfig = { + ...(config.functionsDirectory && { functions: config.functionsDirectory }), + ...('publish' in config.build && config.build.publish && { publish: config.build.publish }), + ...config.dev, + ...options, + // Override the `framework` value so that we start a static server and not + // the framework's development server. + framework: '#static', + }; + let { env } = cachedConfig; + if (!options.offline) { + env = await getEnvelopeEnv({ api, context: options.context, env, siteInfo }); + log(`${NETLIFYDEVLOG} Injecting environment variable values for ${chalk.yellow('all scopes')}`); + } + env = await getDotEnvVariables({ devConfig, env, site }); + injectEnvVariables(env); + await promptEditorHelper({ chalk, config, log, NETLIFYDEVLOG, repositoryRoot, state }); + const { accountId, addonsUrls, capabilities, siteUrl, timeouts } = await getSiteInformation({ + // inherited from base command --offline + offline: options.offline, + api, + site, + siteInfo, + }); + if (!site.root) { + throw new Error('Site root not found'); + } + // Ensure the internal functions directory exists so that the functions + // server and registry are initialized, and any functions created by + // Netlify Build are loaded. + await getInternalFunctionsDir({ + base: site.root, + ensureExists: true, + packagePath: command.workspacePackage, + }); + await frameworksAPIPaths.functions.ensureExists(); + let settings; + try { + settings = await detectServerSettings(devConfig, options, command); + cachedConfig.config = getConfigWithPlugins(cachedConfig.config, settings); + } + catch (error_) { + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + log(NETLIFYDEVERR, error_.message); + return exit(1); + } + command.setAnalyticsPayload({ live: options.live }); + log(`${NETLIFYDEVLOG} Building project for production`); + log(`${NETLIFYDEVWARN} Changes will not be hot-reloaded, so if you need to rebuild your project you must exit and run 'netlify serve' again`); + const blobsOptions = { + debug: options.debug, + projectRoot: command.workingDir, + siteID: site.id ?? UNLINKED_SITE_MOCK_ID, + }; + // We start by running a build, so we want a Blobs context with API access, + // which is what build plugins use. + process.env[BLOBS_CONTEXT_VARIABLE] = encodeBlobsContext(await getBlobsContextWithAPIAccess(blobsOptions)); + const { configPath: configPathOverride } = await runBuildTimeline({ + command, + settings, + options, + env: {}, + }); + const mergedConfig = await getFrameworksAPIConfig(config, frameworksAPIPaths.config.path); + // Now we generate a second Blobs context object, this time with edge access + // for runtime access (i.e. from functions and edge functions). + const runtimeBlobsContext = await getBlobsContextWithEdgeAccess(blobsOptions); + process.env[BLOBS_CONTEXT_VARIABLE] = encodeBlobsContext(runtimeBlobsContext); + const functionsRegistry = await startFunctionsServer({ + blobsContext: runtimeBlobsContext, + command, + config: mergedConfig, + debug: options.debug, + loadDistFunctions: true, + settings, + site, + siteInfo, + siteUrl, + capabilities, + timeouts, + geolocationMode: options.geo, + geoCountry: options.country, + offline: options.offline, + state, + accountId, + }); + // Try to add `.netlify` to `.gitignore`. + try { + await ensureNetlifyIgnore(repositoryRoot); + } + catch { + // no-op + } + // TODO: We should consolidate this with the existing config watcher. + const getUpdatedConfig = async () => { + const { config: newConfig } = await command.getConfig({ cwd: command.workingDir, offline: true }); + const normalizedNewConfig = normalizeConfig(newConfig); + return normalizedNewConfig; + }; + const inspectSettings = generateInspectSettings(options.edgeInspect, options.edgeInspectBrk); + const url = await startProxyServer({ + addonsUrls, + blobsContext: runtimeBlobsContext, + command, + config: mergedConfig, + configPath: configPathOverride, + debug: options.debug, + disableEdgeFunctions: options.internalDisableEdgeFunctions, + env, + functionsRegistry, + geolocationMode: options.geo, + geoCountry: options.country, + getUpdatedConfig, + inspectSettings, + offline: options.offline, + projectDir: command.workingDir, + settings, + site, + siteInfo, + state, + accountId, + }); + if (devConfig.autoLaunch !== false) { + await openBrowser({ url, silentBrowserNoneError: true }); + } + process.env.URL = url; + process.env.DEPLOY_URL = url; + printBanner({ url }); +}; +//# sourceMappingURL=serve.js.map \ No newline at end of file diff --git a/dist/commands/serve/serve.js.map b/dist/commands/serve/serve.js.map new file mode 100644 index 00000000000..53052ff52bc --- /dev/null +++ b/dist/commands/serve/serve.js.map @@ -0,0 +1 @@ +{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../../src/commands/serve/serve.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAA;AAI7B,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,4BAA4B,EAC5B,6BAA6B,GAC9B,MAAM,0BAA0B,CAAA;AACjC,OAAO,EAAE,kBAAkB,EAAE,MAAM,2CAA2C,CAAA;AAC9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AACpE,OAAO,EAAE,WAAW,EAAE,MAAM,kCAAkC,CAAA;AAC9D,OAAO,EACL,aAAa,EACb,aAAa,EACb,cAAc,EACd,KAAK,EACL,IAAI,EACJ,GAAG,EACH,eAAe,GAChB,MAAM,gCAAgC,CAAA;AACvC,OAAO,oBAAoB,EAAE,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAA;AAClG,OAAO,EAAE,qBAAqB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAA;AACtH,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAA;AACzD,OAAO,EAAE,sBAAsB,EAAE,MAAM,+BAA+B,CAAA;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,oCAAoC,CAAA;AAC5E,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AAC9D,OAAO,WAAW,MAAM,6BAA6B,CAAA;AACrD,OAAO,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,6BAA6B,CAAA;AACvF,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA;AAK3D,MAAM,CAAC,MAAM,KAAK,GAAG,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IACzE,MAAM,EAAE,GAAG,EAAE,YAAY,EAAE,MAAM,EAAE,kBAAkB,EAAE,cAAc,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IAChH,MAAM,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC,SAAS,CAAA;IAC/D,MAAM,CAAC,KAAK,GAAG,EAAE,GAAG,MAAM,CAAC,KAAK,EAAE,CAAA;IAClC,MAAM,SAAS,GAAc;QAC3B,GAAG,CAAC,MAAM,CAAC,kBAAkB,IAAI,EAAE,SAAS,EAAE,MAAM,CAAC,kBAAkB,EAAE,CAAC;QAC1E,GAAG,CAAC,SAAS,IAAI,MAAM,CAAC,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;QAE3F,GAAG,MAAM,CAAC,GAAG;QACb,GAAG,OAAO;QACV,0EAA0E;QAC1E,sCAAsC;QACtC,SAAS,EAAE,SAAS;KACrB,CAAA;IAED,IAAI,EAAE,GAAG,EAAE,GAAG,YAAY,CAAA;IAE1B,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QACrB,GAAG,GAAG,MAAM,cAAc,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,CAAA;QAC5E,GAAG,CAAC,GAAG,aAAa,8CAA8C,KAAK,CAAC,MAAM,CAAC,YAAY,CAAC,EAAE,CAAC,CAAA;IACjG,CAAC;IAED,GAAG,GAAG,MAAM,kBAAkB,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAA;IACxD,kBAAkB,CAAC,GAAG,CAAC,CAAA;IACvB,MAAM,kBAAkB,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,aAAa,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC,CAAA;IAEtF,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,MAAM,kBAAkB,CAAC;QAC1F,wCAAwC;QACxC,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,GAAG;QACH,IAAI;QACJ,QAAQ;KACT,CAAC,CAAA;IAEF,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACf,MAAM,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAA;IACxC,CAAC;IAED,uEAAuE;IACvE,oEAAoE;IACpE,4BAA4B;IAC5B,MAAM,uBAAuB,CAAC;QAC5B,IAAI,EAAE,IAAI,CAAC,IAAI;QACf,YAAY,EAAE,IAAI;QAClB,WAAW,EAAE,OAAO,CAAC,gBAAgB;KACtC,CAAC,CAAA;IAEF,MAAM,kBAAkB,CAAC,SAAS,CAAC,YAAY,EAAE,CAAA;IAEjD,IAAI,QAAwB,CAAA;IAC5B,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,oBAAoB,CAAC,SAAS,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;QAElE,YAAY,CAAC,MAAM,GAAG,oBAAoB,CAAC,YAAY,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;IAC3E,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,gEAAgE;QAChE,GAAG,CAAC,aAAa,EAAE,MAAM,CAAC,OAAO,CAAC,CAAA;QAClC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAA;IAChB,CAAC;IAED,OAAO,CAAC,mBAAmB,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,CAAC,CAAA;IAEnD,GAAG,CAAC,GAAG,aAAa,kCAAkC,CAAC,CAAA;IACvD,GAAG,CACD,GAAG,cAAc,uHAAuH,CACzI,CAAA;IAED,MAAM,YAAY,GAAG;QACnB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,WAAW,EAAE,OAAO,CAAC,UAAU;QAC/B,MAAM,EAAE,IAAI,CAAC,EAAE,IAAI,qBAAqB;KACzC,CAAA;IAED,2EAA2E;IAC3E,mCAAmC;IACnC,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,GAAG,kBAAkB,CAAC,MAAM,4BAA4B,CAAC,YAAY,CAAC,CAAC,CAAA;IAE1G,MAAM,EAAE,UAAU,EAAE,kBAAkB,EAAE,GAAG,MAAM,gBAAgB,CAAC;QAChE,OAAO;QACP,QAAQ;QACR,OAAO;QACP,GAAG,EAAE,EAAE;KACR,CAAC,CAAA;IAEF,MAAM,YAAY,GAAG,MAAM,sBAAsB,CAAC,MAAM,EAAE,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAA;IAEzF,4EAA4E;IAC5E,+DAA+D;IAC/D,MAAM,mBAAmB,GAAG,MAAM,6BAA6B,CAAC,YAAY,CAAC,CAAA;IAE7E,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,GAAG,kBAAkB,CAAC,mBAAmB,CAAC,CAAA;IAE7E,MAAM,iBAAiB,GAAG,MAAM,oBAAoB,CAAC;QACnD,YAAY,EAAE,mBAAmB;QACjC,OAAO;QACP,MAAM,EAAE,YAAY;QACpB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,iBAAiB,EAAE,IAAI;QACvB,QAAQ;QACR,IAAI;QACJ,QAAQ;QACR,OAAO;QACP,YAAY;QACZ,QAAQ;QACR,eAAe,EAAE,OAAO,CAAC,GAAG;QAC5B,UAAU,EAAE,OAAO,CAAC,OAAO;QAC3B,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,KAAK;QACL,SAAS;KACV,CAAC,CAAA;IAEF,yCAAyC;IACzC,IAAI,CAAC;QACH,MAAM,mBAAmB,CAAC,cAAc,CAAC,CAAA;IAC3C,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ;IACV,CAAC;IAED,qEAAqE;IACrE,MAAM,gBAAgB,GAAG,KAAK,IAAI,EAAE;QAClC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,CAAC,UAAU,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAA;QACjG,MAAM,mBAAmB,GAAG,eAAe,CAAC,SAAS,CAAC,CAAA;QAEtD,OAAO,mBAAmB,CAAA;IAC5B,CAAC,CAAA;IAED,MAAM,eAAe,GAAG,uBAAuB,CAAC,OAAO,CAAC,WAAW,EAAE,OAAO,CAAC,cAAc,CAAC,CAAA;IAC5F,MAAM,GAAG,GAAG,MAAM,gBAAgB,CAAC;QACjC,UAAU;QACV,YAAY,EAAE,mBAAmB;QACjC,OAAO;QACP,MAAM,EAAE,YAAY;QACpB,UAAU,EAAE,kBAAkB;QAC9B,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,oBAAoB,EAAE,OAAO,CAAC,4BAA4B;QAC1D,GAAG;QACH,iBAAiB;QACjB,eAAe,EAAE,OAAO,CAAC,GAAG;QAC5B,UAAU,EAAE,OAAO,CAAC,OAAO;QAC3B,gBAAgB;QAChB,eAAe;QACf,OAAO,EAAE,OAAO,CAAC,OAAO;QACxB,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,QAAQ;QACR,IAAI;QACJ,QAAQ;QACR,KAAK;QACL,SAAS;KACV,CAAC,CAAA;IAEF,IAAI,SAAS,CAAC,UAAU,KAAK,KAAK,EAAE,CAAC;QACnC,MAAM,WAAW,CAAC,EAAE,GAAG,EAAE,sBAAsB,EAAE,IAAI,EAAE,CAAC,CAAA;IAC1D,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,GAAG,CAAA;IACrB,OAAO,CAAC,GAAG,CAAC,UAAU,GAAG,GAAG,CAAA;IAE5B,WAAW,CAAC,EAAE,GAAG,EAAE,CAAC,CAAA;AACtB,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/sites/index.d.ts b/dist/commands/sites/index.d.ts new file mode 100644 index 00000000000..bd518cc418a --- /dev/null +++ b/dist/commands/sites/index.d.ts @@ -0,0 +1,2 @@ +export { createSitesCommand } from './sites.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/sites/index.d.ts.map b/dist/commands/sites/index.d.ts.map new file mode 100644 index 00000000000..70aa9a3b211 --- /dev/null +++ b/dist/commands/sites/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/sites/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA"} \ No newline at end of file diff --git a/dist/commands/sites/index.js b/dist/commands/sites/index.js new file mode 100644 index 00000000000..ab381b4e890 --- /dev/null +++ b/dist/commands/sites/index.js @@ -0,0 +1,2 @@ +export { createSitesCommand } from './sites.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/sites/index.js.map b/dist/commands/sites/index.js.map new file mode 100644 index 00000000000..10f3ee6f236 --- /dev/null +++ b/dist/commands/sites/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/sites/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAA"} \ No newline at end of file diff --git a/dist/commands/sites/sites-create-template.d.ts b/dist/commands/sites/sites-create-template.d.ts new file mode 100644 index 00000000000..c1967339a71 --- /dev/null +++ b/dist/commands/sites/sites-create-template.d.ts @@ -0,0 +1,5 @@ +import type { OptionValues } from 'commander'; +import type { SiteInfo } from '../../utils/types.js'; +import type BaseCommand from '../base-command.js'; +export declare const sitesCreateTemplate: (repository: string, options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=sites-create-template.d.ts.map \ No newline at end of file diff --git a/dist/commands/sites/sites-create-template.d.ts.map b/dist/commands/sites/sites-create-template.d.ts.map new file mode 100644 index 00000000000..81e5a5bb1a6 --- /dev/null +++ b/dist/commands/sites/sites-create-template.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"sites-create-template.d.ts","sourceRoot":"","sources":["../../../src/commands/sites/sites-create-template.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAwB7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAIjD,eAAO,MAAM,mBAAmB,GAAU,YAAY,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,sBAqQxG,CAAA"} \ No newline at end of file diff --git a/dist/commands/sites/sites-create-template.js b/dist/commands/sites/sites-create-template.js new file mode 100644 index 00000000000..d8077ab10a1 --- /dev/null +++ b/dist/commands/sites/sites-create-template.js @@ -0,0 +1,235 @@ +import path from 'node:path'; +import { fileURLToPath } from 'node:url'; +import inquirer from 'inquirer'; +import pick from 'lodash/pick.js'; +import { render } from 'prettyjson'; +import { v4 as uuid } from 'uuid'; +import { chalk, logAndThrowError, getTerminalLink, log, logJson, warn, GitHubAPIError, } from '../../utils/command-helpers.js'; +import execa from '../../utils/execa.js'; +import getRepoData from '../../utils/get-repo-data.js'; +import { getGitHubToken } from '../../utils/init/config-github.js'; +import { configureRepo } from '../../utils/init/config.js'; +import { deployedSiteExists, getGitHubLink, getTemplateName } from '../../utils/sites/create-template.js'; +import { callLinkSite, createRepo, validateTemplate } from '../../utils/sites/utils.js'; +import { track } from '../../utils/telemetry/index.js'; +import { getSiteNameInput } from './sites-create.js'; +export const sitesCreateTemplate = async (repository, options, command) => { + const { accounts, api } = command.netlify; + await command.authenticate(); + const { globalConfig } = command.netlify; + const ghToken = await getGitHubToken({ globalConfig }); + const templateName = await getTemplateName({ ghToken, options, repository }); + const { exists, isTemplate } = await validateTemplate({ templateName, ghToken }); + if (!exists) { + const githubLink = getGitHubLink({ options, templateName }); + return logAndThrowError(`Could not find template ${chalk.bold(templateName)}. Please verify it exists and you can ${getTerminalLink('access to it on GitHub', githubLink)}`); + } + if (!isTemplate) { + const githubLink = getGitHubLink({ options, templateName }); + return logAndThrowError(`${getTerminalLink(chalk.bold(templateName), githubLink)} is not a valid GitHub template`); + } + let { accountSlug } = options; + if (!accountSlug) { + const { accountSlug: accountSlugInput } = await inquirer.prompt([ + { + type: 'list', + name: 'accountSlug', + message: 'Team:', + choices: accounts.map((account) => ({ + value: account.slug, + name: account.name, + })), + }, + ]); + accountSlug = accountSlugInput; + } + const { name: nameFlag } = options; + let site; + let repoResp; + // Allow the user to reenter project name if selected one isn't available + const inputSiteName = async (name, hasExistingRepo) => { + const { name: inputName } = await getSiteNameInput(name); + const siteName = inputName.trim(); + if (siteName && (await deployedSiteExists(siteName))) { + log('A project with that name already exists'); + return inputSiteName(); + } + try { + const sites = await api.listSites({ name: siteName, filter: 'all' }); + const siteFoundByName = sites.find((filteredSite) => filteredSite.name === siteName); + if (siteFoundByName) { + log('A project with that name already exists on your account'); + return inputSiteName(); + } + } + catch (error_) { + return logAndThrowError(error_); + } + if (!hasExistingRepo) { + try { + // Create new repo from template + let gitHubInputName = siteName || templateName; + repoResp = await createRepo(templateName, ghToken, gitHubInputName); + if (repoResp.errors && repoResp.errors[0].includes('Name already exists on this account')) { + if (gitHubInputName === templateName) { + gitHubInputName += `-${uuid().split('-')[0]}`; + repoResp = await createRepo(templateName, ghToken, gitHubInputName); + } + else { + warn(`It seems you have already created a repository with the name ${gitHubInputName}.`); + return inputSiteName(); + } + } + if (!repoResp.id) { + throw new GitHubAPIError(repoResp.status, repoResp.message); + } + hasExistingRepo = true; + } + catch (error_) { + if (error_.status === '404') { + return logAndThrowError(`Could not create repository: ${error_.message}. Ensure that your GitHub personal access token grants permission to create repositories`); + } + else { + return logAndThrowError(`Something went wrong trying to create the repository. We're getting the following error: '${error_.message}'. You can try to re-run this command again or open an issue in our repository: https://github.com/netlify/cli/issues`); + } + } + } + try { + // FIXME(serhalp): `id` and `name` should be required in `netlify` package type + site = (await api.createSiteInTeam({ + accountSlug, + body: { + repo: { + provider: 'github', + // @ts-expect-error -- FIXME(serhalp): Supposedly this is does not exist. Investigate. + repo: repoResp.full_name, + // FIXME(serhalp): Supposedly this should be `public_repo`. Investigate. + private: repoResp.private, + // FIXME(serhalp): Supposedly this should be `repo_branch`. Investigate. + branch: repoResp.default_branch, + }, + name: siteName, + }, + })); + } + catch (error_) { + if (error_.status === 422) { + log(`createSiteInTeam error: ${error_.status}: ${error_.message}`); + log('Cannot create a project with that name. Project name may already exist. Please try a new name.'); + return inputSiteName(undefined, hasExistingRepo); + } + return logAndThrowError(`createSiteInTeam error: ${error_.status}: ${error_.message}`); + } + return [site, repoResp]; + }; + [site, repoResp] = await inputSiteName(nameFlag); + log(); + log(chalk.greenBright.bold.underline(`Project Created`)); + log(); + const siteUrl = site.ssl_url || site.url; + log(render({ + 'Admin URL': site.admin_url, + URL: siteUrl, + 'Project ID': site.id, + 'Repo URL': site.build_settings?.repo_url ?? '', + })); + track('sites_createdFromTemplate', { + siteId: site.id, + adminUrl: site.admin_url, + siteUrl, + }); + const { cloneConfirm } = await inquirer.prompt({ + type: 'confirm', + name: 'cloneConfirm', + message: `Do you want to clone the repository to your local machine?`, + default: true, + }); + if (cloneConfirm) { + log(); + if (repoResp.clone_url) { + await execa('git', ['clone', repoResp.clone_url, `${repoResp.name}`]); + } + log(`šŸš€ Repository cloned successfully. You can find it under the ${chalk.magenta(repoResp.name)} folder`); + const { linkConfirm } = await inquirer.prompt({ + type: 'confirm', + name: 'linkConfirm', + message: `Do you want to link the cloned directory to the project?`, + default: true, + }); + if (linkConfirm) { + const __dirname = path.dirname(fileURLToPath(import.meta.url)); + const cliPath = path.resolve(__dirname, '../../../bin/run.js'); + let stdout; + // TODO(serhalp): Why is this condition here? We've asked the user multiple prompts, but we already knew we had + // invalid repo data. Move upstream. + if (repoResp.name) { + stdout = await callLinkSite(cliPath, repoResp.name, '\n'); + } + else { + return logAndThrowError('Failed to fetch the repo'); + } + const linkedSiteUrlRegex = /Project url:\s+(\S+)/; + const lineMatch = linkedSiteUrlRegex.exec(stdout); + const urlMatch = lineMatch ? lineMatch[1] : undefined; + if (urlMatch) { + log(`\nDirectory ${chalk.cyanBright(repoResp.name)} linked to project ${chalk.cyanBright(urlMatch)}\n`); + log(`${chalk.cyanBright.bold('cd', repoResp.name)} to use other netlify cli commands in the cloned directory.\n`); + } + else { + const linkedSiteMatch = /Project already linked to\s+(\S+)/.exec(stdout); + const linkedSiteNameMatch = linkedSiteMatch ? linkedSiteMatch[1] : undefined; + if (linkedSiteNameMatch) { + log(`\nThis directory appears to be linked to ${chalk.cyanBright(linkedSiteNameMatch)}`); + log('This can happen if you cloned the template into a subdirectory of an existing Netlify project.'); + log(`You may need to move the ${chalk.cyanBright(repoResp.name)} directory out of its parent directory and then re-run the ${chalk.cyanBright('link')} command manually\n`); + } + else { + log('A problem occurred linking the project'); + log('You can try again manually by running:'); + log(chalk.cyanBright(`cd ${repoResp.name} && netlify link\n`)); + } + } + } + else { + log('To link the cloned directory manually, run:'); + log(chalk.cyanBright(`cd ${repoResp.name} && netlify link\n`)); + } + } + if (options.withCi) { + log('Configuring CI'); + const repoData = await getRepoData({ workingDir: command.workingDir }); + if ('error' in repoData) { + return logAndThrowError('Failed to get repo data'); + } + await configureRepo({ command, siteId: site.id, repoData, manual: options.manual }); + } + if (options.json) { + logJson(pick(site, [ + 'id', + 'state', + 'plan', + 'name', + 'custom_domain', + 'domain_aliases', + 'url', + 'ssl_url', + 'admin_url', + 'screenshot_url', + 'created_at', + 'updated_at', + 'user_id', + 'ssl', + 'force_ssl', + 'managed_dns', + 'deploy_url', + 'account_name', + 'account_slug', + 'git_provider', + 'deploy_hook', + 'capabilities', + 'id_domain', + ])); + } + return site; +}; +//# sourceMappingURL=sites-create-template.js.map \ No newline at end of file diff --git a/dist/commands/sites/sites-create-template.js.map b/dist/commands/sites/sites-create-template.js.map new file mode 100644 index 00000000000..84eb9c44939 --- /dev/null +++ b/dist/commands/sites/sites-create-template.js.map @@ -0,0 +1 @@ +{"version":3,"file":"sites-create-template.js","sourceRoot":"","sources":["../../../src/commands/sites/sites-create-template.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/sites/sites-create.d.ts b/dist/commands/sites/sites-create.d.ts new file mode 100644 index 00000000000..d77138e7a2f --- /dev/null +++ b/dist/commands/sites/sites-create.d.ts @@ -0,0 +1,8 @@ +import type { OptionValues } from 'commander'; +import type { SiteInfo } from '../../utils/types.js'; +import type BaseCommand from '../base-command.js'; +export declare const getSiteNameInput: (name: string | undefined) => Promise<{ + name: string; +}>; +export declare const sitesCreate: (options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=sites-create.d.ts.map \ No newline at end of file diff --git a/dist/commands/sites/sites-create.d.ts.map b/dist/commands/sites/sites-create.d.ts.map new file mode 100644 index 00000000000..e449eb40111 --- /dev/null +++ b/dist/commands/sites/sites-create.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"sites-create.d.ts","sourceRoot":"","sources":["../../../src/commands/sites/sites-create.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAS7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AACpD,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAGjD,eAAO,MAAM,gBAAgB,GAAU,MAAM,MAAM,GAAG,SAAS,KAAG,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAezF,CAAA;AAED,eAAO,MAAM,WAAW,GAAU,SAAS,YAAY,EAAE,SAAS,WAAW,sBAsH5E,CAAA"} \ No newline at end of file diff --git a/dist/commands/sites/sites-create.js b/dist/commands/sites/sites-create.js new file mode 100644 index 00000000000..04af664f1ad --- /dev/null +++ b/dist/commands/sites/sites-create.js @@ -0,0 +1,122 @@ +import inquirer from 'inquirer'; +import pick from 'lodash/pick.js'; +import prettyjson from 'prettyjson'; +import { chalk, logAndThrowError, log, logJson, warn } from '../../utils/command-helpers.js'; +import getRepoData from '../../utils/get-repo-data.js'; +import { configureRepo } from '../../utils/init/config.js'; +import { track } from '../../utils/telemetry/index.js'; +import { link } from '../link/link.js'; +export const getSiteNameInput = async (name) => { + if (!name) { + const { name: nameInput } = await inquirer.prompt([ + { + type: 'input', + name: 'name', + message: 'Project name (leave blank for a random name; you can change it later):', + validate: (input) => /^[a-zA-Z\d-]+$/.test(input || undefined) || 'Only alphanumeric characters and hyphens are allowed', + }, + ]); + name = typeof nameInput === 'string' ? nameInput : ''; + } + return { name }; +}; +export const sitesCreate = async (options, command) => { + const { accounts, api } = command.netlify; + await command.authenticate(); + let { accountSlug } = options; + if (!accountSlug) { + const { accountSlug: accountSlugInput } = await inquirer.prompt([ + { + type: 'list', + name: 'accountSlug', + message: 'Team:', + choices: accounts.map((account) => ({ + value: account.slug, + name: account.name, + })), + }, + ]); + accountSlug = accountSlugInput; + } + let site; + // Allow the user to reenter site name if selected one isn't available + const inputSiteName = async (name) => { + const { name: siteName } = await getSiteNameInput(name); + const body = {}; + if (typeof siteName === 'string') { + body.name = siteName.trim(); + } + try { + // FIXME(serhalp): `id` and `name` should be required in `netlify` package type + site = (await api.createSiteInTeam({ + accountSlug: accountSlug, + body, + })); + } + catch (error_) { + if (error_.status === 422) { + warn(`${siteName}.netlify.app already exists. Please try a different slug.`); + await inputSiteName(); + } + else { + return logAndThrowError(`createSiteInTeam error: ${error_.status}: ${error_.message}`); + } + } + }; + await inputSiteName(options.name); + log(); + log(chalk.greenBright.bold.underline(`Project Created`)); + log(); + const siteUrl = site.ssl_url || site.url; + log(prettyjson.render({ + 'Admin URL': site.admin_url, + URL: siteUrl, + 'Project ID': site.id, + })); + track('sites_created', { + siteId: site.id, + adminUrl: site.admin_url, + siteUrl, + }); + if (options.withCi) { + log('Configuring CI'); + const repoData = await getRepoData({ workingDir: command.workingDir }); + if ('error' in repoData) { + return logAndThrowError('Failed to get repo data'); + } + await configureRepo({ command, siteId: site.id, repoData, manual: options.manual }); + } + if (options.json) { + logJson(pick(site, [ + 'id', + 'state', + 'plan', + 'name', + 'custom_domain', + 'domain_aliases', + 'url', + 'ssl_url', + 'admin_url', + 'screenshot_url', + 'created_at', + 'updated_at', + 'user_id', + 'ssl', + 'force_ssl', + 'managed_dns', + 'deploy_url', + 'account_name', + 'account_slug', + 'git_provider', + 'deploy_hook', + 'capabilities', + 'id_domain', + ])); + } + if (!options.disableLinking) { + log(); + await link({ id: site.id }, command); + } + return site; +}; +//# sourceMappingURL=sites-create.js.map \ No newline at end of file diff --git a/dist/commands/sites/sites-create.js.map b/dist/commands/sites/sites-create.js.map new file mode 100644 index 00000000000..0d6d7c55c78 --- /dev/null +++ b/dist/commands/sites/sites-create.js.map @@ -0,0 +1 @@ +{"version":3,"file":"sites-create.js","sourceRoot":"","sources":["../../../src/commands/sites/sites-create.ts"],"names":[],"mappings":"AACA,OAAO,QAAQ,MAAM,UAAU,CAAA;AAC/B,OAAO,IAAI,MAAM,gBAAgB,CAAA;AACjC,OAAO,UAAU,MAAM,YAAY,CAAA;AAEnC,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,EAAiB,MAAM,gCAAgC,CAAA;AAC3G,OAAO,WAAW,MAAM,8BAA8B,CAAA;AACtD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAA;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAA;AAGtD,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AAEtC,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EAAE,IAAwB,EAA6B,EAAE;IAC5F,IAAI,CAAC,IAAI,EAAE,CAAC;QACV,MAAM,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;YAChD;gBACE,IAAI,EAAE,OAAO;gBACb,IAAI,EAAE,MAAM;gBACZ,OAAO,EAAE,wEAAwE;gBACjF,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE,CAClB,gBAAgB,CAAC,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC,IAAI,sDAAsD;aACtG;SACF,CAAC,CAAA;QACF,IAAI,GAAG,OAAO,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,CAAA;IACvD,CAAC;IAED,OAAO,EAAE,IAAI,EAAE,CAAA;AACjB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IAC/E,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IAEzC,MAAM,OAAO,CAAC,YAAY,EAAE,CAAA;IAE5B,IAAI,EAAE,WAAW,EAAE,GAA6B,OAAO,CAAA;IACvD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,GAA4B,MAAM,QAAQ,CAAC,MAAM,CAEtF;YACA;gBACE,IAAI,EAAE,MAAM;gBACZ,IAAI,EAAE,aAAa;gBACnB,OAAO,EAAE,OAAO;gBAChB,OAAO,EAAE,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;oBAClC,KAAK,EAAE,OAAO,CAAC,IAAI;oBACnB,IAAI,EAAE,OAAO,CAAC,IAAI;iBACnB,CAAC,CAAC;aACJ;SACF,CAAC,CAAA;QACF,WAAW,GAAG,gBAAgB,CAAA;IAChC,CAAC;IAED,IAAI,IAAe,CAAA;IAEnB,sEAAsE;IACtE,MAAM,aAAa,GAAG,KAAK,EAAE,IAAa,EAAE,EAAE;QAC5C,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAA;QAEvD,MAAM,IAAI,GAAsB,EAAE,CAAA;QAClC,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACjC,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAA;QAC7B,CAAC;QACD,IAAI,CAAC;YACH,+EAA+E;YAC/E,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,gBAAgB,CAAC;gBACjC,WAAW,EAAE,WAAW;gBACxB,IAAI;aACL,CAAC,CAAwB,CAAA;QAC5B,CAAC;QAAC,OAAO,MAAM,EAAE,CAAC;YAChB,IAAK,MAAmB,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;gBACxC,IAAI,CAAC,GAAG,QAAQ,2DAA2D,CAAC,CAAA;gBAC5E,MAAM,aAAa,EAAE,CAAA;YACvB,CAAC;iBAAM,CAAC;gBACN,OAAO,gBAAgB,CACrB,2BAA4B,MAAmB,CAAC,MAAM,KAAM,MAAmB,CAAC,OAAO,EAAE,CAC1F,CAAA;YACH,CAAC;QACH,CAAC;IACH,CAAC,CAAA;IACD,MAAM,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA;IAEjC,GAAG,EAAE,CAAA;IACL,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,iBAAiB,CAAC,CAAC,CAAA;IACxD,GAAG,EAAE,CAAA;IAEL,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,CAAA;IACxC,GAAG,CACD,UAAU,CAAC,MAAM,CAAC;QAChB,WAAW,EAAE,IAAI,CAAC,SAAS;QAC3B,GAAG,EAAE,OAAO;QACZ,YAAY,EAAE,IAAI,CAAC,EAAE;KACtB,CAAC,CACH,CAAA;IAED,KAAK,CAAC,eAAe,EAAE;QACrB,MAAM,EAAE,IAAI,CAAC,EAAE;QACf,QAAQ,EAAE,IAAI,CAAC,SAAS;QACxB,OAAO;KACR,CAAC,CAAA;IAEF,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;QACnB,GAAG,CAAC,gBAAgB,CAAC,CAAA;QACrB,MAAM,QAAQ,GAAG,MAAM,WAAW,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,UAAU,EAAE,CAAC,CAAA;QAEtE,IAAI,OAAO,IAAI,QAAQ,EAAE,CAAC;YACxB,OAAO,gBAAgB,CAAC,yBAAyB,CAAC,CAAA;QACpD,CAAC;QAED,MAAM,aAAa,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAA;IACrF,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;QACjB,OAAO,CACL,IAAI,CAAC,IAAI,EAAE;YACT,IAAI;YACJ,OAAO;YACP,MAAM;YACN,MAAM;YACN,eAAe;YACf,gBAAgB;YAChB,KAAK;YACL,SAAS;YACT,WAAW;YACX,gBAAgB;YAChB,YAAY;YACZ,YAAY;YACZ,SAAS;YACT,KAAK;YACL,WAAW;YACX,aAAa;YACb,YAAY;YACZ,cAAc;YACd,cAAc;YACd,cAAc;YACd,aAAa;YACb,cAAc;YACd,WAAW;SACZ,CAAC,CACH,CAAA;IACH,CAAC;IAED,IAAI,CAAC,OAAO,CAAC,cAAc,EAAE,CAAC;QAC5B,GAAG,EAAE,CAAA;QACL,MAAM,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,CAAA;IACtC,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/sites/sites-delete.d.ts b/dist/commands/sites/sites-delete.d.ts new file mode 100644 index 00000000000..1c82ab40a52 --- /dev/null +++ b/dist/commands/sites/sites-delete.d.ts @@ -0,0 +1,4 @@ +import type { OptionValues } from 'commander'; +import type BaseCommand from '../base-command.js'; +export declare const sitesDelete: (siteId: string, options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=sites-delete.d.ts.map \ No newline at end of file diff --git a/dist/commands/sites/sites-delete.d.ts.map b/dist/commands/sites/sites-delete.d.ts.map new file mode 100644 index 00000000000..dacd0971405 --- /dev/null +++ b/dist/commands/sites/sites-delete.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"sites-delete.d.ts","sourceRoot":"","sources":["../../../src/commands/sites/sites-delete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAI7C,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAEjD,eAAO,MAAM,WAAW,GAAU,QAAQ,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,WAAW,uBA4E5F,CAAA"} \ No newline at end of file diff --git a/dist/commands/sites/sites-delete.js b/dist/commands/sites/sites-delete.js new file mode 100644 index 00000000000..d253b5a85e1 --- /dev/null +++ b/dist/commands/sites/sites-delete.js @@ -0,0 +1,74 @@ +import inquirer from 'inquirer'; +import { chalk, logAndThrowError, exit, log } from '../../utils/command-helpers.js'; +export const sitesDelete = async (siteId, options, command) => { + command.setAnalyticsPayload({ force: options.force }); + const { api, site } = command.netlify; + const cwdSiteId = site.id; + // 1. Prompt user for verification + await command.authenticate(options.auth); + let siteData; + try { + siteData = await api.getSite({ siteId }); + } + catch (error_) { + if (error_.status === 404) { + return logAndThrowError(`No project with id ${siteId} found. Please verify the project ID & try again.`); + } + else { + return logAndThrowError(error_); + } + } + const noForce = options.force !== true; + /* Verify the user wants to delete the project */ + if (noForce) { + log(`${chalk.redBright('Warning')}: You are about to permanently delete "${chalk.bold(siteData.name)}"`); + log(` Verify this project ID "${siteId}" supplied is correct and proceed.`); + log(' To skip this prompt, pass a --force flag to the delete command'); + log(); + log(chalk.bold('Be careful here. There is no undo!')); + log(); + const { wantsToDelete } = await inquirer.prompt({ + type: 'confirm', + name: 'wantsToDelete', + message: `WARNING: Are you sure you want to delete the "${siteData.name}" project?`, + default: false, + }); + log(); + if (!wantsToDelete) { + exit(); + } + } + /* Validation logic if siteId passed in does not match current project ID */ + if (noForce && cwdSiteId && cwdSiteId !== siteId) { + log(`${chalk.redBright('Warning')}: The project ID supplied does not match the current working directory project ID`); + log(); + log(`Supplied: "${siteId}"`); + log(`Current Project: "${cwdSiteId}"`); + log(); + log(`Verify this project ID "${siteId}" supplied is correct and proceed.`); + log('To skip this prompt, pass a --force flag to the delete command'); + const { wantsToDelete } = await inquirer.prompt({ + type: 'confirm', + name: 'wantsToDelete', + message: `Verify & Proceed with deletion of project "${siteId}"?`, + default: false, + }); + if (!wantsToDelete) { + exit(); + } + } + log(`Deleting project "${siteId}"...`); + try { + await api.deleteSite({ site_id: siteId }); + } + catch (error_) { + if (error_.status === 404) { + return logAndThrowError(`No project with id ${siteId} found. Please verify the project ID & try again.`); + } + else { + return logAndThrowError(`Delete Project error: ${error_.status}: ${error_.message}`); + } + } + log(`Project "${siteId}" successfully deleted!`); +}; +//# sourceMappingURL=sites-delete.js.map \ No newline at end of file diff --git a/dist/commands/sites/sites-delete.js.map b/dist/commands/sites/sites-delete.js.map new file mode 100644 index 00000000000..765c84c22fe --- /dev/null +++ b/dist/commands/sites/sites-delete.js.map @@ -0,0 +1 @@ +{"version":3,"file":"sites-delete.js","sourceRoot":"","sources":["../../../src/commands/sites/sites-delete.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/sites/sites-list.d.ts b/dist/commands/sites/sites-list.d.ts new file mode 100644 index 00000000000..a7c26614158 --- /dev/null +++ b/dist/commands/sites/sites-list.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const sitesList: (options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=sites-list.d.ts.map \ No newline at end of file diff --git a/dist/commands/sites/sites-list.d.ts.map b/dist/commands/sites/sites-list.d.ts.map new file mode 100644 index 00000000000..d72d40bcdb4 --- /dev/null +++ b/dist/commands/sites/sites-list.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"sites-list.d.ts","sourceRoot":"","sources":["../../../src/commands/sites/sites-list.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAMxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,SAAS,GAAU,SAAS,YAAY,EAAE,SAAS,WAAW,+BA6D1E,CAAA"} \ No newline at end of file diff --git a/dist/commands/sites/sites-list.js b/dist/commands/sites/sites-list.js new file mode 100644 index 00000000000..7ddcb220486 --- /dev/null +++ b/dist/commands/sites/sites-list.js @@ -0,0 +1,59 @@ +import { listSites } from '../../lib/api.js'; +import { startSpinner } from '../../lib/spinner.js'; +import { chalk, log, logJson } from '../../utils/command-helpers.js'; +export const sitesList = async (options, command) => { + const { api } = command.netlify; + let spinner; + if (!options.json) { + spinner = startSpinner({ text: 'Loading your projects' }); + } + await command.authenticate(); + const sites = await listSites({ api, options: { filter: 'all' } }); + if (spinner) { + spinner.success(); + } + if (sites && sites.length !== 0) { + const logSites = sites.map((site) => { + const siteInfo = { + id: site.id, + name: site.name, + ssl_url: site.ssl_url, + account_name: site.account_name, + }; + if (site.build_settings && site.build_settings.repo_url) { + siteInfo.repo_url = site.build_settings.repo_url; + } + return siteInfo; + }); + // Json response for piping commands + if (options.json) { + const redactedSites = sites.map((site) => { + if (site?.build_settings?.env) { + delete site.build_settings.env; + } + return site; + }); + logJson(redactedSites); + return false; + } + log(` +────────────────────────────┐ + Current Netlify Projects │ +ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜ + +Count: ${logSites.length} +`); + logSites.forEach((logSite) => { + log(`${chalk.greenBright(logSite.name)} - ${logSite.id}`); + log(` ${chalk.whiteBright.bold('url:')} ${chalk.yellowBright(logSite.ssl_url)}`); + if (logSite.repo_url) { + log(` ${chalk.whiteBright.bold('repo:')} ${chalk.white(logSite.repo_url)}`); + } + if (logSite.account_name) { + log(` ${chalk.whiteBright.bold('account:')} ${chalk.white(logSite.account_name)}`); + } + log(`─────────────────────────────────────────────────`); + }); + } +}; +//# sourceMappingURL=sites-list.js.map \ No newline at end of file diff --git a/dist/commands/sites/sites-list.js.map b/dist/commands/sites/sites-list.js.map new file mode 100644 index 00000000000..0347ae1ee79 --- /dev/null +++ b/dist/commands/sites/sites-list.js.map @@ -0,0 +1 @@ +{"version":3,"file":"sites-list.js","sourceRoot":"","sources":["../../../src/commands/sites/sites-list.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/sites/sites.d.ts b/dist/commands/sites/sites.d.ts new file mode 100644 index 00000000000..10279b2827a --- /dev/null +++ b/dist/commands/sites/sites.d.ts @@ -0,0 +1,5 @@ +import BaseCommand from '../base-command.js'; +export declare const createSitesFromTemplateCommand: (program: BaseCommand) => void; +export declare const createSitesCreateCommand: (program: BaseCommand) => void; +export declare const createSitesCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=sites.d.ts.map \ No newline at end of file diff --git a/dist/commands/sites/sites.d.ts.map b/dist/commands/sites/sites.d.ts.map new file mode 100644 index 00000000000..9a66d4e6850 --- /dev/null +++ b/dist/commands/sites/sites.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"sites.d.ts","sourceRoot":"","sources":["../../../src/commands/sites/sites.ts"],"names":[],"mappings":"AAEA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAkB5C,eAAO,MAAM,8BAA8B,GAAI,SAAS,WAAW,SAsBlE,CAAA;AAED,eAAO,MAAM,wBAAwB,GAAI,SAAS,WAAW,SAoB5D,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,SAAS,WAAW,gBA4BtD,CAAA"} \ No newline at end of file diff --git a/dist/commands/sites/sites.js b/dist/commands/sites/sites.js new file mode 100644 index 00000000000..99e729a1948 --- /dev/null +++ b/dist/commands/sites/sites.js @@ -0,0 +1,77 @@ +import { InvalidArgumentError } from 'commander'; +const MAX_SITE_NAME_LENGTH = 63; +// @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. +const validateName = function (value) { + // netlify sites:create --name + if (typeof value === 'string' && value.length > MAX_SITE_NAME_LENGTH) { + throw new InvalidArgumentError(`--name should be less than 64 characters, input length: ${value.length}`); + } + return value; +}; +const sites = (_options, command) => { + command.help(); +}; +export const createSitesFromTemplateCommand = (program) => { + program + .command('sites:create-template') + .description(`(Beta) Create a project from a starter template +Create a project from a starter template.`) + .option('-n, --name [name]', 'name of project') + .option('-u, --url [url]', 'template url') + .option('-a, --account-slug [slug]', 'account slug to create the project under') + .option('-c, --with-ci', 'initialize CI hooks during project creation') + .argument('[repository]', 'repository to use as starter template') + .addHelpText('after', `(Beta) Create a project from starter template.`) + .addExamples([ + 'netlify sites:create-template', + 'netlify sites:create-template nextjs-blog-theme', + 'netlify sites:create-template my-github-profile/my-template', + ]) + .action(async (repository, options, command) => { + const { sitesCreateTemplate } = await import('./sites-create-template.js'); + await sitesCreateTemplate(repository, options, command); + }); +}; +export const createSitesCreateCommand = (program) => { + program + .command('sites:create') + .description(`Create an empty project (advanced) +Create a blank project that isn't associated with any git remote. Will link the project to the current working directory.`) + .option('-n, --name ', 'name of project', validateName) + .option('-a, --account-slug ', 'account slug to create the project under') + .option('-c, --with-ci', 'initialize CI hooks during project creation') + .option('-m, --manual', 'force manual CI setup. Used --with-ci flag') + .option('--disable-linking', 'create the project without linking it to current directory') + .addHelpText('after', `Create a blank project that isn't associated with any git remote. Will link the project to the current working directory.`) + .action(async (options, command) => { + const { sitesCreate } = await import('./sites-create.js'); + await sitesCreate(options, command); + }); +}; +export const createSitesCommand = (program) => { + createSitesCreateCommand(program); + createSitesFromTemplateCommand(program); + program + .command('sites:list') + .description('List all projects you have access to') + .option('--json', 'Output project data as JSON') + .action(async (options, command) => { + const { sitesList } = await import('./sites-list.js'); + await sitesList(options, command); + }); + program + .command('sites:delete') + .description('Delete a project\nThis command will permanently delete the project on Netlify. Use with caution.') + .argument('', 'Project ID to delete.') + .addExamples(['netlify sites:delete 1234-3262-1211']) + .action(async (siteId, options, command) => { + const { sitesDelete } = await import('./sites-delete.js'); + await sitesDelete(siteId, options, command); + }); + return program + .command('sites') + .description(`Handle various project operations\nThe sites command will help you manage all your projects`) + .addExamples(['netlify sites:create --name my-new-project', 'netlify sites:list']) + .action(sites); +}; +//# sourceMappingURL=sites.js.map \ No newline at end of file diff --git a/dist/commands/sites/sites.js.map b/dist/commands/sites/sites.js.map new file mode 100644 index 00000000000..ec1deeef5d7 --- /dev/null +++ b/dist/commands/sites/sites.js.map @@ -0,0 +1 @@ +{"version":3,"file":"sites.js","sourceRoot":"","sources":["../../../src/commands/sites/sites.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,oBAAoB,EAAE,MAAM,WAAW,CAAA;AAI9D,MAAM,oBAAoB,GAAG,EAAE,CAAA;AAE/B,mFAAmF;AACnF,MAAM,YAAY,GAAG,UAAU,KAAK;IAClC,+DAA+D;IAC/D,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,MAAM,GAAG,oBAAoB,EAAE,CAAC;QACrE,MAAM,IAAI,oBAAoB,CAAC,2DAA2D,KAAK,CAAC,MAAM,EAAE,CAAC,CAAA;IAC3G,CAAC;IAED,OAAO,KAAK,CAAA;AACd,CAAC,CAAA;AAED,MAAM,KAAK,GAAG,CAAC,QAAsB,EAAE,OAAoB,EAAE,EAAE;IAC7D,OAAO,CAAC,IAAI,EAAE,CAAA;AAChB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,OAAoB,EAAE,EAAE;IACrE,OAAO;SACJ,OAAO,CAAC,uBAAuB,CAAC;SAChC,WAAW,CACV;0CACoC,CACrC;SACA,MAAM,CAAC,mBAAmB,EAAE,iBAAiB,CAAC;SAC9C,MAAM,CAAC,iBAAiB,EAAE,cAAc,CAAC;SACzC,MAAM,CAAC,2BAA2B,EAAE,0CAA0C,CAAC;SAC/E,MAAM,CAAC,eAAe,EAAE,6CAA6C,CAAC;SACtE,QAAQ,CAAC,cAAc,EAAE,uCAAuC,CAAC;SACjE,WAAW,CAAC,OAAO,EAAE,gDAAgD,CAAC;SACtE,WAAW,CAAC;QACX,+BAA+B;QAC/B,iDAAiD;QACjD,6DAA6D;KAC9D,CAAC;SACD,MAAM,CAAC,KAAK,EAAE,UAAkB,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;QAChF,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAA;QAC1E,MAAM,mBAAmB,CAAC,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IACzD,CAAC,CAAC,CAAA;AACN,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,OAAoB,EAAE,EAAE;IAC/D,OAAO;SACJ,OAAO,CAAC,cAAc,CAAC;SACvB,WAAW,CACV;0HACoH,CACrH;SACA,MAAM,CAAC,mBAAmB,EAAE,iBAAiB,EAAE,YAAY,CAAC;SAC5D,MAAM,CAAC,2BAA2B,EAAE,0CAA0C,CAAC;SAC/E,MAAM,CAAC,eAAe,EAAE,6CAA6C,CAAC;SACtE,MAAM,CAAC,cAAc,EAAE,6CAA6C,CAAC;SACrE,MAAM,CAAC,mBAAmB,EAAE,4DAA4D,CAAC;SACzF,WAAW,CACV,OAAO,EACP,2HAA2H,CAC5H;SACA,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;QAC5D,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAA;QACzD,MAAM,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACrC,CAAC,CAAC,CAAA;AACN,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAAoB,EAAE,EAAE;IACzD,wBAAwB,CAAC,OAAO,CAAC,CAAA;IACjC,8BAA8B,CAAC,OAAO,CAAC,CAAA;IAEvC,OAAO;SACJ,OAAO,CAAC,YAAY,CAAC;SACrB,WAAW,CAAC,sCAAsC,CAAC;SACnD,MAAM,CAAC,QAAQ,EAAE,6BAA6B,CAAC;SAC/C,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;QAC5D,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAA;QACrD,MAAM,SAAS,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACnC,CAAC,CAAC,CAAA;IAEJ,OAAO;SACJ,OAAO,CAAC,cAAc,CAAC;SACvB,WAAW,CAAC,kGAAkG,CAAC;SAC/G,QAAQ,CAAC,MAAM,EAAE,uBAAuB,CAAC;SACzC,WAAW,CAAC,CAAC,qCAAqC,CAAC,CAAC;SACpD,MAAM,CAAC,KAAK,EAAE,MAAc,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;QAC5E,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAA;QACzD,MAAM,WAAW,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;IAC7C,CAAC,CAAC,CAAA;IAEJ,OAAO,OAAO;SACX,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,6FAA6F,CAAC;SAC1G,WAAW,CAAC,CAAC,4CAA4C,EAAE,oBAAoB,CAAC,CAAC;SACjF,MAAM,CAAC,KAAK,CAAC,CAAA;AAClB,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/status/index.d.ts b/dist/commands/status/index.d.ts new file mode 100644 index 00000000000..8ac3db01073 --- /dev/null +++ b/dist/commands/status/index.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const createStatusCommand: (program: BaseCommand) => void; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/status/index.d.ts.map b/dist/commands/status/index.d.ts.map new file mode 100644 index 00000000000..9fae89fc422 --- /dev/null +++ b/dist/commands/status/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/status/index.ts"],"names":[],"mappings":"AAGA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,mBAAmB,GAAI,SAAS,WAAW,SAmBvD,CAAA"} \ No newline at end of file diff --git a/dist/commands/status/index.js b/dist/commands/status/index.js new file mode 100644 index 00000000000..668fc7aae46 --- /dev/null +++ b/dist/commands/status/index.js @@ -0,0 +1,21 @@ +import requiresSiteInfo from '../../utils/hooks/requires-site-info.js'; +export const createStatusCommand = (program) => { + program + .command('status:hooks') + .description('Print hook information of the linked project') + .hook('preAction', requiresSiteInfo) + .action(async (options, command) => { + const { statusHooks } = await import('./status-hooks.js'); + await statusHooks(options, command); + }); + program + .command('status') + .description('Print status information') + .option('--verbose', 'Output system info') + .option('--json', 'Output status information as JSON') + .action(async (options, command) => { + const { status } = await import('./status.js'); + await status(options, command); + }); +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/status/index.js.map b/dist/commands/status/index.js.map new file mode 100644 index 00000000000..a9339d352d7 --- /dev/null +++ b/dist/commands/status/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/status/index.ts"],"names":[],"mappings":"AAEA,OAAO,gBAAgB,MAAM,yCAAyC,CAAA;AAGtE,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAAoB,EAAE,EAAE;IAC1D,OAAO;SACJ,OAAO,CAAC,cAAc,CAAC;SACvB,WAAW,CAAC,8CAA8C,CAAC;SAC3D,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC;SACnC,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;QAC5D,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,mBAAmB,CAAC,CAAA;QACzD,MAAM,WAAW,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACrC,CAAC,CAAC,CAAA;IAEJ,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,0BAA0B,CAAC;SACvC,MAAM,CAAC,WAAW,EAAE,oBAAoB,CAAC;SACzC,MAAM,CAAC,QAAQ,EAAE,mCAAmC,CAAC;SACrD,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;QAC5D,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;QAC9C,MAAM,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IAChC,CAAC,CAAC,CAAA;AACN,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/status/status-hooks.d.ts b/dist/commands/status/status-hooks.d.ts new file mode 100644 index 00000000000..cf9f2ef1fb8 --- /dev/null +++ b/dist/commands/status/status-hooks.d.ts @@ -0,0 +1,4 @@ +import type { OptionValues } from 'commander'; +import type BaseCommand from '../base-command.js'; +export declare const statusHooks: (_options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=status-hooks.d.ts.map \ No newline at end of file diff --git a/dist/commands/status/status-hooks.d.ts.map b/dist/commands/status/status-hooks.d.ts.map new file mode 100644 index 00000000000..ccf5ccb7c94 --- /dev/null +++ b/dist/commands/status/status-hooks.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"status-hooks.d.ts","sourceRoot":"","sources":["../../../src/commands/status/status-hooks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAI7C,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAUjD,eAAO,MAAM,WAAW,GAAU,UAAU,YAAY,EAAE,SAAS,WAAW,KAAG,OAAO,CAAC,IAAI,CA6B5F,CAAA"} \ No newline at end of file diff --git a/dist/commands/status/status-hooks.js b/dist/commands/status/status-hooks.js new file mode 100644 index 00000000000..217214ededa --- /dev/null +++ b/dist/commands/status/status-hooks.js @@ -0,0 +1,30 @@ +import prettyjson from 'prettyjson'; +import { log } from '../../utils/command-helpers.js'; +export const statusHooks = async (_options, command) => { + const { api, siteInfo } = command.netlify; + await command.authenticate(); + const ntlHooks = await api.listHooksBySiteId({ siteId: siteInfo.id }); + const data = { + project: siteInfo.name, + hooks: {}, + }; + ntlHooks.forEach((hook) => { + // TODO(serhalp): Surely the `listHooksBySiteId` type is wrong about `id` being optional. Fix. + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + const id = hook.id; + data.hooks[id] = { + type: hook.type, + event: hook.event, + id, + disabled: hook.disabled ?? false, + }; + if (siteInfo.build_settings?.repo_url) { + data.hooks[id].repo_url = siteInfo.build_settings.repo_url; + } + }); + log(`─────────────────┐ +Project Hook Status │ +ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜`); + log(prettyjson.render(data)); +}; +//# sourceMappingURL=status-hooks.js.map \ No newline at end of file diff --git a/dist/commands/status/status-hooks.js.map b/dist/commands/status/status-hooks.js.map new file mode 100644 index 00000000000..43ee2575e86 --- /dev/null +++ b/dist/commands/status/status-hooks.js.map @@ -0,0 +1 @@ +{"version":3,"file":"status-hooks.js","sourceRoot":"","sources":["../../../src/commands/status/status-hooks.ts"],"names":[],"mappings":"AACA,OAAO,UAAU,MAAM,YAAY,CAAA;AAEnC,OAAO,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAA;AAWpD,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,QAAsB,EAAE,OAAoB,EAAiB,EAAE;IAC/F,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IAEzC,MAAM,OAAO,CAAC,YAAY,EAAE,CAAA;IAE5B,MAAM,QAAQ,GAAG,MAAM,GAAG,CAAC,iBAAiB,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,EAAE,CAAC,CAAA;IACrE,MAAM,IAAI,GAAG;QACX,OAAO,EAAE,QAAQ,CAAC,IAAI;QACtB,KAAK,EAAE,EAAgC;KACxC,CAAA;IAED,QAAQ,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE;QACxB,8FAA8F;QAC9F,oEAAoE;QACpE,MAAM,EAAE,GAAG,IAAI,CAAC,EAAG,CAAA;QACnB,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,GAAG;YACf,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,KAAK,EAAE,IAAI,CAAC,KAAK;YACjB,EAAE;YACF,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,KAAK;SACjC,CAAA;QACD,IAAI,QAAQ,CAAC,cAAc,EAAE,QAAQ,EAAE,CAAC;YACtC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,QAAQ,GAAG,QAAQ,CAAC,cAAc,CAAC,QAAQ,CAAA;QAC5D,CAAC;IACH,CAAC,CAAC,CAAA;IACF,GAAG,CAAC;;mBAEa,CAAC,CAAA;IAClB,GAAG,CAAC,UAAU,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;AAC9B,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/status/status.d.ts b/dist/commands/status/status.d.ts new file mode 100644 index 00000000000..d294daa5524 --- /dev/null +++ b/dist/commands/status/status.d.ts @@ -0,0 +1,4 @@ +import type { OptionValues } from 'commander'; +import type BaseCommand from '../base-command.js'; +export declare const status: (options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=status.d.ts.map \ No newline at end of file diff --git a/dist/commands/status/status.d.ts.map b/dist/commands/status/status.d.ts.map new file mode 100644 index 00000000000..12cd9885618 --- /dev/null +++ b/dist/commands/status/status.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../../src/commands/status/status.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAa7C,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AAEjD,eAAO,MAAM,MAAM,GAAU,SAAS,YAAY,EAAE,SAAS,WAAW,uBAkFvE,CAAA"} \ No newline at end of file diff --git a/dist/commands/status/status.js b/dist/commands/status/status.js new file mode 100644 index 00000000000..b3bcf3c5cc1 --- /dev/null +++ b/dist/commands/status/status.js @@ -0,0 +1,73 @@ +import clean from 'clean-deep'; +import prettyjson from 'prettyjson'; +import { chalk, logAndThrowError, exit, getToken, log, logJson, warn, } from '../../utils/command-helpers.js'; +export const status = async (options, command) => { + const { accounts, api, globalConfig, site, siteInfo } = command.netlify; + const currentUserId = globalConfig.get('userId'); + const [accessToken] = await getToken(); + if (!accessToken) { + log(`Not logged in. Please log in to see project status.`); + log(); + log('Login with "netlify login" command'); + return exit(); + } + const siteId = site.id; + log(`──────────────────────┐ + Current Netlify User │ +ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜`); + let user; + try { + user = await api.getCurrentUser(); + } + catch (error_) { + if (error_.status === 401) { + return logAndThrowError('Your session has expired. Please try to re-authenticate by running `netlify logout` and `netlify login`.'); + } + else { + return logAndThrowError(error_); + } + } + const ghuser = currentUserId != null + ? globalConfig.get(`users.${currentUserId}.auth.github.user`) + : undefined; + const accountData = { + Name: user.full_name, + Email: user.email, + GitHub: ghuser, + Teams: accounts.map(({ name }) => name), + }; + const cleanAccountData = + // TODO(serhalp) `deep-clean` type declaration is invalid (this is obscured by `skipLibCheck`). Open a PR or use + // another lib. + clean(accountData); + log(prettyjson.render(cleanAccountData)); + if (!siteId) { + warn('Did you run `netlify link` yet?'); + return logAndThrowError(`You don't appear to be in a folder that is linked to a project`); + } + // Json only logs out if --json flag is passed + if (options.json) { + logJson({ + account: cleanAccountData, + siteData: { + 'site-name': siteInfo.name, + 'config-path': site.configPath, + 'admin-url': siteInfo.admin_url, + 'site-url': siteInfo.ssl_url || siteInfo.url, + 'site-id': siteInfo.id, + }, + }); + } + log(`────────────────────┐ + Netlify Project Info │ +ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”€ā”˜`); + log(prettyjson.render({ + 'Current project': siteInfo.name, + 'Netlify TOML': site.configPath, + 'Admin URL': chalk.magentaBright(siteInfo.admin_url), + 'Project URL': chalk.cyanBright(siteInfo.ssl_url || siteInfo.url), + 'Project Id': chalk.yellowBright(siteInfo.id), + })); + log(); +}; +//# sourceMappingURL=status.js.map \ No newline at end of file diff --git a/dist/commands/status/status.js.map b/dist/commands/status/status.js.map new file mode 100644 index 00000000000..57150b67f9a --- /dev/null +++ b/dist/commands/status/status.js.map @@ -0,0 +1 @@ +{"version":3,"file":"status.js","sourceRoot":"","sources":["../../../src/commands/status/status.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/commands/switch/index.d.ts b/dist/commands/switch/index.d.ts new file mode 100644 index 00000000000..83bc3f3061a --- /dev/null +++ b/dist/commands/switch/index.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const createSwitchCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/switch/index.d.ts.map b/dist/commands/switch/index.d.ts.map new file mode 100644 index 00000000000..07c0a528e31 --- /dev/null +++ b/dist/commands/switch/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/switch/index.ts"],"names":[],"mappings":"AAEA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,mBAAmB,GAAI,SAAS,WAAW,gBAOlD,CAAA"} \ No newline at end of file diff --git a/dist/commands/switch/index.js b/dist/commands/switch/index.js new file mode 100644 index 00000000000..e2a4e5cf80c --- /dev/null +++ b/dist/commands/switch/index.js @@ -0,0 +1,8 @@ +export const createSwitchCommand = (program) => program + .command('switch') + .description('Switch your active Netlify account') + .action(async (options, command) => { + const { switchCommand } = await import('./switch.js'); + await switchCommand(options, command); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/switch/index.js.map b/dist/commands/switch/index.js.map new file mode 100644 index 00000000000..527fd2fab36 --- /dev/null +++ b/dist/commands/switch/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/switch/index.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAAoB,EAAE,EAAE,CAC1D,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,oCAAoC,CAAC;KACjD,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IAC5D,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;IACrD,MAAM,aAAa,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AACvC,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/switch/switch.d.ts b/dist/commands/switch/switch.d.ts new file mode 100644 index 00000000000..3f2a73fe650 --- /dev/null +++ b/dist/commands/switch/switch.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const switchCommand: (_options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=switch.d.ts.map \ No newline at end of file diff --git a/dist/commands/switch/switch.d.ts.map b/dist/commands/switch/switch.d.ts.map new file mode 100644 index 00000000000..042fc36687b --- /dev/null +++ b/dist/commands/switch/switch.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"switch.d.ts","sourceRoot":"","sources":["../../../src/commands/switch/switch.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAIxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAK5C,eAAO,MAAM,aAAa,GAAU,UAAU,YAAY,EAAE,SAAS,WAAW,kBA+B/E,CAAA"} \ No newline at end of file diff --git a/dist/commands/switch/switch.js b/dist/commands/switch/switch.js new file mode 100644 index 00000000000..fe8a269c637 --- /dev/null +++ b/dist/commands/switch/switch.js @@ -0,0 +1,31 @@ +import inquirer from 'inquirer'; +import { chalk, log } from '../../utils/command-helpers.js'; +import { login } from '../login/login.js'; +const LOGIN_NEW = 'I would like to login to a new account'; +export const switchCommand = async (_options, command) => { + const availableUsersChoices = Object.values(command.netlify.globalConfig.get('users') || {}).reduce((prev, current) => + // @ts-expect-error TS(2769) FIXME: No overload matches this call. + Object.assign(prev, { [current.id]: current.name ? `${current.name} (${current.email})` : current.email }), {}); + const { accountSwitchChoice } = await inquirer.prompt([ + { + type: 'list', + name: 'accountSwitchChoice', + message: 'Please select the account you want to use:', + // @ts-expect-error TS(2769) FIXME: No overload matches this call. + choices: [...Object.entries(availableUsersChoices).map(([, val]) => val), LOGIN_NEW], + }, + ]); + if (accountSwitchChoice === LOGIN_NEW) { + await login({ new: true }, command); + } + else { + // @ts-expect-error TS(2769) FIXME: No overload matches this call. + const selectedAccount = Object.entries(availableUsersChoices).find(([, availableUsersChoice]) => availableUsersChoice === accountSwitchChoice); + // @ts-expect-error TS(2532) FIXME: Object is possibly 'undefined'. + command.netlify.globalConfig.set('userId', selectedAccount[0]); + log(''); + // @ts-expect-error TS(2532) FIXME: Object is possibly 'undefined'. + log(`You're now using ${chalk.bold(selectedAccount[1])}.`); + } +}; +//# sourceMappingURL=switch.js.map \ No newline at end of file diff --git a/dist/commands/switch/switch.js.map b/dist/commands/switch/switch.js.map new file mode 100644 index 00000000000..8b45fa854a7 --- /dev/null +++ b/dist/commands/switch/switch.js.map @@ -0,0 +1 @@ +{"version":3,"file":"switch.js","sourceRoot":"","sources":["../../../src/commands/switch/switch.ts"],"names":[],"mappings":"AACA,OAAO,QAAQ,MAAM,UAAU,CAAA;AAE/B,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAA;AAE3D,OAAO,EAAE,KAAK,EAAE,MAAM,mBAAmB,CAAA;AAEzC,MAAM,SAAS,GAAG,wCAAwC,CAAA;AAE1D,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,QAAsB,EAAE,OAAoB,EAAE,EAAE;IAClF,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CACjG,CAAC,IAAI,EAAE,OAAO,EAAE,EAAE;IAChB,kEAAkE;IAClE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC,EAC5G,EAAE,CACH,CAAA;IAED,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;QACpD;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,qBAAqB;YAC3B,OAAO,EAAE,4CAA4C;YACrD,kEAAkE;YAClE,OAAO,EAAE,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,SAAS,CAAC;SACrF;KACF,CAAC,CAAA;IAEF,IAAI,mBAAmB,KAAK,SAAS,EAAE,CAAC;QACtC,MAAM,KAAK,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC,CAAA;IACrC,CAAC;SAAM,CAAC;QACN,kEAAkE;QAClE,MAAM,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAC,IAAI,CAChE,CAAC,CAAC,EAAE,oBAAoB,CAAC,EAAE,EAAE,CAAC,oBAAoB,KAAK,mBAAmB,CAC3E,CAAA;QACD,mEAAmE;QACnE,OAAO,CAAC,OAAO,CAAC,YAAY,CAAC,GAAG,CAAC,QAAQ,EAAE,eAAe,CAAC,CAAC,CAAC,CAAC,CAAA;QAC9D,GAAG,CAAC,EAAE,CAAC,CAAA;QACP,mEAAmE;QACnE,GAAG,CAAC,oBAAoB,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAA;IAC5D,CAAC;AACH,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/unlink/index.d.ts b/dist/commands/unlink/index.d.ts new file mode 100644 index 00000000000..a106f7e6ac8 --- /dev/null +++ b/dist/commands/unlink/index.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const createUnlinkCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/unlink/index.d.ts.map b/dist/commands/unlink/index.d.ts.map new file mode 100644 index 00000000000..edc53f7d0ad --- /dev/null +++ b/dist/commands/unlink/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/unlink/index.ts"],"names":[],"mappings":"AAGA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,mBAAmB,GAAI,SAAS,WAAW,gBAalD,CAAA"} \ No newline at end of file diff --git a/dist/commands/unlink/index.js b/dist/commands/unlink/index.js new file mode 100644 index 00000000000..f89d0e4da7d --- /dev/null +++ b/dist/commands/unlink/index.js @@ -0,0 +1,15 @@ +import terminalLink from 'terminal-link'; +export const createUnlinkCommand = (program) => program + .command('unlink') + .description('Unlink a local folder from a Netlify project') + .addHelpText('after', () => { + const docsUrl = 'https://docs.netlify.com/cli/get-started/#link-and-unlink-sites'; + return ` +For more information about linking projects, see ${terminalLink(docsUrl, docsUrl, { fallback: false })} +`; +}) + .action(async (options, command) => { + const { unlink } = await import('./unlink.js'); + await unlink(options, command); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/unlink/index.js.map b/dist/commands/unlink/index.js.map new file mode 100644 index 00000000000..e7b5c258259 --- /dev/null +++ b/dist/commands/unlink/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/unlink/index.ts"],"names":[],"mappings":"AACA,OAAO,YAAY,MAAM,eAAe,CAAA;AAIxC,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,OAAoB,EAAE,EAAE,CAC1D,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,8CAA8C,CAAC;KAC3D,WAAW,CAAC,OAAO,EAAE,GAAG,EAAE;IACzB,MAAM,OAAO,GAAG,iEAAiE,CAAA;IACjF,OAAO;mDACsC,YAAY,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC;CACrG,CAAA;AACG,CAAC,CAAC;KACD,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IAC5D,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,CAAA;IAC9C,MAAM,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAChC,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/unlink/unlink.d.ts b/dist/commands/unlink/unlink.d.ts new file mode 100644 index 00000000000..3eea450c64f --- /dev/null +++ b/dist/commands/unlink/unlink.d.ts @@ -0,0 +1,4 @@ +import { OptionValues } from 'commander'; +import BaseCommand from '../base-command.js'; +export declare const unlink: (_options: OptionValues, command: BaseCommand) => Promise; +//# sourceMappingURL=unlink.d.ts.map \ No newline at end of file diff --git a/dist/commands/unlink/unlink.d.ts.map b/dist/commands/unlink/unlink.d.ts.map new file mode 100644 index 00000000000..13da455bf93 --- /dev/null +++ b/dist/commands/unlink/unlink.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"unlink.d.ts","sourceRoot":"","sources":["../../../src/commands/unlink/unlink.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAIxC,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAG5C,eAAO,MAAM,MAAM,GAAU,UAAU,YAAY,EAAE,SAAS,WAAW,uBAsBxE,CAAA"} \ No newline at end of file diff --git a/dist/commands/unlink/unlink.js b/dist/commands/unlink/unlink.js new file mode 100644 index 00000000000..3087e869a22 --- /dev/null +++ b/dist/commands/unlink/unlink.js @@ -0,0 +1,23 @@ +import { exit, log } from '../../utils/command-helpers.js'; +import { track } from '../../utils/telemetry/index.js'; +import { chalk, netlifyCommand } from '../../utils/command-helpers.js'; +export const unlink = async (_options, command) => { + const { site, siteInfo, state } = command.netlify; + const siteId = site.id; + if (!siteId) { + log(`Folder is not linked to a Netlify project. Run ${chalk.cyanBright(`${netlifyCommand()} link`)} to link it`); + return exit(); + } + const siteData = siteInfo; + state.delete('siteId'); + await track('sites_unlinked', { + siteId: siteData.id || siteId, + }); + if (site && site.configPath) { + log(`Unlinked ${site.configPath} from ${siteData ? siteData.name : siteId}`); + } + else { + log(`Unlinked from ${siteData ? siteData.name : siteId}`); + } +}; +//# sourceMappingURL=unlink.js.map \ No newline at end of file diff --git a/dist/commands/unlink/unlink.js.map b/dist/commands/unlink/unlink.js.map new file mode 100644 index 00000000000..0ad53c5369e --- /dev/null +++ b/dist/commands/unlink/unlink.js.map @@ -0,0 +1 @@ +{"version":3,"file":"unlink.js","sourceRoot":"","sources":["../../../src/commands/unlink/unlink.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,gCAAgC,CAAA;AAC1D,OAAO,EAAE,KAAK,EAAE,MAAM,gCAAgC,CAAA;AAEtD,OAAO,EAAE,KAAK,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAA;AAEtE,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,EAAE,QAAsB,EAAE,OAAoB,EAAE,EAAE;IAC3E,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,GAAG,OAAO,CAAC,OAAO,CAAA;IACjD,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAA;IAEtB,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,GAAG,CAAC,kDAAkD,KAAK,CAAC,UAAU,CAAC,GAAG,cAAc,EAAE,OAAO,CAAC,aAAa,CAAC,CAAA;QAChH,OAAO,IAAI,EAAE,CAAA;IACf,CAAC;IAED,MAAM,QAAQ,GAAG,QAAQ,CAAA;IAEzB,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;IAEtB,MAAM,KAAK,CAAC,gBAAgB,EAAE;QAC5B,MAAM,EAAE,QAAQ,CAAC,EAAE,IAAI,MAAM;KAC9B,CAAC,CAAA;IAEF,IAAI,IAAI,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;QAC5B,GAAG,CAAC,YAAY,IAAI,CAAC,UAAU,SAAS,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAA;IAC9E,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,iBAAiB,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAA;IAC3D,CAAC;AACH,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/watch/index.d.ts b/dist/commands/watch/index.d.ts new file mode 100644 index 00000000000..c75b74d22a7 --- /dev/null +++ b/dist/commands/watch/index.d.ts @@ -0,0 +1,3 @@ +import BaseCommand from '../base-command.js'; +export declare const createWatchCommand: (program: BaseCommand) => BaseCommand; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/commands/watch/index.d.ts.map b/dist/commands/watch/index.d.ts.map new file mode 100644 index 00000000000..3150ee0c034 --- /dev/null +++ b/dist/commands/watch/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/commands/watch/index.ts"],"names":[],"mappings":"AAEA,OAAO,WAAW,MAAM,oBAAoB,CAAA;AAE5C,eAAO,MAAM,kBAAkB,GAAI,SAAS,WAAW,gBAQjD,CAAA"} \ No newline at end of file diff --git a/dist/commands/watch/index.js b/dist/commands/watch/index.js new file mode 100644 index 00000000000..01cfd80151a --- /dev/null +++ b/dist/commands/watch/index.js @@ -0,0 +1,9 @@ +export const createWatchCommand = (program) => program + .command('watch') + .description('Watch for project deploy to finish') + .addExamples([`netlify watch`, `git push && netlify watch`]) + .action(async (options, command) => { + const { watch } = await import('./watch.js'); + await watch(options, command); +}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/commands/watch/index.js.map b/dist/commands/watch/index.js.map new file mode 100644 index 00000000000..9601ebaacdb --- /dev/null +++ b/dist/commands/watch/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/commands/watch/index.ts"],"names":[],"mappings":"AAIA,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,OAAoB,EAAE,EAAE,CACzD,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,oCAAoC,CAAC;KACjD,WAAW,CAAC,CAAC,eAAe,EAAE,2BAA2B,CAAC,CAAC;KAC3D,MAAM,CAAC,KAAK,EAAE,OAAqB,EAAE,OAAoB,EAAE,EAAE;IAC5D,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAA;IAC5C,MAAM,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;AAC/B,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/commands/watch/watch.d.ts b/dist/commands/watch/watch.d.ts new file mode 100644 index 00000000000..d11c3f2ebe5 --- /dev/null +++ b/dist/commands/watch/watch.d.ts @@ -0,0 +1,3 @@ +import type BaseCommand from '../base-command.js'; +export declare const watch: (_options: unknown, command: BaseCommand) => Promise; +//# sourceMappingURL=watch.d.ts.map \ No newline at end of file diff --git a/dist/commands/watch/watch.d.ts.map b/dist/commands/watch/watch.d.ts.map new file mode 100644 index 00000000000..052bdfe4633 --- /dev/null +++ b/dist/commands/watch/watch.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"watch.d.ts","sourceRoot":"","sources":["../../../src/commands/watch/watch.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,WAAW,MAAM,oBAAoB,CAAA;AA0CjD,eAAO,MAAM,KAAK,GAAU,UAAU,OAAO,EAAE,SAAS,WAAW,uBA6DlE,CAAA"} \ No newline at end of file diff --git a/dist/commands/watch/watch.js b/dist/commands/watch/watch.js new file mode 100644 index 00000000000..b6ff05c005e --- /dev/null +++ b/dist/commands/watch/watch.js @@ -0,0 +1,91 @@ +import pWaitFor from 'p-wait-for'; +import prettyjson from 'prettyjson'; +import { startSpinner, stopSpinner } from '../../lib/spinner.js'; +import { chalk, logAndThrowError, log } from '../../utils/command-helpers.js'; +import { init } from '../init/init.js'; +// 1 second +const INIT_WAIT = 1e3; +// 1 second +const BUILD_FINISH_INTERVAL = 1e3; +// 20 minutes +const BUILD_FINISH_TIMEOUT = 12e5; +const waitForBuildFinish = async function (api, siteId, spinner) { + let firstPass = true; + const waitForBuildToFinish = async function () { + const builds = await api.listSiteBuilds({ siteId }); + // build.error + const currentBuilds = builds.filter((build) => !build.done); + // if build.error + // @TODO implement build error messages into this + if (!currentBuilds || currentBuilds.length === 0) { + stopSpinner({ spinner }); + return true; + } + firstPass = false; + return false; + }; + await pWaitFor(waitForBuildToFinish, { + interval: BUILD_FINISH_INTERVAL, + timeout: { + milliseconds: BUILD_FINISH_TIMEOUT, + message: 'Timeout while waiting for deploy to finish', + }, + }); + // return only when build done or timeout happens + return firstPass; +}; +export const watch = async (_options, command) => { + await command.authenticate(); + const client = command.netlify.api; + let siteId = command.netlify.site.id; + if (!siteId) { + // TODO: build init command + const siteData = await init({}, command); + siteId = siteData.id; + } + // wait for 1 sec for everything to kickoff + console.time('Deploy time'); + await new Promise((resolve) => { + setTimeout(() => { + resolve(undefined); + }, INIT_WAIT); + }); + // Get latest commit and look for that + // git rev-parse HEAD + // if no sha, its a manual "triggered deploy" + // + // { + // "id": "5b4e23db82d3f1780abd74f3", + // "deploy_id": "5b4e23db82d3f1780abd74f2", + // "sha": "pull/1/head", + // "log": [], + // "done": false, + // "error": null, + // "created_at": "2018-07-17T17:14:03.423Z" + // } + // + const spinner = startSpinner({ text: 'Waiting for active project deploys to complete' }); + try { + // Fetch all builds! + // const builds = await client.listSiteBuilds({siteId}) + // + // // Filter down to any that are not done + // const buildsToWatch = builds.filter((build) => { + // return !build.done + // }) + const noActiveBuilds = await waitForBuildFinish(client, siteId, spinner); + const siteData = await client.getSite({ siteId }); + const message = chalk.cyanBright.bold.underline(noActiveBuilds ? 'Last build' : 'Deploy complete'); + log(); + log(message); + log(prettyjson.render({ + URL: siteData.ssl_url || siteData.url, + Admin: siteData.admin_url, + })); + console.timeEnd('Deploy time'); + } + catch (error_) { + return logAndThrowError(error_); + } +}; +//# sourceMappingURL=watch.js.map \ No newline at end of file diff --git a/dist/commands/watch/watch.js.map b/dist/commands/watch/watch.js.map new file mode 100644 index 00000000000..e787f9cef32 --- /dev/null +++ b/dist/commands/watch/watch.js.map @@ -0,0 +1 @@ +{"version":3,"file":"watch.js","sourceRoot":"","sources":["../../../src/commands/watch/watch.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/index.d.ts b/dist/index.d.ts new file mode 100644 index 00000000000..c2af4344d91 --- /dev/null +++ b/dist/index.d.ts @@ -0,0 +1,2 @@ +export { NetlifyAPI, methods } from '@netlify/api'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/index.d.ts.map b/dist/index.d.ts.map new file mode 100644 index 00000000000..1bb7aefb1ba --- /dev/null +++ b/dist/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA"} \ No newline at end of file diff --git a/dist/index.js b/dist/index.js new file mode 100644 index 00000000000..fefd61fba1b --- /dev/null +++ b/dist/index.js @@ -0,0 +1,5 @@ +// This is an entrypoint that mirrors the interface that the `netlify` package +// used to have, before it was renamed to `@netlify/api`. We keep it for +// backwards-compatibility. +export { NetlifyAPI, methods } from '@netlify/api'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/index.js.map b/dist/index.js.map new file mode 100644 index 00000000000..da887cb1217 --- /dev/null +++ b/dist/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,wEAAwE;AACxE,2BAA2B;AAC3B,OAAO,EAAE,UAAU,EAAE,OAAO,EAAE,MAAM,cAAc,CAAA"} \ No newline at end of file diff --git a/dist/lib/account.d.ts b/dist/lib/account.d.ts new file mode 100644 index 00000000000..2c469e0b78e --- /dev/null +++ b/dist/lib/account.d.ts @@ -0,0 +1,3 @@ +import type { Account } from '../utils/dev.js'; +export declare const supportsBackgroundFunctions: (account?: Account) => boolean; +//# sourceMappingURL=account.d.ts.map \ No newline at end of file diff --git a/dist/lib/account.d.ts.map b/dist/lib/account.d.ts.map new file mode 100644 index 00000000000..8afeb2517c2 --- /dev/null +++ b/dist/lib/account.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"account.d.ts","sourceRoot":"","sources":["../../src/lib/account.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAc,MAAM,iBAAiB,CAAA;AAK1D,eAAO,MAAM,2BAA2B,GAAI,UAAU,OAAO,KAAG,OACJ,CAAA"} \ No newline at end of file diff --git a/dist/lib/account.js b/dist/lib/account.js new file mode 100644 index 00000000000..cb1862b4a0c --- /dev/null +++ b/dist/lib/account.js @@ -0,0 +1,3 @@ +const supportsBooleanCapability = (account, capability) => Boolean(account?.capabilities?.[capability]?.included); +export const supportsBackgroundFunctions = (account) => supportsBooleanCapability(account, 'background_functions'); +//# sourceMappingURL=account.js.map \ No newline at end of file diff --git a/dist/lib/account.js.map b/dist/lib/account.js.map new file mode 100644 index 00000000000..3c105a9a04e --- /dev/null +++ b/dist/lib/account.js.map @@ -0,0 +1 @@ +{"version":3,"file":"account.js","sourceRoot":"","sources":["../../src/lib/account.ts"],"names":[],"mappings":"AAEA,MAAM,yBAAyB,GAAG,CAAC,OAA4B,EAAE,UAAsB,EAAE,EAAE,CACzF,OAAO,CAAC,OAAO,EAAE,YAAY,EAAE,CAAC,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAA;AAExD,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,OAAiB,EAAW,EAAE,CACxE,yBAAyB,CAAC,OAAO,EAAE,sBAAsB,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/lib/api.d.ts b/dist/lib/api.d.ts new file mode 100644 index 00000000000..23feebcd60f --- /dev/null +++ b/dist/lib/api.d.ts @@ -0,0 +1,14 @@ +import type { NetlifyAPI } from '@netlify/api'; +import type { SiteInfo } from '../utils/types.js'; +export declare const cancelDeploy: ({ api, deployId }: { + api: NetlifyAPI; + deployId: string; +}) => Promise; +export declare const listSites: ({ api, options, }: { + api: NetlifyAPI; + options: Parameters[0] & { + page?: number; + maxPages?: number; + }; +}) => Promise; +//# sourceMappingURL=api.d.ts.map \ No newline at end of file diff --git a/dist/lib/api.d.ts.map b/dist/lib/api.d.ts.map new file mode 100644 index 00000000000..3ab883f65b7 --- /dev/null +++ b/dist/lib/api.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAG9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEjD,eAAO,MAAM,YAAY,GAAU,mBAAmB;IAAE,GAAG,EAAE,UAAU,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,KAAG,OAAO,CAAC,IAAI,CAUzG,CAAA;AAMD,eAAO,MAAM,SAAS,GAAU,mBAG7B;IACD,GAAG,EAAE,UAAU,CAAA;IAEf,OAAO,EAAE,UAAU,CAAC,OAAO,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,GAAG;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CACpF,KAAG,OAAO,CAAC,QAAQ,EAAE,CAarB,CAAA"} \ No newline at end of file diff --git a/dist/lib/api.js b/dist/lib/api.js new file mode 100644 index 00000000000..7e9f6fabc12 --- /dev/null +++ b/dist/lib/api.js @@ -0,0 +1,27 @@ +import { warn } from '../utils/command-helpers.js'; +export const cancelDeploy = async ({ api, deployId }) => { + try { + await api.cancelSiteDeploy({ deploy_id: deployId }); + } + catch (error) { + warn(`Failed canceling deploy with id ${deployId}: ${error instanceof Error ? error.message : error?.toString() ?? ''}`); + } +}; +const FIRST_PAGE = 1; +const MAX_PAGES = 10; +const MAX_PER_PAGE = 100; +export const listSites = async ({ api, options, }) => { + const { maxPages = MAX_PAGES, page = FIRST_PAGE, ...rest } = options; + const sites = await api.listSites({ page, per_page: MAX_PER_PAGE, ...rest }); + // TODO: use pagination headers when js-client returns them + if (sites.length === MAX_PER_PAGE && page + 1 <= maxPages) { + // FIXME(serhalp): `id` and `name` should be required in `netlify` package type + return [ + ...sites, + ...(await listSites({ api, options: { page: page + 1, maxPages, ...rest } })), + ]; + } + // FIXME(serhalp): See above + return sites; +}; +//# sourceMappingURL=api.js.map \ No newline at end of file diff --git a/dist/lib/api.js.map b/dist/lib/api.js.map new file mode 100644 index 00000000000..2e278c9e6b3 --- /dev/null +++ b/dist/lib/api.js.map @@ -0,0 +1 @@ +{"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,IAAI,EAAE,MAAM,6BAA6B,CAAA;AAGlD,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAyC,EAAiB,EAAE;IAC5G,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,gBAAgB,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,CAAC,CAAA;IACrD,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CACF,mCAAmC,QAAQ,KACzC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,IAAI,EAChE,EAAE,CACH,CAAA;IACH,CAAC;AACH,CAAC,CAAA;AAED,MAAM,UAAU,GAAG,CAAC,CAAA;AACpB,MAAM,SAAS,GAAG,EAAE,CAAA;AACpB,MAAM,YAAY,GAAG,GAAG,CAAA;AAExB,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,EAC9B,GAAG,EACH,OAAO,GAKR,EAAuB,EAAE;IACxB,MAAM,EAAE,QAAQ,GAAG,SAAS,EAAE,IAAI,GAAG,UAAU,EAAE,GAAG,IAAI,EAAE,GAAG,OAAO,CAAA;IACpE,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,GAAG,IAAI,EAAE,CAAC,CAAA;IAC5E,2DAA2D;IAC3D,IAAI,KAAK,CAAC,MAAM,KAAK,YAAY,IAAI,IAAI,GAAG,CAAC,IAAI,QAAQ,EAAE,CAAC;QAC1D,+EAA+E;QAC/E,OAAO;YACL,GAAG,KAAK;YACR,GAAG,CAAC,MAAM,SAAS,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,IAAI,GAAG,CAAC,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,EAAE,CAAC,CAAC;SACnD,CAAA;IAC9B,CAAC;IACD,4BAA4B;IAC5B,OAAO,KAAgC,CAAA;AACzC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/lib/blobs/blobs.d.ts b/dist/lib/blobs/blobs.d.ts new file mode 100644 index 00000000000..301e7535858 --- /dev/null +++ b/dist/lib/blobs/blobs.d.ts @@ -0,0 +1,47 @@ +interface BaseBlobsContext { + deployID: string; + siteID: string; + primaryRegion?: string; + token: string; +} +export interface BlobsContextWithAPIAccess extends BaseBlobsContext { + apiURL: string; +} +export interface BlobsContextWithEdgeAccess extends BaseBlobsContext { + edgeURL: string; + uncachedEdgeURL: string; +} +export type BlobsContext = BlobsContextWithAPIAccess | BlobsContextWithEdgeAccess; +export declare const BLOBS_CONTEXT_VARIABLE = "NETLIFY_BLOBS_CONTEXT"; +interface GetBlobsContextOptions { + debug: boolean; + projectRoot: string; + siteID: string; +} +/** + * Starts a local Blobs server and returns a context object that lets build + * plugins connect to it. + */ +export declare const getBlobsContextWithAPIAccess: ({ debug, projectRoot, siteID }: GetBlobsContextOptions) => Promise; +/** + * Starts a local Blobs server and returns a context object that lets functions + * and edge functions connect to it. + */ +export declare const getBlobsContextWithEdgeAccess: ({ debug, projectRoot, siteID }: GetBlobsContextOptions) => Promise; +/** + * Returns the Blobs metadata that should be added to the Lambda event when + * invoking a serverless function. + */ +export declare const getBlobsEventProperty: (context: BlobsContextWithEdgeAccess) => { + primary_region: string | undefined; + url: string; + url_uncached: string; + token: string; +}; +/** + * Returns a Base-64, JSON-encoded representation of the Blobs context. This is + * the format that the `@netlify/blobs` package expects to find the context in. + */ +export declare const encodeBlobsContext: (context: BlobsContext) => string; +export {}; +//# sourceMappingURL=blobs.d.ts.map \ No newline at end of file diff --git a/dist/lib/blobs/blobs.d.ts.map b/dist/lib/blobs/blobs.d.ts.map new file mode 100644 index 00000000000..595e7a555f2 --- /dev/null +++ b/dist/lib/blobs/blobs.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"blobs.d.ts","sourceRoot":"","sources":["../../../src/lib/blobs/blobs.ts"],"names":[],"mappings":"AASA,UAAU,gBAAgB;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,MAAM,WAAW,yBAA0B,SAAQ,gBAAgB;IACjE,MAAM,EAAE,MAAM,CAAA;CACf;AAED,MAAM,WAAW,0BAA2B,SAAQ,gBAAgB;IAClE,OAAO,EAAE,MAAM,CAAA;IACf,eAAe,EAAE,MAAM,CAAA;CACxB;AAED,MAAM,MAAM,YAAY,GAAG,yBAAyB,GAAG,0BAA0B,CAAA;AAIjF,eAAO,MAAM,sBAAsB,0BAA0B,CAAA;AAoC7D,UAAU,sBAAsB;IAC9B,KAAK,EAAE,OAAO,CAAA;IACd,WAAW,EAAE,MAAM,CAAA;IACnB,MAAM,EAAE,MAAM,CAAA;CACf;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,GAAU,gCAAgC,sBAAsB,uCAWxG,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,6BAA6B,GAAU,gCAAgC,sBAAsB,wCAYzG,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,GAAI,SAAS,0BAA0B;;;;;CAKvE,CAAA;AAEF;;;GAGG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,YAAY,WAA4D,CAAA"} \ No newline at end of file diff --git a/dist/lib/blobs/blobs.js b/dist/lib/blobs/blobs.js new file mode 100644 index 00000000000..366bc6369c3 --- /dev/null +++ b/dist/lib/blobs/blobs.js @@ -0,0 +1,82 @@ +import { Buffer } from 'buffer'; +import path from 'path'; +import { BlobsServer } from '@netlify/blobs/server'; +import { v4 as uuidv4 } from 'uuid'; +import { log, NETLIFYDEVLOG } from '../../utils/command-helpers.js'; +import { getPathInProject } from '../settings.js'; +let hasPrintedLocalBlobsNotice = false; +export const BLOBS_CONTEXT_VARIABLE = 'NETLIFY_BLOBS_CONTEXT'; +const DEV_REGION = 'dev'; +const printLocalBlobsNotice = () => { + if (hasPrintedLocalBlobsNotice) { + return; + } + hasPrintedLocalBlobsNotice = true; + log(`${NETLIFYDEVLOG} Netlify Blobs running in sandbox mode for local development. Refer to https://ntl.fyi/local-blobs for more information.`); +}; +/** + * Starts a local Blobs server on a random port and generates a random token + * for its authentication. + */ +const initializeBlobsServer = async (projectRoot, debug) => { + const token = uuidv4(); + const directory = path.resolve(projectRoot, getPathInProject(['blobs-serve'])); + const server = new BlobsServer({ + debug, + directory, + onRequest: () => { + printLocalBlobsNotice(); + }, + token, + }); + const { port } = await server.start(); + const url = `http://localhost:${port}`; + return { url, token }; +}; +/** + * Starts a local Blobs server and returns a context object that lets build + * plugins connect to it. + */ +export const getBlobsContextWithAPIAccess = async ({ debug, projectRoot, siteID }) => { + const { token, url } = await initializeBlobsServer(projectRoot, debug); + const context = { + apiURL: url, + deployID: '0', + primaryRegion: DEV_REGION, + siteID, + token, + }; + return context; +}; +/** + * Starts a local Blobs server and returns a context object that lets functions + * and edge functions connect to it. + */ +export const getBlobsContextWithEdgeAccess = async ({ debug, projectRoot, siteID }) => { + const { token, url } = await initializeBlobsServer(projectRoot, debug); + const context = { + deployID: '0', + edgeURL: url, + siteID, + token, + uncachedEdgeURL: url, + primaryRegion: DEV_REGION, + }; + return context; +}; +/** + * Returns the Blobs metadata that should be added to the Lambda event when + * invoking a serverless function. + */ +export const getBlobsEventProperty = (context) => ({ + primary_region: context.primaryRegion, + url: context.edgeURL, + url_uncached: context.edgeURL, + token: context.token, +}); +/** + * Returns a Base-64, JSON-encoded representation of the Blobs context. This is + * the format that the `@netlify/blobs` package expects to find the context in. + */ +export const encodeBlobsContext = (context) => Buffer.from(JSON.stringify(context)).toString('base64'); +//# sourceMappingURL=blobs.js.map \ No newline at end of file diff --git a/dist/lib/blobs/blobs.js.map b/dist/lib/blobs/blobs.js.map new file mode 100644 index 00000000000..2618b450e4d --- /dev/null +++ b/dist/lib/blobs/blobs.js.map @@ -0,0 +1 @@ +{"version":3,"file":"blobs.js","sourceRoot":"","sources":["../../../src/lib/blobs/blobs.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/build.d.ts b/dist/lib/build.d.ts new file mode 100644 index 00000000000..f3dce4e2134 --- /dev/null +++ b/dist/lib/build.d.ts @@ -0,0 +1,111 @@ +import build, { type NetlifyConfig, type OnPostBuild } from '@netlify/build'; +import type { MinimalHeader } from '@netlify/headers-parser'; +import type { OptionValues } from 'commander'; +import type { MinimalAccount, EnvironmentVariables, Plugin, SiteInfo } from '../utils/types.js'; +import type { EdgeFunctionDeclaration } from './edge-functions/proxy.js'; +export interface CachedConfig { + accounts: MinimalAccount[] | undefined; + buildDir: string; + env: EnvironmentVariables; + repositoryRoot: string; + siteInfo: SiteInfo; + api?: unknown; + branch?: unknown; + config: { + build: { + base: string; + command?: string | undefined; + functions?: string | undefined; + functionsSource?: string | undefined; + edge_functions?: string | undefined; + environment: Record; + processing: { + css: Record; + html: Record; + images: Record; + js: Record; + }; + publish: string; + publishOrigin: string; + services: Record; + }; + dev?: undefined | { + command?: string | undefined; + functions?: string | undefined; + functionsPort?: number | undefined; + https?: { + certFile: string; + keyFile: string; + } | undefined; + processing: { + html?: { + injections?: { + /** + * The location at which the `html` will be injected. + * Defaults to `before_closing_head_tag` which will inject the HTML before the tag. + */ + location?: 'before_closing_head_tag' | 'before_closing_body_tag'; + /** + * The injected HTML code. + */ + html: string; + }[]; + }; + }; + }; + edge_functions?: EdgeFunctionDeclaration[]; + functions?: NetlifyConfig['functions']; + functionsDirectory?: undefined | string; + headers: MinimalHeader[]; + images: { + remote_images: string[]; + }; + plugins?: Plugin[]; + redirects: undefined | NetlifyConfig['redirects']; + }; + configPath?: undefined | string; + context: string; + headersPath?: unknown; + logs?: unknown; + redirectsPath?: unknown; + token?: unknown; +} +export interface DefaultConfig { + build: { + command?: string | undefined; + commandOrigin?: 'default' | undefined; + publish?: string | undefined; + publishOrigin?: 'default' | undefined; + }; + plugins?: { + package: unknown; + origin: 'default'; + }[]; +} +export type RunBuildOptions = Omit[0]>, 'cachedConfig'> & { + cachedConfig: CachedConfig; + defaultConfig: DefaultConfig | Record; + edgeFunctionsBootstrapURL: string; +}; +interface HandlerResult { + newEnvChanges?: Record; + configMutations?: Record; + status?: string; +} +export type PatchedHandlerType void | Promise> = (opts: Parameters[0]) => HandlerResult | Promise; +export declare const getRunBuildOptions: ({ cachedConfig, currentDir, defaultConfig, deployHandler, options: { context, cwd, debug, dry, json, offline, silent }, packagePath, token, }: { + cachedConfig: CachedConfig; + currentDir: string; + defaultConfig?: undefined | DefaultConfig; + deployHandler?: PatchedHandlerType; + options: OptionValues; + packagePath?: string; + token?: null | string; +}) => Promise; +export declare const runBuild: (options: RunBuildOptions) => Promise<{ + exitCode: number; + newConfig: any; + configMutations: any; +}>; +export {}; +//# sourceMappingURL=build.d.ts.map \ No newline at end of file diff --git a/dist/lib/build.d.ts.map b/dist/lib/build.d.ts.map new file mode 100644 index 00000000000..605f534ee85 --- /dev/null +++ b/dist/lib/build.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"build.d.ts","sourceRoot":"","sources":["../../src/lib/build.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,EAAE,KAAK,aAAa,EAAc,KAAK,WAAW,EAAE,MAAM,gBAAgB,CAAA;AACxF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAA;AAE5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAG7C,OAAO,KAAK,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAI/F,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAA;AAExE,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,cAAc,EAAE,GAAG,SAAS,CAAA;IACtC,QAAQ,EAAE,MAAM,CAAA;IAChB,GAAG,EAAE,oBAAoB,CAAA;IACzB,cAAc,EAAE,MAAM,CAAA;IACtB,QAAQ,EAAE,QAAQ,CAAA;IAGlB,GAAG,CAAC,EAAE,OAAO,CAAA;IACb,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE;QACN,KAAK,EAAE;YACL,IAAI,EAAE,MAAM,CAAA;YACZ,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YAE9B,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YACpC,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YACnC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;YACpC,UAAU,EAAE;gBACV,GAAG,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;gBAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;gBAC7B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;gBAC/B,EAAE,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;aAC5B,CAAA;YACD,OAAO,EAAE,MAAM,CAAA;YACf,aAAa,EAAE,MAAM,CAAA;YACrB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;SAClC,CAAA;QAGD,GAAG,CAAC,EACA,SAAS,GACT;YACE,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YAC5B,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YAC9B,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;YAClC,KAAK,CAAC,EACF;gBACE,QAAQ,EAAE,MAAM,CAAA;gBAChB,OAAO,EAAE,MAAM,CAAA;aAChB,GACD,SAAS,CAAA;YAGb,UAAU,EAAE;gBACV,IAAI,CAAC,EAAE;oBACL,UAAU,CAAC,EAAE;wBACX;;;2BAGG;wBACH,QAAQ,CAAC,EAAE,yBAAyB,GAAG,yBAAyB,CAAA;wBAChE;;2BAEG;wBACH,IAAI,EAAE,MAAM,CAAA;qBACb,EAAE,CAAA;iBACJ,CAAA;aACF,CAAA;SACF,CAAA;QACL,cAAc,CAAC,EAAE,uBAAuB,EAAE,CAAA;QAC1C,SAAS,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,CAAA;QACtC,kBAAkB,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;QACvC,OAAO,EAAE,aAAa,EAAE,CAAA;QACxB,MAAM,EAAE;YACN,aAAa,EAAE,MAAM,EAAE,CAAA;SACxB,CAAA;QACD,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;QAClB,SAAS,EAAE,SAAS,GAAG,aAAa,CAAC,WAAW,CAAC,CAAA;KAClD,CAAA;IACD,UAAU,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,IAAI,CAAC,EAAE,OAAO,CAAA;IACd,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,KAAK,CAAC,EAAE,OAAO,CAAA;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE;QACL,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QAC5B,aAAa,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;QACrC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;QAC5B,aAAa,CAAC,EAAE,SAAS,GAAG,SAAS,CAAA;KACtC,CAAA;IACD,OAAO,CAAC,EAAE;QAAE,OAAO,EAAE,OAAO,CAAC;QAAC,MAAM,EAAE,SAAS,CAAA;KAAE,EAAE,CAAA;CACpD;AAGD,MAAM,MAAM,eAAe,GAAG,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,cAAc,CAAC,GAAG;IAC7F,YAAY,EAAE,YAAY,CAAA;IAC1B,aAAa,EAAE,aAAa,GAAG,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,CAAA;IACnD,yBAAyB,EAAE,MAAM,CAAA;CAClC,CAAA;AAED,UAAU,aAAa;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACxC,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,MAAM,kBAAkB,CAAC,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,IAAI,CAC9E,IAAI,EAAE,UAAU,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,KACnB,aAAa,GAAG,OAAO,CAAC,aAAa,CAAC,CAAA;AAU3C,eAAO,MAAM,kBAAkB,GAAU,+IAQtC;IACD,YAAY,EAAE,YAAY,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;IAClB,aAAa,CAAC,EAAE,SAAS,GAAG,aAAa,CAAA;IACzC,aAAa,CAAC,EAAE,kBAAkB,CAAC,WAAW,CAAC,CAAA;IAC/C,OAAO,EAAE,YAAY,CAAA;IACrB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,CAAA;CACtB,KAAG,OAAO,CAAC,eAAe,CAiD1B,CAAA;AAED,eAAO,MAAM,QAAQ,GAAU,SAAS,eAAe;;;;EAqBtD,CAAA"} \ No newline at end of file diff --git a/dist/lib/build.js b/dist/lib/build.js new file mode 100644 index 00000000000..f69be6d5b85 --- /dev/null +++ b/dist/lib/build.js @@ -0,0 +1,75 @@ +import fs from 'fs'; +import process from 'process'; +import build from '@netlify/build'; +import tomlify from 'tomlify-j0.4'; +import { getFeatureFlagsFromSiteInfo } from '../utils/feature-flags.js'; +import { getBootstrapURL } from './edge-functions/bootstrap.js'; +import { featureFlags as edgeFunctionsFeatureFlags } from './edge-functions/consts.js'; +// We have already resolved the configuration using `@netlify/config` +// This is stored as `netlify.cachedConfig` and can be passed to +// `@netlify/build --cachedConfig`. +export const getRunBuildOptions = async ({ cachedConfig, currentDir, defaultConfig, deployHandler, options: { context, cwd, debug, dry, json, offline, silent }, packagePath, token, }) => { + const eventHandlers = { + onEnd: { + handler: ({ netlifyConfig }) => { + const string = tomlify.toToml(netlifyConfig); + if (!fs.existsSync(`${currentDir}/.netlify`)) { + fs.mkdirSync(`${currentDir}/.netlify`, { recursive: true }); + } + fs.writeFileSync(`${currentDir}/.netlify/netlify.toml`, string); + return {}; + }, + description: 'Save updated config', + }, + }; + if (deployHandler) { + eventHandlers.onPostBuild = { + handler: deployHandler, + description: 'Deploy Site', + }; + } + return { + cachedConfig, + defaultConfig: defaultConfig ?? {}, + siteId: cachedConfig.siteInfo.id, + accountId: cachedConfig.siteInfo.account_id, + packagePath, + token: token ?? undefined, + dry, + debug, + context, + mode: 'cli', + telemetry: false, + // buffer = true will not stream output + buffer: json || silent, + offline, + cwd, + featureFlags: { + ...edgeFunctionsFeatureFlags, + ...getFeatureFlagsFromSiteInfo(cachedConfig.siteInfo), + functionsBundlingManifest: true, + }, + // @ts-expect-error(serhalp) -- TODO(serhalp): Upstream the type fixes above into @netlify/build + eventHandlers, + edgeFunctionsBootstrapURL: await getBootstrapURL(), + }; +}; +export const runBuild = async (options) => { + // If netlify NETLIFY_API_URL is set we need to pass this information to @netlify/build + // TODO don't use testOpts, but add real properties to do this. + if (process.env.NETLIFY_API_URL) { + const apiUrl = new URL(process.env.NETLIFY_API_URL); + const testOpts = { + scheme: apiUrl.protocol.slice(0, -1), + host: apiUrl.host, + }; + // @ts-expect-error(serhalp) -- I don't know what's going on here and I can't convince myself it even works as + // intended. TODO(serhalp): Investigate and fix types. + options = { ...options, testOpts }; + } + const { configMutations, netlifyConfig: newConfig, severityCode: exitCode, + // TODO(serhalp): Upstream the type fixes above into @netlify/build and remove this type assertion + } = await build(options); + return { exitCode, newConfig, configMutations }; +}; +//# sourceMappingURL=build.js.map \ No newline at end of file diff --git a/dist/lib/build.js.map b/dist/lib/build.js.map new file mode 100644 index 00000000000..1076fc72b4c --- /dev/null +++ b/dist/lib/build.js.map @@ -0,0 +1 @@ +{"version":3,"file":"build.js","sourceRoot":"","sources":["../../src/lib/build.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/completion/constants.d.ts b/dist/lib/completion/constants.d.ts new file mode 100644 index 00000000000..3b990e41ceb --- /dev/null +++ b/dist/lib/completion/constants.d.ts @@ -0,0 +1,2 @@ +export declare const AUTOCOMPLETION_FILE: string; +//# sourceMappingURL=constants.d.ts.map \ No newline at end of file diff --git a/dist/lib/completion/constants.d.ts.map b/dist/lib/completion/constants.d.ts.map new file mode 100644 index 00000000000..d46a4b5c581 --- /dev/null +++ b/dist/lib/completion/constants.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/lib/completion/constants.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,mBAAmB,QAAyC,CAAA"} \ No newline at end of file diff --git a/dist/lib/completion/constants.js b/dist/lib/completion/constants.js new file mode 100644 index 00000000000..a08eeec258b --- /dev/null +++ b/dist/lib/completion/constants.js @@ -0,0 +1,3 @@ +import { getPathInHome } from '../settings.js'; +export const AUTOCOMPLETION_FILE = getPathInHome(['autocompletion.json']); +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/dist/lib/completion/constants.js.map b/dist/lib/completion/constants.js.map new file mode 100644 index 00000000000..292f76f8b50 --- /dev/null +++ b/dist/lib/completion/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/lib/completion/constants.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AAE9C,MAAM,CAAC,MAAM,mBAAmB,GAAG,aAAa,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/lib/completion/generate-autocompletion.d.ts b/dist/lib/completion/generate-autocompletion.d.ts new file mode 100644 index 00000000000..2ec2f42166e --- /dev/null +++ b/dist/lib/completion/generate-autocompletion.d.ts @@ -0,0 +1,8 @@ +/** + * Create or updates the autocompletion information for the CLI + * @param {import('../../commands/base-command.js').default} program + * @returns {void} + */ +declare const generateAutocompletion: (program: any) => void; +export default generateAutocompletion; +//# sourceMappingURL=generate-autocompletion.d.ts.map \ No newline at end of file diff --git a/dist/lib/completion/generate-autocompletion.d.ts.map b/dist/lib/completion/generate-autocompletion.d.ts.map new file mode 100644 index 00000000000..b8499d80f77 --- /dev/null +++ b/dist/lib/completion/generate-autocompletion.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"generate-autocompletion.d.ts","sourceRoot":"","sources":["../../../src/lib/completion/generate-autocompletion.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AAEH,QAAA,MAAM,sBAAsB,GAAI,YAAO,SA+BtC,CAAA;AAED,eAAe,sBAAsB,CAAA"} \ No newline at end of file diff --git a/dist/lib/completion/generate-autocompletion.js b/dist/lib/completion/generate-autocompletion.js new file mode 100644 index 00000000000..51a81b7cf86 --- /dev/null +++ b/dist/lib/completion/generate-autocompletion.js @@ -0,0 +1,42 @@ +import fs from 'fs'; +import { dirname } from 'path'; +import { sortOptions, warn } from '../../utils/command-helpers.js'; +import { AUTOCOMPLETION_FILE } from './constants.js'; +/** + * Create or updates the autocompletion information for the CLI + * @param {import('../../commands/base-command.js').default} program + * @returns {void} + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'program' implicitly has an 'any' type. +const generateAutocompletion = (program) => { + try { + const autocomplete = program.commands.reduce( + // @ts-expect-error TS(7006) FIXME: Parameter 'prev' implicitly has an 'any' type. + (prev, cmd) => ({ + ...prev, + [cmd.name()]: { + name: cmd.name(), + description: cmd.description().split('\n')[0], + options: cmd.options + // @ts-expect-error TS(7006) FIXME: Parameter 'option' implicitly has an 'any' type. + .filter((option) => !option.hidden) + .sort(sortOptions) + // @ts-expect-error TS(7006) FIXME: Parameter 'opt' implicitly has an 'any' type. + .map((opt) => ({ name: `--${opt.name()}`, description: opt.description })), + }, + }), {}); + if (!fs.existsSync(dirname(AUTOCOMPLETION_FILE))) { + fs.mkdirSync(dirname(AUTOCOMPLETION_FILE), { recursive: true }); + } + fs.writeFileSync(AUTOCOMPLETION_FILE, JSON.stringify(autocomplete), 'utf-8'); + } + catch (error_) { + // Sometimes it can happen that the autocomplete generation in the postinstall script lacks permissions + // to write files to the home directory of the user. Therefore just warn with the error and don't break install. + if (error_ instanceof Error) { + warn(`could not create autocompletion.\n${error_.message}`); + } + } +}; +export default generateAutocompletion; +//# sourceMappingURL=generate-autocompletion.js.map \ No newline at end of file diff --git a/dist/lib/completion/generate-autocompletion.js.map b/dist/lib/completion/generate-autocompletion.js.map new file mode 100644 index 00000000000..912c345827a --- /dev/null +++ b/dist/lib/completion/generate-autocompletion.js.map @@ -0,0 +1 @@ +{"version":3,"file":"generate-autocompletion.js","sourceRoot":"","sources":["../../../src/lib/completion/generate-autocompletion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,EAAE,OAAO,EAAE,MAAM,MAAM,CAAA;AAE9B,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAA;AAElE,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AAEpD;;;;GAIG;AACH,qFAAqF;AACrF,MAAM,sBAAsB,GAAG,CAAC,OAAO,EAAE,EAAE;IACzC,IAAI,CAAC;QACH,MAAM,YAAY,GAAG,OAAO,CAAC,QAAQ,CAAC,MAAM;QAC1C,kFAAkF;QAClF,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE,CAAC,CAAC;YACd,GAAG,IAAI;YACP,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE;gBACZ,IAAI,EAAE,GAAG,CAAC,IAAI,EAAE;gBAChB,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;gBAC7C,OAAO,EAAE,GAAG,CAAC,OAAO;oBAClB,oFAAoF;qBACnF,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;qBAClC,IAAI,CAAC,WAAW,CAAC;oBAClB,iFAAiF;qBAChF,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,KAAK,GAAG,CAAC,IAAI,EAAE,EAAE,EAAE,WAAW,EAAE,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;aAC7E;SACF,CAAC,EACF,EAAE,CACH,CAAA;QAED,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,EAAE,CAAC;YACjD,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,mBAAmB,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;QACjE,CAAC;QACD,EAAE,CAAC,aAAa,CAAC,mBAAmB,EAAE,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,EAAE,OAAO,CAAC,CAAA;IAC9E,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,uGAAuG;QACvG,gHAAgH;QAChH,IAAI,MAAM,YAAY,KAAK,EAAE,CAAC;YAC5B,IAAI,CAAC,qCAAqC,MAAM,CAAC,OAAO,EAAE,CAAC,CAAA;QAC7D,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED,eAAe,sBAAsB,CAAA"} \ No newline at end of file diff --git a/dist/lib/completion/get-autocompletion.d.ts b/dist/lib/completion/get-autocompletion.d.ts new file mode 100644 index 00000000000..b1a36cece96 --- /dev/null +++ b/dist/lib/completion/get-autocompletion.d.ts @@ -0,0 +1,13 @@ +import type { CompletionItem } from '@pnpm/tabtab'; +declare const getAutocompletion: (env: { + complete: boolean; + lastPartial: string; + line: string; + words: number; +}, program: Record) => CompletionItem[] | undefined; +export default getAutocompletion; +//# sourceMappingURL=get-autocompletion.d.ts.map \ No newline at end of file diff --git a/dist/lib/completion/get-autocompletion.d.ts.map b/dist/lib/completion/get-autocompletion.d.ts.map new file mode 100644 index 00000000000..22626859f57 --- /dev/null +++ b/dist/lib/completion/get-autocompletion.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"get-autocompletion.d.ts","sourceRoot":"","sources":["../../../src/lib/completion/get-autocompletion.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAA;AAElD,QAAA,MAAM,iBAAiB,GACrB,KAAK;IAAE,QAAQ,EAAE,OAAO,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,EAC5E,SAAS,MAAM,CACb,MAAM,EACN,cAAc,GAAG;IAAE,WAAW,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,OAAO,EAAE,cAAc,EAAE,CAAA;CAAE,CAC5G,KACA,cAAc,EAAE,GAAG,SAkCrB,CAAA;AAED,eAAe,iBAAiB,CAAA"} \ No newline at end of file diff --git a/dist/lib/completion/get-autocompletion.js b/dist/lib/completion/get-autocompletion.js new file mode 100644 index 00000000000..97ae7adb79a --- /dev/null +++ b/dist/lib/completion/get-autocompletion.js @@ -0,0 +1,31 @@ +const getAutocompletion = function (env, program) { + if (!env.complete) { + return; + } + // means that we are currently in the first command (the root command) + if (env.words === 1) { + const rootCommands = Object.values(program).map(({ description, name }) => ({ name, description })); + // suggest all commands + // $ netlify + if (env.lastPartial.length === 0) { + return rootCommands; + } + // $ netlify add + // we can now check if a command starts with the last partial + const autocomplete = rootCommands.filter(({ name }) => name.startsWith(env.lastPartial)); + return autocomplete; + } + const [, command, ...args] = env.line.split(' '); + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (program[command]) { + const usedArgs = new Set(args); + const unusedOptions = program[command].options.filter(({ name }) => !usedArgs.has(name)); + if (env.lastPartial.length !== 0) { + return unusedOptions.filter(({ name }) => name.startsWith(env.lastPartial)); + } + // suggest options that are not used + return unusedOptions; + } +}; +export default getAutocompletion; +//# sourceMappingURL=get-autocompletion.js.map \ No newline at end of file diff --git a/dist/lib/completion/get-autocompletion.js.map b/dist/lib/completion/get-autocompletion.js.map new file mode 100644 index 00000000000..91e28915f26 --- /dev/null +++ b/dist/lib/completion/get-autocompletion.js.map @@ -0,0 +1 @@ +{"version":3,"file":"get-autocompletion.js","sourceRoot":"","sources":["../../../src/lib/completion/get-autocompletion.ts"],"names":[],"mappings":"AAEA,MAAM,iBAAiB,GAAG,UACxB,GAA4E,EAC5E,OAGC;IAED,IAAI,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;QAClB,OAAM;IACR,CAAC;IACD,sEAAsE;IACtE,IAAI,GAAG,CAAC,KAAK,KAAK,CAAC,EAAE,CAAC;QACpB,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC,CAAC,CAAA;QAEnG,uBAAuB;QACvB,qBAAqB;QACrB,IAAI,GAAG,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,OAAO,YAAY,CAAA;QACrB,CAAC;QAED,wBAAwB;QACxB,6DAA6D;QAC7D,MAAM,YAAY,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAA;QACxF,OAAO,YAAY,CAAA;IACrB,CAAC;IAED,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAEhD,uEAAuE;IACvE,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC;QACrB,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAA;QAC9B,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAA;QAExF,IAAI,GAAG,CAAC,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,OAAO,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAA;QAC7E,CAAC;QAED,oCAAoC;QACpC,OAAO,aAAa,CAAA;IACtB,CAAC;AACH,CAAC,CAAA;AAED,eAAe,iBAAiB,CAAA"} \ No newline at end of file diff --git a/dist/lib/completion/index.d.ts b/dist/lib/completion/index.d.ts new file mode 100644 index 00000000000..4d270b9d98f --- /dev/null +++ b/dist/lib/completion/index.d.ts @@ -0,0 +1,2 @@ +export { default as generateAutocompletion } from './generate-autocompletion.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/lib/completion/index.d.ts.map b/dist/lib/completion/index.d.ts.map new file mode 100644 index 00000000000..a308ad09d71 --- /dev/null +++ b/dist/lib/completion/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/completion/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,8BAA8B,CAAA"} \ No newline at end of file diff --git a/dist/lib/completion/index.js b/dist/lib/completion/index.js new file mode 100644 index 00000000000..4087d253d1c --- /dev/null +++ b/dist/lib/completion/index.js @@ -0,0 +1,2 @@ +export { default as generateAutocompletion } from './generate-autocompletion.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/lib/completion/index.js.map b/dist/lib/completion/index.js.map new file mode 100644 index 00000000000..e87cde0d9c9 --- /dev/null +++ b/dist/lib/completion/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/lib/completion/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,sBAAsB,EAAE,MAAM,8BAA8B,CAAA"} \ No newline at end of file diff --git a/dist/lib/completion/script.d.ts b/dist/lib/completion/script.d.ts new file mode 100644 index 00000000000..cae4dd92e7f --- /dev/null +++ b/dist/lib/completion/script.d.ts @@ -0,0 +1,3 @@ +#!/usr/bin/env node +export {}; +//# sourceMappingURL=script.d.ts.map \ No newline at end of file diff --git a/dist/lib/completion/script.d.ts.map b/dist/lib/completion/script.d.ts.map new file mode 100644 index 00000000000..a7324c0db6d --- /dev/null +++ b/dist/lib/completion/script.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"script.d.ts","sourceRoot":"","sources":["../../../src/lib/completion/script.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/lib/completion/script.js b/dist/lib/completion/script.js new file mode 100644 index 00000000000..ed5e628f2f5 --- /dev/null +++ b/dist/lib/completion/script.js @@ -0,0 +1,19 @@ +#!/usr/bin/env node +// This script is run by the completion (every log output will be displayed on tab) +// src/commands/completion/completion.js -> dynamically references this file +// if this file is renamed or moved then it needs to be adapted there +import { existsSync, readFileSync } from 'fs'; +import process from 'process'; +import { getShellFromEnv, log, parseEnv } from '@pnpm/tabtab'; +import { AUTOCOMPLETION_FILE } from './constants.js'; +import getAutocompletion from './get-autocompletion.js'; +const env = parseEnv(process.env); +const shell = getShellFromEnv(process.env); +if (existsSync(AUTOCOMPLETION_FILE)) { + const program = JSON.parse(readFileSync(AUTOCOMPLETION_FILE, 'utf-8')); + const autocomplete = getAutocompletion(env, program); + if (autocomplete && autocomplete.length !== 0) { + log(autocomplete, shell); + } +} +//# sourceMappingURL=script.js.map \ No newline at end of file diff --git a/dist/lib/completion/script.js.map b/dist/lib/completion/script.js.map new file mode 100644 index 00000000000..8953fe55bcc --- /dev/null +++ b/dist/lib/completion/script.js.map @@ -0,0 +1 @@ +{"version":3,"file":"script.js","sourceRoot":"","sources":["../../../src/lib/completion/script.ts"],"names":[],"mappings":";AAEA,mFAAmF;AACnF,4EAA4E;AAC5E,qEAAqE;AACrE,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAA;AAC7C,OAAO,OAAO,MAAM,SAAS,CAAA;AAE7B,OAAO,EAAE,eAAe,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAE7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,gBAAgB,CAAA;AACpD,OAAO,iBAAiB,MAAM,yBAAyB,CAAA;AAEvD,MAAM,GAAG,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;AACjC,MAAM,KAAK,GAAG,eAAe,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;AAE1C,IAAI,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;IACpC,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC,CAAA;IACtE,MAAM,YAAY,GAAG,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;IAEpD,IAAI,YAAY,IAAI,YAAY,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC9C,GAAG,CAAC,YAAY,EAAE,KAAK,CAAC,CAAA;IAC1B,CAAC;AACH,CAAC"} \ No newline at end of file diff --git a/dist/lib/edge-functions/bootstrap.d.ts b/dist/lib/edge-functions/bootstrap.d.ts new file mode 100644 index 00000000000..b3c1c80a0c3 --- /dev/null +++ b/dist/lib/edge-functions/bootstrap.d.ts @@ -0,0 +1,3 @@ +export declare const FALLBACK_BOOTSTRAP_URL = "https://edge.netlify.com/bootstrap/index-combined.ts"; +export declare const getBootstrapURL: () => Promise; +//# sourceMappingURL=bootstrap.d.ts.map \ No newline at end of file diff --git a/dist/lib/edge-functions/bootstrap.d.ts.map b/dist/lib/edge-functions/bootstrap.d.ts.map new file mode 100644 index 00000000000..97e8e884213 --- /dev/null +++ b/dist/lib/edge-functions/bootstrap.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../../src/lib/edge-functions/bootstrap.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,sBAAsB,yDAAyD,CAAA;AAE5F,eAAO,MAAM,eAAe,uBAmB3B,CAAA"} \ No newline at end of file diff --git a/dist/lib/edge-functions/bootstrap.js b/dist/lib/edge-functions/bootstrap.js new file mode 100644 index 00000000000..0ef8d42dd6d --- /dev/null +++ b/dist/lib/edge-functions/bootstrap.js @@ -0,0 +1,20 @@ +import { env } from 'process'; +import { getURL } from '@netlify/edge-functions/version'; +import { warn } from '../../utils/command-helpers.js'; +export const FALLBACK_BOOTSTRAP_URL = 'https://edge.netlify.com/bootstrap/index-combined.ts'; +export const getBootstrapURL = async () => { + if (env.NETLIFY_EDGE_BOOTSTRAP) { + return env.NETLIFY_EDGE_BOOTSTRAP; + } + try { + return await getURL(); + } + catch (error) { + warn(`Could not load latest version of Edge Functions environment: ${error?.message ?? ''}`); + // If there was an error getting the bootstrap URL from the module, let's + // use the latest version of the bootstrap. This is not ideal, but better + // than failing to serve requests with edge functions. + return FALLBACK_BOOTSTRAP_URL; + } +}; +//# sourceMappingURL=bootstrap.js.map \ No newline at end of file diff --git a/dist/lib/edge-functions/bootstrap.js.map b/dist/lib/edge-functions/bootstrap.js.map new file mode 100644 index 00000000000..50356cc1555 --- /dev/null +++ b/dist/lib/edge-functions/bootstrap.js.map @@ -0,0 +1 @@ +{"version":3,"file":"bootstrap.js","sourceRoot":"","sources":["../../../src/lib/edge-functions/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,SAAS,CAAA;AAE7B,OAAO,EAAE,MAAM,EAAE,MAAM,iCAAiC,CAAA;AAExD,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAA;AAErD,MAAM,CAAC,MAAM,sBAAsB,GAAG,sDAAsD,CAAA;AAE5F,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,IAAI,EAAE;IACxC,IAAI,GAAG,CAAC,sBAAsB,EAAE,CAAC;QAC/B,OAAO,GAAG,CAAC,sBAAsB,CAAA;IACnC,CAAC;IAED,IAAI,CAAC;QACH,OAAO,MAAM,MAAM,EAAE,CAAA;IACvB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,CACF,gEACG,KAA2C,EAAE,OAAO,IAAI,EAC3D,EAAE,CACH,CAAA;QAED,yEAAyE;QACzE,yEAAyE;QACzE,sDAAsD;QACtD,OAAO,sBAAsB,CAAA;IAC/B,CAAC;AACH,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/lib/edge-functions/consts.d.ts b/dist/lib/edge-functions/consts.d.ts new file mode 100644 index 00000000000..9541633410e --- /dev/null +++ b/dist/lib/edge-functions/consts.d.ts @@ -0,0 +1,11 @@ +export declare const DIST_IMPORT_MAP_PATH = "edge-functions-import-map.json"; +export declare const INTERNAL_EDGE_FUNCTIONS_FOLDER = "edge-functions"; +export declare const EDGE_FUNCTIONS_FOLDER = "edge-functions-dist"; +export declare const EDGE_FUNCTIONS_SERVE_FOLDER = "edge-functions-serve"; +export declare const PUBLIC_URL_PATH = ".netlify/internal/edge-functions"; +export declare const featureFlags: { + edge_functions_config_export: boolean; + edge_functions_npm_modules: boolean; + edge_functions_read_deno_config: boolean; +}; +//# sourceMappingURL=consts.d.ts.map \ No newline at end of file diff --git a/dist/lib/edge-functions/consts.d.ts.map b/dist/lib/edge-functions/consts.d.ts.map new file mode 100644 index 00000000000..1f9fdc59ed6 --- /dev/null +++ b/dist/lib/edge-functions/consts.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"consts.d.ts","sourceRoot":"","sources":["../../../src/lib/edge-functions/consts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,oBAAoB,mCAAmC,CAAA;AACpE,eAAO,MAAM,8BAA8B,mBAAmB,CAAA;AAC9D,eAAO,MAAM,qBAAqB,wBAAwB,CAAA;AAC1D,eAAO,MAAM,2BAA2B,yBAAyB,CAAA;AACjE,eAAO,MAAM,eAAe,qCAAqC,CAAA;AAIjE,eAAO,MAAM,YAAY;;;;CAIxB,CAAA"} \ No newline at end of file diff --git a/dist/lib/edge-functions/consts.js b/dist/lib/edge-functions/consts.js new file mode 100644 index 00000000000..8b740269d2a --- /dev/null +++ b/dist/lib/edge-functions/consts.js @@ -0,0 +1,13 @@ +export const DIST_IMPORT_MAP_PATH = 'edge-functions-import-map.json'; +export const INTERNAL_EDGE_FUNCTIONS_FOLDER = 'edge-functions'; +export const EDGE_FUNCTIONS_FOLDER = 'edge-functions-dist'; +export const EDGE_FUNCTIONS_SERVE_FOLDER = 'edge-functions-serve'; +export const PUBLIC_URL_PATH = '.netlify/internal/edge-functions'; +// Feature flags related to Edge Functions that should be passed along to +// Netlify Build. +export const featureFlags = { + edge_functions_config_export: true, + edge_functions_npm_modules: true, + edge_functions_read_deno_config: true, +}; +//# sourceMappingURL=consts.js.map \ No newline at end of file diff --git a/dist/lib/edge-functions/consts.js.map b/dist/lib/edge-functions/consts.js.map new file mode 100644 index 00000000000..c1f58148061 --- /dev/null +++ b/dist/lib/edge-functions/consts.js.map @@ -0,0 +1 @@ +{"version":3,"file":"consts.js","sourceRoot":"","sources":["../../../src/lib/edge-functions/consts.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,oBAAoB,GAAG,gCAAgC,CAAA;AACpE,MAAM,CAAC,MAAM,8BAA8B,GAAG,gBAAgB,CAAA;AAC9D,MAAM,CAAC,MAAM,qBAAqB,GAAG,qBAAqB,CAAA;AAC1D,MAAM,CAAC,MAAM,2BAA2B,GAAG,sBAAsB,CAAA;AACjE,MAAM,CAAC,MAAM,eAAe,GAAG,kCAAkC,CAAA;AAEjE,yEAAyE;AACzE,iBAAiB;AACjB,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,4BAA4B,EAAE,IAAI;IAClC,0BAA0B,EAAE,IAAI;IAChC,+BAA+B,EAAE,IAAI;CACtC,CAAA"} \ No newline at end of file diff --git a/dist/lib/edge-functions/deploy.d.ts b/dist/lib/edge-functions/deploy.d.ts new file mode 100644 index 00000000000..2476a51e50f --- /dev/null +++ b/dist/lib/edge-functions/deploy.d.ts @@ -0,0 +1,8 @@ +/** + * @param {string} workingDir + * @param {*} file + */ +export declare const deployFileNormalizer: (workingDir: string, file: any) => any; +export declare const getDistPathIfExists: (workingDir: string) => Promise; +export declare const isEdgeFunctionFile: (filePath: string) => boolean; +//# sourceMappingURL=deploy.d.ts.map \ No newline at end of file diff --git a/dist/lib/edge-functions/deploy.d.ts.map b/dist/lib/edge-functions/deploy.d.ts.map new file mode 100644 index 00000000000..ce0b75c877e --- /dev/null +++ b/dist/lib/edge-functions/deploy.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"deploy.d.ts","sourceRoot":"","sources":["../../../src/lib/edge-functions/deploy.ts"],"names":[],"mappings":"AASA;;;GAGG;AAEH,eAAO,MAAM,oBAAoB,GAAI,YAAY,MAAM,EAAE,SAAI,QAS5D,CAAA;AAED,eAAO,MAAM,mBAAmB,GAAU,YAAY,MAAM,gCAa3D,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAI,UAAU,MAAM,YAA+C,CAAA"} \ No newline at end of file diff --git a/dist/lib/edge-functions/deploy.js b/dist/lib/edge-functions/deploy.js new file mode 100644 index 00000000000..de2f7eab8ba --- /dev/null +++ b/dist/lib/edge-functions/deploy.js @@ -0,0 +1,34 @@ +import { stat } from 'fs/promises'; +import { join } from 'path'; +import { getPathInProject } from '../settings.js'; +import { EDGE_FUNCTIONS_FOLDER, PUBLIC_URL_PATH } from './consts.js'; +const distPath = getPathInProject([EDGE_FUNCTIONS_FOLDER]); +/** + * @param {string} workingDir + * @param {*} file + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'workingDir' implicitly has an 'any' typ... Remove this comment to see the full error message +export const deployFileNormalizer = (workingDir, file) => { + const absoluteDistPath = join(workingDir, distPath); + const isEdgeFunction = file.root === absoluteDistPath; + const normalizedPath = isEdgeFunction ? `${PUBLIC_URL_PATH}/${file.normalizedPath}` : file.normalizedPath; + return { + ...file, + normalizedPath, + }; +}; +export const getDistPathIfExists = async (workingDir) => { + try { + const absoluteDistPath = join(workingDir, distPath); + const stats = await stat(absoluteDistPath); + if (!stats.isDirectory()) { + throw new Error(`Path ${absoluteDistPath} must be a directory.`); + } + return absoluteDistPath; + } + catch { + // no-op + } +}; +export const isEdgeFunctionFile = (filePath) => filePath.startsWith(`${PUBLIC_URL_PATH}/`); +//# sourceMappingURL=deploy.js.map \ No newline at end of file diff --git a/dist/lib/edge-functions/deploy.js.map b/dist/lib/edge-functions/deploy.js.map new file mode 100644 index 00000000000..bd33816edd0 --- /dev/null +++ b/dist/lib/edge-functions/deploy.js.map @@ -0,0 +1 @@ +{"version":3,"file":"deploy.js","sourceRoot":"","sources":["../../../src/lib/edge-functions/deploy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAE3B,OAAO,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAA;AAEjD,OAAO,EAAE,qBAAqB,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAEpE,MAAM,QAAQ,GAAG,gBAAgB,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAA;AAE1D;;;GAGG;AACH,2IAA2I;AAC3I,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,UAAkB,EAAE,IAAI,EAAE,EAAE;IAC/D,MAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;IACnD,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,KAAK,gBAAgB,CAAA;IACrD,MAAM,cAAc,GAAG,cAAc,CAAC,CAAC,CAAC,GAAG,eAAe,IAAI,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAA;IAEzG,OAAO;QACL,GAAG,IAAI;QACP,cAAc;KACf,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,EAAE,UAAkB,EAAE,EAAE;IAC9D,IAAI,CAAC;QACH,MAAM,gBAAgB,GAAG,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;QACnD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,gBAAgB,CAAC,CAAA;QAE1C,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACzB,MAAM,IAAI,KAAK,CAAC,QAAQ,gBAAgB,uBAAuB,CAAC,CAAA;QAClE,CAAC;QAED,OAAO,gBAAgB,CAAA;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,QAAQ;IACV,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,QAAgB,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,eAAe,GAAG,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/lib/edge-functions/editor-helper.d.ts b/dist/lib/edge-functions/editor-helper.d.ts new file mode 100644 index 00000000000..4011d92d087 --- /dev/null +++ b/dist/lib/edge-functions/editor-helper.d.ts @@ -0,0 +1,9 @@ +export declare const promptEditorHelper: ({ NETLIFYDEVLOG, chalk, config, log, repositoryRoot, state }: { + NETLIFYDEVLOG: any; + chalk: any; + config: any; + log: any; + repositoryRoot: any; + state: any; +}) => Promise; +//# sourceMappingURL=editor-helper.d.ts.map \ No newline at end of file diff --git a/dist/lib/edge-functions/editor-helper.d.ts.map b/dist/lib/edge-functions/editor-helper.d.ts.map new file mode 100644 index 00000000000..d5bc0243706 --- /dev/null +++ b/dist/lib/edge-functions/editor-helper.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"editor-helper.d.ts","sourceRoot":"","sources":["../../../src/lib/edge-functions/editor-helper.ts"],"names":[],"mappings":"AASA,eAAO,MAAM,kBAAkB,GAAU;;;;;;;CAA4D,kBAkCpG,CAAA"} \ No newline at end of file diff --git a/dist/lib/edge-functions/editor-helper.js b/dist/lib/edge-functions/editor-helper.js new file mode 100644 index 00000000000..47205b2fb5c --- /dev/null +++ b/dist/lib/edge-functions/editor-helper.js @@ -0,0 +1,31 @@ +import { env } from 'process'; +import inquirer from 'inquirer'; +import { runRecipe } from '../../commands/recipes/recipes.js'; +const STATE_PROMPT_PROPERTY = 'promptVSCodeSettings'; +// @ts-expect-error TS(7031) FIXME: Binding element 'NETLIFYDEVLOG' implicitly has an ... Remove this comment to see the full error message +export const promptEditorHelper = async ({ NETLIFYDEVLOG, chalk, config, log, repositoryRoot, state }) => { + // This prevents tests from hanging when running them inside the VS Code + // terminal, as otherwise we'll show the prompt and wait for a response. + if (env.NODE_ENV === 'test') + return; + const isVSCode = env.TERM_PROGRAM === 'vscode'; + const hasShownPrompt = Boolean(state.get(STATE_PROMPT_PROPERTY)); + const hasEdgeFunctions = Boolean(config.edge_functions && config.edge_functions.length !== 0); + if (!isVSCode || hasShownPrompt || !hasEdgeFunctions) { + return; + } + state.set(STATE_PROMPT_PROPERTY, true); + const message = 'Would you like to configure VS Code to use Edge Functions?'; + const { confirm } = await inquirer.prompt({ + type: 'confirm', + name: 'confirm', + message, + default: true, + }); + if (!confirm) { + log(`${NETLIFYDEVLOG} You can start this configuration manually by running ${chalk.magenta.bold('netlify recipes vscode')}.`); + return; + } + await runRecipe({ args: [], config, recipeName: 'vscode', repositoryRoot }); +}; +//# sourceMappingURL=editor-helper.js.map \ No newline at end of file diff --git a/dist/lib/edge-functions/editor-helper.js.map b/dist/lib/edge-functions/editor-helper.js.map new file mode 100644 index 00000000000..25070c22374 --- /dev/null +++ b/dist/lib/edge-functions/editor-helper.js.map @@ -0,0 +1 @@ +{"version":3,"file":"editor-helper.js","sourceRoot":"","sources":["../../../src/lib/edge-functions/editor-helper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,SAAS,CAAA;AAE7B,OAAO,QAAQ,MAAM,UAAU,CAAA;AAE/B,OAAO,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAA;AAE7D,MAAM,qBAAqB,GAAG,sBAAsB,CAAA;AAEpD,2IAA2I;AAC3I,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,EAAE,EAAE;IACvG,wEAAwE;IACxE,wEAAwE;IACxE,IAAI,GAAG,CAAC,QAAQ,KAAK,MAAM;QAAE,OAAM;IAEnC,MAAM,QAAQ,GAAG,GAAG,CAAC,YAAY,KAAK,QAAQ,CAAA;IAC9C,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAA;IAChE,MAAM,gBAAgB,GAAG,OAAO,CAAC,MAAM,CAAC,cAAc,IAAI,MAAM,CAAC,cAAc,CAAC,MAAM,KAAK,CAAC,CAAC,CAAA;IAE7F,IAAI,CAAC,QAAQ,IAAI,cAAc,IAAI,CAAC,gBAAgB,EAAE,CAAC;QACrD,OAAM;IACR,CAAC;IAED,KAAK,CAAC,GAAG,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAA;IAEtC,MAAM,OAAO,GAAG,4DAA4D,CAAA;IAC5E,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;QACxC,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,SAAS;QACf,OAAO;QACP,OAAO,EAAE,IAAI;KACd,CAAC,CAAA;IAEF,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,GAAG,CACD,GAAG,aAAa,yDAAyD,KAAK,CAAC,OAAO,CAAC,IAAI,CACzF,wBAAwB,CACzB,GAAG,CACL,CAAA;QAED,OAAM;IACR,CAAC;IAED,MAAM,SAAS,CAAC,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,cAAc,EAAE,CAAC,CAAA;AAC7E,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/lib/edge-functions/headers.d.ts b/dist/lib/edge-functions/headers.d.ts new file mode 100644 index 00000000000..4d5d33c5439 --- /dev/null +++ b/dist/lib/edge-functions/headers.d.ts @@ -0,0 +1,35 @@ +export declare const headers: { + BlobsInfo: string; + DeployID: string; + DeployContext: string; + FeatureFlags: string; + ForwardedHost: string; + ForwardedProtocol: string; + Functions: string; + InvocationMetadata: string; + Geo: string; + Passthrough: string; + PassthroughHost: string; + PassthroughProtocol: string; + IP: string; + Site: string; + DebugLogging: string; + Account: string; +}; +/** + * Takes an array of feature flags and produces a Base64-encoded JSON object + * that the bootstrap layer can understand. + * + * @param {Array} featureFlags + * @returns {string} + */ +export declare const getFeatureFlagsHeader: (featureFlags: any) => string; +/** + * Takes the invocation metadata object and produces a Base64-encoded JSON + * object that the bootstrap layer can understand. + * + * @param {object} metadata + * @returns {string} + */ +export declare const getInvocationMetadataHeader: (metadata: any) => string; +//# sourceMappingURL=headers.d.ts.map \ No newline at end of file diff --git a/dist/lib/edge-functions/headers.d.ts.map b/dist/lib/edge-functions/headers.d.ts.map new file mode 100644 index 00000000000..34d58844d6a --- /dev/null +++ b/dist/lib/edge-functions/headers.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../../src/lib/edge-functions/headers.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,OAAO;;;;;;;;;;;;;;;;;CAiBnB,CAAA;AAED;;;;;;GAMG;AAEH,eAAO,MAAM,qBAAqB,GAAI,iBAAY,WAKjD,CAAA;AAED;;;;;;GAMG;AAEH,eAAO,MAAM,2BAA2B,GAAI,aAAQ,WAA6D,CAAA"} \ No newline at end of file diff --git a/dist/lib/edge-functions/headers.js b/dist/lib/edge-functions/headers.js new file mode 100644 index 00000000000..f07c46fe843 --- /dev/null +++ b/dist/lib/edge-functions/headers.js @@ -0,0 +1,42 @@ +import { Buffer } from 'buffer'; +export const headers = { + BlobsInfo: 'x-nf-blobs-info', + DeployID: 'x-nf-deploy-id', + DeployContext: 'x-nf-deploy-context', + FeatureFlags: 'x-nf-feature-flags', + ForwardedHost: 'x-forwarded-host', + ForwardedProtocol: 'x-forwarded-proto', + Functions: 'x-nf-edge-functions', + InvocationMetadata: 'x-nf-edge-functions-metadata', + Geo: 'x-nf-geo', + Passthrough: 'x-nf-passthrough', + PassthroughHost: 'x-nf-passthrough-host', + PassthroughProtocol: 'x-nf-passthrough-proto', + IP: 'x-nf-client-connection-ip', + Site: 'X-NF-Site-Info', + DebugLogging: 'x-nf-debug-logging', + Account: 'x-nf-account-info', +}; +/** + * Takes an array of feature flags and produces a Base64-encoded JSON object + * that the bootstrap layer can understand. + * + * @param {Array} featureFlags + * @returns {string} + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'featureFlags' implicitly has an 'any' t... Remove this comment to see the full error message +export const getFeatureFlagsHeader = (featureFlags) => { + // @ts-expect-error TS(7006) FIXME: Parameter 'acc' implicitly has an 'any' type. + const featureFlagsObject = featureFlags.reduce((acc, flagName) => ({ ...acc, [flagName]: true }), {}); + return Buffer.from(JSON.stringify(featureFlagsObject)).toString('base64'); +}; +/** + * Takes the invocation metadata object and produces a Base64-encoded JSON + * object that the bootstrap layer can understand. + * + * @param {object} metadata + * @returns {string} + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'metadata' implicitly has an 'any' type. +export const getInvocationMetadataHeader = (metadata) => Buffer.from(JSON.stringify(metadata)).toString('base64'); +//# sourceMappingURL=headers.js.map \ No newline at end of file diff --git a/dist/lib/edge-functions/headers.js.map b/dist/lib/edge-functions/headers.js.map new file mode 100644 index 00000000000..de1abdd93ac --- /dev/null +++ b/dist/lib/edge-functions/headers.js.map @@ -0,0 +1 @@ +{"version":3,"file":"headers.js","sourceRoot":"","sources":["../../../src/lib/edge-functions/headers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B,MAAM,CAAC,MAAM,OAAO,GAAG;IACrB,SAAS,EAAE,iBAAiB;IAC5B,QAAQ,EAAE,gBAAgB;IAC1B,aAAa,EAAE,qBAAqB;IACpC,YAAY,EAAE,oBAAoB;IAClC,aAAa,EAAE,kBAAkB;IACjC,iBAAiB,EAAE,mBAAmB;IACtC,SAAS,EAAE,qBAAqB;IAChC,kBAAkB,EAAE,8BAA8B;IAClD,GAAG,EAAE,UAAU;IACf,WAAW,EAAE,kBAAkB;IAC/B,eAAe,EAAE,uBAAuB;IACxC,mBAAmB,EAAE,wBAAwB;IAC7C,EAAE,EAAE,2BAA2B;IAC/B,IAAI,EAAE,gBAAgB;IACtB,YAAY,EAAE,oBAAoB;IAClC,OAAO,EAAE,mBAAmB;CAC7B,CAAA;AAED;;;;;;GAMG;AACH,2IAA2I;AAC3I,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,YAAY,EAAE,EAAE;IACpD,iFAAiF;IACjF,MAAM,kBAAkB,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,GAAG,EAAE,CAAC,QAAQ,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE,CAAC,CAAA;IAErG,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;AAC3E,CAAC,CAAA;AAED;;;;;;GAMG;AACH,sFAAsF;AACtF,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,QAAQ,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/lib/edge-functions/proxy.d.ts b/dist/lib/edge-functions/proxy.d.ts new file mode 100644 index 00000000000..f4c37d5bca2 --- /dev/null +++ b/dist/lib/edge-functions/proxy.d.ts @@ -0,0 +1,42 @@ +import type { IncomingMessage, ClientRequest } from 'http'; +import * as bundler from '@netlify/edge-bundler'; +import type BaseCommand from '../../commands/base-command.js'; +import type { $TSFixMe } from '../../commands/types.js'; +import { type NormalizedCachedConfigConfig } from '../../utils/command-helpers.js'; +import { BlobsContextWithEdgeAccess } from '../blobs/blobs.js'; +import type { CLIState, ServerSettings } from '../../utils/types.js'; +export type EdgeFunctionDeclaration = bundler.Declaration; +declare const headersSymbol: unique symbol; +type ExtendedIncomingMessage = IncomingMessage & { + [headersSymbol]: Record; +}; +export declare const handleProxyRequest: (req: ExtendedIncomingMessage, proxyReq: ClientRequest) => void; +export declare const createSiteInfoHeader: (siteInfo: { + id?: string | undefined; + name?: string | undefined; + url?: string | undefined; +}, localURL?: string) => string; +export declare const initializeProxy: ({ accountId, blobsContext, command, config, configPath, debug, env: configEnv, geoCountry, geolocationMode, getUpdatedConfig, inspectSettings, mainPort, offline, passthroughPort, projectDir, repositoryRoot, settings, siteInfo, state, }: { + accountId: string; + blobsContext: BlobsContextWithEdgeAccess; + command: BaseCommand; + config: NormalizedCachedConfigConfig; + configPath: string; + debug: boolean; + env: $TSFixMe; + offline: $TSFixMe; + geoCountry: $TSFixMe; + geolocationMode: $TSFixMe; + getUpdatedConfig: () => Promise; + inspectSettings: $TSFixMe; + mainPort: $TSFixMe; + passthroughPort: $TSFixMe; + projectDir: string; + repositoryRoot?: string; + settings: ServerSettings; + siteInfo: $TSFixMe; + state: CLIState; +}) => Promise<(req: ExtendedIncomingMessage) => Promise>; +export declare const isEdgeFunctionsRequest: (req: IncomingMessage) => req is ExtendedIncomingMessage; +export {}; +//# sourceMappingURL=proxy.d.ts.map \ No newline at end of file diff --git a/dist/lib/edge-functions/proxy.d.ts.map b/dist/lib/edge-functions/proxy.d.ts.map new file mode 100644 index 00000000000..d567f0d38bf --- /dev/null +++ b/dist/lib/edge-functions/proxy.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../../src/lib/edge-functions/proxy.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,MAAM,CAAA;AAG1D,OAAO,KAAK,OAAO,MAAM,uBAAuB,CAAA;AAGhD,OAAO,KAAK,WAAW,MAAM,gCAAgC,CAAA;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AACvD,OAAO,EAEL,KAAK,4BAA4B,EAGlC,MAAM,gCAAgC,CAAA;AAEvC,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAA;AAI9D,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAOpE,MAAM,MAAM,uBAAuB,GAAG,OAAO,CAAC,WAAW,CAAA;AAEzD,QAAA,MAAM,aAAa,eAAmC,CAAA;AAItD,KAAK,uBAAuB,GAAG,eAAe,GAAG;IAAE,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;CAAE,CAAA;AAmB5F,eAAO,MAAM,kBAAkB,GAAI,KAAK,uBAAuB,EAAE,UAAU,aAAa,KAAG,IAI1F,CAAA;AAED,eAAO,MAAM,oBAAoB,GAC/B,UAAU;IAAE,EAAE,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAAE,EAC1F,WAAW,MAAM,KAChB,MAKF,CAAA;AAQD,eAAO,MAAM,eAAe,GAAU,6OAoBnC;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,YAAY,EAAE,0BAA0B,CAAA;IACxC,OAAO,EAAE,WAAW,CAAA;IACpB,MAAM,EAAE,4BAA4B,CAAA;IACpC,UAAU,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,OAAO,CAAA;IACd,GAAG,EAAE,QAAQ,CAAA;IACb,OAAO,EAAE,QAAQ,CAAA;IACjB,UAAU,EAAE,QAAQ,CAAA;IACpB,eAAe,EAAE,QAAQ,CAAA;IACzB,gBAAgB,EAAE,MAAM,OAAO,CAAC,4BAA4B,CAAC,CAAA;IAC7D,eAAe,EAAE,QAAQ,CAAA;IACzB,QAAQ,EAAE,QAAQ,CAAA;IAClB,eAAe,EAAE,QAAQ,CAAA;IACzB,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,QAAQ,EAAE,cAAc,CAAA;IACxB,QAAQ,EAAE,QAAQ,CAAA;IAClB,KAAK,EAAE,QAAQ,CAAA;CAChB,mBAwBoB,uBAAuB,iCAmD3C,CAAA;AAED,eAAO,MAAM,sBAAsB,GAAI,KAAK,eAAe,KAAG,GAAG,IAAI,uBAClC,CAAA"} \ No newline at end of file diff --git a/dist/lib/edge-functions/proxy.js b/dist/lib/edge-functions/proxy.js new file mode 100644 index 00000000000..09931ec2f5a --- /dev/null +++ b/dist/lib/edge-functions/proxy.js @@ -0,0 +1,151 @@ +import { Buffer } from 'buffer'; +import { rm } from 'fs/promises'; +import { join, resolve } from 'path'; +import * as bundler from '@netlify/edge-bundler'; +import getAvailablePort from 'get-port'; +import { NETLIFYDEVERR, chalk, logAndThrowError, } from '../../utils/command-helpers.js'; +import { getFeatureFlagsFromSiteInfo } from '../../utils/feature-flags.js'; +import { getGeoLocation } from '../geo-location.js'; +import { getPathInProject } from '../settings.js'; +import { startSpinner, stopSpinner } from '../spinner.js'; +import { getBootstrapURL } from './bootstrap.js'; +import { DIST_IMPORT_MAP_PATH, EDGE_FUNCTIONS_SERVE_FOLDER } from './consts.js'; +import { getFeatureFlagsHeader, getInvocationMetadataHeader, headers } from './headers.js'; +import { EdgeFunctionsRegistry } from './registry.js'; +const headersSymbol = Symbol('Edge Functions Headers'); +const LOCAL_HOST = '127.0.0.1'; +const getDownloadUpdateFunctions = () => { + let spinner; + const onAfterDownload = (error_) => { + stopSpinner({ error: Boolean(error_), spinner }); + }; + const onBeforeDownload = () => { + spinner = startSpinner({ text: 'Setting up the Edge Functions environment. This may take a couple of minutes.' }); + }; + return { + onAfterDownload, + onBeforeDownload, + }; +}; +export const handleProxyRequest = (req, proxyReq) => { + Object.entries(req[headersSymbol]).forEach(([header, value]) => { + proxyReq.setHeader(header, value); + }); +}; +export const createSiteInfoHeader = (siteInfo, localURL) => { + const { id, name, url } = siteInfo; + const site = { id, name, url: localURL ?? url }; + const siteString = JSON.stringify(site); + return Buffer.from(siteString).toString('base64'); +}; +const createAccountInfoHeader = ({ id }) => { + const account = { id }; + const accountString = JSON.stringify(account); + return Buffer.from(accountString).toString('base64'); +}; +export const initializeProxy = async ({ accountId, blobsContext, command, config, configPath, debug, env: configEnv, geoCountry, geolocationMode, getUpdatedConfig, inspectSettings, mainPort, offline, passthroughPort, projectDir, repositoryRoot, settings, siteInfo, state, }) => { + const userFunctionsPath = config.build.edge_functions; + const isolatePort = await getAvailablePort(); + const runtimeFeatureFlags = ['edge_functions_bootstrap_failure_mode', 'edge_functions_bootstrap_populate_environment']; + const protocol = settings.https ? 'https' : 'http'; + const buildFeatureFlags = { ...getFeatureFlagsFromSiteInfo(siteInfo), edge_functions_npm_modules: true }; + // Initializes the server, bootstrapping the Deno CLI and downloading it from + // the network if needed. We don't want to wait for that to be completed, or + // the command will be left hanging. + const server = prepareServer({ + command, + config, + configPath, + debug, + directory: userFunctionsPath, + env: configEnv, + featureFlags: buildFeatureFlags, + getUpdatedConfig, + inspectSettings, + port: isolatePort, + projectDir, + repositoryRoot, + }); + return async (req) => { + if (req.headers[headers.Passthrough] !== undefined) { + return; + } + const [geoLocation, registry] = await Promise.all([ + getGeoLocation({ mode: geolocationMode, geoCountry, offline, state }), + server, + ]); + if (!registry) + return; + // Setting header with geolocation and site info. + req.headers[headers.Geo] = Buffer.from(JSON.stringify(geoLocation)).toString('base64'); + req.headers[headers.DeployID] = '0'; + req.headers[headers.DeployContext] = 'dev'; + req.headers[headers.Site] = createSiteInfoHeader(siteInfo, `${protocol}://localhost:${mainPort}`); + req.headers[headers.Account] = createAccountInfoHeader({ id: accountId }); + if (blobsContext?.edgeURL && blobsContext?.token) { + req.headers[headers.BlobsInfo] = Buffer.from(JSON.stringify({ url: blobsContext.edgeURL, url_uncached: blobsContext.edgeURL, token: blobsContext.token })).toString('base64'); + } + await registry.initialize(); + const url = new URL(req.url, `http://${LOCAL_HOST}:${mainPort}`); + const { functionNames, invocationMetadata } = registry.matchURLPath(url.pathname, req.method); + if (functionNames.length === 0) { + return; + } + req[headersSymbol] = { + [headers.FeatureFlags]: getFeatureFlagsHeader(runtimeFeatureFlags), + [headers.ForwardedProtocol]: `${protocol}:`, + [headers.Functions]: functionNames.join(','), + [headers.InvocationMetadata]: getInvocationMetadataHeader(invocationMetadata), + [headers.IP]: LOCAL_HOST, + [headers.Passthrough]: 'passthrough', + [headers.PassthroughHost]: `localhost:${passthroughPort}`, + [headers.PassthroughProtocol]: 'http:', + }; + if (debug) { + req[headersSymbol][headers.DebugLogging] = '1'; + } + return `http://${LOCAL_HOST}:${isolatePort}`; + }; +}; +export const isEdgeFunctionsRequest = (req) => Object.hasOwn(req, headersSymbol); +const prepareServer = async ({ command, config, configPath, debug, directory, env: configEnv, featureFlags, getUpdatedConfig, inspectSettings, port, projectDir, repositoryRoot, }) => { + try { + const distImportMapPath = getPathInProject([DIST_IMPORT_MAP_PATH]); + const servePath = resolve(projectDir, command.getPathInProject(EDGE_FUNCTIONS_SERVE_FOLDER)); + await rm(servePath, { force: true, recursive: true }); + const runIsolate = await bundler.serve({ + ...getDownloadUpdateFunctions(), + basePath: projectDir, + bootstrapURL: await getBootstrapURL(), + debug, + distImportMapPath: join(projectDir, distImportMapPath), + featureFlags, + formatExportTypeError: (name) => `${NETLIFYDEVERR} ${chalk.red('Failed')} to load Edge Function ${chalk.yellow(name)}. The file does not seem to have a function as the default export.`, + formatImportError: (name) => `${NETLIFYDEVERR} ${chalk.red('Failed')} to run Edge Function ${chalk.yellow(name)}:`, + inspectSettings, + port, + rootPath: repositoryRoot, + servePath, + }); + const registry = new EdgeFunctionsRegistry({ + command, + bundler, + config, + configPath, + debug, + directories: directory ? [directory] : [], + env: configEnv, + featureFlags, + getUpdatedConfig, + importMapFromTOML: config.functions?.['*'].deno_import_map, + projectDir, + runIsolate, + servePath, + }); + return registry; + } + catch (error) { + return logAndThrowError(error instanceof Error ? error.message : error?.toString()); + } +}; +//# sourceMappingURL=proxy.js.map \ No newline at end of file diff --git a/dist/lib/edge-functions/proxy.js.map b/dist/lib/edge-functions/proxy.js.map new file mode 100644 index 00000000000..1743c72a0c3 --- /dev/null +++ b/dist/lib/edge-functions/proxy.js.map @@ -0,0 +1 @@ +{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../../src/lib/edge-functions/proxy.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/edge-functions/registry.d.ts b/dist/lib/edge-functions/registry.d.ts new file mode 100644 index 00000000000..4d6e88a3a6b --- /dev/null +++ b/dist/lib/edge-functions/registry.d.ts @@ -0,0 +1,103 @@ +import BaseCommand from '../../commands/base-command.js'; +import { type NormalizedCachedConfigConfig } from '../../utils/command-helpers.js'; +import type { FeatureFlags } from '../../utils/feature-flags.js'; +type RunIsolate = Awaited>; +interface EdgeFunctionsRegistryOptions { + command: BaseCommand; + bundler: typeof import('@netlify/edge-bundler'); + config: NormalizedCachedConfigConfig; + configPath: string; + debug: boolean; + directories: string[]; + env: Record; + featureFlags: FeatureFlags; + getUpdatedConfig: () => Promise; + projectDir: string; + runIsolate: RunIsolate; + servePath: string; + importMapFromTOML?: string; +} +export declare class EdgeFunctionsRegistry { + importMapFromDeployConfig?: string; + private buildError; + private bundler; + private configPath; + private importMapFromTOML?; + private declarationsFromDeployConfig; + private declarationsFromTOML; + private dependencyPaths; + private directories; + private directoryWatchers; + private env; + private featureFlags; + private userFunctions; + private internalFunctions; + private functionPaths; + private getUpdatedConfig; + private initialScan; + private manifest; + private routes; + private runIsolate; + private servePath; + private projectDir; + private command; + constructor({ bundler, command, config, configPath, directories, env, featureFlags, getUpdatedConfig, importMapFromTOML, projectDir, runIsolate, servePath, }: EdgeFunctionsRegistryOptions); + private doInitialScan; + private get functions(); + private build; + /** + * Builds a manifest and corresponding routes for the functions in the + * registry, taking into account the declarations from the TOML, from + * the deploy configuration API, and from the in-source configuration + * found in both internal and user functions. + */ + private buildRoutes; + private checkForAddedOrDeletedFunctions; + private static getDeclarationsFromTOML; + private getDisplayName; + private static getEnvironmentVariables; + private handleFileChange; + initialize(): Promise; + /** + * Logs an event associated with functions. + */ + private logEvent; + /** + * Returns the functions in the registry that should run for a given URL path + * and HTTP method, based on the routes registered for each function. + */ + matchURLPath(urlPath: string, method: string): { + functionNames: string[]; + invocationMetadata: { + function_config: Record | undefined; + req_routes: number[]; + routes: { + function: string; + path: string | undefined; + pattern: string; + }[]; + }; + }; + /** + * Takes the module graph returned from the server and tracks dependencies of + * each function. + */ + private processGraph; + /** + * Thin wrapper for `#runIsolate` that skips running a build and returns an + * empty response if there are no functions in the registry. + */ + private runBuild; + private get internalDirectory(); + private readDeployConfig; + private scanForDeployConfig; + private scanForFunctions; + private setupWatchers; + private setupWatcherForDirectory; + private get usesFrameworksAPI(); +} +export {}; +//# sourceMappingURL=registry.d.ts.map \ No newline at end of file diff --git a/dist/lib/edge-functions/registry.d.ts.map b/dist/lib/edge-functions/registry.d.ts.map new file mode 100644 index 00000000000..ebfb5d47512 --- /dev/null +++ b/dist/lib/edge-functions/registry.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/lib/edge-functions/registry.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/edge-functions/registry.js b/dist/lib/edge-functions/registry.js new file mode 100644 index 00000000000..ddfbcd69072 --- /dev/null +++ b/dist/lib/edge-functions/registry.js @@ -0,0 +1,441 @@ +import { readFile } from 'fs/promises'; +import { join } from 'path'; +import { fileURLToPath } from 'url'; +import { NETLIFYDEVERR, NETLIFYDEVLOG, NETLIFYDEVWARN, nonNullable, chalk, log, warn, watchDebounced, isNodeError, } from '../../utils/command-helpers.js'; +import { MultiMap } from '../../utils/multimap.js'; +import { getPathInProject } from '../settings.js'; +import { INTERNAL_EDGE_FUNCTIONS_FOLDER } from './consts.js'; +/** + * Given an Edge Bundler module graph and an index of modules by path, + * traverses its dependency tree and returns an array of all of its + * local dependencies. + */ +function traverseLocalDependencies({ dependencies = [], specifier }, modulesByPath, cache) { + // If we've already traversed this specifier, return the cached list of + // dependencies. + if (cache[specifier] !== undefined) { + return cache[specifier]; + } + return dependencies.flatMap((dependency) => { + // We're interested in tracking local dependencies, so we only look at + // specifiers with the `file:` protocol. + if (dependency.code === undefined || + typeof dependency.code.specifier !== 'string' || + !dependency.code.specifier.startsWith('file://')) { + return []; + } + const { specifier: dependencyURL } = dependency.code; + const dependencyPath = fileURLToPath(dependencyURL); + const dependencyModule = modulesByPath.get(dependencyPath); + // No module indexed for this dependency. + if (dependencyModule === undefined) { + return [dependencyPath]; + } + // Keep traversing the child dependencies and return the current dependency path. + cache[specifier] = [...traverseLocalDependencies(dependencyModule, modulesByPath, cache), dependencyPath]; + return cache[specifier]; + }); +} +export class EdgeFunctionsRegistry { + importMapFromDeployConfig; + buildError = null; + bundler; + configPath; + importMapFromTOML; + declarationsFromDeployConfig = []; + declarationsFromTOML; + // Mapping file URLs to names of functions that use them as dependencies. + dependencyPaths = new MultiMap(); + directories; + directoryWatchers = new Map(); + env; + featureFlags; + userFunctions = []; + internalFunctions = []; + // a Map from `this.functions` that maps function paths to function + // names. This allows us to match modules against functions in O(1) time as + // opposed to O(n). + functionPaths = new Map(); + getUpdatedConfig; + initialScan; + manifest = null; + routes = []; + runIsolate; + servePath; + projectDir; + command; + constructor({ bundler, command, config, configPath, directories, env, featureFlags, getUpdatedConfig, importMapFromTOML, projectDir, runIsolate, servePath, }) { + this.command = command; + this.bundler = bundler; + this.configPath = configPath; + this.directories = directories; + this.featureFlags = featureFlags; + this.getUpdatedConfig = getUpdatedConfig; + this.runIsolate = runIsolate; + this.servePath = servePath; + this.projectDir = projectDir; + this.importMapFromTOML = importMapFromTOML; + this.declarationsFromTOML = EdgeFunctionsRegistry.getDeclarationsFromTOML(config); + this.env = EdgeFunctionsRegistry.getEnvironmentVariables(env); + this.initialScan = this.doInitialScan(); + this.setupWatchers(); + } + async doInitialScan() { + await this.scanForFunctions(); + try { + const { warnings } = await this.build(); + this.functions.forEach((func) => { + this.logEvent('loaded', { functionName: func.name, warnings: warnings[func.name] }); + }); + } + catch { + // no-op + } + } + get functions() { + return [...this.internalFunctions, ...this.userFunctions]; + } + async build() { + const warnings = {}; + try { + const { functionsConfig, graph, success } = await this.runBuild(); + if (!success) { + throw new Error('Build error'); + } + this.buildError = null; + // We use one index to loop over both internal and user function, because we know that this.#functions has internalFunctions first. + // functionsConfig therefore contains first all internal functionConfigs and then user functionConfigs + let index = 0; + const internalFunctionConfigs = this.internalFunctions.reduce((acc, func) => ({ ...acc, [func.name]: functionsConfig[index++] }), {}); + const userFunctionConfigs = this.userFunctions.reduce((acc, func) => ({ ...acc, [func.name]: functionsConfig[index++] }), {}); + const { manifest, routes, unroutedFunctions } = this.buildRoutes(internalFunctionConfigs, userFunctionConfigs); + this.manifest = manifest; + this.routes = routes; + unroutedFunctions.forEach((name) => { + warnings[name] = warnings[name] || []; + warnings[name].push(`Edge function is not accessible because it does not have a path configured. Learn more at https://ntl.fyi/edge-create.`); + }); + for (const functionName in userFunctionConfigs) { + if ('paths' in userFunctionConfigs[functionName]) { + warnings[functionName] = warnings[functionName] || []; + warnings[functionName].push(`Unknown 'paths' configuration property. Did you mean 'path'?`); + } + } + this.processGraph(graph); + return { warnings }; + } + catch (error) { + if (error instanceof Error) { + this.buildError = error; + } + throw error; + } + } + /** + * Builds a manifest and corresponding routes for the functions in the + * registry, taking into account the declarations from the TOML, from + * the deploy configuration API, and from the in-source configuration + * found in both internal and user functions. + */ + buildRoutes(internalFunctionConfigs, userFunctionConfigs) { + const declarations = this.bundler.mergeDeclarations(this.declarationsFromTOML, userFunctionConfigs, internalFunctionConfigs, this.declarationsFromDeployConfig, this.featureFlags); + const { declarationsWithoutFunction, manifest, unroutedFunctions } = this.bundler.generateManifest({ + declarations, + userFunctionConfig: userFunctionConfigs, + internalFunctionConfig: internalFunctionConfigs, + functions: this.functions, + featureFlags: this.featureFlags, + }); + const routes = [...manifest.routes, ...manifest.post_cache_routes].map((route) => ({ + ...route, + pattern: new RegExp(route.pattern), + })); + return { declarationsWithoutFunction, manifest, routes, unroutedFunctions }; + } + async checkForAddedOrDeletedFunctions() { + const { deleted: deletedFunctions, new: newFunctions } = await this.scanForFunctions(); + if (newFunctions.length === 0 && deletedFunctions.length === 0) { + return; + } + try { + const { warnings } = await this.build(); + deletedFunctions.forEach((func) => { + this.logEvent('removed', { functionName: func.name, warnings: warnings[func.name] }); + }); + newFunctions.forEach((func) => { + this.logEvent('loaded', { functionName: func.name, warnings: warnings[func.name] }); + }); + } + catch { + // no-op + } + } + static getDeclarationsFromTOML(config) { + const { edge_functions: edgeFunctions = [] } = config; + return edgeFunctions; + } + getDisplayName(func) { + const declarations = [...this.declarationsFromTOML, ...this.declarationsFromDeployConfig]; + return declarations.find((declaration) => declaration.function === func)?.name ?? func; + } + static getEnvironmentVariables(envConfig) { + const env = Object.create(null); + Object.entries(envConfig).forEach(([key, variable]) => { + if (variable.sources.includes('ui') || + variable.sources.includes('account') || + variable.sources.includes('addons') || + variable.sources.includes('internal') || + variable.sources.some((source) => source.startsWith('.env'))) { + env[key] = variable.value; + } + }); + env.DENO_REGION = 'local'; + return env; + } + async handleFileChange(paths) { + const matchingFunctions = new Set([ + ...paths.map((path) => this.functionPaths.get(path)), + ...paths.flatMap((path) => this.dependencyPaths.get(path)), + ].filter(nonNullable)); + // If the file is not associated with any function, there's no point in + // building. However, it might be that the path is in fact associated with + // a function but we just haven't registered it due to a build error. So if + // there was a build error, let's always build. + if (matchingFunctions.size === 0 && this.buildError === null) { + return; + } + this.logEvent('reloading', {}); + try { + const { warnings } = await this.build(); + const functionNames = [...matchingFunctions]; + if (functionNames.length === 0) { + this.logEvent('reloaded', {}); + } + else { + functionNames.forEach((functionName) => { + this.logEvent('reloaded', { functionName, warnings: warnings[functionName] }); + }); + } + } + catch (error) { + if (isNodeError(error)) { + this.logEvent('buildError', { buildError: error }); + } + } + } + async initialize() { + await this.initialScan; + } + /** + * Logs an event associated with functions. + */ + logEvent(event, { buildError, functionName, warnings = [] }) { + const subject = functionName ? `edge function ${chalk.yellow(this.getDisplayName(functionName))}` : 'edge functions'; + const warningsText = warnings.length === 0 ? '' : ` with warnings:\n${warnings.map((warning) => ` - ${warning}`).join('\n')}`; + if (event === 'buildError') { + log(`${NETLIFYDEVERR} ${chalk.red('Failed to load')} ${subject}: ${buildError}`); + return; + } + if (event === 'loaded') { + const icon = warningsText ? NETLIFYDEVWARN : NETLIFYDEVLOG; + const color = warningsText ? chalk.yellow : chalk.green; + log(`${icon} ${color('Loaded')} ${subject}${warningsText}`); + return; + } + if (event === 'reloaded') { + const icon = warningsText ? NETLIFYDEVWARN : NETLIFYDEVLOG; + const color = warningsText ? chalk.yellow : chalk.green; + log(`${icon} ${color('Reloaded')} ${subject}${warningsText}`); + return; + } + if (event === 'reloading') { + log(`${NETLIFYDEVLOG} ${chalk.magenta('Reloading')} ${subject}...`); + return; + } + if (event === 'removed') { + log(`${NETLIFYDEVLOG} ${chalk.magenta('Removed')} ${subject}`); + } + } + /** + * Returns the functions in the registry that should run for a given URL path + * and HTTP method, based on the routes registered for each function. + */ + matchURLPath(urlPath, method) { + const functionNames = []; + const routeIndexes = []; + this.routes.forEach((route, index) => { + if (route.methods && route.methods.length !== 0 && !route.methods.includes(method)) { + return; + } + if (!route.pattern.test(urlPath)) { + return; + } + const isExcludedForFunction = this.manifest?.function_config[route.function]?.excluded_patterns?.some((pattern) => new RegExp(pattern).test(urlPath)); + if (isExcludedForFunction) { + return; + } + const isExcludedForRoute = route.excluded_patterns.some((pattern) => new RegExp(pattern).test(urlPath)); + if (isExcludedForRoute) { + return; + } + functionNames.push(route.function); + routeIndexes.push(index); + }); + const routes = [...(this.manifest?.routes || []), ...(this.manifest?.post_cache_routes || [])].map((route) => ({ + function: route.function, + path: route.path, + pattern: route.pattern, + })); + const invocationMetadata = { + function_config: this.manifest?.function_config, + req_routes: routeIndexes, + routes, + }; + return { functionNames, invocationMetadata }; + } + /** + * Takes the module graph returned from the server and tracks dependencies of + * each function. + */ + processGraph(graph) { + if (!graph) { + if (this.functions.length !== 0) { + warn('Could not process edge functions dependency graph. Live reload will not be available.'); + } + return; + } + this.dependencyPaths = new MultiMap(); + // Mapping file URLs to modules. Used by the traversal function. + const modulesByPath = new Map(); + // a set of edge function modules that we'll use to start traversing the dependency tree from + const functionModules = new Set(); + graph.modules.forEach((module) => { + // We're interested in tracking local dependencies, so we only look at + // specifiers with the `file:` protocol. + const { specifier } = module; + if (!specifier.startsWith('file://')) { + return; + } + const path = fileURLToPath(specifier); + modulesByPath.set(path, module); + const functionName = this.functionPaths.get(path); + if (functionName) { + functionModules.add({ functionName, module }); + } + }); + const dependencyCache = {}; + // We start from our functions and we traverse through their dependency tree + functionModules.forEach(({ functionName, module }) => { + const traversedPaths = traverseLocalDependencies(module, modulesByPath, dependencyCache); + traversedPaths.forEach((dependencyPath) => { + this.dependencyPaths.add(dependencyPath, functionName); + }); + }); + } + /** + * Thin wrapper for `#runIsolate` that skips running a build and returns an + * empty response if there are no functions in the registry. + */ + async runBuild() { + if (this.functions.length === 0) { + return { + functionsConfig: [], + success: true, + }; + } + const importMapPaths = [this.importMapFromTOML, this.importMapFromDeployConfig]; + if (this.usesFrameworksAPI) { + const { edgeFunctionsImportMap } = this.command.netlify.frameworksAPIPaths; + if (await edgeFunctionsImportMap.exists()) { + importMapPaths.push(edgeFunctionsImportMap.path); + } + } + const { functionsConfig, graph, success } = await this.runIsolate(this.functions, this.env, { + getFunctionsConfig: true, + importMapPaths: importMapPaths.filter(nonNullable), + }); + return { functionsConfig, graph, success }; + } + get internalDirectory() { + return join(this.projectDir, getPathInProject([INTERNAL_EDGE_FUNCTIONS_FOLDER])); + } + async readDeployConfig() { + const manifestPath = join(this.internalDirectory, 'manifest.json'); + try { + const contents = await readFile(manifestPath, 'utf8'); + const manifest = JSON.parse(contents); + return manifest; + } + catch { } + } + async scanForDeployConfig() { + const deployConfig = await this.readDeployConfig(); + if (!deployConfig) { + return; + } + if (deployConfig.version !== 1) { + throw new Error('Unsupported manifest format'); + } + this.declarationsFromDeployConfig = deployConfig.functions; + this.importMapFromDeployConfig = deployConfig.import_map + ? join(this.internalDirectory, deployConfig.import_map) + : undefined; + } + async scanForFunctions() { + const [frameworkFunctions, integrationFunctions, userFunctions] = await Promise.all([ + this.usesFrameworksAPI ? this.bundler.find([this.command.netlify.frameworksAPIPaths.edgeFunctions.path]) : [], + this.bundler.find([this.internalDirectory]), + this.bundler.find(this.directories), + this.scanForDeployConfig(), + ]); + const internalFunctions = [...frameworkFunctions, ...integrationFunctions]; + const functions = [...internalFunctions, ...userFunctions]; + const newFunctions = functions.filter((func) => { + const functionExists = this.functions.some((existingFunc) => func.name === existingFunc.name && func.path === existingFunc.path); + return !functionExists; + }); + const deletedFunctions = this.functions.filter((existingFunc) => { + const functionExists = functions.some((func) => func.name === existingFunc.name && func.path === existingFunc.path); + return !functionExists; + }); + this.internalFunctions = internalFunctions; + this.userFunctions = userFunctions; + this.functionPaths = new Map(Array.from(this.functions, (func) => [func.path, func.name])); + return { all: functions, new: newFunctions, deleted: deletedFunctions }; + } + async setupWatchers() { + // While functions are guaranteed to be inside one of the configured + // directories, they might be importing files that are located in + // parent directories. So we watch the entire project directory for + // changes. + await this.setupWatcherForDirectory(); + if (!this.configPath) { + return; + } + // Creating a watcher for the config file. When it changes, we update the + // declarations and see if we need to register or unregister any functions. + await watchDebounced(this.configPath, { + onChange: async () => { + const newConfig = await this.getUpdatedConfig(); + this.declarationsFromTOML = EdgeFunctionsRegistry.getDeclarationsFromTOML(newConfig); + await this.checkForAddedOrDeletedFunctions(); + }, + }); + } + async setupWatcherForDirectory() { + const ignored = [`${this.servePath}/**`]; + const watcher = await watchDebounced(this.projectDir, { + ignored, + onAdd: () => this.checkForAddedOrDeletedFunctions(), + onChange: (paths) => this.handleFileChange(paths), + onUnlink: () => this.checkForAddedOrDeletedFunctions(), + }); + this.directoryWatchers.set(this.projectDir, watcher); + } + // We only take into account edge functions from the Frameworks API in + // the `serve` command, since we don't run the build command in `dev`. + get usesFrameworksAPI() { + return this.command.name() === 'serve'; + } +} +//# sourceMappingURL=registry.js.map \ No newline at end of file diff --git a/dist/lib/edge-functions/registry.js.map b/dist/lib/edge-functions/registry.js.map new file mode 100644 index 00000000000..b99c0fb3c64 --- /dev/null +++ b/dist/lib/edge-functions/registry.js.map @@ -0,0 +1 @@ +{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/lib/edge-functions/registry.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/exec-fetcher.d.ts b/dist/lib/exec-fetcher.d.ts new file mode 100644 index 00000000000..f452107a402 --- /dev/null +++ b/dist/lib/exec-fetcher.d.ts @@ -0,0 +1,20 @@ +export declare const getExecName: ({ execName }: { + execName: string; +}) => string; +export declare const shouldFetchLatestVersion: ({ binPath, execArgs, execName, latestVersion, packageName, pattern, }: { + binPath: string; + execArgs: string[]; + execName: string; + latestVersion?: string | undefined; + packageName: string; + pattern: string; +}) => Promise; +export declare const getArch: () => "amd64" | "386" | "arm" | "arm64" | "mips" | "mipsel" | "ppc" | "ppc64" | "s390" | "s390x"; +export declare const fetchLatestVersion: ({ destination, execName, extension, latestVersion, packageName, }: { + destination: string; + execName: string; + extension: string; + latestVersion?: string | undefined; + packageName: string; +}) => Promise; +//# sourceMappingURL=exec-fetcher.d.ts.map \ No newline at end of file diff --git a/dist/lib/exec-fetcher.d.ts.map b/dist/lib/exec-fetcher.d.ts.map new file mode 100644 index 00000000000..2ff334e53be --- /dev/null +++ b/dist/lib/exec-fetcher.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"exec-fetcher.d.ts","sourceRoot":"","sources":["../../src/lib/exec-fetcher.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,WAAW,GAAI,cAAc;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,WAAiD,CAAA;AA6B/G,eAAO,MAAM,wBAAwB,GAAU,uEAO5C;IACD,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,MAAM,EAAE,CAAA;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,EAAE,MAAM,CAAA;CAChB,KAAG,OAAO,CAAC,OAAO,CAkClB,CAAA;AAED,eAAO,MAAM,OAAO,kGASnB,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAU,mEAMtC;IACD,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,WAAW,EAAE,MAAM,CAAA;CACpB,KAAG,OAAO,CAAC,IAAI,CA0Cf,CAAA"} \ No newline at end of file diff --git a/dist/lib/exec-fetcher.js b/dist/lib/exec-fetcher.js new file mode 100644 index 00000000000..12ed742375b --- /dev/null +++ b/dist/lib/exec-fetcher.js @@ -0,0 +1,104 @@ +import path from 'path'; +import process from 'process'; +import { fetchLatest, fetchVersion, newerVersion, updateAvailable } from 'gh-release-fetch'; +import { isexe } from 'isexe'; +import { NETLIFYDEVWARN, logAndThrowError, getTerminalLink, log } from '../utils/command-helpers.js'; +import execa from '../utils/execa.js'; +const isWindows = () => process.platform === 'win32'; +const getRepository = ({ packageName }) => `netlify/${packageName}`; +export const getExecName = ({ execName }) => (isWindows() ? `${execName}.exe` : execName); +const getOptions = () => { + // this is used in out CI tests to avoid hitting GitHub API limit + // when calling gh-release-fetch + if (process.env.NETLIFY_TEST_GITHUB_TOKEN) { + return { + headers: { Authorization: `token ${process.env.NETLIFY_TEST_GITHUB_TOKEN}` }, + }; + } +}; +const isVersionOutdated = async ({ currentVersion, latestVersion, packageName, }) => { + if (latestVersion) { + return newerVersion(latestVersion, currentVersion); + } + const options = getOptions(); + const outdated = await updateAvailable(getRepository({ packageName }), currentVersion, options); + return outdated; +}; +export const shouldFetchLatestVersion = async ({ binPath, execArgs, execName, latestVersion, packageName, pattern, }) => { + const execPath = path.join(binPath, getExecName({ execName })); + const exists = await isexe(execPath, { ignoreErrors: true }); + if (!exists) { + return true; + } + const { stdout } = await execa(execPath, execArgs); + if (!stdout) { + return false; + } + const match = stdout.match(new RegExp(pattern)); + if (!match) { + return false; + } + try { + const [, currentVersion] = match; + const outdated = await isVersionOutdated({ + packageName, + currentVersion, + latestVersion, + }); + return outdated; + } + catch (error_) { + if (exists) { + log(NETLIFYDEVWARN, `failed checking for new version of '${packageName}'. Using existing version`); + return false; + } + throw error_; + } +}; +export const getArch = () => { + switch (process.arch) { + case 'x64': + return 'amd64'; + case 'ia32': + return '386'; + default: + return process.arch; + } +}; +export const fetchLatestVersion = async ({ destination, execName, extension, latestVersion, packageName, }) => { + const win = isWindows(); + const arch = getArch(); + const platform = win ? 'windows' : process.platform; + const pkgName = `${execName}-${platform}-${arch}.${extension}`; + const release = { + repository: getRepository({ packageName }), + package: pkgName, + destination, + extract: true, + }; + const options = getOptions(); + const fetch = latestVersion + ? // @ts-expect-error(serhalp) -- Either `gh-release-fetch` is not typed correctly or `options.headers` is useless + fetchVersion({ ...release, version: latestVersion }, options) + : // @ts-expect-error(serhalp) -- Either `gh-release-fetch` is not typed correctly or `options.version` should be passed + fetchLatest(release, options); + try { + await fetch; + } + catch (error_) { + if (error_ != null && typeof error_ === 'object' && 'statusCode' in error_ && error_.statusCode === 404) { + const createIssueLink = new URL('https://github.com/netlify/cli/issues/new'); + createIssueLink.searchParams.set('assignees', ''); + createIssueLink.searchParams.set('labels', 'type: bug'); + createIssueLink.searchParams.set('template', 'bug_report.md'); + createIssueLink.searchParams.set('title', `${execName} is not supported on ${platform} with CPU architecture ${arch}`); + const issueLink = getTerminalLink('Create a new CLI issue', createIssueLink.href); + return logAndThrowError(`The operating system ${platform} with the CPU architecture ${arch} is currently not supported! + +Please open up an issue on our CLI repository so that we can support it: +${issueLink}`); + } + return logAndThrowError(error_); + } +}; +//# sourceMappingURL=exec-fetcher.js.map \ No newline at end of file diff --git a/dist/lib/exec-fetcher.js.map b/dist/lib/exec-fetcher.js.map new file mode 100644 index 00000000000..32a76c4c3e7 --- /dev/null +++ b/dist/lib/exec-fetcher.js.map @@ -0,0 +1 @@ +{"version":3,"file":"exec-fetcher.js","sourceRoot":"","sources":["../../src/lib/exec-fetcher.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/extensions.d.ts b/dist/lib/extensions.d.ts new file mode 100644 index 00000000000..64aa0817d3b --- /dev/null +++ b/dist/lib/extensions.d.ts @@ -0,0 +1,12 @@ +import type { Project } from '@netlify/build-info'; +import type { NetlifySite } from '../commands/types.js'; +import type { SiteInfo } from '../utils/types.js'; +export declare const packagesThatNeedSites: Set; +export type DoesProjectRequireLinkedSiteParams = { + project: Project; + site: NetlifySite; + siteInfo: SiteInfo; + options: Record; +}; +export declare const doesProjectRequireLinkedSite: ({ options, project, site, siteInfo, }: DoesProjectRequireLinkedSiteParams) => Promise<[boolean, string[]]>; +//# sourceMappingURL=extensions.d.ts.map \ No newline at end of file diff --git a/dist/lib/extensions.d.ts.map b/dist/lib/extensions.d.ts.map new file mode 100644 index 00000000000..1fcaa194011 --- /dev/null +++ b/dist/lib/extensions.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"extensions.d.ts","sourceRoot":"","sources":["../../src/lib/extensions.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAElD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEjD,eAAO,MAAM,qBAAqB,aAA6B,CAAA;AAE/D,MAAM,MAAM,kCAAkC,GAAG;IAC/C,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,EAAE,QAAQ,CAAA;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;CACjC,CAAA;AAED,eAAO,MAAM,4BAA4B,GAAU,uCAKhD,kCAAkC,KAAG,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,CAAC,CAWlE,CAAA"} \ No newline at end of file diff --git a/dist/lib/extensions.js b/dist/lib/extensions.js new file mode 100644 index 00000000000..926ac0344e0 --- /dev/null +++ b/dist/lib/extensions.js @@ -0,0 +1,15 @@ +import isEmpty from 'lodash/isEmpty.js'; +export const packagesThatNeedSites = new Set(['@netlify/neon']); +export const doesProjectRequireLinkedSite = async ({ options, project, site, siteInfo, }) => { + // If we don't have a site, these extensions need one initialized + // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing + const hasSiteData = Boolean(site.id || options.site) && !isEmpty(siteInfo); + if (hasSiteData) { + return [false, []]; + } + const packageJson = await project.getPackageJSON(); + const dependencies = packageJson.dependencies ?? {}; + const packageNames = Object.keys(dependencies).filter((packageName) => packagesThatNeedSites.has(packageName)); + return [packageNames.length > 0, packageNames]; +}; +//# sourceMappingURL=extensions.js.map \ No newline at end of file diff --git a/dist/lib/extensions.js.map b/dist/lib/extensions.js.map new file mode 100644 index 00000000000..403c180bf51 --- /dev/null +++ b/dist/lib/extensions.js.map @@ -0,0 +1 @@ +{"version":3,"file":"extensions.js","sourceRoot":"","sources":["../../src/lib/extensions.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,mBAAmB,CAAA;AAIvC,MAAM,CAAC,MAAM,qBAAqB,GAAG,IAAI,GAAG,CAAC,CAAC,eAAe,CAAC,CAAC,CAAA;AAS/D,MAAM,CAAC,MAAM,4BAA4B,GAAG,KAAK,EAAE,EACjD,OAAO,EACP,OAAO,EACP,IAAI,EACJ,QAAQ,GAC2B,EAAgC,EAAE;IACrE,iEAAiE;IACjE,wEAAwE;IACxE,MAAM,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,EAAE,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;IAC1E,IAAI,WAAW,EAAE,CAAC;QAChB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAA;IACpB,CAAC;IACD,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,cAAc,EAAE,CAAA;IAClD,MAAM,YAAY,GAAG,WAAW,CAAC,YAAY,IAAI,EAAE,CAAA;IACnD,MAAM,YAAY,GAAG,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,qBAAqB,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAA;IAC9G,OAAO,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,YAAY,CAAC,CAAA;AAChD,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/lib/fs.d.ts b/dist/lib/fs.d.ts new file mode 100644 index 00000000000..6de2627f605 --- /dev/null +++ b/dist/lib/fs.d.ts @@ -0,0 +1,10 @@ +export declare const fileExistsAsync: (filePath: string) => Promise; +/** + * Checks if the provided filePath is a file + */ +export declare const isFileAsync: (filePath: string) => Promise; +/** + * Checks if the provided filePath is a directory + */ +export declare const isDirectoryAsync: (filePath: string) => Promise; +//# sourceMappingURL=fs.d.ts.map \ No newline at end of file diff --git a/dist/lib/fs.d.ts.map b/dist/lib/fs.d.ts.map new file mode 100644 index 00000000000..e481f271cd4 --- /dev/null +++ b/dist/lib/fs.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"fs.d.ts","sourceRoot":"","sources":["../../src/lib/fs.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,eAAe,GAAU,UAAU,MAAM,qBAOrD,CAAA;AAmBD;;GAEG;AACH,eAAO,MAAM,WAAW,GAAU,UAAU,MAAM,qBAA+B,CAAA;AAEjF;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAU,UAAU,MAAM,qBAAoC,CAAA"} \ No newline at end of file diff --git a/dist/lib/fs.js b/dist/lib/fs.js new file mode 100644 index 00000000000..983e61e77f2 --- /dev/null +++ b/dist/lib/fs.js @@ -0,0 +1,38 @@ +import { constants } from 'fs'; +import { access, stat } from 'fs/promises'; +const isErrnoException = (value) => value instanceof Error && Object.hasOwn(value, 'code'); +export const fileExistsAsync = async (filePath) => { + try { + await access(filePath, constants.F_OK); + return true; + } + catch { + return false; + } +}; +/** + * calls stat async with a function and catches potential errors + */ +const isType = async (filePath, type) => { + try { + const stats = await stat(filePath); + if (type === 'isFile') + return stats.isFile(); + return stats.isDirectory(); + } + catch (error) { + if (isErrnoException(error) && error.code === 'ENOENT') { + return false; + } + throw error; + } +}; +/** + * Checks if the provided filePath is a file + */ +export const isFileAsync = async (filePath) => isType(filePath, 'isFile'); +/** + * Checks if the provided filePath is a directory + */ +export const isDirectoryAsync = async (filePath) => isType(filePath, 'isDirectory'); +//# sourceMappingURL=fs.js.map \ No newline at end of file diff --git a/dist/lib/fs.js.map b/dist/lib/fs.js.map new file mode 100644 index 00000000000..7c302fcb41d --- /dev/null +++ b/dist/lib/fs.js.map @@ -0,0 +1 @@ +{"version":3,"file":"fs.js","sourceRoot":"","sources":["../../src/lib/fs.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,IAAI,CAAA;AAC9B,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,aAAa,CAAA;AAE1C,MAAM,gBAAgB,GAAG,CAAC,KAAc,EAAkC,EAAE,CAC1E,KAAK,YAAY,KAAK,IAAI,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;AAExD,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,QAAgB,EAAE,EAAE;IACxD,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,QAAQ,EAAE,SAAS,CAAC,IAAI,CAAC,CAAA;QACtC,OAAO,IAAI,CAAA;IACb,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAA;IACd,CAAC;AACH,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,MAAM,GAAG,KAAK,EAAE,QAAgB,EAAE,IAA8B,EAAE,EAAE;IACxE,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,CAAA;QAClC,IAAI,IAAI,KAAK,QAAQ;YAAE,OAAO,KAAK,CAAC,MAAM,EAAE,CAAA;QAC5C,OAAO,KAAK,CAAC,WAAW,EAAE,CAAA;IAC5B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,gBAAgB,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;YACvD,OAAO,KAAK,CAAA;QACd,CAAC;QAED,MAAM,KAAK,CAAA;IACb,CAAC;AACH,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,QAAgB,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAA;AAEjF;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EAAE,QAAgB,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/background.d.ts b/dist/lib/functions/background.d.ts new file mode 100644 index 00000000000..687be3bbf6b --- /dev/null +++ b/dist/lib/functions/background.d.ts @@ -0,0 +1,5 @@ +import express from 'express'; +import type { InvocationError } from './netlify-function.js'; +export declare const handleBackgroundFunction: (functionName: string, response: express.Response) => void; +export declare const handleBackgroundFunctionResult: (functionName: string, err: null | Error | InvocationError) => void; +//# sourceMappingURL=background.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/background.d.ts.map b/dist/lib/functions/background.d.ts.map new file mode 100644 index 00000000000..005ffd7b1cc --- /dev/null +++ b/dist/lib/functions/background.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"background.d.ts","sourceRoot":"","sources":["../../../src/lib/functions/background.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAA;AAK7B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAI5D,eAAO,MAAM,wBAAwB,GAAI,cAAc,MAAM,EAAE,UAAU,OAAO,CAAC,QAAQ,KAAG,IAI3F,CAAA;AAED,eAAO,MAAM,8BAA8B,GAAI,cAAc,MAAM,EAAE,KAAK,IAAI,GAAG,KAAK,GAAG,eAAe,KAAG,IAS1G,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/background.js b/dist/lib/functions/background.js new file mode 100644 index 00000000000..abb3c1067f2 --- /dev/null +++ b/dist/lib/functions/background.js @@ -0,0 +1,17 @@ +import { NETLIFYDEVERR, NETLIFYDEVLOG } from '../../utils/command-helpers.js'; +import { formatLambdaError, styleFunctionName } from './utils.js'; +const BACKGROUND_FUNCTION_STATUS_CODE = 202; +export const handleBackgroundFunction = (functionName, response) => { + console.log(`${NETLIFYDEVLOG} Queueing background function ${styleFunctionName(functionName)} for execution`); + response.status(BACKGROUND_FUNCTION_STATUS_CODE); + response.end(); +}; +export const handleBackgroundFunctionResult = (functionName, err) => { + if (err) { + console.log(`${NETLIFYDEVERR} Error during background function ${styleFunctionName(functionName)} execution:`, formatLambdaError(err)); + } + else { + console.log(`${NETLIFYDEVLOG} Done executing background function ${styleFunctionName(functionName)}`); + } +}; +//# sourceMappingURL=background.js.map \ No newline at end of file diff --git a/dist/lib/functions/background.js.map b/dist/lib/functions/background.js.map new file mode 100644 index 00000000000..579a2b26ded --- /dev/null +++ b/dist/lib/functions/background.js.map @@ -0,0 +1 @@ +{"version":3,"file":"background.js","sourceRoot":"","sources":["../../../src/lib/functions/background.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAA;AAE7E,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAGjE,MAAM,+BAA+B,GAAG,GAAG,CAAA;AAE3C,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,YAAoB,EAAE,QAA0B,EAAQ,EAAE;IACjG,OAAO,CAAC,GAAG,CAAC,GAAG,aAAa,iCAAiC,iBAAiB,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAA;IAC7G,QAAQ,CAAC,MAAM,CAAC,+BAA+B,CAAC,CAAA;IAChD,QAAQ,CAAC,GAAG,EAAE,CAAA;AAChB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,8BAA8B,GAAG,CAAC,YAAoB,EAAE,GAAmC,EAAQ,EAAE;IAChH,IAAI,GAAG,EAAE,CAAC;QACR,OAAO,CAAC,GAAG,CACT,GAAG,aAAa,qCAAqC,iBAAiB,CAAC,YAAY,CAAC,aAAa,EACjG,iBAAiB,CAAC,GAAG,CAAC,CACvB,CAAA;IACH,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,GAAG,CAAC,GAAG,aAAa,uCAAuC,iBAAiB,CAAC,YAAY,CAAC,EAAE,CAAC,CAAA;IACvG,CAAC;AACH,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/config.d.ts b/dist/lib/functions/config.d.ts new file mode 100644 index 00000000000..aba51fdb34e --- /dev/null +++ b/dist/lib/functions/config.d.ts @@ -0,0 +1,23 @@ +import type { NetlifyConfig } from '@netlify/build'; +import type { NodeBundlerName } from '@netlify/zip-it-and-ship-it'; +export interface NormalizedFunctionConfigObject { + externalNodeModules?: undefined | string[]; + includedFiles?: undefined | string[]; + includedFilesBasePath: string; + ignoredNodeModules?: undefined | string[]; + nodeBundler?: undefined | NodeBundlerName; + nodeVersion?: undefined | string; + processDynamicNodeImports: true; + zipGo: true; + schedule?: undefined | string; +} +export type NormalizedFunctionsConfig = { + '*': NormalizedFunctionConfigObject; + [pattern: string]: NormalizedFunctionConfigObject; +}; +export declare const normalizeFunctionsConfig: ({ functionsConfig, projectRoot, siteEnv, }: { + functionsConfig?: NetlifyConfig["functions"]; + projectRoot: string; + siteEnv?: Record; +}) => NormalizedFunctionsConfig; +//# sourceMappingURL=config.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/config.d.ts.map b/dist/lib/functions/config.d.ts.map new file mode 100644 index 00000000000..b2c1f1e949e --- /dev/null +++ b/dist/lib/functions/config.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/lib/functions/config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAA;AACnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAElE,MAAM,WAAW,8BAA8B;IAC7C,mBAAmB,CAAC,EAAE,SAAS,GAAG,MAAM,EAAE,CAAA;IAC1C,aAAa,CAAC,EAAE,SAAS,GAAG,MAAM,EAAE,CAAA;IACpC,qBAAqB,EAAE,MAAM,CAAA;IAC7B,kBAAkB,CAAC,EAAE,SAAS,GAAG,MAAM,EAAE,CAAA;IACzC,WAAW,CAAC,EAAE,SAAS,GAAG,eAAe,CAAA;IACzC,WAAW,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IAChC,yBAAyB,EAAE,IAAI,CAAA;IAC/B,KAAK,EAAE,IAAI,CAAA;IACX,QAAQ,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;CAC9B;AAED,MAAM,MAAM,yBAAyB,GAAG;IACtC,GAAG,EAAE,8BAA8B,CAAA;IACnC,CAAC,OAAO,EAAE,MAAM,GAAG,8BAA8B,CAAA;CAClD,CAAA;AAKD,eAAO,MAAM,wBAAwB,GAAI,4CAItC;IACD,eAAe,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,CAAA;IAC5C,WAAW,EAAE,MAAM,CAAA;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,GAAG,MAAM,CAAC,CAAA;CAC7C,KAAG,yBAkBD,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/config.js b/dist/lib/functions/config.js new file mode 100644 index 00000000000..9b1c91844ae --- /dev/null +++ b/dist/lib/functions/config.js @@ -0,0 +1,19 @@ +// The function configuration keys returned by @netlify/config are not an exact +// match to the properties that @netlify/zip-it-and-ship-it expects. We do that +// translation here. +export const normalizeFunctionsConfig = ({ functionsConfig = { '*': {} }, projectRoot, siteEnv = {}, }) => Object.entries(functionsConfig).reduce((result, [pattern, value]) => ({ + ...result, + [pattern]: { + externalNodeModules: 'external_node_modules' in value ? value.external_node_modules : undefined, + includedFiles: value.included_files, + includedFilesBasePath: projectRoot, + ignoredNodeModules: 'ignored_node_modules' in value ? value.ignored_node_modules : undefined, + nodeBundler: value.node_bundler === 'esbuild' ? 'esbuild_zisi' : value.node_bundler, + nodeVersion: siteEnv.AWS_LAMBDA_JS_RUNTIME, + processDynamicNodeImports: true, + zipGo: true, + // XXX(serhalp): Unnecessary check -- fixed in stack PR (bumps to https://github.com/netlify/build/pull/6165) + schedule: 'schedule' in value ? value.schedule : undefined, + }, +}), { '*': {} }); +//# sourceMappingURL=config.js.map \ No newline at end of file diff --git a/dist/lib/functions/config.js.map b/dist/lib/functions/config.js.map new file mode 100644 index 00000000000..c9e48b0fe75 --- /dev/null +++ b/dist/lib/functions/config.js.map @@ -0,0 +1 @@ +{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/lib/functions/config.ts"],"names":[],"mappings":"AAoBA,+EAA+E;AAC/E,+EAA+E;AAC/E,oBAAoB;AACpB,MAAM,CAAC,MAAM,wBAAwB,GAAG,CAAC,EACvC,eAAe,GAAG,EAAE,GAAG,EAAE,EAAE,EAAE,EAC7B,WAAW,EACX,OAAO,GAAG,EAAE,GAKb,EAA6B,EAAE,CAC9B,MAAM,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC,MAAM,CACpC,CAAC,MAAM,EAAE,CAAC,OAAO,EAAE,KAAK,CAAC,EAA6B,EAAE,CAAC,CAAC;IACxD,GAAG,MAAM;IACT,CAAC,OAAO,CAAC,EAAE;QACT,mBAAmB,EAAE,uBAAuB,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAC,SAAS;QAC/F,aAAa,EAAE,KAAK,CAAC,cAAc;QACnC,qBAAqB,EAAE,WAAW;QAClC,kBAAkB,EAAE,sBAAsB,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC,CAAC,SAAS;QAC5F,WAAW,EAAE,KAAK,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,YAAY;QACnF,WAAW,EAAE,OAAO,CAAC,qBAAqB;QAC1C,yBAAyB,EAAE,IAAI;QAC/B,KAAK,EAAE,IAAI;QACX,6GAA6G;QAC7G,QAAQ,EAAE,UAAU,IAAI,KAAK,CAAC,CAAC,CAAE,KAAK,CAAC,QAA+B,CAAC,CAAC,CAAC,SAAS;KACnF;CACF,CAAC,EACF,EAAE,GAAG,EAAE,EAAE,EAA+B,CACzC,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/form-submissions-handler.d.ts b/dist/lib/functions/form-submissions-handler.d.ts new file mode 100644 index 00000000000..bbafb93c7fe --- /dev/null +++ b/dist/lib/functions/form-submissions-handler.d.ts @@ -0,0 +1,11 @@ +import type { RequestHandler } from 'express'; +import type { FunctionsRegistry } from './registry.js'; +export declare const getFormHandler: ({ functionsRegistry, logWarning, }: { + functionsRegistry: FunctionsRegistry; + logWarning?: boolean; +}) => string | undefined; +export declare const createFormSubmissionHandler: ({ functionsRegistry, siteUrl, }: { + functionsRegistry: FunctionsRegistry; + siteUrl: string; +}) => RequestHandler; +//# sourceMappingURL=form-submissions-handler.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/form-submissions-handler.d.ts.map b/dist/lib/functions/form-submissions-handler.d.ts.map new file mode 100644 index 00000000000..67a130115b9 --- /dev/null +++ b/dist/lib/functions/form-submissions-handler.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"form-submissions-handler.d.ts","sourceRoot":"","sources":["../../../src/lib/functions/form-submissions-handler.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAS7C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAGtD,eAAO,MAAM,cAAc,GAAa,oCAGrC;IACD,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB,uBAsBA,CAAA;AAED,eAAO,MAAM,2BAA2B,GAAa,iCAGlD;IACD,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,OAAO,EAAE,MAAM,CAAA;CAChB,KAAG,cAgJH,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/form-submissions-handler.js b/dist/lib/functions/form-submissions-handler.js new file mode 100644 index 00000000000..132bdaaf7ed --- /dev/null +++ b/dist/lib/functions/form-submissions-handler.js @@ -0,0 +1,154 @@ +import { Readable } from 'stream'; +import { parse as parseContentType } from 'content-type'; +import multiparty from 'multiparty'; +import getRawBody from 'raw-body'; +import { warn } from '../../utils/command-helpers.js'; +import { BACKGROUND } from '../../utils/functions/index.js'; +import { capitalize } from '../string.js'; +export const getFormHandler = function ({ functionsRegistry, logWarning = true, }) { + const handlers = ['submission-created', `submission-created${BACKGROUND}`] + .map((name) => functionsRegistry.get(name)) + .filter((func) => func != null) + .map(({ name }) => name); + if (handlers.length === 0) { + if (logWarning) { + warn(`Missing form submission function handler`); + } + return; + } + if (handlers.length === 2) { + if (logWarning) { + warn(`Detected both '${handlers[0]}' and '${handlers[1]}' form submission functions handlers, using ${handlers[0]}`); + } + } + return handlers[0]; +}; +export const createFormSubmissionHandler = function ({ functionsRegistry, siteUrl, }) { + return async function formSubmissionHandler(req, _res, next) { + if (req.url.startsWith('/.netlify/') || + req.method !== 'POST' || + (await functionsRegistry.getFunctionForURLPath(req.url, req.method, () => Promise.resolve(false)))) { + next(); + return; + } + const fakeRequest = new Readable({ + read() { + this.push(req.body); + this.push(null); + }, + }); + // @ts-expect-error TS(2339) FIXME: Property 'headers' does not exist on type 'Readabl... Remove this comment to see the full error message + fakeRequest.headers = req.headers; + const handlerName = getFormHandler({ functionsRegistry }); + if (!handlerName) { + next(); + return; + } + const originalUrl = new URL(req.url, 'http://localhost'); + req.url = `/.netlify/functions/${handlerName}${originalUrl.search}`; + const ct = parseContentType(req); + let fields = {}; + let files = {}; + if (ct.type.endsWith('/x-www-form-urlencoded')) { + const bodyData = await getRawBody(fakeRequest, { + length: req.headers['content-length'], + limit: '10mb', + encoding: ct.parameters.charset, + }); + fields = Object.fromEntries(new URLSearchParams(bodyData.toString())); + } + else if (ct.type === 'multipart/form-data') { + try { + ; + [fields, files] = await new Promise((resolve, reject) => { + const form = new multiparty.Form({ encoding: ct.parameters.charset || 'utf8' }); + // @ts-expect-error TS(7006) FIXME: Parameter 'err' implicitly has an 'any' type. + form.parse(fakeRequest, (err, Fields, Files) => { + if (err) { + reject(err); + return; + } + Files = Object.entries(Files).reduce((prev, [name, values]) => ({ + ...prev, + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + [name]: values.map((value) => ({ + filename: value.originalFilename, + size: value.size, + type: value.headers?.['content-type'], + url: value.path, + })), + }), {}); + resolve([ + Object.entries(Fields).reduce( + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + (prev, [name, values]) => ({ ...prev, [name]: values.length > 1 ? values : values[0] }), {}), + Object.entries(Files).reduce( + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + (prev, [name, values]) => ({ ...prev, [name]: values.length > 1 ? values : values[0] }), {}), + ]); + }); + }); + } + catch (error) { + // @ts-expect-error TS(2345) FIXME: Argument of type 'unknown' is not assignable to pa... Remove this comment to see the full error message + warn(error); + next(); + return; + } + } + else { + warn('Invalid Content-Type for Netlify Dev forms request'); + next(); + return; + } + const data = JSON.stringify({ + payload: { + company: + // @ts-expect-error TS(2538) FIXME: Type 'undefined' cannot be used as an index type. + fields[Object.keys(fields).find((name) => ['company', 'business', 'employer'].includes(name.toLowerCase()))], + last_name: + // @ts-expect-error TS(2538) FIXME: Type 'undefined' cannot be used as an index type. + fields[Object.keys(fields).find((name) => ['lastname', 'surname', 'byname'].includes(name.toLowerCase()))], + first_name: fields[ + // @ts-expect-error TS(2538) FIXME: Type 'undefined' cannot be used as an index type. + Object.keys(fields).find((name) => ['firstname', 'givenname', 'forename'].includes(name.toLowerCase()))], + // @ts-expect-error TS(2538) FIXME: Type 'undefined' cannot be used as an index type. + name: fields[Object.keys(fields).find((name) => ['name', 'fullname'].includes(name.toLowerCase()))], + email: fields[ + // @ts-expect-error TS(2538) FIXME: Type 'undefined' cannot be used as an index type. + Object.keys(fields).find((name) => ['email', 'mail', 'from', 'twitter', 'sender'].includes(name.toLowerCase()))], + // @ts-expect-error TS(2538) FIXME: Type 'undefined' cannot be used as an index type. + title: fields[Object.keys(fields).find((name) => ['title', 'subject'].includes(name.toLowerCase()))], + data: { + ...fields, + ...files, + ip: req.connection.remoteAddress, + user_agent: req.headers['user-agent'], + referrer: req.headers.referer, + }, + created_at: new Date().toISOString(), + human_fields: Object.entries({ + ...fields, + // @ts-expect-error TS(2339) FIXME: Property 'url' does not exist on type 'unknown'. + ...Object.entries(files).reduce((prev, [name, { url }]) => ({ ...prev, [name]: url }), {}), + }).reduce((prev, [key, val]) => ({ ...prev, [capitalize(key)]: val }), {}), + ordered_human_fields: Object.entries({ + ...fields, + // @ts-expect-error TS(2339) FIXME: Property 'url' does not exist on type 'unknown'. + ...Object.entries(files).reduce((prev, [name, { url }]) => ({ ...prev, [name]: url }), {}), + }).map(([key, val]) => ({ title: capitalize(key), name: key, value: val })), + site_url: siteUrl, + }, + }); + req.body = data; + req.headers = { + ...req.headers, + 'content-length': String(data.length), + 'content-type': 'application/json', + 'x-netlify-original-pathname': originalUrl.pathname, + 'x-netlify-original-search': originalUrl.search, + }; + next(); + }; +}; +//# sourceMappingURL=form-submissions-handler.js.map \ No newline at end of file diff --git a/dist/lib/functions/form-submissions-handler.js.map b/dist/lib/functions/form-submissions-handler.js.map new file mode 100644 index 00000000000..952826c6b59 --- /dev/null +++ b/dist/lib/functions/form-submissions-handler.js.map @@ -0,0 +1 @@ +{"version":3,"file":"form-submissions-handler.js","sourceRoot":"","sources":["../../../src/lib/functions/form-submissions-handler.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/functions/local-proxy.d.ts b/dist/lib/functions/local-proxy.d.ts new file mode 100644 index 00000000000..ee300296966 --- /dev/null +++ b/dist/lib/functions/local-proxy.d.ts @@ -0,0 +1,9 @@ +export declare const runFunctionsProxy: ({ binaryPath, context, directory, event, name, timeout, }: { + binaryPath: string; + context: Record; + directory: string; + event: Record; + name: string; + timeout: number; +}) => Promise>; +//# sourceMappingURL=local-proxy.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/local-proxy.d.ts.map b/dist/lib/functions/local-proxy.d.ts.map new file mode 100644 index 00000000000..f4031233604 --- /dev/null +++ b/dist/lib/functions/local-proxy.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"local-proxy.d.ts","sourceRoot":"","sources":["../../../src/lib/functions/local-proxy.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,iBAAiB,GAAU,2DAOrC;IACD,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAChC,SAAS,EAAE,MAAM,CAAA;IACjB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE,MAAM,CAAA;CAChB,sDAqCA,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/local-proxy.js b/dist/lib/functions/local-proxy.js new file mode 100644 index 00000000000..e92223e182b --- /dev/null +++ b/dist/lib/functions/local-proxy.js @@ -0,0 +1,38 @@ +import { stdout } from 'process'; +import { getBinaryPath as getFunctionsProxyPath } from '@netlify/local-functions-proxy'; +import execa from '../../utils/execa.js'; +export const runFunctionsProxy = async ({ binaryPath, context, directory, event, name, timeout, }) => { + const functionsProxyPath = await getFunctionsProxyPath(); + const requestData = { + resource: '', + ...event, + headers: { + ...(typeof event.headers === 'object' ? event.headers : {}), + 'X-Amzn-Trace-Id': '1a2b3c4d5e6f', + }, + requestContext: { + ...context, + httpMethod: event.httpMethod || 'GET', + requestTimeEpoch: 0, + }, + }; + if (functionsProxyPath === null) { + throw new Error('Host machine does not support local functions proxy server'); + } + const parameters = [ + '--event', + JSON.stringify(requestData), + '--command', + binaryPath, + '--working-dir', + directory, + '--name', + name, + '--timeout', + `${timeout.toString()}s`, + ]; + const proxyProcess = execa(functionsProxyPath, parameters); + proxyProcess.stderr?.pipe(stdout); + return proxyProcess; +}; +//# sourceMappingURL=local-proxy.js.map \ No newline at end of file diff --git a/dist/lib/functions/local-proxy.js.map b/dist/lib/functions/local-proxy.js.map new file mode 100644 index 00000000000..f69cad353b6 --- /dev/null +++ b/dist/lib/functions/local-proxy.js.map @@ -0,0 +1 @@ +{"version":3,"file":"local-proxy.js","sourceRoot":"","sources":["../../../src/lib/functions/local-proxy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAEhC,OAAO,EAAE,aAAa,IAAI,qBAAqB,EAAE,MAAM,gCAAgC,CAAA;AAEvF,OAAO,KAAK,MAAM,sBAAsB,CAAA;AAExC,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,EACtC,UAAU,EACV,OAAO,EACP,SAAS,EACT,KAAK,EACL,IAAI,EACJ,OAAO,GAQR,EAAE,EAAE;IACH,MAAM,kBAAkB,GAAG,MAAM,qBAAqB,EAAE,CAAA;IACxD,MAAM,WAAW,GAAG;QAClB,QAAQ,EAAE,EAAE;QACZ,GAAG,KAAK;QACR,OAAO,EAAE;YACP,GAAG,CAAC,OAAO,KAAK,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;YAC3D,iBAAiB,EAAE,cAAc;SAClC;QACD,cAAc,EAAE;YACd,GAAG,OAAO;YACV,UAAU,EAAE,KAAK,CAAC,UAAU,IAAI,KAAK;YACrC,gBAAgB,EAAE,CAAC;SACpB;KACF,CAAA;IAED,IAAI,kBAAkB,KAAK,IAAI,EAAE,CAAC;QAChC,MAAM,IAAI,KAAK,CAAC,4DAA4D,CAAC,CAAA;IAC/E,CAAC;IAED,MAAM,UAAU,GAAG;QACjB,SAAS;QACT,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;QAC3B,WAAW;QACX,UAAU;QACV,eAAe;QACf,SAAS;QACT,QAAQ;QACR,IAAI;QACJ,WAAW;QACX,GAAG,OAAO,CAAC,QAAQ,EAAE,GAAG;KACzB,CAAA;IACD,MAAM,YAAY,GAAG,KAAK,CAAC,kBAAkB,EAAE,UAAU,CAAC,CAAA;IAE1D,YAAY,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;IAEjC,OAAO,YAAY,CAAA;AACrB,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/memoized-build.d.ts b/dist/lib/functions/memoized-build.d.ts new file mode 100644 index 00000000000..1a82a2b8d80 --- /dev/null +++ b/dist/lib/functions/memoized-build.d.ts @@ -0,0 +1,11 @@ +export type BuildCommandCache> = Record; + timestamp: number; +}>; +export declare const memoizedBuild: >({ cache, cacheKey, command, }: { + cache: BuildCommandCache; + cacheKey: string; + command: () => Promise; +}) => Promise; +//# sourceMappingURL=memoized-build.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/memoized-build.d.ts.map b/dist/lib/functions/memoized-build.d.ts.map new file mode 100644 index 00000000000..2254dbc923f --- /dev/null +++ b/dist/lib/functions/memoized-build.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"memoized-build.d.ts","sourceRoot":"","sources":["../../../src/lib/functions/memoized-build.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,iBAAiB,CAAC,CAAC,SAAS,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI,MAAM,CACnF,MAAM,EACN,SAAS,GAAG;IAAE,QAAQ,CAAC,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CACrE,CAAA;AAUD,eAAO,MAAM,aAAa,GAAI,CAAC,SAAS,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,+BAI1E;IACD,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC,CAAA;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,CAAA;CAC1B,KAAG,OAAO,CAAC,CAAC,CAmBZ,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/memoized-build.js b/dist/lib/functions/memoized-build.js new file mode 100644 index 00000000000..dee89a61cf2 --- /dev/null +++ b/dist/lib/functions/memoized-build.js @@ -0,0 +1,28 @@ +const DEBOUNCE_INTERVAL = 300; +// `memoizedBuild` will avoid running the same build command multiple times +// until the previous operation has been completed. If another call is made +// within that period, it will be: +// - discarded if it happens before `DEBOUNCE_WAIT` has elapsed; +// - enqueued if it happens after `DEBOUNCE_WAIT` has elapsed. +// This allows us to discard any duplicate filesystem events, while ensuring +// that actual updates happening during the zip operation will be executed +// after it finishes (only the last update will run). +export const memoizedBuild = ({ cache, cacheKey, command, }) => { + if (cache[cacheKey] === undefined) { + cache[cacheKey] = { + task: command().finally(() => { + const entry = cache[cacheKey]; + cache[cacheKey] = undefined; + if (entry?.enqueued !== undefined) { + void memoizedBuild({ cacheKey, command, cache }); + } + }), + timestamp: Date.now(), + }; + } + else if (Date.now() > cache[cacheKey].timestamp + DEBOUNCE_INTERVAL) { + cache[cacheKey].enqueued = true; + } + return cache[cacheKey].task; +}; +//# sourceMappingURL=memoized-build.js.map \ No newline at end of file diff --git a/dist/lib/functions/memoized-build.js.map b/dist/lib/functions/memoized-build.js.map new file mode 100644 index 00000000000..9b77a55f76b --- /dev/null +++ b/dist/lib/functions/memoized-build.js.map @@ -0,0 +1 @@ +{"version":3,"file":"memoized-build.js","sourceRoot":"","sources":["../../../src/lib/functions/memoized-build.ts"],"names":[],"mappings":"AAAA,MAAM,iBAAiB,GAAG,GAAG,CAAA;AAO7B,2EAA2E;AAC3E,2EAA2E;AAC3E,kCAAkC;AAClC,gEAAgE;AAChE,8DAA8D;AAC9D,4EAA4E;AAC5E,0EAA0E;AAC1E,qDAAqD;AACrD,MAAM,CAAC,MAAM,aAAa,GAAG,CAAgD,EAC3E,KAAK,EACL,QAAQ,EACR,OAAO,GAKR,EAAc,EAAE;IACf,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,SAAS,EAAE,CAAC;QAClC,KAAK,CAAC,QAAQ,CAAC,GAAG;YAChB,IAAI,EAAE,OAAO,EAAE,CAAC,OAAO,CAAC,GAAG,EAAE;gBAC3B,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAA;gBAE7B,KAAK,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAA;gBAE3B,IAAI,KAAK,EAAE,QAAQ,KAAK,SAAS,EAAE,CAAC;oBAClC,KAAK,aAAa,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAA;gBAClD,CAAC;YACH,CAAC,CAAC;YACF,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;SACtB,CAAA;IACH,CAAC;SAAM,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,SAAS,GAAG,iBAAiB,EAAE,CAAC;QACtE,KAAK,CAAC,QAAQ,CAAC,CAAC,QAAQ,GAAG,IAAI,CAAA;IACjC,CAAC;IAED,OAAO,KAAK,CAAC,QAAQ,CAAC,CAAC,IAAI,CAAA;AAC7B,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/netlify-function.d.ts b/dist/lib/functions/netlify-function.d.ts new file mode 100644 index 00000000000..5dc3fdc6266 --- /dev/null +++ b/dist/lib/functions/netlify-function.d.ts @@ -0,0 +1,91 @@ +import type { ExtendedRoute } from '@netlify/zip-it-and-ship-it'; +import { type NormalizedCachedConfigConfig } from '../../utils/command-helpers.js'; +import { type BlobsContextWithEdgeAccess } from '../blobs/blobs.js'; +import type { ServerSettings } from '../../utils/types.js'; +import type { BaseBuildResult, InvokeFunctionResult, Runtime } from './runtimes/index.js'; +import type { BuildCommandCache } from './memoized-build.js'; +export interface InvocationError { + errorMessage: string; + errorType: string; + stackTrace: string[]; +} +export type InvokeFunctionResultWithError = { + error: Error | InvocationError; + result: null; +}; +export type InvokeFunctionResultWithSuccess = { + error: null; + result: InvokeFunctionResult; +}; +export type InvokeResult = InvokeFunctionResultWithError | InvokeFunctionResultWithSuccess; +type MappedOmit = { + [P in keyof T as P extends K ? never : P]: T[P]; +}; +export default class NetlifyFunction { + private readonly blobsContext; + private readonly config; + private readonly directory?; + private readonly projectRoot; + private readonly timeoutBackground?; + private readonly timeoutSynchronous?; + private readonly settings; + readonly displayName: string; + mainFile: string; + readonly name: string; + readonly runtime: Runtime; + schedule?: string; + readonly isBackground: boolean; + private buildQueue?; + buildData?: MappedOmit | undefined; + buildError: Error | null; + private srcFiles; + constructor({ blobsContext, config, directory, displayName, mainFile, name, projectRoot, runtime, settings, timeoutBackground, timeoutSynchronous, }: { + blobsContext: BlobsContextWithEdgeAccess; + config: NormalizedCachedConfigConfig; + directory?: string; + displayName?: string; + mainFile: string; + name: string; + projectRoot: string; + runtime: Runtime; + settings: Pick; + timeoutBackground?: number; + timeoutSynchronous?: number; + }); + get filename(): string | null; + getRecommendedExtension(): ".mjs" | ".mts" | undefined; + hasValidName(): boolean; + isScheduled(): Promise; + isSupported(): boolean; + isTypeScript(): boolean; + getNextRun(): Promise; + build({ cache }: { + cache?: BuildCommandCache>; + }): Promise<{ + includedFiles: string[]; + srcFilesDiff: { + added: Set; + deleted: Set; + }; + error?: undefined; + } | { + error: unknown; + includedFiles?: undefined; + srcFilesDiff?: undefined; + }>; + getBuildData(): Promise; + getSrcFilesDiff(newSrcFiles: Set): { + added: Set; + deleted: Set; + }; + invoke(event?: Record, context?: Record): Promise; + /** + * Matches all routes agains the incoming request. If a match is found, then the matched route is returned. + * @returns matched route + */ + matchURLPath(rawPath: string, method: string, hasStaticFile: () => Promise): Promise; + get runtimeAPIVersion(): 1 | NonNullable; + get url(): string; +} +export {}; +//# sourceMappingURL=netlify-function.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/netlify-function.d.ts.map b/dist/lib/functions/netlify-function.d.ts.map new file mode 100644 index 00000000000..f4750001c65 --- /dev/null +++ b/dist/lib/functions/netlify-function.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"netlify-function.d.ts","sourceRoot":"","sources":["../../../src/lib/functions/netlify-function.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/functions/netlify-function.js b/dist/lib/functions/netlify-function.js new file mode 100644 index 00000000000..85b5eab194d --- /dev/null +++ b/dist/lib/functions/netlify-function.js @@ -0,0 +1,256 @@ +import { Buffer } from 'buffer'; +import { basename, extname } from 'path'; +import { version as nodeVersion } from 'process'; +import CronParser from 'cron-parser'; +import semver from 'semver'; +import { logAndThrowError } from '../../utils/command-helpers.js'; +import { BACKGROUND } from '../../utils/functions/get-functions.js'; +import { getBlobsEventProperty } from '../blobs/blobs.js'; +const TYPESCRIPT_EXTENSIONS = new Set(['.cts', '.mts', '.ts']); +const V2_MIN_NODE_VERSION = '20.12.2'; +// Returns a new set with all elements of `setA` that don't exist in `setB`. +const difference = (setA, setB) => new Set([...setA].filter((item) => !setB.has(item))); +const getNextRun = function (schedule) { + const cron = CronParser.parseExpression(schedule, { + tz: 'Etc/UTC', + }); + return cron.next().toDate(); +}; +export default class NetlifyFunction { + blobsContext; + config; + directory; + projectRoot; + timeoutBackground; + timeoutSynchronous; + settings; + displayName; + mainFile; + name; + runtime; + schedule; + // Determines whether this is a background function based on the function + // name. + isBackground; + buildQueue; + buildData; + buildError = null; + // List of the function's source files. This starts out as an empty set + // and will get populated on every build. + srcFiles = new Set(); + constructor({ blobsContext, config, directory, displayName, mainFile, name, projectRoot, runtime, settings, timeoutBackground, timeoutSynchronous, }) { + this.blobsContext = blobsContext; + this.config = config; + this.directory = directory; + this.mainFile = mainFile; + this.name = name; + this.displayName = displayName ?? name; + this.projectRoot = projectRoot; + this.runtime = runtime; + this.timeoutBackground = timeoutBackground; + this.timeoutSynchronous = timeoutSynchronous; + this.settings = settings; + this.isBackground = name.endsWith(BACKGROUND); + const functionConfig = config.functions?.[name]; + // @ts-expect-error -- XXX(serhalp): fixed in stack PR (bumps to https://github.com/netlify/build/pull/6165) + this.schedule = functionConfig && functionConfig.schedule; + this.srcFiles = new Set(); + } + get filename() { + if (!this.buildData?.mainFile) { + return null; + } + return basename(this.buildData.mainFile); + } + getRecommendedExtension() { + if (this.buildData?.runtimeAPIVersion !== 2) { + return; + } + const extension = this.buildData.mainFile ? extname(this.buildData.mainFile) : undefined; + const moduleFormat = this.buildData.outputModuleFormat; + if (moduleFormat === 'esm') { + return; + } + if (extension === '.ts') { + return '.mts'; + } + if (extension === '.js') { + return '.mjs'; + } + } + hasValidName() { + // same as https://github.com/netlify/bitballoon/blob/fbd7881e6c8e8c48e7a0145da4ee26090c794108/app/models/deploy.rb#L482 + return /^[A-Za-z0-9_-]+$/.test(this.name); + } + async isScheduled() { + await this.buildQueue; + return Boolean(this.schedule); + } + isSupported() { + return !(this.buildData?.runtimeAPIVersion === 2 && semver.lt(nodeVersion, V2_MIN_NODE_VERSION)); + } + isTypeScript() { + if (this.filename === null) { + return false; + } + return TYPESCRIPT_EXTENSIONS.has(extname(this.filename)); + } + async getNextRun() { + if (!(await this.isScheduled())) { + return null; + } + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + return getNextRun(this.schedule); + } + // The `build` method transforms source files into invocable functions. Its + // return value is an object with: + // + // - `srcFilesDiff`: Files that were added and removed since the last time + // the function was built. + async build({ cache }) { + const buildFunction = await this.runtime.getBuildFunction({ + config: this.config, + directory: this.directory, + errorExit: logAndThrowError, + func: this, + projectRoot: this.projectRoot, + }); + this.buildQueue = buildFunction({ cache }); + try { + const { includedFiles = [], schedule, srcFiles, ...buildData } = await this.buildQueue; + const srcFilesSet = new Set(srcFiles); + const srcFilesDiff = this.getSrcFilesDiff(srcFilesSet); + this.buildData = buildData; + this.buildError = null; + this.srcFiles = srcFilesSet; + this.schedule = schedule ?? this.schedule; + if (!this.isSupported()) { + throw new Error(`Function requires Node.js version ${V2_MIN_NODE_VERSION} or above, but ${nodeVersion.slice(1)} is installed. Refer to https://ntl.fyi/functions-runtime for information on how to update.`); + } + return { includedFiles, srcFilesDiff }; + } + catch (error) { + if (error instanceof Error) { + this.buildError = error; + } + return { error }; + } + } + async getBuildData() { + await this.buildQueue; + return this.buildData; + } + // Compares a new set of source files against a previous one, returning an + // object with two Sets, one with added and the other with deleted files. + getSrcFilesDiff(newSrcFiles) { + const added = difference(newSrcFiles, this.srcFiles); + const deleted = difference(this.srcFiles, newSrcFiles); + return { + added, + deleted, + }; + } + // Invokes the function and returns its response object. + async invoke(event = {}, context = {}) { + await this.buildQueue; + if (this.buildError) { + // TODO(serhalp): I don't think this error handling works as expected. Investigate. + return { result: null, error: { errorType: '', stackTrace: [], errorMessage: this.buildError.message } }; + } + const timeout = this.isBackground ? this.timeoutBackground : this.timeoutSynchronous; + if (timeout == null) { + throw new Error('Function timeout (`timeoutBackground` or `timeoutSynchronous`) not set'); + } + // Get function environment variables from config.build.environment + // This allows build event handlers to add function-specific environment variables + // Only include config environment variables that are not already set in process.env + // to ensure process environment variables take precedence + const configEnvVars = {}; + if (this.config.build?.environment) { + Object.entries(this.config.build.environment).forEach(([key, value]) => { + if (typeof value === 'string' && !(key in process.env)) { + configEnvVars[key] = value; + } + }); + } + const environment = { + // Include function-specific environment variables from config + ...configEnvVars, + }; + if (this.blobsContext) { + const payload = JSON.stringify(getBlobsEventProperty(this.blobsContext)); + event.blobs = Buffer.from(payload).toString('base64'); + } + try { + const result = await this.runtime.invokeFunction({ + context, + environment, + event, + func: this, + timeout, + }); + return { result, error: null }; + } + catch (error) { + return { result: null, error: error }; + } + } + /** + * Matches all routes agains the incoming request. If a match is found, then the matched route is returned. + * @returns matched route + */ + async matchURLPath(rawPath, method, hasStaticFile) { + await this.buildQueue; + let path = rawPath !== '/' && rawPath.endsWith('/') ? rawPath.slice(0, -1) : rawPath; + path = path.toLowerCase(); + const { excludedRoutes = [], routes = [] } = this.buildData ?? {}; + const matchingRoute = routes.find((route) => { + if (route.methods && route.methods.length !== 0 && !route.methods.includes(method)) { + return false; + } + if ('literal' in route && route.literal !== undefined) { + return path === route.literal; + } + if ('expression' in route && route.expression !== undefined) { + const regex = new RegExp(route.expression); + return regex.test(path); + } + return false; + }); + if (!matchingRoute) { + return; + } + const isExcluded = excludedRoutes.some((excludedRoute) => { + if ('literal' in excludedRoute && excludedRoute.literal !== undefined) { + return path === excludedRoute.literal; + } + if ('expression' in excludedRoute && excludedRoute.expression !== undefined) { + const regex = new RegExp(excludedRoute.expression); + return regex.test(path); + } + return false; + }); + if (isExcluded) { + return; + } + if (matchingRoute.prefer_static && (await hasStaticFile())) { + return; + } + return matchingRoute; + } + get runtimeAPIVersion() { + return this.buildData?.runtimeAPIVersion ?? 1; + } + get url() { + // This line fixes the issue here https://github.com/netlify/cli/issues/4116 + // Not sure why `settings.port` was used here nor does a valid reference exist. + // However, it remains here to serve whatever purpose for which it was added. + // @ts-expect-error(serhalp) -- Remove use of `port` here? Otherwise, pass it in from `functions:serve`. + const port = this.settings.port || this.settings.functionsPort; + // @ts-expect-error(serhalp) -- Same as above for `https` + const protocol = this.settings.https ? 'https' : 'http'; + const url = new URL(`/.netlify/functions/${this.name}`, `${protocol}://localhost:${port}`); + return url.href; + } +} +//# sourceMappingURL=netlify-function.js.map \ No newline at end of file diff --git a/dist/lib/functions/netlify-function.js.map b/dist/lib/functions/netlify-function.js.map new file mode 100644 index 00000000000..aa0bc30572b --- /dev/null +++ b/dist/lib/functions/netlify-function.js.map @@ -0,0 +1 @@ +{"version":3,"file":"netlify-function.js","sourceRoot":"","sources":["../../../src/lib/functions/netlify-function.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/functions/registry.d.ts b/dist/lib/functions/registry.d.ts new file mode 100644 index 00000000000..80df744ad57 --- /dev/null +++ b/dist/lib/functions/registry.d.ts @@ -0,0 +1,121 @@ +import { type ListedFunction, listFunctions, type Manifest } from '@netlify/zip-it-and-ship-it'; +import { type NormalizedCachedConfigConfig } from '../../utils/command-helpers.js'; +import { getFrameworksAPIPaths } from '../../utils/frameworks-api.js'; +import type { BlobsContextWithEdgeAccess } from '../blobs/blobs.js'; +import type { ServerSettings } from '../../utils/types.js'; +import NetlifyFunction from './netlify-function.js'; +import { type BaseBuildResult } from './runtimes/index.js'; +export declare const DEFAULT_FUNCTION_URL_EXPRESSION: RegExp; +export declare class FunctionsRegistry { + /** + * The functions held by the registry + */ + private functions; + /** + * File watchers for function files. Maps function names to objects built + * by the `watchDebounced` utility. + */ + private functionWatchers; + private directoryWatchers; + /** + * Keeps track of whether we've checked whether `TYPES_PACKAGE` is + * installed. + */ + private hasCheckedTypesPackage; + /** + * Context object for Netlify Blobs + */ + private blobsContext; + private buildCommandCache?; + private capabilities; + private config; + private debug; + private frameworksAPIPaths; + private isConnected; + private logLambdaCompat; + private manifest?; + private projectRoot; + private settings; + private timeouts; + constructor({ blobsContext, capabilities, config, debug, frameworksAPIPaths, isConnected, logLambdaCompat, manifest, projectRoot, settings, timeouts, }: { + blobsContext: BlobsContextWithEdgeAccess; + buildCache?: Record; + capabilities: { + backgroundFunctions?: boolean; + }; + config: NormalizedCachedConfigConfig; + debug?: boolean; + frameworksAPIPaths: ReturnType; + isConnected?: boolean; + logLambdaCompat: boolean; + manifest?: Manifest; + projectRoot: string; + settings: Pick; + timeouts: { + backgroundFunctions: number; + syncFunctions: number; + }; + }); + checkTypesPackage(): void; + static prepareDirectory(directory: string): Promise; + /** + * Builds a function and sets up the appropriate file watchers so that any + * changes will trigger another build. + */ + buildFunctionAndWatchFiles(func: NetlifyFunction, firstLoad?: boolean): Promise; + /** + * Returns a function by name. + */ + get(name: string): NetlifyFunction | undefined; + /** + * Looks for the first function that matches a given URL path. If a match is + * found, returns an object with the function and the route. If the URL path + * matches the default functions URL (i.e. can only be for a function) but no + * function with the given name exists, returns an object with the function + * and the route set to `null`. Otherwise, `undefined` is returned, + */ + getFunctionForURLPath(urlPath: string, method: string, hasStaticFile: () => Promise): Promise<{ + func: null; + route: null; + } | { + func: NetlifyFunction; + route: null; + } | { + func: NetlifyFunction; + route: import("@netlify/zip-it-and-ship-it").ExtendedRoute; + } | undefined>; + /** + * Logs an event associated with functions. + */ + private logEvent; + /** + * Adds a function to the registry + */ + registerFunction(name: string, funcBeforeHook: NetlifyFunction, isReload?: boolean): Promise; + /** + * A proxy to zip-it-and-ship-it's `listFunctions` method. It exists just so + * that we can mock it in tests. + */ + listFunctions(...args: Parameters): Promise; + /** + * Takes a list of directories and scans for functions. It keeps tracks of + * any functions in those directories that we've previously seen, and takes + * care of registering and unregistering functions as they come and go. + */ + scan(relativeDirs: (string | undefined)[]): Promise; + /** + * Creates a watcher that looks at files being added or removed from a + * functions directory. It doesn't care about files being changed, because + * those will be handled by each functions' watcher. + */ + setupDirectoryWatcher(directory: string): Promise; + /** + * Removes a function from the registry and closes its file watchers. + */ + unregisterFunction(func: NetlifyFunction): Promise; + /** + * Takes a zipped function and extracts its contents to an internal directory. + */ + unzipFunction(func: NetlifyFunction): Promise; +} +//# sourceMappingURL=registry.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/registry.d.ts.map b/dist/lib/functions/registry.d.ts.map new file mode 100644 index 00000000000..711c980bbf1 --- /dev/null +++ b/dist/lib/functions/registry.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/lib/functions/registry.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/functions/registry.js b/dist/lib/functions/registry.js new file mode 100644 index 00000000000..624f829ca5a --- /dev/null +++ b/dist/lib/functions/registry.js @@ -0,0 +1,437 @@ +import { mkdir, stat } from 'fs/promises'; +import { createRequire } from 'module'; +import { basename, extname, isAbsolute, join, resolve } from 'path'; +import { env } from 'process'; +import { listFunctions } from '@netlify/zip-it-and-ship-it'; +import extractZip from 'extract-zip'; +import { chalk, log, getTerminalLink, NETLIFYDEVERR, NETLIFYDEVLOG, NETLIFYDEVWARN, warn, watchDebounced, } from '../../utils/command-helpers.js'; +import { INTERNAL_FUNCTIONS_FOLDER, SERVE_FUNCTIONS_FOLDER } from '../../utils/functions/functions.js'; +import { BACKGROUND_FUNCTIONS_WARNING } from '../log.js'; +import { getPathInProject } from '../settings.js'; +import NetlifyFunction from './netlify-function.js'; +import runtimes from './runtimes/index.js'; +export const DEFAULT_FUNCTION_URL_EXPRESSION = /^\/.netlify\/(functions|builders)\/([^/]+).*/; +const TYPES_PACKAGE = '@netlify/functions'; +const ZIP_EXTENSION = '.zip'; +const isErrnoException = (value) => value instanceof Error && Object.hasOwn(value, 'code'); +const isInternalFunction = (func, frameworksAPIFunctionsPath) => func.mainFile.includes(getPathInProject([INTERNAL_FUNCTIONS_FOLDER])) || + func.mainFile.includes(frameworksAPIFunctionsPath); +export class FunctionsRegistry { + /** + * The functions held by the registry + */ + functions = new Map(); + /** + * File watchers for function files. Maps function names to objects built + * by the `watchDebounced` utility. + */ + functionWatchers = new Map(); + directoryWatchers; + /** + * Keeps track of whether we've checked whether `TYPES_PACKAGE` is + * installed. + */ + hasCheckedTypesPackage = false; + /** + * Context object for Netlify Blobs + */ + blobsContext; + buildCommandCache; + capabilities; + config; + debug; + frameworksAPIPaths; + isConnected; + logLambdaCompat; + manifest; + projectRoot; + // TODO(serhalp): This is confusing. Refactor to accept entire settings or rename or something? + settings; + timeouts; + constructor({ blobsContext, capabilities, config, debug = false, frameworksAPIPaths, isConnected = false, logLambdaCompat, manifest, projectRoot, settings, timeouts, }) { + this.capabilities = capabilities; + this.config = config; + this.debug = debug; + this.frameworksAPIPaths = frameworksAPIPaths; + this.isConnected = isConnected; + this.projectRoot = projectRoot; + this.timeouts = timeouts; + this.settings = settings; + this.blobsContext = blobsContext; + /** + * An object to be shared among all functions in the registry. It can be + * used to cache the results of the build function — e.g. it's used in + * the `memoizedBuild` method in the JavaScript runtime. + */ + this.buildCommandCache = {}; + /** + * File watchers for parent directories where functions live — i.e. the + * ones supplied to `scan()`. This is a Map because in the future we + * might have several function directories. + */ + this.directoryWatchers = new Map(); + /** + * Whether to log V1 functions as using the "Lambda compatibility mode" + * + */ + this.logLambdaCompat = Boolean(logLambdaCompat); + /** + * Contents of a `manifest.json` file that can be looked up when dealing + * with built functions. + * + */ + this.manifest = manifest; + } + checkTypesPackage() { + if (this.hasCheckedTypesPackage) { + return; + } + this.hasCheckedTypesPackage = true; + const require = createRequire(this.projectRoot); + try { + require.resolve(TYPES_PACKAGE, { paths: [this.projectRoot] }); + } + catch (error) { + if (isErrnoException(error) && error.code === 'MODULE_NOT_FOUND') { + this.logEvent('missing-types-package', {}); + } + } + } + // TODO(serhalp): Is this really the right place to do this mutation? Should we do this at all? + static async prepareDirectory(directory) { + await mkdir(directory, { recursive: true }); + } + /** + * Builds a function and sets up the appropriate file watchers so that any + * changes will trigger another build. + */ + async buildFunctionAndWatchFiles(func, firstLoad = false) { + if (!firstLoad) { + this.logEvent('reloading', { func }); + } + const { error: buildError, includedFiles, srcFilesDiff } = await func.build({ cache: this.buildCommandCache }); + if (buildError) { + this.logEvent('buildError', { func }); + } + else { + const event = firstLoad ? 'loaded' : 'reloaded'; + const recommendedExtension = func.getRecommendedExtension(); + if (recommendedExtension) { + const { filename } = func; + const newFilename = filename ? `${basename(filename, extname(filename))}${recommendedExtension}` : null; + const action = newFilename + ? `rename the function file to ${chalk.underline(newFilename)}. Refer to https://ntl.fyi/functions-runtime for more information` + : `refer to https://ntl.fyi/functions-runtime`; + const warning = `The function is using the legacy CommonJS format. To start using ES modules, ${action}.`; + this.logEvent(event, { func, warnings: [warning] }); + } + else { + this.logEvent(event, { func }); + } + } + if (func.isTypeScript()) { + this.checkTypesPackage(); + } + // If the build hasn't resulted in any files being added or removed, there + // is nothing else we need to do. + if (!srcFilesDiff) { + return; + } + const watcher = this.functionWatchers.get(func.name); + // If there is already a watcher for this function, we need to unwatch any + // files that have been removed and watch any files that have been added. + if (watcher) { + srcFilesDiff.deleted.forEach((path) => { + watcher.unwatch(path); + }); + srcFilesDiff.added.forEach((path) => { + watcher.add(path); + }); + return; + } + // If there is no watcher for this function but the build produced files, + // we create a new watcher and watch them. + if (srcFilesDiff.added.size !== 0) { + const filesToWatch = [...srcFilesDiff.added, ...includedFiles]; + const newWatcher = await watchDebounced(filesToWatch, { + onChange: () => { + this.buildFunctionAndWatchFiles(func, false); + }, + }); + this.functionWatchers.set(func.name, newWatcher); + } + } + /** + * Returns a function by name. + */ + get(name) { + return this.functions.get(name); + } + /** + * Looks for the first function that matches a given URL path. If a match is + * found, returns an object with the function and the route. If the URL path + * matches the default functions URL (i.e. can only be for a function) but no + * function with the given name exists, returns an object with the function + * and the route set to `null`. Otherwise, `undefined` is returned, + */ + async getFunctionForURLPath(urlPath, method, hasStaticFile) { + // We're constructing a URL object just so that we can extract the path from + // the incoming URL. It doesn't really matter that we don't have the actual + // local URL with the correct port. + const url = new URL(`http://localhost${urlPath}`); + const defaultURLMatch = DEFAULT_FUNCTION_URL_EXPRESSION.exec(url.pathname); + if (defaultURLMatch) { + const func = this.get(defaultURLMatch[2]); + if (!func) { + return { func: null, route: null }; + } + const { routes = [] } = (await func.getBuildData()) ?? {}; + if (routes.length !== 0) { + const paths = routes.map((route) => chalk.underline(route.pattern)).join(', '); + warn(`Function ${chalk.yellow(func.name)} cannot be invoked on ${chalk.underline(url.pathname)}, because the function has the following URL paths defined: ${paths}`); + return; + } + return { func, route: null }; + } + for (const func of this.functions.values()) { + const route = await func.matchURLPath(url.pathname, method, hasStaticFile); + if (route) { + return { func, route }; + } + } + } + /** + * Logs an event associated with functions. + */ + logEvent(event, { func, warnings = [] }) { + let warningsText = ''; + if (warnings.length !== 0) { + warningsText = ` with warnings:\n${warnings.map((warning) => ` - ${warning}`).join('\n')}`; + } + if (event === 'buildError') { + log(`${NETLIFYDEVERR} ${chalk.red('Failed to load')} function ${chalk.yellow(func?.displayName)}: ${func?.buildError?.message ?? ''}`); + } + if (event === 'extracted') { + log(`${NETLIFYDEVLOG} ${chalk.green('Extracted')} function ${chalk.yellow(func?.displayName)} from ${func?.mainFile ?? ''}.`); + return; + } + if (event === 'loaded') { + const icon = warningsText ? NETLIFYDEVWARN : NETLIFYDEVLOG; + const color = warningsText ? chalk.yellow : chalk.green; + const mode = func?.runtimeAPIVersion === 1 && this.logLambdaCompat + ? ` in ${getTerminalLink('Lambda compatibility mode', 'https://ntl.fyi/lambda-compat')}` + : ''; + log(`${icon} ${color('Loaded')} function ${chalk.yellow(func?.displayName)}${mode}${warningsText}`); + return; + } + if (event === 'missing-types-package') { + log(`${NETLIFYDEVWARN} For a better experience with TypeScript functions, consider installing the ${chalk.underline(TYPES_PACKAGE)} package. Refer to https://ntl.fyi/function-types for more information.`); + } + if (event === 'reloaded') { + const icon = warningsText ? NETLIFYDEVWARN : NETLIFYDEVLOG; + const color = warningsText ? chalk.yellow : chalk.green; + log(`${icon} ${color('Reloaded')} function ${chalk.yellow(func?.displayName)}${warningsText}`); + return; + } + if (event === 'reloading') { + log(`${NETLIFYDEVLOG} ${chalk.magenta('Reloading')} function ${chalk.yellow(func?.displayName)}...`); + return; + } + if (event === 'removed') { + log(`${NETLIFYDEVLOG} ${chalk.magenta('Removed')} function ${chalk.yellow(func?.displayName)}`); + } + } + /** + * Adds a function to the registry + */ + async registerFunction(name, funcBeforeHook, isReload = false) { + const { runtime } = funcBeforeHook; + // The `onRegister` hook allows runtimes to modify the function before it's + // registered, or to prevent it from being registered altogether if the + // hook returns `null`. + const func = typeof runtime.onRegister === 'function' ? runtime.onRegister(funcBeforeHook) : funcBeforeHook; + if (func === null) { + return; + } + if (func.isBackground && this.isConnected && !this.capabilities.backgroundFunctions) { + warn(BACKGROUND_FUNCTIONS_WARNING); + } + if (!func.hasValidName()) { + warn(`Function name '${func.name}' is invalid. It should consist only of alphanumeric characters, hyphen & underscores.`); + } + // If the function file is a ZIP, we extract it and rewire its main file to + // the new location. + if (extname(func.mainFile) === ZIP_EXTENSION) { + const unzippedDirectory = await this.unzipFunction(func); + // If there's a manifest file, look up the function in order to extract the build data. + const manifestEntry = (this.manifest?.functions ?? []).find((manifestFunc) => manifestFunc.name === func.name); + // We found a zipped function that does not have a corresponding entry in + // the manifest. This shouldn't happen, but we ignore the function in + // this case. + if (!manifestEntry) { + return; + } + if (this.debug) { + this.logEvent('extracted', { func }); + } + func.buildData = { + ...manifestEntry.buildData, + routes: manifestEntry.routes, + }; + // When we look at an unzipped function, we don't know whether it uses + // the legacy entry file format (i.e. `[function name].mjs`) or the new + // one (i.e. `___netlify-entry-point.mjs`). Let's look for the new one + // and use it if it exists, otherwise use the old one. + try { + const v2EntryPointPath = join(unzippedDirectory, '___netlify-entry-point.mjs'); + await stat(v2EntryPointPath); + func.mainFile = v2EntryPointPath; + } + catch { + func.mainFile = join(unzippedDirectory, basename(manifestEntry.mainFile)); + } + } + else { + this.buildFunctionAndWatchFiles(func, !isReload); + } + this.functions.set(name, func); + } + /** + * A proxy to zip-it-and-ship-it's `listFunctions` method. It exists just so + * that we can mock it in tests. + */ + async listFunctions(...args) { + return await listFunctions(...args); + } + /** + * Takes a list of directories and scans for functions. It keeps tracks of + * any functions in those directories that we've previously seen, and takes + * care of registering and unregistering functions as they come and go. + */ + async scan(relativeDirs) { + const directories = relativeDirs + .filter((dir) => Boolean(dir)) + .map((dir) => (isAbsolute(dir) ? dir : join(this.projectRoot, dir))); + // check after filtering to filter out [undefined] for example + if (directories.length === 0) { + return; + } + await Promise.all(directories.map((path) => FunctionsRegistry.prepareDirectory(path))); + const functions = await this.listFunctions(directories, { + featureFlags: { + buildRustSource: env.NETLIFY_EXPERIMENTAL_BUILD_RUST_SOURCE === 'true', + }, + configFileDirectories: [getPathInProject([INTERNAL_FUNCTIONS_FOLDER])], + // @ts-expect-error -- TODO(serhalp): Function config types do not match. Investigate and fix. + config: this.config.functions, + }); + // user-defined functions take precedence over internal functions, + // so we want to ignore any internal functions where there's a user-defined one with the same name + const ignoredFunctions = new Set(functions + .filter((func) => isInternalFunction(func, this.frameworksAPIPaths.functions.path) && + this.functions.has(func.name) && + !isInternalFunction(this.functions.get(func.name), this.frameworksAPIPaths.functions.path)) + .map((func) => func.name)); + // Before registering any functions, we look for any functions that were on + // the previous list but are missing from the new one. We unregister them. + const deletedFunctions = [...this.functions.values()].filter((oldFunc) => { + const isFound = functions.some((newFunc) => ignoredFunctions.has(newFunc.name) || + (newFunc.name === oldFunc.name && newFunc.mainFile === oldFunc.mainFile)); + return !isFound; + }); + await Promise.all(deletedFunctions.map((func) => this.unregisterFunction(func))); + const deletedFunctionNames = new Set(deletedFunctions.map((func) => func.name)); + const addedFunctions = await Promise.all( + // zip-it-and-ship-it returns an array sorted based on which extension should have precedence, + // where the last ones precede the previous ones. This is why + // we reverse the array so we get the right functions precedence in the CLI. + functions.reverse().map(async ({ displayName, mainFile, name, runtime: runtimeName }) => { + if (ignoredFunctions.has(name)) { + return; + } + const runtime = runtimes[runtimeName]; + // If there is no matching runtime, it means this function is not yet + // supported in Netlify Dev. + if (runtime === undefined) { + return; + } + // If this function has already been registered, we skip it. + if (this.functions.has(name)) { + return; + } + const func = new NetlifyFunction({ + blobsContext: this.blobsContext, + config: this.config, + directory: directories.find((directory) => mainFile.startsWith(directory)), + mainFile, + name, + displayName, + projectRoot: this.projectRoot, + // @ts-expect-error(serhalp) -- I think TS needs to know that a given instance of `runtime` in this loop at + // this point will have a refined type of only one of the runtime types in the union, and this type is + // consistent between the `NetlifyFunction` and the `runtime`. But... how do? + runtime, + timeoutBackground: this.timeouts.backgroundFunctions, + timeoutSynchronous: this.timeouts.syncFunctions, + settings: this.settings, + }); + // If a function we're registering was also unregistered in this run, + // then it was a rename. Let's flag it as such so that the messaging + // is adjusted accordingly. + const isReload = deletedFunctionNames.has(name); + await this.registerFunction(name, func, isReload); + return func; + })); + const addedFunctionNames = new Set(addedFunctions.filter(Boolean).map((func) => func?.name)); + deletedFunctions.forEach((func) => { + // If a function we've unregistered was also registered in this run, then + // it was a rename that we've already logged. Nothing to do in this case. + if (addedFunctionNames.has(func.name)) { + return; + } + this.logEvent('removed', { func }); + }); + await Promise.all(directories.map((path) => this.setupDirectoryWatcher(path))); + } + /** + * Creates a watcher that looks at files being added or removed from a + * functions directory. It doesn't care about files being changed, because + * those will be handled by each functions' watcher. + */ + async setupDirectoryWatcher(directory) { + if (this.directoryWatchers.has(directory)) { + return; + } + const watcher = await watchDebounced(directory, { + depth: 1, + onAdd: () => { + this.scan([directory]); + }, + onUnlink: () => { + this.scan([directory]); + }, + }); + this.directoryWatchers.set(directory, watcher); + } + /** + * Removes a function from the registry and closes its file watchers. + */ + async unregisterFunction(func) { + const { name } = func; + this.functions.delete(name); + const watcher = this.functionWatchers.get(name); + if (watcher) { + await watcher.close(); + } + this.functionWatchers.delete(name); + } + /** + * Takes a zipped function and extracts its contents to an internal directory. + */ + async unzipFunction(func) { + const targetDirectory = resolve(this.projectRoot, getPathInProject([SERVE_FUNCTIONS_FOLDER, '.unzipped', func.name])); + await extractZip(func.mainFile, { dir: targetDirectory }); + return targetDirectory; + } +} +//# sourceMappingURL=registry.js.map \ No newline at end of file diff --git a/dist/lib/functions/registry.js.map b/dist/lib/functions/registry.js.map new file mode 100644 index 00000000000..e9c41c238dc --- /dev/null +++ b/dist/lib/functions/registry.js.map @@ -0,0 +1 @@ +{"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/lib/functions/registry.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/functions/runtimes/go/index.d.ts b/dist/lib/functions/runtimes/go/index.d.ts new file mode 100644 index 00000000000..2d5e110c4df --- /dev/null +++ b/dist/lib/functions/runtimes/go/index.d.ts @@ -0,0 +1,11 @@ +import type { LambdaEvent } from 'lambda-local'; +import type { BaseBuildResult, BuildFunction, GetBuildFunctionOpts, InvokeFunction, OnRegisterFunction } from '../index.js'; +export declare const name = "go"; +export type GoBuildResult = BaseBuildResult & { + binaryPath: string; +}; +export type GoInvokeFunctionResult = LambdaEvent; +export declare const getBuildFunction: ({ func, }: GetBuildFunctionOpts) => Promise>; +export declare const invokeFunction: InvokeFunction; +export declare const onRegister: OnRegisterFunction; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/runtimes/go/index.d.ts.map b/dist/lib/functions/runtimes/go/index.d.ts.map new file mode 100644 index 00000000000..234213232ab --- /dev/null +++ b/dist/lib/functions/runtimes/go/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/lib/functions/runtimes/go/index.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE/C,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EACnB,MAAM,aAAa,CAAA;AAOpB,eAAO,MAAM,IAAI,OAAO,CAAA;AAExB,MAAM,MAAM,aAAa,GAAG,eAAe,GAAG;IAC5C,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG,WAAW,CAAA;AAoChD,eAAO,MAAM,gBAAgB,GAAI,WAE9B,oBAAoB,CAAC,aAAa,CAAC,KAAG,OAAO,CAAC,aAAa,CAAC,aAAa,CAAC,CAM1E,CAAA;AAEH,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,aAAa,CA2BxD,CAAA;AAED,eAAO,MAAM,UAAU,EAAE,kBAAkB,CAAC,aAAa,CAIxD,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/runtimes/go/index.js b/dist/lib/functions/runtimes/go/index.js new file mode 100644 index 00000000000..05090b62b0a --- /dev/null +++ b/dist/lib/functions/runtimes/go/index.js @@ -0,0 +1,65 @@ +import { dirname, extname } from 'path'; +import { platform } from 'process'; +import execa from '../../../../utils/execa.js'; +import { runFunctionsProxy } from '../../local-proxy.js'; +import { temporaryFile } from '../../../../utils/temporary-file.js'; +const isWindows = platform === 'win32'; +export const name = 'go'; +const build = async ({ binaryPath, functionDirectory, }) => { + try { + await execa('go', ['build', '-o', binaryPath], { cwd: functionDirectory }); + return { binaryPath, srcFiles: [functionDirectory] }; + } + catch (error) { + const isGoInstalled = await checkGoInstallation({ cwd: functionDirectory }); + if (!isGoInstalled) { + throw new Error("You don't seem to have Go installed. Go to https://golang.org/doc/install for installation instructions."); + } + throw error; + } +}; +const checkGoInstallation = async ({ cwd }) => { + try { + await execa('go', ['version'], { cwd }); + return true; + } + catch { + return false; + } +}; +export const getBuildFunction = ({ func, }) => Promise.resolve(async () => build({ + binaryPath: temporaryFile(isWindows ? { extension: 'exe' } : undefined), + functionDirectory: dirname(func.mainFile), +})); +export const invokeFunction = async ({ context, event, func, timeout }) => { + if (func.buildData == null) { + throw new Error('Cannot invoke a function that has not been built'); + } + const { stdout } = await runFunctionsProxy({ + binaryPath: func.buildData.binaryPath, + context, + directory: dirname(func.mainFile), + event, + name: func.name, + timeout, + }); + try { + const { body, headers, multiValueHeaders, statusCode } = JSON.parse(stdout); + return { + body, + headers, + multiValueHeaders, + statusCode, + }; + } + catch { + return { + statusCode: 500, + }; + } +}; +export const onRegister = (func) => { + const isSource = extname(func.mainFile) === '.go'; + return isSource ? func : null; +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/lib/functions/runtimes/go/index.js.map b/dist/lib/functions/runtimes/go/index.js.map new file mode 100644 index 00000000000..510fcdf94a2 --- /dev/null +++ b/dist/lib/functions/runtimes/go/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/lib/functions/runtimes/go/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/functions/runtimes/index.d.ts b/dist/lib/functions/runtimes/index.d.ts new file mode 100644 index 00000000000..d125f553e35 --- /dev/null +++ b/dist/lib/functions/runtimes/index.d.ts @@ -0,0 +1,55 @@ +import type { ExtendedRoute, Route } from '@netlify/zip-it-and-ship-it'; +import type { BuildCommandCache } from '../memoized-build.js'; +import type NetlifyFunction from '../netlify-function.js'; +import type { NormalizedCachedConfigConfig } from '../../../utils/command-helpers.js'; +import * as go from './go/index.js'; +import type { GoInvokeFunctionResult } from './go/index.js'; +import * as js from './js/index.js'; +import type { JsInvokeFunctionResult } from './js/index.js'; +import * as rust from './rust/index.js'; +import type { RustInvokeFunctionResult } from './rust/index.js'; +export type BaseBuildResult = { + includedFiles?: undefined | string[]; + mainFile?: undefined | string; + outputModuleFormat?: undefined | string; + schedule?: undefined | string; + srcFiles: string[]; + excludedRoutes?: Route[] | undefined; + routes?: ExtendedRoute[] | undefined; + runtimeAPIVersion?: number | undefined; +}; +export type GetBuildFunctionOpts = { + config: NormalizedCachedConfigConfig; + context?: Record; + directory?: string; + errorExit: (msg: string) => void; + func: NetlifyFunction; + functionsDirectory?: string; + projectRoot: string; +}; +export type BuildFunction = Record> = ({ cache }: { + cache?: BuildCommandCache; +}) => Promise; +export type GetBuildFunction = Record> = (params: GetBuildFunctionOpts) => Promise>; +export type InvokeFunctionResult = JsInvokeFunctionResult | GoInvokeFunctionResult | RustInvokeFunctionResult; +export type InvokeFunction = (params: { + context: Record; + environment: Record; + event: Record; + func: NetlifyFunction; + timeout: number; +}) => Promise; +export type OnRegisterFunction = (func: NetlifyFunction) => NetlifyFunction | null; +export interface Runtime { + getBuildFunction: GetBuildFunction; + invokeFunction: InvokeFunction; + onRegister?: OnRegisterFunction; + name: string; +} +declare const runtimes: { + go: typeof go; + js: typeof js; + rs: typeof rust; +}; +export default runtimes; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/runtimes/index.d.ts.map b/dist/lib/functions/runtimes/index.d.ts.map new file mode 100644 index 00000000000..145b747011f --- /dev/null +++ b/dist/lib/functions/runtimes/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/lib/functions/runtimes/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/functions/runtimes/index.js b/dist/lib/functions/runtimes/index.js new file mode 100644 index 00000000000..1d619a5982a --- /dev/null +++ b/dist/lib/functions/runtimes/index.js @@ -0,0 +1,10 @@ +import * as go from './go/index.js'; +import * as js from './js/index.js'; +import * as rust from './rust/index.js'; +const runtimes = { + [go.name]: go, + [js.name]: js, + [rust.name]: rust, +}; +export default runtimes; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/lib/functions/runtimes/index.js.map b/dist/lib/functions/runtimes/index.js.map new file mode 100644 index 00000000000..096d649c339 --- /dev/null +++ b/dist/lib/functions/runtimes/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/lib/functions/runtimes/index.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AAEnC,OAAO,KAAK,EAAE,MAAM,eAAe,CAAA;AAEnC,OAAO,KAAK,IAAI,MAAM,iBAAiB,CAAA;AAyDvC,MAAM,QAAQ,GAAG;IACf,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE;IACb,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE;IACb,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI;CAClB,CAAA;AAED,eAAe,QAAQ,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/runtimes/js/builders/zisi.d.ts b/dist/lib/functions/runtimes/js/builders/zisi.d.ts new file mode 100644 index 00000000000..075dd9ad0c7 --- /dev/null +++ b/dist/lib/functions/runtimes/js/builders/zisi.d.ts @@ -0,0 +1,35 @@ +import { type FunctionResult } from '@netlify/zip-it-and-ship-it'; +import { type NormalizedCachedConfigConfig } from '../../../../../utils/command-helpers.js'; +import { type BuildCommandCache } from '../../../memoized-build.js'; +import type NetlifyFunction from '../../../netlify-function.js'; +import type { BaseBuildResult } from '../../index.js'; +import type { JsBuildResult } from '../index.js'; +export type ZisiBuildResult = BaseBuildResult & { + buildPath: string; + includedFiles: FunctionResult['includedFiles']; + outputModuleFormat: FunctionResult['outputModuleFormat']; + mainFile: FunctionResult['mainFile']; + runtimeAPIVersion: FunctionResult['runtimeAPIVersion']; +}; +export declare const getFunctionMetadata: ({ config, mainFile, projectRoot, }: { + config: NormalizedCachedConfigConfig; + mainFile: string; + projectRoot: string; +}) => Promise; +type FunctionMetadata = NonNullable>>; +export default function detectZisiBuilder({ config, directory, errorExit, func, metadata, projectRoot, }: { + config: NormalizedCachedConfigConfig; + directory?: string | undefined; + errorExit: (msg: string) => void; + func: NetlifyFunction; + metadata?: FunctionMetadata | undefined; + projectRoot: string; +}): Promise; + }) => Promise; + builderName: string; + target: string; +}>; +export {}; +//# sourceMappingURL=zisi.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/runtimes/js/builders/zisi.d.ts.map b/dist/lib/functions/runtimes/js/builders/zisi.d.ts.map new file mode 100644 index 00000000000..b4548a176c8 --- /dev/null +++ b/dist/lib/functions/runtimes/js/builders/zisi.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"zisi.d.ts","sourceRoot":"","sources":["../../../../../../src/lib/functions/runtimes/js/builders/zisi.ts"],"names":[],"mappings":"AAIA,OAAO,EAA6C,KAAK,cAAc,EAAE,MAAM,6BAA6B,CAAA;AAO5G,OAAO,EAAiB,KAAK,4BAA4B,EAAE,MAAM,yCAAyC,CAAA;AAI1G,OAAO,EAAE,KAAK,iBAAiB,EAAiB,MAAM,4BAA4B,CAAA;AAClF,OAAO,KAAK,eAAe,MAAM,8BAA8B,CAAA;AAC/D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAA;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAIhD,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG;IAC9C,SAAS,EAAE,MAAM,CAAA;IACjB,aAAa,EAAE,cAAc,CAAC,eAAe,CAAC,CAAA;IAC9C,kBAAkB,EAAE,cAAc,CAAC,oBAAoB,CAAC,CAAA;IACxD,QAAQ,EAAE,cAAc,CAAC,UAAU,CAAC,CAAA;IACpC,iBAAiB,EAAE,cAAc,CAAC,mBAAmB,CAAC,CAAA;CACvD,CAAA;AAkGD,eAAO,MAAM,mBAAmB,GAAU,oCAIvC;IACD,MAAM,EAAE,4BAA4B,CAAA;IACpC,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,EAAE,MAAM,CAAA;CACpB,8EAMG,CAAA;AAEJ,KAAK,gBAAgB,GAAG,WAAW,CAAC,OAAO,CAAC,UAAU,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAC,CAAA;AAqCpF,wBAA8B,iBAAiB,CAAC,EAC9C,MAAM,EACN,SAAS,EACT,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,WAAW,GACZ,EAAE;IACD,MAAM,EAAE,4BAA4B,CAAA;IACpC,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,SAAS,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IAGhC,IAAI,EAAE,eAAe,CAAC,aAAa,CAAC,CAAA;IACpC,QAAQ,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAA;IACvC,WAAW,EAAE,MAAM,CAAA;CACpB;uBAoCsC;QAAE,KAAK,CAAC,EAAE,iBAAiB,CAAC,cAAc,CAAC,CAAA;KAAE;;;GAiBnF"} \ No newline at end of file diff --git a/dist/lib/functions/runtimes/js/builders/zisi.js b/dist/lib/functions/runtimes/js/builders/zisi.js new file mode 100644 index 00000000000..84c4bb9488b --- /dev/null +++ b/dist/lib/functions/runtimes/js/builders/zisi.js @@ -0,0 +1,139 @@ +import { mkdir, writeFile } from 'fs/promises'; +import { createRequire } from 'module'; +import path from 'path'; +import { ARCHIVE_FORMAT, zipFunction, listFunction } from '@netlify/zip-it-and-ship-it'; +import decache from 'decache'; +import { readPackageUp } from 'read-package-up'; +import sourceMapSupport from 'source-map-support'; +import { NETLIFYDEVERR } from '../../../../../utils/command-helpers.js'; +import { SERVE_FUNCTIONS_FOLDER } from '../../../../../utils/functions/functions.js'; +import { getPathInProject } from '../../../../settings.js'; +import { normalizeFunctionsConfig } from '../../../config.js'; +import { memoizedBuild } from '../../../memoized-build.js'; +const require = createRequire(import.meta.url); +const addFunctionsConfigDefaults = (config) => ({ + ...config, + '*': { + nodeSourcemap: true, + ...config['*'], + }, +}); +const buildFunction = async ({ cache, config, directory, featureFlags, func, hasTypeModule, projectRoot, targetDirectory, }) => { + const zipOptions = { + archiveFormat: ARCHIVE_FORMAT.NONE, + basePath: projectRoot, + config, + featureFlags: { ...featureFlags, zisi_functions_api_v2: true }, + }; + const functionDirectory = path.dirname(func.mainFile); + // If we have a function at `functions/my-func/index.js` and we pass + // that path to `zipFunction`, it will lack the context of the whole + // functions directory and will infer the name of the function to be + // `index`, not `my-func`. Instead, we need to pass the directory of + // the function. The exception is when the function is a file at the + // root of the functions directory (e.g. `functions/my-func.js`). In + // this case, we use `mainFile` as the function path of `zipFunction`. + const entryPath = functionDirectory === directory ? func.mainFile : functionDirectory; + const { entryFilename, excludedRoutes, includedFiles, inputs, mainFile, outputModuleFormat, path: functionPath, routes, runtimeAPIVersion, schedule, } = await memoizedBuild({ + cache, + cacheKey: `zisi-${entryPath}`, + command: async () => { + const result = await zipFunction(entryPath, targetDirectory, zipOptions); + if (result == null) { + throw new Error('Failed to build function'); + } + return result; + }, + }); + const srcFiles = (inputs ?? []).filter((inputPath) => !inputPath.includes(`${path.sep}node_modules${path.sep}`)); + const buildPath = path.join(functionPath, entryFilename); + // some projects include a package.json with "type=module", forcing Node to interpret every descending file + // as ESM. ZISI outputs CJS, so we emit an overriding directive into the output directory. + if (hasTypeModule) { + await writeFile(path.join(functionPath, 'package.json'), JSON.stringify({ + type: 'commonjs', + })); + } + clearFunctionsCache(targetDirectory); + return { + buildPath, + excludedRoutes, + includedFiles, + outputModuleFormat, + mainFile, + routes, + runtimeAPIVersion, + srcFiles, + schedule, + }; +}; +export const getFunctionMetadata = async ({ config, mainFile, projectRoot, }) => +// TODO(serhalp): Throw if this returns `undefined`? It doesn't seem like this is expected. +await listFunction(mainFile, { + config: netlifyConfigToZisiConfig({ config, projectRoot }), + featureFlags: {}, + parseISC: true, +}); +// Clears the cache for any files inside the directory from which functions are served. +const clearFunctionsCache = (functionsPath) => { + Object.keys(require.cache) + .filter((key) => key.startsWith(functionsPath)) + // @ts-expect-error(serhalp) -- `decache` is typed but TS thinks it isn't callable. Investigate. + // eslint-disable-next-line @typescript-eslint/no-unsafe-return -- What in the world is going on? + .forEach((key) => decache(key)); +}; +const getTargetDirectory = async ({ errorExit, projectRoot, }) => { + const targetDirectory = path.resolve(projectRoot, getPathInProject([SERVE_FUNCTIONS_FOLDER])); + try { + await mkdir(targetDirectory, { recursive: true }); + } + catch { + errorExit(`${NETLIFYDEVERR} Could not create directory: ${targetDirectory}`); + } + return targetDirectory; +}; +const netlifyConfigToZisiConfig = ({ config, projectRoot, }) => addFunctionsConfigDefaults(normalizeFunctionsConfig({ functionsConfig: config.functions, projectRoot })); +export default async function detectZisiBuilder({ config, directory, errorExit, func, metadata, projectRoot, }) { + const functionsConfig = netlifyConfigToZisiConfig({ config, projectRoot }); + // @ts-expect-error(serhalp) -- We seem to be incorrectly using this function, but it seems to work... Investigate. + const packageJson = await readPackageUp(func.mainFile); + const hasTypeModule = packageJson?.packageJson.type === 'module'; + const featureFlags = {}; + if (metadata?.runtimeAPIVersion === 2) { + featureFlags.zisi_pure_esm = true; + featureFlags.zisi_pure_esm_mjs = true; + } + else { + // We must use esbuild for certain file extensions. + const mustTranspile = ['.mjs', '.ts', '.mts', '.cts'].includes(path.extname(func.mainFile)); + const mustUseEsbuild = hasTypeModule || mustTranspile; + if (mustUseEsbuild && !functionsConfig['*'].nodeBundler) { + functionsConfig['*'].nodeBundler = 'esbuild'; + } + // TODO: Resolve functions config globs so that we can check for the bundler + // on a per-function basis. + const isUsingEsbuild = functionsConfig['*'].nodeBundler != null && ['esbuild_zisi', 'esbuild'].includes(functionsConfig['*'].nodeBundler); + if (!isUsingEsbuild) { + return false; + } + } + // Enable source map support. + sourceMapSupport.install(); + const targetDirectory = await getTargetDirectory({ projectRoot, errorExit }); + const build = async ({ cache = {} }) => buildFunction({ + cache, + config: functionsConfig, + directory, + func, + projectRoot, + targetDirectory, + hasTypeModule, + featureFlags, + }); + return { + build, + builderName: 'zip-it-and-ship-it', + target: targetDirectory, + }; +} +//# sourceMappingURL=zisi.js.map \ No newline at end of file diff --git a/dist/lib/functions/runtimes/js/builders/zisi.js.map b/dist/lib/functions/runtimes/js/builders/zisi.js.map new file mode 100644 index 00000000000..356d302aec9 --- /dev/null +++ b/dist/lib/functions/runtimes/js/builders/zisi.js.map @@ -0,0 +1 @@ +{"version":3,"file":"zisi.js","sourceRoot":"","sources":["../../../../../../src/lib/functions/runtimes/js/builders/zisi.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/functions/runtimes/js/constants.d.ts b/dist/lib/functions/runtimes/js/constants.d.ts new file mode 100644 index 00000000000..0bc6476cf38 --- /dev/null +++ b/dist/lib/functions/runtimes/js/constants.d.ts @@ -0,0 +1,2 @@ +export declare const SECONDS_TO_MILLISECONDS = 1000; +//# sourceMappingURL=constants.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/runtimes/js/constants.d.ts.map b/dist/lib/functions/runtimes/js/constants.d.ts.map new file mode 100644 index 00000000000..bcc23ac1adc --- /dev/null +++ b/dist/lib/functions/runtimes/js/constants.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../../../src/lib/functions/runtimes/js/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB,OAAO,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/runtimes/js/constants.js b/dist/lib/functions/runtimes/js/constants.js new file mode 100644 index 00000000000..6d00412915f --- /dev/null +++ b/dist/lib/functions/runtimes/js/constants.js @@ -0,0 +1,2 @@ +export const SECONDS_TO_MILLISECONDS = 1000; +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/dist/lib/functions/runtimes/js/constants.js.map b/dist/lib/functions/runtimes/js/constants.js.map new file mode 100644 index 00000000000..01487edd9f5 --- /dev/null +++ b/dist/lib/functions/runtimes/js/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../../../src/lib/functions/runtimes/js/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,uBAAuB,GAAG,IAAI,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/runtimes/js/index.d.ts b/dist/lib/functions/runtimes/js/index.d.ts new file mode 100644 index 00000000000..f0a998bf213 --- /dev/null +++ b/dist/lib/functions/runtimes/js/index.d.ts @@ -0,0 +1,25 @@ +import { type LambdaEvent } from 'lambda-local'; +import type { BuildFunction, GetBuildFunction, InvokeFunction } from '../index.js'; +import type NetlifyFunction from '../../netlify-function.js'; +import { ZisiBuildResult } from './builders/zisi.js'; +import type { WorkerMessage } from './worker.js'; +export declare const name = "js"; +type SimpleJsBuildResult = { + schedule?: string; + srcFiles: string[]; +}; +export type JsBuildResult = ZisiBuildResult | SimpleJsBuildResult; +export type JsInvokeFunctionResult = WorkerMessage | LambdaEvent; +export declare function getBuildFunction({ config, directory, errorExit, func, projectRoot, }: Parameters>[0]): Promise<(({ cache }: { + cache?: import("../../memoized-build.js").BuildCommandCache; +}) => Promise) | BuildFunction>; +export declare const invokeFunction: ({ context, environment, event, func, timeout, }: Parameters>[0]) => Promise; +export declare const invokeFunctionDirectly: ({ context, environment, event, func, timeout, }: { + context: Record; + environment: Record; + event: Record; + func: NetlifyFunction; + timeout: number; +}) => Promise; +export {}; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/runtimes/js/index.d.ts.map b/dist/lib/functions/runtimes/js/index.d.ts.map new file mode 100644 index 00000000000..20dbcfda4fe --- /dev/null +++ b/dist/lib/functions/runtimes/js/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/lib/functions/runtimes/js/index.ts"],"names":[],"mappings":"AAKA,OAAoB,EAAE,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AAE5D,OAAO,KAAK,EAAE,aAAa,EAAE,gBAAgB,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAElF,OAAO,KAAK,eAAe,MAAM,2BAA2B,CAAA;AAE5D,OAA0B,EAAuB,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAE5F,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAEhD,eAAO,MAAM,IAAI,OAAO,CAAA;AAExB,KAAK,mBAAmB,GAAG;IACzB,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,EAAE,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,aAAa,GAAG,eAAe,GAAG,mBAAmB,CAAA;AAIjE,MAAM,MAAM,sBAAsB,GAAG,aAAa,GAAG,WAAW,CAAA;AAIhE,wBAAsB,gBAAgB,CAAC,EACrC,MAAM,EACN,SAAS,EACT,SAAS,EACT,IAAI,EACJ,WAAW,GACZ,EAAE,UAAU,CAAC,gBAAgB,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;SA8HgmE,CAAC;gEA9GjpE;AAID,eAAO,MAAM,cAAc,GAAU,iDAMlC,UAAU,CAAC,cAAc,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,KAAG,OAAO,CAAC,sBAAsB,CAwD/E,CAAA;AAED,eAAO,MAAM,sBAAsB,GAAU,WAAW,SAAS,aAAa,EAAE,iDAM7E;IACD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAChC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACnC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;IAC9B,IAAI,EAAE,eAAe,CAAC,WAAW,CAAC,CAAA;IAClC,OAAO,EAAE,MAAM,CAAA;CAChB,KAAG,OAAO,CAAC,WAAW,CA6BtB,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/runtimes/js/index.js b/dist/lib/functions/runtimes/js/index.js new file mode 100644 index 00000000000..4d886b1444c --- /dev/null +++ b/dist/lib/functions/runtimes/js/index.js @@ -0,0 +1,103 @@ +import { createConnection } from 'net'; +import { dirname } from 'path'; +import { pathToFileURL } from 'url'; +import { Worker } from 'worker_threads'; +import lambdaLocal from 'lambda-local'; +import { BLOBS_CONTEXT_VARIABLE } from '../../../blobs/blobs.js'; +import detectZisiBuilder, { getFunctionMetadata } from './builders/zisi.js'; +import { SECONDS_TO_MILLISECONDS } from './constants.js'; +export const name = 'js'; +lambdaLocal.getLogger().level = 'alert'; +export async function getBuildFunction({ config, directory, errorExit, func, projectRoot, }) { + const metadata = await getFunctionMetadata({ mainFile: func.mainFile, config, projectRoot }); + const zisiBuilder = await detectZisiBuilder({ config, directory, errorExit, func, metadata, projectRoot }); + if (zisiBuilder) { + return zisiBuilder.build; + } + // If there's no function builder, we create a simple one on-the-fly which + // returns as `srcFiles` the function directory, if there is one, or its + // main file otherwise. + const functionDirectory = dirname(func.mainFile); + const srcFiles = functionDirectory === directory ? [func.mainFile] : [functionDirectory]; + const build = () => Promise.resolve({ schedule: metadata?.schedule, srcFiles }); + return build; +} +const workerURL = new URL('worker.js', import.meta.url); +export const invokeFunction = async ({ context, environment, event, func, timeout, }) => { + const { buildData } = func; + // I have no idea why, but it appears that treating the case of a missing `buildData` or missing + // `buildData.runtimeAPIVersion` as V1 is important. + const runtimeAPIVersion = buildData != null && 'runtimeAPIVersion' in buildData && typeof buildData.runtimeAPIVersion === 'number' + ? buildData.runtimeAPIVersion + : null; + if (runtimeAPIVersion == null || runtimeAPIVersion !== 2) { + return await invokeFunctionDirectly({ + context, + environment: environment, + event, + func, + timeout, + }); + } + const workerData = { + clientContext: JSON.stringify(context), + environment, + event, + // If a function builder has defined a `buildPath` property, we use it. + // Otherwise, we'll invoke the function's main file. + // Because we use import() we have to use file:// URLs for Windows. + entryFilePath: pathToFileURL(buildData != null && 'buildPath' in buildData && buildData.buildPath ? buildData.buildPath : func.mainFile).href, + timeoutMs: timeout * SECONDS_TO_MILLISECONDS, + }; + const worker = new Worker(workerURL, { workerData }); + return await new Promise((resolve, reject) => { + worker.on('message', (result) => { + // TODO(serhalp): Improve `WorkerMessage` type. It sure would be nice to keep it simple as it + // is now, but technically this is an arbitrary type from the user function return... + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + if (result?.streamPort != null) { + const client = createConnection({ + port: result.streamPort, + host: 'localhost', + }, () => { + result.body = client; + resolve(result); + }); + client.on('error', reject); + } + else { + resolve(result); + } + }); + worker.on('error', reject); + }); +}; +export const invokeFunctionDirectly = async ({ context, environment, event, func, timeout, }) => { + const buildData = await func.getBuildData(); + if (buildData == null) { + throw new Error('Cannot invoke a function that has not been built'); + } + // If a function builder has defined a `buildPath` property, we use it. + // Otherwise, we'll invoke the function's main file. + const lambdaPath = 'buildPath' in buildData && typeof buildData.buildPath === 'string' ? buildData.buildPath : func.mainFile; + const result = await lambdaLocal.execute({ + clientContext: JSON.stringify(context), + environment: { + // Include environment variables from config + ...environment, + // We've set the Blobs context on the parent process, which means it will + // be available to the Lambda. This would be inconsistent with production + // where only V2 functions get the context injected. To fix it, unset the + // context variable before invoking the function. + // This has the side-effect of also removing the variable from `process.env`. + [BLOBS_CONTEXT_VARIABLE]: undefined, + }, + event, + lambdaPath, + timeoutMs: timeout * SECONDS_TO_MILLISECONDS, + verboseLevel: 3, + esm: lambdaPath.endsWith('.mjs'), + }); + return result; +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/lib/functions/runtimes/js/index.js.map b/dist/lib/functions/runtimes/js/index.js.map new file mode 100644 index 00000000000..19c213d1387 --- /dev/null +++ b/dist/lib/functions/runtimes/js/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/lib/functions/runtimes/js/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/functions/runtimes/js/worker.d.ts b/dist/lib/functions/runtimes/js/worker.d.ts new file mode 100644 index 00000000000..2f97c51cd30 --- /dev/null +++ b/dist/lib/functions/runtimes/js/worker.d.ts @@ -0,0 +1,8 @@ +import { type LambdaEvent, type Options as LambdaLocalOptions } from 'lambda-local'; +export type WorkerData = LambdaLocalOptions & { + entryFilePath: string; +}; +export interface WorkerMessage extends LambdaEvent { + streamPort?: number; +} +//# sourceMappingURL=worker.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/runtimes/js/worker.d.ts.map b/dist/lib/functions/runtimes/js/worker.d.ts.map new file mode 100644 index 00000000000..a3a12366651 --- /dev/null +++ b/dist/lib/functions/runtimes/js/worker.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"worker.d.ts","sourceRoot":"","sources":["../../../../../src/lib/functions/runtimes/js/worker.ts"],"names":[],"mappings":"AAKA,OAAoB,EAAE,KAAK,WAAW,EAAE,KAAK,OAAO,IAAI,kBAAkB,EAAE,MAAM,cAAc,CAAA;AAGhG,MAAM,MAAM,UAAU,GAAG,kBAAkB,GAAG;IAAE,aAAa,EAAE,MAAM,CAAA;CAAE,CAAA;AAEvE,MAAM,WAAW,aAAc,SAAQ,WAAW;IAChD,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB"} \ No newline at end of file diff --git a/dist/lib/functions/runtimes/js/worker.js b/dist/lib/functions/runtimes/js/worker.js new file mode 100644 index 00000000000..c37d42797e2 --- /dev/null +++ b/dist/lib/functions/runtimes/js/worker.js @@ -0,0 +1,64 @@ +import { createServer } from 'net'; +import process from 'process'; +import { isMainThread, workerData, parentPort } from 'worker_threads'; +import { isStream } from 'is-stream'; +import lambdaLocal from 'lambda-local'; +import sourceMapSupport from 'source-map-support'; +if (isMainThread) { + throw new Error(`Do not import "${import.meta.url}" in the main thread.`); +} +sourceMapSupport.install(); +lambdaLocal.getLogger().level = 'alert'; +const { clientContext, entryFilePath, environment = {}, event, timeoutMs } = workerData; +// Injecting into the environment any properties passed in by the parent. +for (const key in environment) { + process.env[key] = environment[key]; +} +// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment +const lambdaFunc = await import(entryFilePath); +const lambdaEvent = await lambdaLocal.execute({ + clientContext, + event, + lambdaFunc, + region: 'dev', + timeoutMs, + verboseLevel: 3, +}); +let streamPort = null; +// When the result body is a StreamResponse +// we open up a http server that proxies back to the main thread. +// TODO(serhalp): Improve `LambdaEvent` type. It sure would be nice to keep it simple as it +// is now, but technically this is an arbitrary type from the user function return... +// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition +if (lambdaEvent != null && isStream(lambdaEvent.body)) { + const { body } = lambdaEvent; + delete lambdaEvent.body; + await new Promise((resolve, reject) => { + const server = createServer((socket) => { + body.pipe(socket).on('end', () => server.close()); + }); + server.on('error', (error) => { + reject(error); + }); + server.listen({ port: 0, host: 'localhost' }, () => { + const address = server.address(); + if (address == null || typeof address !== 'object') { + throw new Error('Expected server.address() to return an object'); + } + streamPort = address.port; + resolve(undefined); + }); + }); +} +// See TODO above. +// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition +if (lambdaEvent == null) { + parentPort?.postMessage(lambdaEvent); +} +else { + // Looks like some sort of eslint bug...? It thinks `streamPort` can't be null here + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition + const message = { ...lambdaEvent, ...(streamPort != null ? { streamPort } : {}) }; + parentPort?.postMessage(message); +} +//# sourceMappingURL=worker.js.map \ No newline at end of file diff --git a/dist/lib/functions/runtimes/js/worker.js.map b/dist/lib/functions/runtimes/js/worker.js.map new file mode 100644 index 00000000000..dbbc00f3f45 --- /dev/null +++ b/dist/lib/functions/runtimes/js/worker.js.map @@ -0,0 +1 @@ +{"version":3,"file":"worker.js","sourceRoot":"","sources":["../../../../../src/lib/functions/runtimes/js/worker.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/functions/runtimes/rust/index.d.ts b/dist/lib/functions/runtimes/rust/index.d.ts new file mode 100644 index 00000000000..39faf7eada8 --- /dev/null +++ b/dist/lib/functions/runtimes/rust/index.d.ts @@ -0,0 +1,11 @@ +import type { LambdaEvent } from 'lambda-local'; +import type { BaseBuildResult, BuildFunction, GetBuildFunctionOpts, InvokeFunction, OnRegisterFunction } from '../index.js'; +export declare const name = "rs"; +export type RustBuildResult = BaseBuildResult & { + binaryPath: string; +}; +export type RustInvokeFunctionResult = LambdaEvent; +export declare const getBuildFunction: ({ func, }: GetBuildFunctionOpts) => Promise>; +export declare const invokeFunction: InvokeFunction; +export declare const onRegister: OnRegisterFunction; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/runtimes/rust/index.d.ts.map b/dist/lib/functions/runtimes/rust/index.d.ts.map new file mode 100644 index 00000000000..7c10901f475 --- /dev/null +++ b/dist/lib/functions/runtimes/rust/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../src/lib/functions/runtimes/rust/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAG/C,OAAO,KAAK,EACV,eAAe,EACf,aAAa,EACb,oBAAoB,EACpB,cAAc,EACd,kBAAkB,EACnB,MAAM,aAAa,CAAA;AASpB,eAAO,MAAM,IAAI,OAAO,CAAA;AAExB,MAAM,MAAM,eAAe,GAAG,eAAe,GAAG;IAC9C,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG,WAAW,CAAA;AAoBlD,eAAO,MAAM,gBAAgB,GAAI,WAE9B,oBAAoB,CAAC,eAAe,CAAC,KAAG,OAAO,CAAC,aAAa,CAAC,eAAe,CAAC,CACnC,CAAA;AAkB9C,eAAO,MAAM,cAAc,EAAE,cAAc,CAAC,eAAe,CA2B1D,CAAA;AAED,eAAO,MAAM,UAAU,EAAE,kBAAkB,CAAC,eAAe,CAI1D,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/runtimes/rust/index.js b/dist/lib/functions/runtimes/rust/index.js new file mode 100644 index 00000000000..bf861d7b2ba --- /dev/null +++ b/dist/lib/functions/runtimes/rust/index.js @@ -0,0 +1,72 @@ +import { readFile } from 'fs/promises'; +import { dirname, extname, join, resolve } from 'path'; +import { platform } from 'process'; +import { findUp } from 'find-up'; +import toml from 'toml'; +import execa from '../../../../utils/execa.js'; +import { SERVE_FUNCTIONS_FOLDER } from '../../../../utils/functions/functions.js'; +import { getPathInProject } from '../../../settings.js'; +import { runFunctionsProxy } from '../../local-proxy.js'; +const isWindows = platform === 'win32'; +export const name = 'rs'; +const build = async ({ func }) => { + const functionDirectory = dirname(func.mainFile); + const cacheDirectory = resolve(getPathInProject([SERVE_FUNCTIONS_FOLDER])); + const targetDirectory = join(cacheDirectory, func.name); + const crateName = await getCrateName(functionDirectory); + const binaryName = `${crateName}${isWindows ? '.exe' : ''}`; + const binaryPath = join(targetDirectory, 'debug', binaryName); + await execa('cargo', ['build', '--target-dir', targetDirectory], { + cwd: functionDirectory, + }); + return { + binaryPath, + srcFiles: [functionDirectory], + }; +}; +export const getBuildFunction = ({ func, }) => Promise.resolve(async () => build({ func })); +const getCrateName = async (cwd) => { + const manifestPath = await findUp('Cargo.toml', { cwd, type: 'file' }); + if (!manifestPath) { + throw new Error('Cargo.toml not found'); + } + const parsedManifest = toml.parse(await readFile(manifestPath, 'utf-8')); + // TODO(serhalp): Also validate `.package.name`? + if (parsedManifest == null || typeof parsedManifest !== 'object' || !('package' in parsedManifest)) { + throw new Error('Cargo.toml is missing or invalid'); + } + const { package: CargoPackage } = parsedManifest; + return CargoPackage.name; +}; +export const invokeFunction = async ({ context, event, func, timeout }) => { + if (func.buildData == null) { + throw new Error('Cannot invoke a function that has not been built'); + } + const { stdout } = await runFunctionsProxy({ + binaryPath: func.buildData.binaryPath, + context, + directory: dirname(func.mainFile), + event, + name: func.name, + timeout, + }); + try { + const { body, headers, multiValueHeaders, statusCode } = JSON.parse(stdout); + return { + body, + headers, + multiValueHeaders, + statusCode, + }; + } + catch { + return { + statusCode: 500, + }; + } +}; +export const onRegister = (func) => { + const isSource = extname(func.mainFile) === '.rs'; + return isSource ? func : null; +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/lib/functions/runtimes/rust/index.js.map b/dist/lib/functions/runtimes/rust/index.js.map new file mode 100644 index 00000000000..bbb699feb89 --- /dev/null +++ b/dist/lib/functions/runtimes/rust/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/lib/functions/runtimes/rust/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/functions/scheduled.d.ts b/dist/lib/functions/scheduled.d.ts new file mode 100644 index 00000000000..ece78bb14e5 --- /dev/null +++ b/dist/lib/functions/scheduled.d.ts @@ -0,0 +1,21 @@ +import type { IncomingHttpHeaders } from 'node:http'; +import express from 'express'; +import type { LambdaEvent } from 'lambda-local'; +import type { InvocationError } from './netlify-function.js'; +export declare const buildHelpResponse: ({ error, headers, path, result, }: { + error: null | Error | InvocationError; + headers: IncomingHttpHeaders; + path: string; + result: null | LambdaEvent; +}) => { + contentType: string; + message: string; + statusCode: number; +}; +export declare const handleScheduledFunction: ({ error, request, response, result, }: { + error: null | Error | InvocationError; + request: express.Request; + response: express.Response; + result: null | LambdaEvent; +}) => void; +//# sourceMappingURL=scheduled.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/scheduled.d.ts.map b/dist/lib/functions/scheduled.d.ts.map new file mode 100644 index 00000000000..98b0b8d1798 --- /dev/null +++ b/dist/lib/functions/scheduled.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"scheduled.d.ts","sourceRoot":"","sources":["../../../src/lib/functions/scheduled.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAA;AAGpD,OAAO,OAAO,MAAM,SAAS,CAAA;AAC7B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAK/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAI5D,eAAO,MAAM,iBAAiB,GAAI,mCAK/B;IACD,KAAK,EAAE,IAAI,GAAG,KAAK,GAAG,eAAe,CAAA;IACrC,OAAO,EAAE,mBAAmB,CAAA;IAC5B,IAAI,EAAE,MAAM,CAAA;IACZ,MAAM,EAAE,IAAI,GAAG,WAAW,CAAA;CAC3B,KAAG;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CA2E7D,CAAA;AAED,eAAO,MAAM,uBAAuB,GAAI,uCAKrC;IACD,KAAK,EAAE,IAAI,GAAG,KAAK,GAAG,eAAe,CAAA;IACrC,OAAO,EAAE,OAAO,CAAC,OAAO,CAAA;IACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAA;IAC1B,MAAM,EAAE,IAAI,GAAG,WAAW,CAAA;CAC3B,KAAG,IAWH,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/scheduled.js b/dist/lib/functions/scheduled.js new file mode 100644 index 00000000000..2b9c82a23a4 --- /dev/null +++ b/dist/lib/functions/scheduled.js @@ -0,0 +1,77 @@ +import AnsiToHtml from 'ansi-to-html'; +import { CLOCKWORK_USERAGENT } from '../../utils/functions/index.js'; +import { formatLambdaError } from './utils.js'; +const ansiToHtml = new AnsiToHtml(); +export const buildHelpResponse = ({ error, headers, path, result, }) => { + const acceptsHtml = headers.accept?.includes('text/html') ?? false; + const paragraph = (text) => { + text = text.trim(); + if (acceptsHtml) { + return ansiToHtml.toHtml(`

${text}

`); + } + text = text + .replace(/
/gm, '```\n')
+            .replace(/<\/code><\/pre>/gm, '\n```')
+            .replace(//gm, '`')
+            .replace(/<\/code>/gm, '`');
+        return `${text}\n\n`;
+    };
+    const isSimulatedRequest = headers['user-agent'] === CLOCKWORK_USERAGENT;
+    let message = '';
+    if (!isSimulatedRequest) {
+        message += paragraph(`
+You performed an HTTP request to ${path}, which is a scheduled function.
+You can do this to test your functions locally, but it won't work in production.
+    `);
+    }
+    if (error) {
+        message += paragraph(`
+There was an error during execution of your scheduled function:
+
+
${formatLambdaError(error)}
`); + } + if (result) { + // lambda emulator adds level field, which isn't user-provided + const { level, ...returnValue } = { ...result }; + const { statusCode } = returnValue; + if (statusCode != null && statusCode >= 500) { + message += paragraph(` +Your function returned a status code of ${statusCode.toString()}. +At the moment, Netlify does nothing about that. In the future, there might be a retry mechanism based on this. +`); + } + const allowedKeys = new Set(['statusCode']); + const returnedKeys = Object.keys(returnValue); + const ignoredKeys = returnedKeys.filter((key) => !allowedKeys.has(key)); + if (ignoredKeys.length !== 0) { + message += paragraph(`Your function returned ${ignoredKeys + .map((key) => `${key}`) + .join(', ')}. Is this an accident? It won't be interpreted by Netlify.`); + } + } + const statusCode = error ? 500 : 200; + return acceptsHtml + ? { + statusCode, + contentType: 'text/html', + message: `\n + ${message}`, + } + : { + statusCode, + contentType: 'text/plain', + message, + }; +}; +export const handleScheduledFunction = ({ error, request, response, result, }) => { + const { contentType, message, statusCode } = buildHelpResponse({ + error, + headers: request.headers, + path: request.path, + result, + }); + response.status(statusCode); + response.set('Content-Type', contentType); + response.send(message); +}; +//# sourceMappingURL=scheduled.js.map \ No newline at end of file diff --git a/dist/lib/functions/scheduled.js.map b/dist/lib/functions/scheduled.js.map new file mode 100644 index 00000000000..8259048fa3a --- /dev/null +++ b/dist/lib/functions/scheduled.js.map @@ -0,0 +1 @@ +{"version":3,"file":"scheduled.js","sourceRoot":"","sources":["../../../src/lib/functions/scheduled.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/functions/server.d.ts b/dist/lib/functions/server.d.ts new file mode 100644 index 00000000000..e2e656db6cf --- /dev/null +++ b/dist/lib/functions/server.d.ts @@ -0,0 +1,38 @@ +import { type RequestHandler } from 'express'; +import type BaseCommand from '../../commands/base-command.js'; +import type { NetlifySite } from '../../commands/types.js'; +import { type NormalizedCachedConfigConfig } from '../../utils/command-helpers.js'; +import type { BlobsContextWithEdgeAccess } from '../blobs/blobs.js'; +import type { CLIState, ServerSettings, SiteInfo } from '../../utils/types.js'; +import { FunctionsRegistry } from './registry.js'; +export declare const createHandler: (options: GetFunctionsServerOptions) => RequestHandler; +interface GetFunctionsServerOptions { + functionsRegistry: FunctionsRegistry; + siteUrl: string; + siteInfo?: SiteInfo; + accountId?: string | undefined; + geoCountry: string; + offline: boolean; + state: CLIState; + config: NormalizedCachedConfigConfig; + geolocationMode: 'cache' | 'update' | 'mock'; +} +export declare const startFunctionsServer: (options: { + blobsContext: BlobsContextWithEdgeAccess; + command: BaseCommand; + config: NormalizedCachedConfigConfig; + capabilities: { + backgroundFunctions?: boolean; + }; + debug: boolean; + loadDistFunctions?: boolean; + settings: Pick; + site: NetlifySite; + siteInfo: SiteInfo; + timeouts: { + backgroundFunctions: number; + syncFunctions: number; + }; +} & Omit) => Promise; +export {}; +//# sourceMappingURL=server.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/server.d.ts.map b/dist/lib/functions/server.d.ts.map new file mode 100644 index 00000000000..ebe5c862be2 --- /dev/null +++ b/dist/lib/functions/server.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../../src/lib/functions/server.ts"],"names":[],"mappings":"AAKA,OAAgB,EAAgB,KAAK,cAAc,EAAE,MAAM,SAAS,CAAA;AAIpE,OAAO,KAAK,WAAW,MAAM,gCAAgC,CAAA;AAC7D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAC1D,OAAO,EAAiB,KAAK,4BAA4B,EAAO,MAAM,gCAAgC,CAAA;AAUtG,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAA;AAGnE,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAI9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAA;AAsDjD,eAAO,MAAM,aAAa,GAAa,SAAS,yBAAyB,KAAG,cAiL3E,CAAA;AAED,UAAU,yBAAyB;IACjC,iBAAiB,EAAE,iBAAiB,CAAA;IACpC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,UAAU,EAAE,MAAM,CAAA;IAClB,OAAO,EAAE,OAAO,CAAA;IAChB,KAAK,EAAE,QAAQ,CAAA;IACf,MAAM,EAAE,4BAA4B,CAAA;IACpC,eAAe,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;CAC7C;AA4BD,eAAO,MAAM,oBAAoB,GAC/B,SAAS;IACP,YAAY,EAAE,0BAA0B,CAAA;IACxC,OAAO,EAAE,WAAW,CAAA;IACpB,MAAM,EAAE,4BAA4B,CAAA;IACpC,YAAY,EAAE;QACZ,mBAAmB,CAAC,EAAE,OAAO,CAAA;KAC9B,CAAA;IACD,KAAK,EAAE,OAAO,CAAA;IACd,iBAAiB,CAAC,EAAE,OAAO,CAAA;IAE3B,QAAQ,EAAE,IAAI,CAAC,cAAc,EAAE,WAAW,GAAG,eAAe,CAAC,CAAA;IAC7D,IAAI,EAAE,WAAW,CAAA;IACjB,QAAQ,EAAE,QAAQ,CAAA;IAClB,QAAQ,EAAE;QAAE,mBAAmB,EAAE,MAAM,CAAC;QAAC,aAAa,EAAE,MAAM,CAAA;KAAE,CAAA;CACjE,GAAG,IAAI,CAAC,yBAAyB,EAAE,mBAAmB,CAAC,KACvD,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAoFvC,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/server.js b/dist/lib/functions/server.js new file mode 100644 index 00000000000..dd4b7a0c9d4 --- /dev/null +++ b/dist/lib/functions/server.js @@ -0,0 +1,293 @@ +import { Buffer } from 'buffer'; +import { promises as fs } from 'fs'; +import path from 'path'; +import express from 'express'; +import expressLogging from 'express-logging'; +import { jwtDecode } from 'jwt-decode'; +import { NETLIFYDEVLOG, log } from '../../utils/command-helpers.js'; +import { UNLINKED_SITE_MOCK_ID } from '../../utils/dev.js'; +import { isFeatureFlagEnabled } from '../../utils/feature-flags.js'; +import { CLOCKWORK_USERAGENT, getFunctionsDistPath, getFunctionsServePath, getInternalFunctionsDir, } from '../../utils/functions/index.js'; +import { NFFunctionName, NFFunctionRoute } from '../../utils/headers.js'; +import { headers as efHeaders } from '../edge-functions/headers.js'; +import { getGeoLocation } from '../geo-location.js'; +import { handleBackgroundFunction, handleBackgroundFunctionResult } from './background.js'; +import { createFormSubmissionHandler } from './form-submissions-handler.js'; +import { FunctionsRegistry } from './registry.js'; +import { handleScheduledFunction } from './scheduled.js'; +import { handleSynchronousFunction } from './synchronous.js'; +import { shouldBase64Encode } from './utils.js'; +const buildClientContext = function (headers) { + // inject a client context based on auth header, ported over from netlify-lambda (https://github.com/netlify/netlify-lambda/pull/57) + if (!headers.authorization) + return; + const parts = headers.authorization.split(' '); + if (parts.length !== 2 || parts[0] !== 'Bearer') + return; + const identity = { + url: 'https://netlify-dev-locally-emulated-identity.netlify.app/.netlify/identity', + token: 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzb3VyY2UiOiJuZXRsaWZ5IGRldiIsInRlc3REYXRhIjoiTkVUTElGWV9ERVZfTE9DQUxMWV9FTVVMQVRFRF9JREVOVElUWSJ9.2eSDqUOZAOBsx39FHFePjYj12k0LrxldvGnlvDu3GMI', + // you can decode this with https://jwt.io/ + // just says + // { + // "source": "netlify dev", + // "testData": "NETLIFY_DEV_LOCALLY_EMULATED_IDENTITY" + // } + }; + try { + // This data is available on both the context root and under custom.netlify for retro-compatibility. + // In the future it will only be available in custom.netlify. + const user = jwtDecode(parts[1]); + const netlifyContext = JSON.stringify({ + identity, + user, + }); + return { + identity, + user, + custom: { + netlify: Buffer.from(netlifyContext).toString('base64'), + }, + }; + } + catch { + // Ignore errors - bearer token is not a JWT, probably not intended for us + } +}; +const hasBody = (req) => +// copied from is-type package +(req.header('transfer-encoding') !== undefined || !Number.isNaN(Number(req.header('content-length')))) && + // we expect a string or a buffer, because we use the two bodyParsers(text, raw) from express + (typeof req.body === 'string' || Buffer.isBuffer(req.body)); +export const createHandler = function (options) { + const { functionsRegistry } = options; + return async function handler(request, response) { + // If these headers are set, it means we've already matched a function and we + // can just grab its name directly. We delete the header from the request + // because we don't want to expose it to user code. + let functionName = request.header(NFFunctionName); + delete request.headers[NFFunctionName]; + const functionRoute = request.header(NFFunctionRoute); + delete request.headers[NFFunctionRoute]; + // If there's still no function found, we check the functionsRegistry again. + // This is needed for the functions:serve command, where the dev server that normally does the matching doesn't run. + // It also matches the default URL (.netlify/functions/builders) + if (!functionName) { + const match = await functionsRegistry.getFunctionForURLPath(request.url, request.method, + // we're pretending there's no static file at the same URL. + // This is wrong, but in local dev we already did the matching + // in a downstream server where we had access to the file system, so this never hits. + () => Promise.resolve(false)); + functionName = match?.func?.name; + } + const func = functionsRegistry.get(functionName ?? ''); + if (func === undefined) { + response.statusCode = 404; + response.end('Function not found...'); + return; + } + // Technically it follows from `func.hasValidName()` that `functionName != null`, but TS doesn't know that. + if (!func.hasValidName() || functionName == null) { + response.statusCode = 400; + response.end('Function name should consist only of alphanumeric characters, hyphen & underscores.'); + return; + } + const isBase64Encoded = shouldBase64Encode(request.header('content-type')); + let body; + if (hasBody(request)) { + body = request.body.toString(isBase64Encoded ? 'base64' : 'utf8'); + } + let remoteAddress = request.header('x-forwarded-for') || request.connection.remoteAddress || ''; + remoteAddress = + remoteAddress + .split(remoteAddress.includes('.') ? ':' : ',') + .pop() + ?.trim() ?? ''; + const requestPath = request.header('x-netlify-original-pathname') ?? request.path; + delete request.headers['x-netlify-original-pathname']; + let requestQuery = request.query; + if (request.header('x-netlify-original-search')) { + const newRequestQuery = {}; + const searchParams = new URLSearchParams(request.header('x-netlify-original-search')); + for (const key of searchParams.keys()) { + newRequestQuery[key] = searchParams.getAll(key); + } + requestQuery = newRequestQuery; + delete request.headers['x-netlify-original-search']; + } + const queryParamsAsMultiValue = Object.entries(requestQuery).reduce((prev, [key, value]) => ({ ...prev, [key]: Array.isArray(value) ? value : [value] }), {}); + const geoLocation = await getGeoLocation({ ...options, mode: options.geolocationMode }); + const multiValueHeaders = Object.entries({ + ...request.headers, + 'client-ip': [remoteAddress], + 'x-nf-client-connection-ip': [remoteAddress], + 'x-nf-account-id': [options.accountId], + 'x-nf-site-id': [options.siteInfo?.id ?? UNLINKED_SITE_MOCK_ID], + [efHeaders.Geo]: Buffer.from(JSON.stringify(geoLocation)).toString('base64'), + }).reduce((prev, [key, value]) => ({ ...prev, [key]: Array.isArray(value) ? value : [value] }), {}); + const rawQuery = new URL(request.originalUrl, 'http://example.com').search.slice(1); + // TODO(serhalp): Update several tests to pass realistic `config` objects and remove nullish coalescing. + const protocol = options.config?.dev?.https ? 'https' : 'http'; + const hostname = request.get('host') || 'localhost'; + const url = new URL(requestPath, `${protocol}://${hostname}`); + url.search = rawQuery; + const rawUrl = url.toString(); + const event = { + path: requestPath, + httpMethod: request.method, + queryStringParameters: Object.entries(queryParamsAsMultiValue).reduce((prev, [key, value]) => ({ ...prev, [key]: value.join(', ') }), {}), + multiValueQueryStringParameters: queryParamsAsMultiValue, + headers: Object.entries(multiValueHeaders).reduce((prev, [key, value]) => ({ ...prev, [key]: value.join(', ') }), {}), + multiValueHeaders, + body, + isBase64Encoded, + rawUrl, + rawQuery, + route: functionRoute, + }; + const clientContext = buildClientContext(request.headers) || {}; + if (func.isBackground) { + handleBackgroundFunction(functionName, response); + // background functions do not receive a clientContext + const { error } = await func.invoke(event); + handleBackgroundFunctionResult(functionName, error); + } + else if (await func.isScheduled()) { + // In production, scheduled functions always receive POST requests, so we + // have to emulate that here, even if a user has triggered a GET request + // as part of their tests. If we don't do this, we'll hit problems when + // we send the invocation body in a request that can't have a body. + event.httpMethod = 'POST'; + const { error, result } = await func.invoke({ + ...event, + body: JSON.stringify({ + next_run: await func.getNextRun(), + }), + isBase64Encoded: false, + headers: { + ...event.headers, + 'user-agent': CLOCKWORK_USERAGENT, + 'X-NF-Event': 'schedule', + }, + }, clientContext); + handleScheduledFunction({ + error, + request, + response, + // When we handle the result of invoking a scheduled function, we'll warn + // people in case their function returned a body or headers, since those + // will have no practical effect in production. However, in v2 functions + // we don't currently have a good way of asserting whether the body we're + // seeing has been actually produced by user code or by the bootstrap, so + // we risk printing that warn unnecessarily, which causes more harm than + // good. Until we find a way of making this detection better, ignore the + // invocation result entirely for v2 functions. + result: func.runtimeAPIVersion === 1 ? result : {}, + }); + } + else { + const { error, result } = await func.invoke(event, clientContext); + // check for existence of metadata if this is a builder function + // @ts-expect-error(serhalp) -- Investigate. There doesn't appear to be such a thing as `metadata`? + if (/^\/.netlify\/(builders)/.test(request.path) && !result?.metadata?.builder_function) { + response.status(400).send({ + message: 'Function is not an on-demand builder. See https://ntl.fyi/create-builder for how to convert a function to a builder.', + }); + response.end(); + return; + } + await handleSynchronousFunction({ error, functionName: func.name, result, request, response }); + } + }; +}; +const getFunctionsServer = (options) => { + const { functionsRegistry, siteUrl } = options; + const app = express(); + const functionHandler = createHandler(options); + app.set('query parser', 'simple'); + app.use(express.text({ + limit: '6mb', + type: ['text/*', 'application/json'], + })); + app.use(express.raw({ limit: '6mb', type: '*/*' })); + app.use(createFormSubmissionHandler({ functionsRegistry, siteUrl })); + app.use(expressLogging(console, { + blacklist: ['/favicon.ico'], + })); + app.all('*', functionHandler); + return app; +}; +export const startFunctionsServer = async (options) => { + const { blobsContext, capabilities, command, config, debug, loadDistFunctions, settings, site, siteInfo, siteUrl, timeouts, } = options; + const internalFunctionsDir = await getInternalFunctionsDir({ base: site.root, packagePath: command.workspacePackage }); + const functionsDirectories = []; + let manifest; + // If the `loadDistFunctions` parameter is sent, the functions server will + // use the built functions created by zip-it-and-ship-it rather than building + // them from source. + if (loadDistFunctions) { + const distPath = await getFunctionsDistPath({ base: site.root, packagePath: command.workspacePackage }); + if (distPath) { + functionsDirectories.push(distPath); + // When using built functions, read the manifest file so that we can + // extract metadata such as routes and API version. + try { + const manifestPath = path.join(distPath, 'manifest.json'); + const data = await fs.readFile(manifestPath, 'utf8'); + manifest = JSON.parse(data); + } + catch { + // no-op + } + } + } + else { + // The order of the function directories matters. Rightmost directories take + // precedence. + const sourceDirectories = [ + internalFunctionsDir, + command.netlify.frameworksAPIPaths.functions.path, + settings.functions, + ].filter((x) => x != null); + functionsDirectories.push(...sourceDirectories); + } + try { + const functionsServePath = getFunctionsServePath({ base: site.root, packagePath: command.workspacePackage }); + await fs.rm(functionsServePath, { force: true, recursive: true }); + } + catch { + // no-op + } + if (functionsDirectories.length === 0) { + return; + } + const functionsRegistry = new FunctionsRegistry({ + blobsContext, + capabilities, + config, + debug, + frameworksAPIPaths: command.netlify.frameworksAPIPaths, + isConnected: Boolean(siteUrl), + logLambdaCompat: isFeatureFlagEnabled('cli_log_lambda_compat', siteInfo), + manifest, + // functions always need to be inside the packagePath if set inside a monorepo + projectRoot: command.workingDir, + settings, + timeouts, + }); + await functionsRegistry.scan(functionsDirectories); + const server = getFunctionsServer({ ...options, functionsRegistry }); + await startWebServer({ server, settings, debug }); + return functionsRegistry; +}; +const startWebServer = async ({ debug, server, settings, }) => { + await new Promise((resolve) => { + server.listen(settings.functionsPort, () => { + if (debug) { + log(`${NETLIFYDEVLOG} Functions server is listening on ${settings.functionsPort.toString()}`); + } + resolve(); + }); + }); +}; +//# sourceMappingURL=server.js.map \ No newline at end of file diff --git a/dist/lib/functions/server.js.map b/dist/lib/functions/server.js.map new file mode 100644 index 00000000000..646b044e595 --- /dev/null +++ b/dist/lib/functions/server.js.map @@ -0,0 +1 @@ +{"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/lib/functions/server.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/functions/synchronous.d.ts b/dist/lib/functions/synchronous.d.ts new file mode 100644 index 00000000000..bd2607bcf10 --- /dev/null +++ b/dist/lib/functions/synchronous.d.ts @@ -0,0 +1,11 @@ +import express from 'express'; +import type { LambdaEvent } from 'lambda-local'; +import type { InvocationError } from './netlify-function.js'; +export declare const handleSynchronousFunction: ({ error: invocationError, functionName, request, response, result, }: { + error: null | Error | InvocationError; + functionName: string; + request: express.Request; + response: express.Response; + result: null | LambdaEvent; +}) => Promise; +//# sourceMappingURL=synchronous.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/synchronous.d.ts.map b/dist/lib/functions/synchronous.d.ts.map new file mode 100644 index 00000000000..94eb3a79a93 --- /dev/null +++ b/dist/lib/functions/synchronous.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"synchronous.d.ts","sourceRoot":"","sources":["../../../src/lib/functions/synchronous.ts"],"names":[],"mappings":"AAGA,OAAO,OAAO,MAAM,SAAS,CAAA;AAE7B,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAM/C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAgB5D,eAAO,MAAM,yBAAyB,GAAmB,sEAMtD;IACD,KAAK,EAAE,IAAI,GAAG,KAAK,GAAG,eAAe,CAAA;IACrC,YAAY,EAAE,MAAM,CAAA;IACpB,OAAO,EAAE,OAAO,CAAC,OAAO,CAAA;IACxB,QAAQ,EAAE,OAAO,CAAC,QAAQ,CAAA;IAC1B,MAAM,EAAE,IAAI,GAAG,WAAW,CAAA;CAC3B,KAAG,OAAO,CAAC,IAAI,CA6Df,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/synchronous.js b/dist/lib/functions/synchronous.js new file mode 100644 index 00000000000..2c2654e6c41 --- /dev/null +++ b/dist/lib/functions/synchronous.js @@ -0,0 +1,132 @@ +import { Buffer } from 'buffer'; +import { inspect } from 'util'; +import { isReadableStream as baseIsReadableStream } from 'is-stream'; +import { chalk, logPadded, NETLIFYDEVERR } from '../../utils/command-helpers.js'; +import renderErrorTemplate from '../render-error-template.js'; +import { warnIfAwsSdkError } from './utils.js'; +// Annoyingly, `isReadableStream` refines to the `Readable` interface rather than the +// `ReadableStream` class. Refining to the class makes further refinements work as expected. +const isReadableStream = (value) => baseIsReadableStream(value); +const addHeaders = (headers, response) => { + if (!headers) { + return; + } + Object.entries(headers).forEach(([key, value]) => { + response.setHeader(key, value); + }); +}; +export const handleSynchronousFunction = async function ({ error: invocationError, functionName, request, response, result, }) { + if (invocationError) { + const error = getNormalizedError(invocationError); + logPadded(`${NETLIFYDEVERR} Function ${chalk.yellow(functionName)} has returned an error: ${error.errorMessage}\n${chalk.dim(error.stackTrace.join('\n'))}`); + await handleErr(invocationError, request, response); + return; + } + const { error } = validateLambdaResponse(result); + if (error) { + logPadded(`${NETLIFYDEVERR} ${error}`); + await handleErr(error, request, response); + return; + } + // This shouldn't happen (see `InvokeFunctionResult`), but due to type lossiness TS doesn't know this here. + if (result == null) { + logPadded(`${NETLIFYDEVERR} Unexpected empty function response`); + await handleErr('Unexpected empty function response', request, response); + return; + } + if (result.statusCode != null) { + response.statusCode = result.statusCode; + } + try { + addHeaders(result.headers, response); + addHeaders(result.multiValueHeaders, response); + } + catch (headersError) { + const wrappedHeadersError = headersError instanceof Error ? headersError : new Error(headersError?.toString()); + const normalizedError = getNormalizedError(wrappedHeadersError); + logPadded(`${NETLIFYDEVERR} Failed to set header in function ${chalk.yellow(functionName)}: ${normalizedError.errorMessage}`); + await handleErr(wrappedHeadersError, request, response); + return; + } + if (result.body) { + if (isReadableStream(result.body)) { + result.body.pipe(response); + return; + } + response.write(result.isBase64Encoded ? Buffer.from(result.body, 'base64') : result.body); + } + response.end(); +}; +/** + * Accepts an error generated by `lambda-local` or an instance of `Error` and + * returns a normalized error that we can treat in the same way. + */ +const getNormalizedError = (error) => { + if (error instanceof Error) { + const normalizedError = { + errorMessage: error.message, + errorType: error.name, + stackTrace: error.stack ? error.stack.split('\n') : [], + }; + if ('code' in error && error.code === 'ERR_REQUIRE_ESM') { + return { + ...normalizedError, + errorMessage: 'a CommonJS file cannot import ES modules. Consider switching your function to ES modules. For more information, refer to https://ntl.fyi/functions-runtime.', + }; + } + return normalizedError; + } + // Formatting stack trace lines in the same way that Node.js formats native errors. + const stackTrace = error.stackTrace.map((line) => ` at ${line}`); + return { + errorType: error.errorType, + errorMessage: error.errorMessage, + stackTrace, + }; +}; +const formatLambdaLocalError = (rawError, acceptsHTML) => { + const error = getNormalizedError(rawError); + if (acceptsHTML) { + return JSON.stringify({ + ...error, + stackTrace: undefined, + trace: error.stackTrace, + }); + } + return `${error.errorType}: ${error.errorMessage}\n ${error.stackTrace.join('\n')}`; +}; +const handleErr = async (err, request, response) => { + warnIfAwsSdkError({ error: err }); + const acceptsHtml = request.headers.accept?.includes('text/html') ?? false; + const errorString = typeof err === 'string' ? err : formatLambdaLocalError(err, acceptsHtml); + response.statusCode = 500; + if (acceptsHtml) { + response.setHeader('Content-Type', 'text/html'); + response.end(await renderErrorTemplate(errorString, '../../src/lib/templates/function-error.html', 'function')); + } + else { + response.end(errorString); + } +}; +const validateLambdaResponse = (lambdaResponse) => { + if (lambdaResponse === undefined) { + return { error: 'lambda response was undefined. check your function code again' }; + } + if (lambdaResponse === null) { + return { + error: 'no lambda response. check your function code again. make sure to return a promise or use the callback.', + }; + } + if (!Number(lambdaResponse.statusCode)) { + return { + error: `Your function response must have a numerical statusCode. You gave: ${inspect(lambdaResponse.statusCode)}`, + }; + } + if (lambdaResponse.body && typeof lambdaResponse.body !== 'string' && !isReadableStream(lambdaResponse.body)) { + return { + error: `Your function response must have a string or a stream body. You gave: ${inspect(lambdaResponse.body)}`, + }; + } + return {}; +}; +//# sourceMappingURL=synchronous.js.map \ No newline at end of file diff --git a/dist/lib/functions/synchronous.js.map b/dist/lib/functions/synchronous.js.map new file mode 100644 index 00000000000..f620b076db2 --- /dev/null +++ b/dist/lib/functions/synchronous.js.map @@ -0,0 +1 @@ +{"version":3,"file":"synchronous.js","sourceRoot":"","sources":["../../../src/lib/functions/synchronous.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/functions/utils.d.ts b/dist/lib/functions/utils.d.ts new file mode 100644 index 00000000000..aee589dec97 --- /dev/null +++ b/dist/lib/functions/utils.d.ts @@ -0,0 +1,8 @@ +import type { InvocationError } from './netlify-function.js'; +export declare const warnIfAwsSdkError: ({ error }: { + error: Error | InvocationError | string; +}) => void; +export declare const formatLambdaError: (err: Error | InvocationError) => string; +export declare const shouldBase64Encode: (contentType?: string) => boolean; +export declare const styleFunctionName: (name: string) => string; +//# sourceMappingURL=utils.d.ts.map \ No newline at end of file diff --git a/dist/lib/functions/utils.d.ts.map b/dist/lib/functions/utils.d.ts.map new file mode 100644 index 00000000000..e15f5e36797 --- /dev/null +++ b/dist/lib/functions/utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/lib/functions/utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAE5D,eAAO,MAAM,iBAAiB,GAAI,WAAW;IAAE,KAAK,EAAE,KAAK,GAAG,eAAe,GAAG,MAAM,CAAA;CAAE,KAAG,IAU1F,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,KAAK,KAAK,GAAG,eAAe,KAAG,MAG9D,CAAA;AAaH,eAAO,MAAM,kBAAkB,GAAa,cAAc,MAAM,KAAG,OAsBlE,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,MAAM,MAAM,KAAG,MAA6B,CAAA"} \ No newline at end of file diff --git a/dist/lib/functions/utils.js b/dist/lib/functions/utils.js new file mode 100644 index 00000000000..20890aefd4e --- /dev/null +++ b/dist/lib/functions/utils.js @@ -0,0 +1,42 @@ +import { chalk, warn } from '../../utils/command-helpers.js'; +import { MISSING_AWS_SDK_WARNING } from '../log.js'; +export const warnIfAwsSdkError = ({ error }) => { + const isAwsSdkError = typeof error === 'object' && + 'errorMessage' in error && + typeof error.errorMessage === 'string' && + error.errorMessage.includes("Cannot find module 'aws-sdk'"); + if (isAwsSdkError) { + warn(MISSING_AWS_SDK_WARNING); + } +}; +export const formatLambdaError = (err) => chalk.red(`${'errorType' in err ? err.errorType : 'Error'}: ${'errorMessage' in err ? err.errorMessage : err.message}`); +// should be equivalent to https://github.com/netlify/proxy/blob/main/pkg/functions/request.go#L105 +const exceptionsList = new Set([ + 'application/csp-report', + 'application/graphql', + 'application/json', + 'application/javascript', + 'application/x-www-form-urlencoded', + 'application/x-ndjson', + 'application/xml', +]); +export const shouldBase64Encode = function (contentType) { + if (!contentType) { + return true; + } + const [contentTypeSegment] = contentType.split(';'); + contentType = contentTypeSegment; + contentType = contentType.toLowerCase(); + if (contentType.startsWith('text/')) { + return false; + } + if (contentType.endsWith('+json') || contentType.endsWith('+xml')) { + return false; + } + if (exceptionsList.has(contentType)) { + return false; + } + return true; +}; +export const styleFunctionName = (name) => chalk.magenta(name); +//# sourceMappingURL=utils.js.map \ No newline at end of file diff --git a/dist/lib/functions/utils.js.map b/dist/lib/functions/utils.js.map new file mode 100644 index 00000000000..35cd1c2c686 --- /dev/null +++ b/dist/lib/functions/utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/lib/functions/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAA;AAC5D,OAAO,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAA;AAInD,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,EAAE,KAAK,EAA+C,EAAQ,EAAE;IAChG,MAAM,aAAa,GACjB,OAAO,KAAK,KAAK,QAAQ;QACzB,cAAc,IAAI,KAAK;QACvB,OAAO,KAAK,CAAC,YAAY,KAAK,QAAQ;QACtC,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,8BAA8B,CAAC,CAAA;IAE7D,IAAI,aAAa,EAAE,CAAC;QAClB,IAAI,CAAC,uBAAuB,CAAC,CAAA;IAC/B,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,GAA4B,EAAU,EAAE,CACxE,KAAK,CAAC,GAAG,CACP,GAAG,WAAW,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,KAAK,cAAc,IAAI,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,EAAE,CAC7G,CAAA;AAEH,mGAAmG;AACnG,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC;IAC7B,wBAAwB;IACxB,qBAAqB;IACrB,kBAAkB;IAClB,wBAAwB;IACxB,mCAAmC;IACnC,sBAAsB;IACtB,iBAAiB;CAClB,CAAC,CAAA;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG,UAAU,WAAoB;IAC9D,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,OAAO,IAAI,CAAA;IACb,CAAC;IAED,MAAM,CAAC,kBAAkB,CAAC,GAAG,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IACnD,WAAW,GAAG,kBAAkB,CAAA;IAChC,WAAW,GAAG,WAAW,CAAC,WAAW,EAAE,CAAA;IAEvC,IAAI,WAAW,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;QACpC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,WAAW,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;QAClE,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,cAAc,CAAC,GAAG,CAAC,WAAW,CAAC,EAAE,CAAC;QACpC,OAAO,KAAK,CAAA;IACd,CAAC;IAED,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/lib/geo-location.d.ts b/dist/lib/geo-location.d.ts new file mode 100644 index 00000000000..e398b0b6ce4 --- /dev/null +++ b/dist/lib/geo-location.d.ts @@ -0,0 +1,31 @@ +export type Geolocation = { + city: string; + country: { + code: string; + name: string; + }; + subdivision: { + code: string; + name: string; + }; + longitude: number; + latitude: number; + timezone: string; +}; +interface State { + get(key: string): unknown; + set(key: string, value: unknown): void; +} +export declare const mockLocation: Geolocation; +/** + * Returns geolocation data from a remote API, the local cache, or a mock location, depending on the + * specified mode. + */ +export declare const getGeoLocation: ({ geoCountry, mode, offline, state, }: { + mode: "cache" | "update" | "mock"; + geoCountry?: string | undefined; + offline?: boolean | undefined; + state: State; +}) => Promise; +export {}; +//# sourceMappingURL=geo-location.d.ts.map \ No newline at end of file diff --git a/dist/lib/geo-location.d.ts.map b/dist/lib/geo-location.d.ts.map new file mode 100644 index 00000000000..a6156f22871 --- /dev/null +++ b/dist/lib/geo-location.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"geo-location.d.ts","sourceRoot":"","sources":["../../src/lib/geo-location.ts"],"names":[],"mappings":"AAUA,MAAM,MAAM,WAAW,GAAG;IACxB,IAAI,EAAE,MAAM,CAAA;IACZ,OAAO,EAAE;QACP,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IACD,WAAW,EAAE;QACX,IAAI,EAAE,MAAM,CAAA;QACZ,IAAI,EAAE,MAAM,CAAA;KACb,CAAA;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,UAAU,KAAK;IACb,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;IACzB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAA;CACvC;AAED,eAAO,MAAM,YAAY,EAAE,WAO1B,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAU,uCAKlC;IACD,IAAI,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAA;IACjC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IAC7B,KAAK,EAAE,KAAK,CAAA;CACb,KAAG,OAAO,CAAC,WAAW,CAyDtB,CAAA"} \ No newline at end of file diff --git a/dist/lib/geo-location.js b/dist/lib/geo-location.js new file mode 100644 index 00000000000..42c1ca8c79a --- /dev/null +++ b/dist/lib/geo-location.js @@ -0,0 +1,84 @@ +import fetch from 'node-fetch'; +const API_URL = 'https://netlifind.netlify.app'; +const STATE_GEO_PROPERTY = 'geolocation'; +// 24 hours +const CACHE_TTL = 8.64e7; +// 10 seconds +const REQUEST_TIMEOUT = 1e4; +export const mockLocation = { + city: 'San Francisco', + country: { code: 'US', name: 'United States' }, + subdivision: { code: 'CA', name: 'California' }, + longitude: 0, + latitude: 0, + timezone: 'UTC', +}; +/** + * Returns geolocation data from a remote API, the local cache, or a mock location, depending on the + * specified mode. + */ +export const getGeoLocation = async ({ geoCountry, mode, offline = false, state, }) => { + const cacheObject = state.get(STATE_GEO_PROPERTY); + // If `--country` was used, we also set `--mode=mock`. + if (geoCountry) { + mode = 'mock'; + } + // If we have cached geolocation data and the `--geo` option is set to + // `cache`, let's try to use it. + // Or, if the country we're trying to mock is the same one as we have in the + // cache, let's use the cache instead of the mock. + if (cacheObject !== undefined && (mode === 'cache' || cacheObject.data.country.code === geoCountry)) { + const age = Date.now() - cacheObject.timestamp; + // Let's use the cached data if it's not older than the TTL. Also, if the + // `--offline` option was used, it's best to use the cached location than + // the mock one. + if (age < CACHE_TTL || offline) { + return cacheObject.data; + } + } + // If the `--geo` option is set to `mock`, we use the default mock location. + // If the `--offline` option was used, we can't talk to the API, so let's + // also use the mock location. Otherwise, use the country code passed in by + // the user. + if (mode === 'mock' || offline || geoCountry) { + if (geoCountry) { + return { + city: 'Mock City', + country: { code: geoCountry, name: 'Mock Country' }, + subdivision: { code: 'SD', name: 'Mock Subdivision' }, + longitude: 0, + latitude: 0, + timezone: 'UTC', + }; + } + return mockLocation; + } + // Trying to retrieve geolocation data from the API and caching it locally. + try { + const data = await getGeoLocationFromAPI(); + const newCacheObject = { + data, + timestamp: Date.now(), + }; + state.set(STATE_GEO_PROPERTY, newCacheObject); + return data; + } + catch { + // We couldn't get geolocation data from the API, so let's return the + // mock location. + return mockLocation; + } +}; +/** + * Returns geolocation data from a remote API. + */ +const getGeoLocationFromAPI = async () => { + const res = await fetch(API_URL, { + method: 'GET', + signal: AbortSignal.timeout(REQUEST_TIMEOUT), + }); + // @ts-expect-error TS(2339) - Property 'geo' does not exist on type 'unknown' + const { geo } = await res.json(); + return geo; +}; +//# sourceMappingURL=geo-location.js.map \ No newline at end of file diff --git a/dist/lib/geo-location.js.map b/dist/lib/geo-location.js.map new file mode 100644 index 00000000000..c6bab2c2ba2 --- /dev/null +++ b/dist/lib/geo-location.js.map @@ -0,0 +1 @@ +{"version":3,"file":"geo-location.js","sourceRoot":"","sources":["../../src/lib/geo-location.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/http-agent.d.ts b/dist/lib/http-agent.d.ts new file mode 100644 index 00000000000..6a05af1c3e2 --- /dev/null +++ b/dist/lib/http-agent.d.ts @@ -0,0 +1,22 @@ +import { HttpsProxyAgent } from 'https-proxy-agent'; +declare class HttpsProxyAgentWithCA extends HttpsProxyAgent { + constructor(opts: any); + callback(req: any, opts: any): any; +} +export declare const tryGetAgent: ({ certificateFile, httpProxy, }: { + httpProxy?: string | undefined; + certificateFile?: string | undefined; +}) => Promise<{ + error?: string | undefined; + warning?: string | undefined; + message?: string | undefined; +} | { + agent: HttpsProxyAgentWithCA; + response: unknown; +}>; +export declare const getAgent: ({ certificateFile, httpProxy }: { + certificateFile: any; + httpProxy: any; +}) => Promise; +export {}; +//# sourceMappingURL=http-agent.d.ts.map \ No newline at end of file diff --git a/dist/lib/http-agent.d.ts.map b/dist/lib/http-agent.d.ts.map new file mode 100644 index 00000000000..e5478a8785f --- /dev/null +++ b/dist/lib/http-agent.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"http-agent.d.ts","sourceRoot":"","sources":["../../src/lib/http-agent.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAQnD,cAAM,qBAAsB,SAAQ,eAAe;gBAErC,IAAI,KAAA;IAOhB,QAAQ,CAAC,GAAG,KAAA,EAAE,IAAI,KAAA;CAOnB;AAOD,eAAO,MAAM,WAAW,GAAU,iCAG/B;IACD,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,eAAe,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CACrC,KAAG,OAAO,CACP;IACE,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;CAC7B,GACD;IACE,KAAK,EAAE,qBAAqB,CAAA;IAC5B,QAAQ,EAAE,OAAO,CAAA;CAClB,CA4DJ,CAAA;AAGD,eAAO,MAAM,QAAQ,GAAU;;;CAA8B,iBAW5D,CAAA"} \ No newline at end of file diff --git a/dist/lib/http-agent.js b/dist/lib/http-agent.js new file mode 100644 index 00000000000..0e55d5a341c --- /dev/null +++ b/dist/lib/http-agent.js @@ -0,0 +1,96 @@ +import { readFile } from 'fs/promises'; +import { HttpsProxyAgent } from 'https-proxy-agent'; +import waitPort from 'wait-port'; +import { NETLIFYDEVERR, NETLIFYDEVWARN, exit, log } from '../utils/command-helpers.js'; +// https://github.com/TooTallNate/node-https-proxy-agent/issues/89 +// Maybe replace with https://github.com/delvedor/hpagent +// @ts-expect-error TS(2507) FIXME: Type 'typeof createHttpsProxyAgent' is not a const... Remove this comment to see the full error message +class HttpsProxyAgentWithCA extends HttpsProxyAgent { + // @ts-expect-error TS(7006) FIXME: Parameter 'opts' implicitly has an 'any' type. + constructor(opts) { + super(opts); + // @ts-expect-error TS(2339) FIXME: Property 'ca' does not exist on type 'HttpsProxyAg... Remove this comment to see the full error message + this.ca = opts.ca; + } + // @ts-expect-error TS(7006) FIXME: Parameter 'req' implicitly has an 'any' type. + callback(req, opts) { + return super.callback(req, { + ...opts, + // @ts-expect-error TS(2339) FIXME: Property 'ca' does not exist on type 'HttpsProxyAg... Remove this comment to see the full error message + ...(this.ca && { ca: this.ca }), + }); + } +} +const DEFAULT_HTTP_PORT = 80; +const DEFAULT_HTTPS_PORT = 443; +// 50 seconds +const AGENT_PORT_TIMEOUT = 50; +export const tryGetAgent = async ({ certificateFile, httpProxy, }) => { + if (!httpProxy) { + return {}; + } + let proxyUrl; + try { + proxyUrl = new URL(httpProxy); + } + catch { + return { error: `${httpProxy} is not a valid URL` }; + } + const scheme = proxyUrl.protocol.slice(0, -1); + if (!['http', 'https'].includes(scheme)) { + return { error: `${httpProxy} must have a scheme of http or https` }; + } + let port; + try { + port = await waitPort({ + port: Number.parseInt(proxyUrl.port) || (scheme === 'http' ? DEFAULT_HTTP_PORT : DEFAULT_HTTPS_PORT), + host: proxyUrl.hostname, + timeout: AGENT_PORT_TIMEOUT, + output: 'silent', + }); + } + catch (error) { + // unknown error + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + return { error: `${httpProxy} is not available.`, message: error.message }; + } + if (!port.open) { + // timeout error + return { error: `Could not connect to '${httpProxy}'` }; + } + let response = {}; + let certificate; + if (certificateFile) { + try { + certificate = await readFile(certificateFile); + } + catch (error) { + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + response = { warning: `Could not read certificate file '${certificateFile}'.`, message: error.message }; + } + } + const opts = { + port: proxyUrl.port, + host: proxyUrl.host, + hostname: proxyUrl.hostname, + protocol: proxyUrl.protocol, + ca: certificate, + }; + const agent = new HttpsProxyAgentWithCA(opts); + response = { ...response, agent }; + return response; +}; +// @ts-expect-error TS(7031) FIXME: Binding element 'certificateFile' implicitly has a... Remove this comment to see the full error message +export const getAgent = async ({ certificateFile, httpProxy }) => { + // @ts-expect-error TS(2339) FIXME: Property 'agent' does not exist on type '{ error?:... Remove this comment to see the full error message + const { agent, error, message, warning } = await tryGetAgent({ httpProxy, certificateFile }); + if (error) { + log(NETLIFYDEVERR, error, message || ''); + exit(1); + } + if (warning) { + log(NETLIFYDEVWARN, warning, message || ''); + } + return agent; +}; +//# sourceMappingURL=http-agent.js.map \ No newline at end of file diff --git a/dist/lib/http-agent.js.map b/dist/lib/http-agent.js.map new file mode 100644 index 00000000000..b9ac1ddf342 --- /dev/null +++ b/dist/lib/http-agent.js.map @@ -0,0 +1 @@ +{"version":3,"file":"http-agent.js","sourceRoot":"","sources":["../../src/lib/http-agent.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/images/proxy.d.ts b/dist/lib/images/proxy.d.ts new file mode 100644 index 00000000000..3bcc56268ae --- /dev/null +++ b/dist/lib/images/proxy.d.ts @@ -0,0 +1,30 @@ +import type { IncomingMessage } from 'http'; +import { type NormalizedCachedConfigConfig } from '../../utils/command-helpers.js'; +import type { ServerSettings } from '../../utils/types.d.ts'; +export declare const IMAGE_URL_PATTERN = "/.netlify/images"; +interface QueryParams { + w?: string; + width?: string; + h?: string; + height?: string; + q?: string; + quality?: string; + fm?: string; + fit?: string; + position?: string; +} +export declare const parseAllRemoteImages: (config: Pick) => { + errors: ErrorObject[]; + remotePatterns: RegExp[]; +}; +interface ErrorObject { + message: string; +} +export declare const isImageRequest: (req: IncomingMessage) => boolean; +export declare const transformImageParams: (query: QueryParams) => string; +export declare const initializeProxy: ({ config, settings, }: { + config: NormalizedCachedConfigConfig; + settings: ServerSettings; +}) => import("express-serve-static-core").Express; +export {}; +//# sourceMappingURL=proxy.d.ts.map \ No newline at end of file diff --git a/dist/lib/images/proxy.d.ts.map b/dist/lib/images/proxy.d.ts.map new file mode 100644 index 00000000000..1a34410658a --- /dev/null +++ b/dist/lib/images/proxy.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../../src/lib/images/proxy.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAK3C,OAAO,EAAsB,KAAK,4BAA4B,EAAE,MAAM,gCAAgC,CAAA;AAEtG,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAA;AAE5D,eAAO,MAAM,iBAAiB,qBAAqB,CAAA;AAEnD,UAAU,WAAW;IACnB,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,CAAC,CAAC,EAAE,MAAM,CAAA;IACV,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAYD,eAAO,MAAM,oBAAoB,GAAa,QAAQ,IAAI,CAAC,4BAA4B,EAAE,QAAQ,CAAC,KAAG;IACnG,MAAM,EAAE,WAAW,EAAE,CAAA;IACrB,cAAc,EAAE,MAAM,EAAE,CAAA;CAsBzB,CAAA;AAED,UAAU,WAAW;IACnB,OAAO,EAAE,MAAM,CAAA;CAChB;AA0BD,eAAO,MAAM,cAAc,GAAa,KAAK,eAAe,KAAG,OAE9D,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAa,OAAO,WAAW,KAAG,MAyBlE,CAAA;AAED,eAAO,MAAM,eAAe,GAAa,uBAGtC;IACD,MAAM,EAAE,4BAA4B,CAAA;IACpC,QAAQ,EAAE,cAAc,CAAA;CACzB,gDA2DA,CAAA"} \ No newline at end of file diff --git a/dist/lib/images/proxy.js b/dist/lib/images/proxy.js new file mode 100644 index 00000000000..2d08546672c --- /dev/null +++ b/dist/lib/images/proxy.js @@ -0,0 +1,117 @@ +import express from 'express'; +import { createIPX, ipxFSStorage, ipxHttpStorage, createIPXNodeServer } from 'ipx'; +import { log, NETLIFYDEVERR } from '../../utils/command-helpers.js'; +import { getProxyUrl } from '../../utils/proxy.js'; +export const IMAGE_URL_PATTERN = '/.netlify/images'; +export const parseAllRemoteImages = function (config) { + const remotePatterns = []; + const errors = []; + const remoteImages = config?.images?.remote_images; + if (!remoteImages) { + return { errors, remotePatterns }; + } + for (const patternString of remoteImages) { + try { + const urlRegex = new RegExp(patternString); + remotePatterns.push(urlRegex); + } + catch (error) { + const message = error instanceof Error ? error.message : 'An unknown error occurred'; + errors.push({ message }); + } + } + return { errors, remotePatterns }; +}; +const getErrorMessage = function ({ message }) { + return message; +}; +const handleRemoteImagesErrors = function (errors) { + if (errors.length === 0) { + return; + } + const errorMessage = errors.map(getErrorMessage).join('\n\n'); + log(NETLIFYDEVERR, `Remote images syntax errors:\n${errorMessage}`); +}; +const parseRemoteImages = function ({ config }) { + if (!config) { + return []; + } + const { errors, remotePatterns } = parseAllRemoteImages(config); + handleRemoteImagesErrors(errors); + return remotePatterns; +}; +export const isImageRequest = function (req) { + return req.url?.startsWith(IMAGE_URL_PATTERN) ?? false; +}; +export const transformImageParams = function (query) { + const params = {}; + const width = query.w || query.width || null; + const height = query.h || query.height || null; + if (width && height) { + params.s = `${width}x${height}`; + } + else { + params.w = width; + params.h = height; + } + params.quality = query.q || query.quality || null; + params.format = query.fm || null; + const fit = query.fit || null; + params.fit = fit === 'contain' ? 'inside' : fit; + params.position = query.position || null; + return Object.entries(params) + .filter(([, value]) => value !== null) + .map(([key, value]) => `${key}_${value}`) + .join(','); +}; +export const initializeProxy = function ({ config, settings, }) { + const remoteImages = parseRemoteImages({ config }); + const devServerUrl = getProxyUrl(settings); + const ipx = createIPX({ + storage: ipxFSStorage({ dir: ('publish' in config.build ? config.build.publish : undefined) ?? './public' }), + httpStorage: ipxHttpStorage({ + allowAllDomains: true, + }), + }); + const handler = createIPXNodeServer(ipx); + const app = express(); + let lastTimeRemoteImagesConfigurationDetailsMessageWasLogged = 0; + app.use(IMAGE_URL_PATTERN, (req, res) => { + const { url, ...query } = req.query; + const sourceImagePath = url; + const modifiers = transformImageParams(query) || `_`; + if (!sourceImagePath.startsWith('http://') && !sourceImagePath.startsWith('https://')) { + // Construct the full URL for relative paths to request from development server + const sourceImagePathWithLeadingSlash = sourceImagePath.startsWith('/') ? sourceImagePath : `/${sourceImagePath}`; + const fullImageUrl = `${devServerUrl}${encodeURIComponent(sourceImagePathWithLeadingSlash)}`; + req.url = `/${modifiers}/${fullImageUrl}`; + } + else { + // If the image is remote, we first check if it's allowed by any of patterns + if (!remoteImages.some((remoteImage) => remoteImage.test(sourceImagePath))) { + const remoteImageNotAllowedLogMessage = `Remote image "${sourceImagePath}" source for Image CDN is not allowed.`; + // Contextual information about the remote image configuration is throttled + // to avoid spamming the console as it's quite verbose + // Each not allowed remote image will still be logged, just without configuration details + if (Date.now() - lastTimeRemoteImagesConfigurationDetailsMessageWasLogged > 1000 * 30) { + log(`${remoteImageNotAllowedLogMessage}\n\n${remoteImages.length === 0 + ? 'Currently no remote images are allowed.' + : `Currently allowed remote images configuration details:\n${remoteImages + .map((pattern) => ` - ${pattern}`) + .join('\n')}`}\n\nRefer to https://ntl.fyi/remote-images for information about how to configure allowed remote images.`); + lastTimeRemoteImagesConfigurationDetailsMessageWasLogged = Date.now(); + } + else { + log(remoteImageNotAllowedLogMessage); + } + res.status(400).end(); + return; + } + // Construct the full URL for remote paths + req.url = `/${modifiers}/${encodeURIComponent(sourceImagePath)}`; + } + handler(req, res); + }); + return app; +}; +//# sourceMappingURL=proxy.js.map \ No newline at end of file diff --git a/dist/lib/images/proxy.js.map b/dist/lib/images/proxy.js.map new file mode 100644 index 00000000000..657d899521c --- /dev/null +++ b/dist/lib/images/proxy.js.map @@ -0,0 +1 @@ +{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../../src/lib/images/proxy.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/lib/log.d.ts b/dist/lib/log.d.ts new file mode 100644 index 00000000000..94dc5f38e0e --- /dev/null +++ b/dist/lib/log.d.ts @@ -0,0 +1,3 @@ +export declare const BACKGROUND_FUNCTIONS_WARNING: string; +export declare const MISSING_AWS_SDK_WARNING: string; +//# sourceMappingURL=log.d.ts.map \ No newline at end of file diff --git a/dist/lib/log.d.ts.map b/dist/lib/log.d.ts.map new file mode 100644 index 00000000000..5f7fc137f70 --- /dev/null +++ b/dist/lib/log.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/lib/log.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,4BAA4B,QAKxC,CAAA;AACD,eAAO,MAAM,uBAAuB,QAOmB,CAAA"} \ No newline at end of file diff --git a/dist/lib/log.js b/dist/lib/log.js new file mode 100644 index 00000000000..fddf8919b86 --- /dev/null +++ b/dist/lib/log.js @@ -0,0 +1,16 @@ +import { chalk } from '../utils/command-helpers.js'; +const RED_BACKGROUND = chalk.red('-background'); +const [PRO, BUSINESS, ENTERPRISE] = ['Pro', 'Business', 'Enterprise'].map((plan) => chalk.magenta(plan)); +export const BACKGROUND_FUNCTIONS_WARNING = `A serverless function ending in \`${RED_BACKGROUND}\` was detected. +Your team’s current plan doesn’t support Background Functions, which have names ending in \`${RED_BACKGROUND}\`. +To be able to deploy this function successfully either: + - change the function name to remove \`${RED_BACKGROUND}\` and execute it synchronously + - upgrade your team plan to a level that supports Background Functions (${PRO}, ${BUSINESS}, or ${ENTERPRISE}) +`; +export const MISSING_AWS_SDK_WARNING = `A function has thrown an error due to a missing dependency: ${chalk.yellow('aws-sdk')}. +You should add this module to the project's dependencies, using your package manager of choice: + +${chalk.yellow('npm install aws-sdk --save')} or ${chalk.yellow('yarn add aws-sdk')} + +For more information, see https://ntl.fyi/cli-aws-sdk.`; +//# sourceMappingURL=log.js.map \ No newline at end of file diff --git a/dist/lib/log.js.map b/dist/lib/log.js.map new file mode 100644 index 00000000000..a3facc22a57 --- /dev/null +++ b/dist/lib/log.js.map @@ -0,0 +1 @@ +{"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/lib/log.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,6BAA6B,CAAA;AAEnD,MAAM,cAAc,GAAG,KAAK,CAAC,GAAG,CAAC,aAAa,CAAC,CAAA;AAC/C,MAAM,CAAC,GAAG,EAAE,QAAQ,EAAE,UAAU,CAAC,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,YAAY,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;AACxG,MAAM,CAAC,MAAM,4BAA4B,GAAG,qCAAqC,cAAc;8FACD,cAAc;;2CAEjE,cAAc;4EACmB,GAAG,KAAK,QAAQ,QAAQ,UAAU;CAC7G,CAAA;AACD,MAAM,CAAC,MAAM,uBAAuB,GAAG,+DAA+D,KAAK,CAAC,MAAM,CAChH,SAAS,CACV;;;EAGC,KAAK,CAAC,MAAM,CAAC,4BAA4B,CAAC,OAAO,KAAK,CAAC,MAAM,CAAC,kBAAkB,CAAC;;uDAE5B,CAAA"} \ No newline at end of file diff --git a/dist/lib/path.d.ts b/dist/lib/path.d.ts new file mode 100644 index 00000000000..93fb84529e1 --- /dev/null +++ b/dist/lib/path.d.ts @@ -0,0 +1,2 @@ +export declare const normalizeBackslash: (path: string) => string; +//# sourceMappingURL=path.d.ts.map \ No newline at end of file diff --git a/dist/lib/path.d.ts.map b/dist/lib/path.d.ts.map new file mode 100644 index 00000000000..6342a3a17e9 --- /dev/null +++ b/dist/lib/path.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/lib/path.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,kBAAkB,GAAI,MAAM,MAAM,KAAG,MAAkC,CAAA"} \ No newline at end of file diff --git a/dist/lib/path.js b/dist/lib/path.js new file mode 100644 index 00000000000..f339f4d46b3 --- /dev/null +++ b/dist/lib/path.js @@ -0,0 +1,2 @@ +export const normalizeBackslash = (path) => path.replace(/\\/g, '/'); +//# sourceMappingURL=path.js.map \ No newline at end of file diff --git a/dist/lib/path.js.map b/dist/lib/path.js.map new file mode 100644 index 00000000000..cf07e53f7ff --- /dev/null +++ b/dist/lib/path.js.map @@ -0,0 +1 @@ +{"version":3,"file":"path.js","sourceRoot":"","sources":["../../src/lib/path.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,IAAY,EAAU,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/lib/render-error-template.d.ts b/dist/lib/render-error-template.d.ts new file mode 100644 index 00000000000..923d73b6b8d --- /dev/null +++ b/dist/lib/render-error-template.d.ts @@ -0,0 +1,3 @@ +declare const renderErrorTemplate: (errString: any, templatePath: any, functionType: any) => Promise; +export default renderErrorTemplate; +//# sourceMappingURL=render-error-template.d.ts.map \ No newline at end of file diff --git a/dist/lib/render-error-template.d.ts.map b/dist/lib/render-error-template.d.ts.map new file mode 100644 index 00000000000..a2680ccc9b2 --- /dev/null +++ b/dist/lib/render-error-template.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"render-error-template.d.ts","sourceRoot":"","sources":["../../src/lib/render-error-template.ts"],"names":[],"mappings":"AASA,QAAA,MAAM,mBAAmB,GAAU,cAAS,EAAE,iBAAY,EAAE,iBAAY,iBAYvE,CAAA;AAED,eAAe,mBAAmB,CAAA"} \ No newline at end of file diff --git a/dist/lib/render-error-template.js b/dist/lib/render-error-template.js new file mode 100644 index 00000000000..0f04e950c89 --- /dev/null +++ b/dist/lib/render-error-template.js @@ -0,0 +1,21 @@ +import { readFile } from 'fs/promises'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; +// @ts-expect-error TS(7034) FIXME: Variable 'errorTemplateFile' implicitly has type '... Remove this comment to see the full error message +let errorTemplateFile; +const dir = dirname(fileURLToPath(import.meta.url)); +// @ts-expect-error TS(7006) FIXME: Parameter 'errString' implicitly has an 'any' type... Remove this comment to see the full error message +const renderErrorTemplate = async (errString, templatePath, functionType) => { + const errorDetailsRegex = //g; + const functionTypeRegex = //g; + try { + // @ts-expect-error TS(7005) FIXME: Variable 'errorTemplateFile' implicitly has an 'an... Remove this comment to see the full error message + errorTemplateFile = errorTemplateFile || (await readFile(join(dir, templatePath), 'utf-8')); + return errorTemplateFile.replace(errorDetailsRegex, errString).replace(functionTypeRegex, functionType); + } + catch { + return errString; + } +}; +export default renderErrorTemplate; +//# sourceMappingURL=render-error-template.js.map \ No newline at end of file diff --git a/dist/lib/render-error-template.js.map b/dist/lib/render-error-template.js.map new file mode 100644 index 00000000000..f8be2319c80 --- /dev/null +++ b/dist/lib/render-error-template.js.map @@ -0,0 +1 @@ +{"version":3,"file":"render-error-template.js","sourceRoot":"","sources":["../../src/lib/render-error-template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AAEnC,2IAA2I;AAC3I,IAAI,iBAAiB,CAAA;AACrB,MAAM,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAEnD,2IAA2I;AAC3I,MAAM,mBAAmB,GAAG,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE;IAC1E,MAAM,iBAAiB,GAAG,wBAAwB,CAAA;IAClD,MAAM,iBAAiB,GAAG,wBAAwB,CAAA;IAElD,IAAI,CAAC;QACH,2IAA2I;QAC3I,iBAAiB,GAAG,iBAAiB,IAAI,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,CAAC,CAAA;QAE3F,OAAO,iBAAiB,CAAC,OAAO,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC,OAAO,CAAC,iBAAiB,EAAE,YAAY,CAAC,CAAA;IACzG,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAA;IAClB,CAAC;AACH,CAAC,CAAA;AAED,eAAe,mBAAmB,CAAA"} \ No newline at end of file diff --git a/dist/lib/settings.d.ts b/dist/lib/settings.d.ts new file mode 100644 index 00000000000..eb85fa203fb --- /dev/null +++ b/dist/lib/settings.d.ts @@ -0,0 +1,14 @@ +/** + * Deprecated method to get netlify's home config - ~/.netlify/... + * @deprecated + */ +export declare const getLegacyPathInHome: (paths: string[]) => string; +/** + * get a global path on the os base path + */ +export declare const getPathInHome: (paths: string[]) => string; +/** + * get a path inside the project folder "NOT WORKSPACE AWARE" + */ +export declare const getPathInProject: (paths: string[]) => string; +//# sourceMappingURL=settings.d.ts.map \ No newline at end of file diff --git a/dist/lib/settings.d.ts.map b/dist/lib/settings.d.ts.map new file mode 100644 index 00000000000..20c9b497c08 --- /dev/null +++ b/dist/lib/settings.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../src/lib/settings.ts"],"names":[],"mappings":"AAQA;;;GAGG;AACH,eAAO,MAAM,mBAAmB,GAAI,OAAO,MAAM,EAAE,WAAoD,CAAA;AAEvG;;GAEG;AACH,eAAO,MAAM,aAAa,GAAI,OAAO,MAAM,EAAE,WAA6C,CAAA;AAE1F;;GAEG;AACH,eAAO,MAAM,gBAAgB,GAAI,OAAO,MAAM,EAAE,WAAsC,CAAA"} \ No newline at end of file diff --git a/dist/lib/settings.js b/dist/lib/settings.js new file mode 100644 index 00000000000..13431927c4b --- /dev/null +++ b/dist/lib/settings.js @@ -0,0 +1,19 @@ +import os from 'os'; +import path from 'path'; +import envPaths from 'env-paths'; +const OSBasedPaths = envPaths('netlify', { suffix: '' }); +const NETLIFY_HOME = '.netlify'; +/** + * Deprecated method to get netlify's home config - ~/.netlify/... + * @deprecated + */ +export const getLegacyPathInHome = (paths) => path.join(os.homedir(), NETLIFY_HOME, ...paths); +/** + * get a global path on the os base path + */ +export const getPathInHome = (paths) => path.join(OSBasedPaths.config, ...paths); +/** + * get a path inside the project folder "NOT WORKSPACE AWARE" + */ +export const getPathInProject = (paths) => path.join(NETLIFY_HOME, ...paths); +//# sourceMappingURL=settings.js.map \ No newline at end of file diff --git a/dist/lib/settings.js.map b/dist/lib/settings.js.map new file mode 100644 index 00000000000..03450a5addd --- /dev/null +++ b/dist/lib/settings.js.map @@ -0,0 +1 @@ +{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../src/lib/settings.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,OAAO,QAAQ,MAAM,WAAW,CAAA;AAEhC,MAAM,YAAY,GAAG,QAAQ,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAA;AACxD,MAAM,YAAY,GAAG,UAAU,CAAA;AAE/B;;;GAGG;AACH,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAe,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,EAAE,GAAG,KAAK,CAAC,CAAA;AAEvG;;GAEG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,KAAe,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAA;AAE1F;;GAEG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,KAAe,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,GAAG,KAAK,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/lib/spinner.d.ts b/dist/lib/spinner.d.ts new file mode 100644 index 00000000000..52b948da41e --- /dev/null +++ b/dist/lib/spinner.d.ts @@ -0,0 +1,23 @@ +import { type Spinner } from 'nanospinner'; +/** + * Creates a spinner with the following text + */ +export declare const startSpinner: ({ text }: { + text: string; +}) => Spinner; +/** + * Stops the spinner with the following text + */ +export declare const stopSpinner: ({ error, spinner, text }: { + error?: boolean; + spinner: Spinner; + text?: string; +}) => void; +/** + * Clears the spinner + */ +export declare const clearSpinner: ({ spinner }: { + spinner: Spinner; +}) => void; +export type { Spinner }; +//# sourceMappingURL=spinner.d.ts.map \ No newline at end of file diff --git a/dist/lib/spinner.d.ts.map b/dist/lib/spinner.d.ts.map new file mode 100644 index 00000000000..b87bd5892d7 --- /dev/null +++ b/dist/lib/spinner.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"spinner.d.ts","sourceRoot":"","sources":["../../src/lib/spinner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAiB,KAAK,OAAO,EAAE,MAAM,aAAa,CAAA;AAOzD;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,UAAU;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,YAA8C,CAAA;AAErG;;GAEG;AACH,eAAO,MAAM,WAAW,GAAI,0BAA0B;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,OAAO,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,SASzG,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,YAAY,GAAI,aAAa;IAAE,OAAO,EAAE,OAAO,CAAA;CAAE,SAE7D,CAAA;AAED,YAAY,EAAE,OAAO,EAAE,CAAA"} \ No newline at end of file diff --git a/dist/lib/spinner.js b/dist/lib/spinner.js new file mode 100644 index 00000000000..d331d9371c5 --- /dev/null +++ b/dist/lib/spinner.js @@ -0,0 +1,30 @@ +import { createSpinner } from 'nanospinner'; +const DOTS_SPINNER = { + interval: 80, + frames: ['ā ‹', 'ā ™', 'ā ¹', 'ā ø', 'ā ¼', 'ā “', 'ā ¦', 'ā §', 'ā ‡', 'ā '], +}; +/** + * Creates a spinner with the following text + */ +export const startSpinner = ({ text }) => createSpinner(text, DOTS_SPINNER).start(); +/** + * Stops the spinner with the following text + */ +export const stopSpinner = ({ error, spinner, text }) => { + if (!spinner) { + return; + } + if (error === true) { + spinner.error(text); + } + else { + spinner.stop(text); + } +}; +/** + * Clears the spinner + */ +export const clearSpinner = ({ spinner }) => { + spinner.clear(); +}; +//# sourceMappingURL=spinner.js.map \ No newline at end of file diff --git a/dist/lib/spinner.js.map b/dist/lib/spinner.js.map new file mode 100644 index 00000000000..c113ec83d2e --- /dev/null +++ b/dist/lib/spinner.js.map @@ -0,0 +1 @@ +{"version":3,"file":"spinner.js","sourceRoot":"","sources":["../../src/lib/spinner.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAgB,MAAM,aAAa,CAAA;AAEzD,MAAM,YAAY,GAAG;IACnB,QAAQ,EAAE,EAAE;IACZ,MAAM,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;CAC3D,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAAE,IAAI,EAAoB,EAAE,EAAE,CAAC,aAAa,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC,KAAK,EAAE,CAAA;AAErG;;GAEG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,IAAI,EAAwD,EAAE,EAAE;IAC5G,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,OAAM;IACR,CAAC;IACD,IAAI,KAAK,KAAK,IAAI,EAAE,CAAC;QACnB,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACrB,CAAC;SAAM,CAAC;QACN,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACpB,CAAC;AACH,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAAE,OAAO,EAAwB,EAAE,EAAE;IAChE,OAAO,CAAC,KAAK,EAAE,CAAA;AACjB,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/lib/string.d.ts b/dist/lib/string.d.ts new file mode 100644 index 00000000000..fe9fcfc4349 --- /dev/null +++ b/dist/lib/string.d.ts @@ -0,0 +1,2 @@ +export declare const capitalize: (t: any) => any; +//# sourceMappingURL=string.d.ts.map \ No newline at end of file diff --git a/dist/lib/string.d.ts.map b/dist/lib/string.d.ts.map new file mode 100644 index 00000000000..36dcc1b5a2e --- /dev/null +++ b/dist/lib/string.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"string.d.ts","sourceRoot":"","sources":["../../src/lib/string.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,UAAU,GAAa,MAAC,QAGpC,CAAA"} \ No newline at end of file diff --git a/dist/lib/string.js b/dist/lib/string.js new file mode 100644 index 00000000000..599e152036d --- /dev/null +++ b/dist/lib/string.js @@ -0,0 +1,6 @@ +// @ts-expect-error TS(7006) FIXME: Parameter 't' implicitly has an 'any' type. +export const capitalize = function (t) { + // @ts-expect-error TS(7006) FIXME: Parameter 'string' implicitly has an 'any' type. + return t.replace(/(^\w|\s\w)/g, (string) => string.toUpperCase()); +}; +//# sourceMappingURL=string.js.map \ No newline at end of file diff --git a/dist/lib/string.js.map b/dist/lib/string.js.map new file mode 100644 index 00000000000..eef76d63dc1 --- /dev/null +++ b/dist/lib/string.js.map @@ -0,0 +1 @@ +{"version":3,"file":"string.js","sourceRoot":"","sources":["../../src/lib/string.ts"],"names":[],"mappings":"AAAA,+EAA+E;AAC/E,MAAM,CAAC,MAAM,UAAU,GAAG,UAAU,CAAC;IACnC,oFAAoF;IACpF,OAAO,CAAC,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAA;AACnE,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/recipes/ai-context/context.d.ts b/dist/recipes/ai-context/context.d.ts new file mode 100644 index 00000000000..433646387ff --- /dev/null +++ b/dist/recipes/ai-context/context.d.ts @@ -0,0 +1,59 @@ +import type { RunRecipeOptions } from '../../commands/recipes/recipes.js'; +export declare const NTL_DEV_MCP_FILE_NAME = "netlify-development.mdc"; +export declare const NETLIFY_PROVIDER = "netlify"; +export interface ContextConfig { + scope: string; + glob?: string; + shared?: string[]; + endpoint?: string; +} +export interface ContextFile { + key: string; + config: ContextConfig; + content: string; +} +export interface ConsumerConfig { + key: string; + presentedName: string; + consumerProcessCmd?: string; + path: string; + ext: string; + truncationLimit?: number; + contextScopes: Record; + hideFromCLI?: boolean; + consumerTrigger?: string; +} +export declare const getContextConsumers: (cliVersion: string) => Promise; +export declare const downloadFile: (cliVersion: string, contextConfig: ContextConfig, consumer: ConsumerConfig) => Promise<{ + contents: string; + minimumCLIVersion: string | undefined; +} | null>; +interface ParsedContextFile { + contents: string; + innerContents?: string; + overrides?: { + contents?: string; + innerContents?: string; + }; + provider?: string; + version?: string; +} +/** + * Parses the `` and `` blocks in + * a context file. + */ +export declare const parseContextFile: (contents: string) => ParsedContextFile; +/** + * Takes a context file (a template) and injects a string in an overrides block + * if one is found. Returns the resulting context file. + */ +export declare const applyOverrides: (template: string, overrides?: string) => string; +/** + * Reads a file on disk and tries to parse it as a context file. + */ +export declare const getExistingContext: (path: string) => Promise; +export declare const writeFile: (path: string, contents: string) => Promise; +export declare const deleteFile: (path: string) => Promise; +export declare const downloadAndWriteContextFiles: (consumer: ConsumerConfig, { command }: RunRecipeOptions) => Promise; +export {}; +//# sourceMappingURL=context.d.ts.map \ No newline at end of file diff --git a/dist/recipes/ai-context/context.d.ts.map b/dist/recipes/ai-context/context.d.ts.map new file mode 100644 index 00000000000..89db655cae7 --- /dev/null +++ b/dist/recipes/ai-context/context.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../../src/recipes/ai-context/context.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAA;AAMzE,eAAO,MAAM,qBAAqB,4BAA4B,CAAA;AAE9D,eAAO,MAAM,gBAAgB,YAAY,CAAA;AAKzC,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAA;IACb,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,aAAa,CAAA;IACrB,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,WAAW,cAAc;IAC7B,GAAG,EAAE,MAAM,CAAA;IACX,aAAa,EAAE,MAAM,CAAA;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;IAC5C,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,eAAe,CAAC,EAAE,MAAM,CAAA;CACzB;AAGD,eAAO,MAAM,mBAAmB,GAAU,YAAY,MAAM,8BAoB3D,CAAA;AAED,eAAO,MAAM,YAAY,GAAU,YAAY,MAAM,EAAE,eAAe,aAAa,EAAE,UAAU,cAAc;;;SAsC5G,CAAA;AAED,UAAU,iBAAiB;IACzB,QAAQ,EAAE,MAAM,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,SAAS,CAAC,EAAE;QACV,QAAQ,CAAC,EAAE,MAAM,CAAA;QACjB,aAAa,CAAC,EAAE,MAAM,CAAA;KACvB,CAAA;IACD,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;GAGG;AACH,eAAO,MAAM,gBAAgB,GAAI,UAAU,MAAM,sBA0ChD,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,cAAc,GAAI,UAAU,MAAM,EAAE,YAAY,MAAM,WAWlE,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAU,MAAM,MAAM,sCAqBpD,CAAA;AAED,eAAO,MAAM,SAAS,GAAU,MAAM,MAAM,EAAE,UAAU,MAAM,kBAK7D,CAAA;AAED,eAAO,MAAM,UAAU,GAAU,MAAM,MAAM,kBAO5C,CAAA;AAED,eAAO,MAAM,4BAA4B,GAAU,UAAU,cAAc,EAAE,aAAa,gBAAgB,kBAsEzG,CAAA"} \ No newline at end of file diff --git a/dist/recipes/ai-context/context.js b/dist/recipes/ai-context/context.js new file mode 100644 index 00000000000..5442de0e3d3 --- /dev/null +++ b/dist/recipes/ai-context/context.js @@ -0,0 +1,195 @@ +import { promises as fs } from 'node:fs'; +import { dirname, resolve } from 'node:path'; +import semver from 'semver'; +import { chalk, logAndThrowError, log, version } from '../../utils/command-helpers.js'; +const ATTRIBUTES_REGEX = /(\S*)="([^\s"]*)"/gim; +// AI_CONTEXT_BASE_URL is used to help with local testing at non-production +// versions of the context apis. +const BASE_URL = new URL(process.env.AI_CONTEXT_BASE_URL ?? 'https://docs.netlify.com/ai-context').toString(); +export const NTL_DEV_MCP_FILE_NAME = 'netlify-development.mdc'; +const MINIMUM_CLI_VERSION_HEADER = 'x-cli-min-ver'; +export const NETLIFY_PROVIDER = 'netlify'; +const PROVIDER_CONTEXT_REGEX = /]*)>(.*)<\/providercontext>/ims; +const PROVIDER_CONTEXT_OVERRIDES_REGEX = /]*)>(.*)<\/providercontextoverrides>/ims; +const PROVIDER_CONTEXT_OVERRIDES_TAG = 'ProviderContextOverrides'; +let contextConsumers = []; +export const getContextConsumers = async (cliVersion) => { + if (contextConsumers.length > 0) { + return contextConsumers; + } + try { + const res = await fetch(`${BASE_URL}/context-consumers`, { + headers: { + 'user-agent': `NetlifyCLI ${cliVersion}`, + }, + }); + if (!res.ok) { + return []; + } + const data = (await res.json()); + contextConsumers = data?.consumers ?? []; + } + catch { } + return contextConsumers; +}; +export const downloadFile = async (cliVersion, contextConfig, consumer) => { + try { + if (!contextConfig.endpoint) { + return null; + } + const url = new URL(contextConfig.endpoint, BASE_URL); + url.searchParams.set('consumer', consumer.key); + if (process.env.AI_CONTEXT_BASE_URL) { + const overridingUrl = new URL(process.env.AI_CONTEXT_BASE_URL); + url.host = overridingUrl.host; + url.port = overridingUrl.port; + url.protocol = overridingUrl.protocol; + } + const res = await fetch(url, { + headers: { + 'user-agent': `NetlifyCLI ${cliVersion}`, + }, + }); + if (!res.ok) { + return null; + } + const contents = await res.text(); + const minimumCLIVersion = res.headers.get(MINIMUM_CLI_VERSION_HEADER) ?? undefined; + return { + contents, + minimumCLIVersion, + }; + } + catch { + // no-op + } + return null; +}; +/** + * Parses the `` and `` blocks in + * a context file. + */ +export const parseContextFile = (contents) => { + const result = { + contents, + }; + const providerContext = contents.match(PROVIDER_CONTEXT_REGEX); + if (providerContext) { + const [, attributes, innerContents] = providerContext; + result.innerContents = innerContents; + for (const [, name, value] of attributes.matchAll(ATTRIBUTES_REGEX)) { + switch (name.toLowerCase()) { + case 'provider': + result.provider = value; + break; + case 'version': + result.version = value; + break; + default: + continue; + } + } + } + const contextOverrides = contents.match(PROVIDER_CONTEXT_OVERRIDES_REGEX); + if (contextOverrides) { + const [overrideContents, , innerContents] = contextOverrides; + result.overrides = { + contents: overrideContents, + innerContents, + }; + } + return result; +}; +/** + * Takes a context file (a template) and injects a string in an overrides block + * if one is found. Returns the resulting context file. + */ +export const applyOverrides = (template, overrides) => { + if (!overrides) { + return template; + } + return template + .replace(PROVIDER_CONTEXT_OVERRIDES_REGEX, `<${PROVIDER_CONTEXT_OVERRIDES_TAG}>${overrides}`) + .trim(); +}; +/** + * Reads a file on disk and tries to parse it as a context file. + */ +export const getExistingContext = async (path) => { + try { + const stats = await fs.stat(path); + if (!stats.isFile()) { + throw new Error(`${path} already exists but is not a file. Please remove it or rename it and try again.`); + } + const file = await fs.readFile(path, 'utf8'); + const parsedFile = parseContextFile(file); + return parsedFile; + } + catch (error) { + const exception = error; + if (exception.code !== 'ENOENT') { + throw new Error(`Could not open context file at ${path}: ${exception.message}`); + } + return null; + } +}; +export const writeFile = async (path, contents) => { + const directory = dirname(path); + await fs.mkdir(directory, { recursive: true }); + await fs.writeFile(path, contents); +}; +export const deleteFile = async (path) => { + try { + // delete file from file system - not just unlinking it + await fs.rm(path); + } + catch { + // ignore + } +}; +export const downloadAndWriteContextFiles = async (consumer, { command }) => { + await Promise.allSettled(Object.keys(consumer.contextScopes).map(async (contextKey) => { + const contextConfig = consumer.contextScopes[contextKey]; + const { contents: downloadedFile, minimumCLIVersion } = (await downloadFile(version, contextConfig, consumer).catch(() => null)) ?? {}; + if (!downloadedFile) { + return logAndThrowError(`An error occurred when pulling the latest context file for scope ${contextConfig.scope}. Please try again.`); + } + if (minimumCLIVersion && semver.lt(version, minimumCLIVersion)) { + return logAndThrowError(`This command requires version ${minimumCLIVersion} or above of the Netlify CLI. Refer to ${chalk.underline('https://ntl.fyi/update-cli')} for information on how to update.`); + } + const absoluteFilePath = resolve(command?.workingDir ?? '', consumer.path, `netlify-${contextKey}.${consumer.ext || 'mdc'}`); + const existing = await getExistingContext(absoluteFilePath); + const remote = parseContextFile(downloadedFile); + let { contents } = remote; + // Does a file already exist at this path? + if (existing) { + // If it's a file we've created, let's check the version and bail if we're + // already on the latest, otherwise rewrite it with the latest version. + if (existing.provider?.toLowerCase() === NETLIFY_PROVIDER) { + if (remote.version === existing.version) { + log(`You're all up to date! ${chalk.underline(absoluteFilePath)} contains the latest version of the context files.`); + return; + } + // We must preserve any overrides found in the existing file. + contents = applyOverrides(remote.contents, existing.overrides?.innerContents); + } + else { + // Whatever exists in the file goes in the overrides block. + contents = applyOverrides(remote.contents, existing.contents); + } + } + // we don't want to cut off content, but if we _have_ to + // then we need to do so before writing or the user's + // context gets in a bad state. Note, this can result in + // a file that's not parsable next time. This will be + // fine because the file will simply be replaced. Not ideal + // but solves the issue of a truncated file in a bad state + // being updated. + if (consumer.truncationLimit && contents.length > consumer.truncationLimit) { + contents = contents.slice(0, consumer.truncationLimit); + } + await writeFile(absoluteFilePath, contents); + log(`${existing ? 'Updated' : 'Created'} context files at ${chalk.underline(absoluteFilePath)}`); + })); +}; +//# sourceMappingURL=context.js.map \ No newline at end of file diff --git a/dist/recipes/ai-context/context.js.map b/dist/recipes/ai-context/context.js.map new file mode 100644 index 00000000000..18d217aabf2 --- /dev/null +++ b/dist/recipes/ai-context/context.js.map @@ -0,0 +1 @@ +{"version":3,"file":"context.js","sourceRoot":"","sources":["../../../src/recipes/ai-context/context.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/recipes/ai-context/index.d.ts b/dist/recipes/ai-context/index.d.ts new file mode 100644 index 00000000000..c1d15d75f3c --- /dev/null +++ b/dist/recipes/ai-context/index.d.ts @@ -0,0 +1,22 @@ +import type { RunRecipeOptions } from '../../commands/recipes/recipes.js'; +import { ConsumerConfig } from './context.js'; +export declare const description = "Manage context files for AI tools"; +/** + * Checks if a command belongs to a known IDEs by checking if it includes a specific string. + * For example, the command that starts windsurf looks something like "/applications/windsurf.app/contents/...". + */ +export declare const getConsumerKeyFromCommand: (command: string) => string | null; +/** + * Receives a process ID (pid) and returns both the command that the process was run with and its parent process ID. If the process is a known IDE, also returns information about that IDE. + */ +export declare const getCommandAndParentPID: (pid: number) => Promise<{ + parentPID: number; + command: string; + consumerKey: string | null; +}>; +/** + * Detects the IDE by walking up the process tree and matching against known consumer processes + */ +export declare const detectIDE: () => Promise; +export declare const run: (runOptions: RunRecipeOptions) => Promise; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/recipes/ai-context/index.d.ts.map b/dist/recipes/ai-context/index.d.ts.map new file mode 100644 index 00000000000..0c34b13b8f2 --- /dev/null +++ b/dist/recipes/ai-context/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/recipes/ai-context/index.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAA;AAGzE,OAAO,EAIL,cAAc,EAGf,MAAM,cAAc,CAAA;AAErB,eAAO,MAAM,WAAW,sCAAsC,CAAA;AA0D9D;;;GAGG;AACH,eAAO,MAAM,yBAAyB,GAAI,SAAS,MAAM,KAAG,MAAM,GAAG,IAMpE,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,sBAAsB,GACjC,KAAK,MAAM,KACV,OAAO,CAAC;IACT,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;CAC3B,CAWA,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,QAAa,OAAO,CAAC,cAAc,GAAG,IAAI,CAuB/D,CAAA;AAED,eAAO,MAAM,GAAG,GAAU,YAAY,gBAAgB,kBAuCrD,CAAA"} \ No newline at end of file diff --git a/dist/recipes/ai-context/index.js b/dist/recipes/ai-context/index.js new file mode 100644 index 00000000000..0b9483ea67d --- /dev/null +++ b/dist/recipes/ai-context/index.js @@ -0,0 +1,135 @@ +import { resolve } from 'node:path'; +import inquirer from 'inquirer'; +import execa from 'execa'; +import { logAndThrowError, log, version } from '../../utils/command-helpers.js'; +import { getExistingContext, NTL_DEV_MCP_FILE_NAME, getContextConsumers, deleteFile, downloadAndWriteContextFiles, } from './context.js'; +export const description = 'Manage context files for AI tools'; +// context consumers endpoints returns all supported IDE and other consumers +// that can be used to pull context files. It also includes a catchall consumer +// for outlining all context that an unspecified consumer would handle. +const allContextConsumers = await getContextConsumers(version); +const cliContextConsumers = allContextConsumers.filter((consumer) => !consumer.hideFromCLI); +const rulesForDefaultConsumer = allContextConsumers.find((consumer) => consumer.key === 'catchall-consumer') ?? { + key: 'catchall-consumer', + path: './ai-context', + presentedName: '', + ext: 'mdc', + contextScopes: {}, + hideFromCLI: true, +}; +const presets = cliContextConsumers.map((consumer) => ({ + name: consumer.presentedName, + value: consumer.key, +})); +// always add the custom location option (not preset from API) +presets.push({ name: 'Custom location', value: rulesForDefaultConsumer.key }); +const promptForContextConsumerSelection = async () => { + const { consumerKey } = await inquirer.prompt([ + { + name: 'consumerKey', + message: 'Where should we put the context files?', + type: 'list', + choices: presets, + }, + ]); + const contextConsumer = consumerKey ? cliContextConsumers.find((consumer) => consumer.key === consumerKey) : null; + if (contextConsumer) { + return contextConsumer; + } + const { customPath } = await inquirer.prompt([ + { + type: 'input', + name: 'customPath', + message: 'Enter the path, relative to the project root, where the context files should be placed', + default: './ai-context', + }, + ]); + if (customPath) { + return { ...rulesForDefaultConsumer, path: customPath || rulesForDefaultConsumer.path }; + } + log('You must select a path.'); + return promptForContextConsumerSelection(); +}; +/** + * Checks if a command belongs to a known IDEs by checking if it includes a specific string. + * For example, the command that starts windsurf looks something like "/applications/windsurf.app/contents/...". + */ +export const getConsumerKeyFromCommand = (command) => { + // The actual command is something like "/applications/windsurf.app/contents/...", but we are only looking for windsurf + const match = cliContextConsumers.find((consumer) => consumer.consumerProcessCmd && command.includes(consumer.consumerProcessCmd)); + return match ? match.key : null; +}; +/** + * Receives a process ID (pid) and returns both the command that the process was run with and its parent process ID. If the process is a known IDE, also returns information about that IDE. + */ +export const getCommandAndParentPID = async (pid) => { + const { stdout } = await execa('ps', ['-p', String(pid), '-o', 'ppid=,comm=']); + const output = stdout.trim(); + const spaceIndex = output.indexOf(' '); + const parentPID = output.substring(0, spaceIndex); + const command = output.substring(spaceIndex + 1).toLowerCase(); + return { + parentPID: Number(parentPID), + command, + consumerKey: getConsumerKeyFromCommand(command), + }; +}; +/** + * Detects the IDE by walking up the process tree and matching against known consumer processes + */ +export const detectIDE = async () => { + // Go up the chain of ancestor process IDs and find if one of their commands matches an IDE. + const ppid = process.ppid; + let result; + try { + result = await getCommandAndParentPID(ppid); + while (result.parentPID !== 1 && !result.consumerKey) { + result = await getCommandAndParentPID(result.parentPID); + } + } + catch { + // The command "ps -p {pid} -o ppid=,comm=" didn't work, + // perhaps we are on a machine that doesn't support it. + return null; + } + if (result?.consumerKey) { + const contextConsumer = cliContextConsumers.find((consumer) => consumer.key === result.consumerKey); + if (contextConsumer) { + return contextConsumer; + } + } + return null; +}; +export const run = async (runOptions) => { + const { args, command } = runOptions; + let consumer = null; + const filePath = args[0]; + if (filePath) { + consumer = { ...rulesForDefaultConsumer, path: filePath }; + } + if (!consumer && process.env.AI_CONTEXT_SKIP_DETECTION !== 'true') { + consumer = await detectIDE(); + } + if (!consumer) { + consumer = await promptForContextConsumerSelection(); + } + if (!consumer?.contextScopes) { + log('No context files found for this consumer. Try again or let us know if this happens again via our support channels.'); + return; + } + try { + await downloadAndWriteContextFiles(consumer, runOptions); + // the deprecated MCP file path + // let's remove that file if it exists. + const priorContextFilePath = resolve(command?.workingDir ?? '', consumer.path, NTL_DEV_MCP_FILE_NAME); + const priorExists = await getExistingContext(priorContextFilePath); + if (priorExists) { + await deleteFile(priorContextFilePath); + } + log('All context files have been added!'); + } + catch (error) { + logAndThrowError(error); + } +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/recipes/ai-context/index.js.map b/dist/recipes/ai-context/index.js.map new file mode 100644 index 00000000000..d46d39a7778 --- /dev/null +++ b/dist/recipes/ai-context/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/recipes/ai-context/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/recipes/blobs-migrate/index.d.ts b/dist/recipes/blobs-migrate/index.d.ts new file mode 100644 index 00000000000..61ceff3217f --- /dev/null +++ b/dist/recipes/blobs-migrate/index.d.ts @@ -0,0 +1,9 @@ +import BaseCommand from '../../commands/base-command.js'; +export declare const description = "Migrate legacy Netlify Blobs stores"; +interface Options { + args: string[]; + command: BaseCommand; +} +export declare const run: ({ args, command }: Options) => Promise; +export {}; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/recipes/blobs-migrate/index.d.ts.map b/dist/recipes/blobs-migrate/index.d.ts.map new file mode 100644 index 00000000000..709ef75a12e --- /dev/null +++ b/dist/recipes/blobs-migrate/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/recipes/blobs-migrate/index.ts"],"names":[],"mappings":"AAIA,OAAO,WAAW,MAAM,gCAAgC,CAAA;AAGxD,eAAO,MAAM,WAAW,wCAAwC,CAAA;AAIhE,UAAU,OAAO;IACf,IAAI,EAAE,MAAM,EAAE,CAAA;IACd,OAAO,EAAE,WAAW,CAAA;CACrB;AAED,eAAO,MAAM,GAAG,GAAU,mBAAmB,OAAO,uBA2FnD,CAAA"} \ No newline at end of file diff --git a/dist/recipes/blobs-migrate/index.js b/dist/recipes/blobs-migrate/index.js new file mode 100644 index 00000000000..f74aa37ac60 --- /dev/null +++ b/dist/recipes/blobs-migrate/index.js @@ -0,0 +1,78 @@ +import { getStore, listStores } from '@netlify/blobs'; +import inquirer from 'inquirer'; +import pMap from 'p-map'; +import { logAndThrowError, log } from '../../utils/command-helpers.js'; +export const description = 'Migrate legacy Netlify Blobs stores'; +const BLOB_OPS_CONCURRENCY = 5; +export const run = async ({ args, command }) => { + if (args.length !== 1) { + return logAndThrowError(`Usage: netlify recipes blobs-migrate `); + } + const [storeName] = args; + const { api, siteInfo } = command.netlify; + const clientOptions = { + apiURL: `${api.scheme}://${api.host}`, + siteID: siteInfo.id, + token: api.accessToken ?? '', + }; + // The store we'll copy from. + const oldStore = getStore({ + ...clientOptions, + name: `netlify-internal/legacy-namespace/${storeName}`, + }); + // The store we'll write to. + const newStore = getStore({ + ...clientOptions, + name: storeName, + }); + const { blobs } = await oldStore.list(); + if (blobs.length === 0) { + log(`Store '${storeName}' does not exist or is empty, so there's nothing to migrate.`); + return; + } + const { stores } = await listStores(clientOptions); + if (stores.includes(storeName)) { + const { confirmExistingStore } = await inquirer.prompt({ + type: 'confirm', + name: 'confirmExistingStore', + message: `The store '${storeName}' already exists in the new format, which means it has already been migrated or it has been used with a newer version of the Netlify Blobs client. If you continue with the migration, any blobs from the legacy store will overwrite newer entries that have the same key. Do you want to proceed?`, + default: false, + }); + if (!confirmExistingStore) { + return; + } + } + const { confirmMigration } = await inquirer.prompt({ + type: 'confirm', + name: 'confirmMigration', + message: `You're about to migrate the store '${storeName}' with ${blobs.length} blobs. Do you want to proceed?`, + default: true, + }); + if (!confirmMigration) { + return; + } + await pMap(blobs, async (blob) => { + log(`Migrating blob with key '${blob.key}'...`); + const result = await oldStore.getWithMetadata(blob.key); + if (result === null) { + return; + } + await newStore.set(blob.key, result.data, { metadata: result.metadata }); + }, { concurrency: BLOB_OPS_CONCURRENCY }); + log('Verifying data in the new store...'); + const { blobs: newBlobs } = await newStore.list(); + const blobsMap = new Map(newBlobs.map((blob) => [blob.key, blob.etag])); + // Before deleting anything, let's first verify that all entries that exist + // in the old store are now also on the new store, with the same etag. + if (!blobs.every((blob) => blobsMap.get(blob.key) === blob.etag)) { + return logAndThrowError(`Failed to migrate some blobs. Try running the command again.`); + } + try { + await pMap(blobs, (blob) => oldStore.delete(blob.key), { concurrency: BLOB_OPS_CONCURRENCY }); + } + catch { + return logAndThrowError('Failed to remove legacy store after migration. Try running the command again.'); + } + log(`Store '${storeName}' has been migrated successfully.`); +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/recipes/blobs-migrate/index.js.map b/dist/recipes/blobs-migrate/index.js.map new file mode 100644 index 00000000000..3d7313e68f1 --- /dev/null +++ b/dist/recipes/blobs-migrate/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/recipes/blobs-migrate/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/recipes/vscode/index.d.ts b/dist/recipes/vscode/index.d.ts new file mode 100644 index 00000000000..5f31e271dae --- /dev/null +++ b/dist/recipes/vscode/index.d.ts @@ -0,0 +1,12 @@ +export declare const description = "Create VS Code settings for an optimal experience with Netlify projects"; +/** + * @param {object} params + * @param {*} params.config + * @param {string} params.repositoryRoot + * @returns + */ +export declare const run: ({ config, repositoryRoot }: { + config: any; + repositoryRoot: any; +}) => Promise; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/recipes/vscode/index.d.ts.map b/dist/recipes/vscode/index.d.ts.map new file mode 100644 index 00000000000..317e85ea518 --- /dev/null +++ b/dist/recipes/vscode/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/recipes/vscode/index.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,WAAW,4EAA4E,CAAA;AAuDpG;;;;;GAKG;AAEH,eAAO,MAAM,GAAG,GAAU;;;CAA0B,uBAuCnD,CAAA"} \ No newline at end of file diff --git a/dist/recipes/vscode/index.js b/dist/recipes/vscode/index.js new file mode 100644 index 00000000000..60c4db38e11 --- /dev/null +++ b/dist/recipes/vscode/index.js @@ -0,0 +1,93 @@ +import { join } from 'path'; +import { DenoBridge } from '@netlify/edge-bundler'; +import execa from 'execa'; +import inquirer from 'inquirer'; +import { NETLIFYDEVLOG, NETLIFYDEVWARN, chalk, logAndThrowError, log } from '../../utils/command-helpers.js'; +import { applySettings, getSettings, writeSettings } from './settings.js'; +export const description = 'Create VS Code settings for an optimal experience with Netlify projects'; +// @ts-expect-error TS(7031) FIXME: Binding element 'fileExists' implicitly has an 'an... Remove this comment to see the full error message +const getPrompt = ({ fileExists, path }) => { + const formattedPath = chalk.underline(path); + const message = fileExists + ? `There is a VS Code settings file at ${formattedPath}. Can we update it?` + : `A new VS Code settings file will be created at ${formattedPath}`; + return inquirer.prompt({ + type: 'confirm', + name: 'confirm', + message, + default: true, + }); +}; +// @ts-expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message +const getEdgeFunctionsPath = ({ config, repositoryRoot }) => config.build.edge_functions || join(repositoryRoot, 'netlify', 'edge-functions'); +/** + * @param {string} repositoryRoot + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'repositoryRoot' implicitly has an 'any'... Remove this comment to see the full error message +const getSettingsPath = (repositoryRoot) => join(repositoryRoot, '.vscode', 'settings.json'); +/** + * @param {string} repositoryRoot + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'repositoryRoot' implicitly has an 'any'... Remove this comment to see the full error message +const hasDenoVSCodeExt = async (repositoryRoot) => { + const { stdout: extensions } = await execa('code', ['--list-extensions'], { stderr: 'inherit', cwd: repositoryRoot }); + return extensions.split('\n').includes('denoland.vscode-deno'); +}; +/** + * @param {string} repositoryRoot + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'repositoryRoot' implicitly has an 'any'... Remove this comment to see the full error message +const getDenoVSCodeExt = async (repositoryRoot) => { + await execa('code', ['--install-extension', 'denoland.vscode-deno'], { stdio: 'inherit', cwd: repositoryRoot }); +}; +const getDenoExtPrompt = () => { + const message = 'The Deno VS Code extension is recommended. Would you like to install it now?'; + return inquirer.prompt({ + type: 'confirm', + name: 'confirm', + message, + default: true, + }); +}; +/** + * @param {object} params + * @param {*} params.config + * @param {string} params.repositoryRoot + * @returns + */ +// @ts-expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message +export const run = async ({ config, repositoryRoot }) => { + const deno = new DenoBridge({ + onBeforeDownload: () => { + log(`${NETLIFYDEVWARN} Setting up the Edge Functions environment. This may take a couple of minutes.`); + }, + }); + const denoBinary = await deno.getBinaryPath(); + const settingsPath = getSettingsPath(repositoryRoot); + const edgeFunctionsPath = getEdgeFunctionsPath({ config, repositoryRoot }); + const { fileExists, settings: existingSettings } = await getSettings(settingsPath); + const settings = applySettings(existingSettings, { denoBinary, edgeFunctionsPath, repositoryRoot }); + const { confirm } = await getPrompt({ fileExists, path: settingsPath }); + if (!confirm) { + return; + } + try { + if (!(await hasDenoVSCodeExt(repositoryRoot))) { + const { confirm: denoExtConfirm } = await getDenoExtPrompt(); + if (denoExtConfirm) { + getDenoVSCodeExt(repositoryRoot); + } + } + } + catch { + log(`${NETLIFYDEVWARN} Unable to install Deno VS Code extension. To install it manually, visit ${chalk.blue('https://ntl.fyi/deno-vscode')}.`); + } + try { + await writeSettings({ settings, settingsPath }); + log(`${NETLIFYDEVLOG} VS Code settings file ${fileExists ? 'updated' : 'created'}.`); + } + catch { + return logAndThrowError('Could not write VS Code settings file.'); + } +}; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/recipes/vscode/index.js.map b/dist/recipes/vscode/index.js.map new file mode 100644 index 00000000000..fbc4cb36233 --- /dev/null +++ b/dist/recipes/vscode/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/recipes/vscode/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/recipes/vscode/settings.d.ts b/dist/recipes/vscode/settings.d.ts new file mode 100644 index 00000000000..f00d3c4f74f --- /dev/null +++ b/dist/recipes/vscode/settings.d.ts @@ -0,0 +1,18 @@ +import * as JSONC from 'comment-json'; +export declare const applySettings: (existingSettings: any, { denoBinary, edgeFunctionsPath, repositoryRoot }: { + denoBinary: any; + edgeFunctionsPath: any; + repositoryRoot: any; +}) => any; +export declare const getSettings: (settingsPath: any) => Promise<{ + fileExists: boolean; + settings: JSONC.CommentJSONValue; +} | { + fileExists: boolean; + settings: {}; +}>; +export declare const writeSettings: ({ settings, settingsPath }: { + settings: any; + settingsPath: any; +}) => Promise; +//# sourceMappingURL=settings.d.ts.map \ No newline at end of file diff --git a/dist/recipes/vscode/settings.d.ts.map b/dist/recipes/vscode/settings.d.ts.map new file mode 100644 index 00000000000..f76347fd852 --- /dev/null +++ b/dist/recipes/vscode/settings.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"settings.d.ts","sourceRoot":"","sources":["../../../src/recipes/vscode/settings.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAKrC,eAAO,MAAM,aAAa,GAAI,qBAAgB,EAAE;;;;CAAiD,QA0BhG,CAAA;AAGD,eAAO,MAAM,WAAW,GAAU,iBAAY;;;;;;EA0B7C,CAAA;AAGD,eAAO,MAAM,aAAa,GAAU;;;CAA0B,kBAK7D,CAAA"} \ No newline at end of file diff --git a/dist/recipes/vscode/settings.js b/dist/recipes/vscode/settings.js new file mode 100644 index 00000000000..ae808696f4a --- /dev/null +++ b/dist/recipes/vscode/settings.js @@ -0,0 +1,61 @@ +import { mkdir, readFile, stat, writeFile } from 'fs/promises'; +import { dirname, posix, relative } from 'path'; +import * as JSONC from 'comment-json'; +const toUnixPath = (path) => path.replace(/\\/g, '/'); +// @ts-expect-error TS(7006) FIXME: Parameter 'existingSettings' implicitly has an 'an... Remove this comment to see the full error message +export const applySettings = (existingSettings, { denoBinary, edgeFunctionsPath, repositoryRoot }) => { + // TODO(serhalp): I'm not convinced we want to convert to Unix paths on Windows? Does this even work? Was this a + // workaround for something, perhaps https://github.com/denoland/vscode_deno/pull/745? + const relativeEdgeFunctionsPath = toUnixPath(posix.normalize(relative(repositoryRoot, edgeFunctionsPath))); + const settings = JSONC.assign(existingSettings, { + 'deno.enable': true, + 'deno.enablePaths': existingSettings['deno.enablePaths'] || [], + 'deno.unstable': true, + 'deno.importMap': '.netlify/edge-functions-import-map.json', + }); + // If the Edge Functions path isn't already in `deno.enabledPaths`, let's add + // it. + if (!settings['deno.enablePaths'].includes(relativeEdgeFunctionsPath)) { + settings['deno.enablePaths'].push(relativeEdgeFunctionsPath); + } + // If the Deno CLI binary isn't globally installed, we need to set the path + // to it in the settings file or the extension won't know where to find it. + // The only exception is when `deno.path` has already been defined, because + // we don't want to override that. + if (!denoBinary.global && settings['deno.path'] === undefined) { + settings['deno.path'] = denoBinary.path; + } + return settings; +}; +// @ts-expect-error TS(7006) FIXME: Parameter 'settingsPath' implicitly has an 'any' t... Remove this comment to see the full error message +export const getSettings = async (settingsPath) => { + try { + const stats = await stat(settingsPath); + if (!stats.isFile()) { + throw new Error(`${settingsPath} is not a valid file.`); + } + const file = await readFile(settingsPath, 'utf8'); + return { + fileExists: true, + settings: JSONC.parse(file), + }; + } + catch (error) { + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + if (error.code !== 'ENOENT') { + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + throw new Error(`Could not open VS Code settings file: ${error.message}`); + } + return { + fileExists: false, + settings: {}, + }; + } +}; +// @ts-expect-error TS(7031) FIXME: Binding element 'settings' implicitly has an 'any'... Remove this comment to see the full error message +export const writeSettings = async ({ settings, settingsPath }) => { + const serializedSettings = JSONC.stringify(settings, null, 2); + await mkdir(dirname(settingsPath), { recursive: true }); + await writeFile(settingsPath, serializedSettings); +}; +//# sourceMappingURL=settings.js.map \ No newline at end of file diff --git a/dist/recipes/vscode/settings.js.map b/dist/recipes/vscode/settings.js.map new file mode 100644 index 00000000000..d3104d3c839 --- /dev/null +++ b/dist/recipes/vscode/settings.js.map @@ -0,0 +1 @@ +{"version":3,"file":"settings.js","sourceRoot":"","sources":["../../../src/recipes/vscode/settings.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/tsconfig.build.tsbuildinfo b/dist/tsconfig.build.tsbuildinfo new file mode 100644 index 00000000000..7f16d0496cf --- /dev/null +++ b/dist/tsconfig.build.tsbuildinfo @@ -0,0 +1 @@ +{"fileNames":["../node_modules/typescript/lib/lib.es5.d.ts","../node_modules/typescript/lib/lib.es2015.d.ts","../node_modules/typescript/lib/lib.es2016.d.ts","../node_modules/typescript/lib/lib.es2017.d.ts","../node_modules/typescript/lib/lib.es2018.d.ts","../node_modules/typescript/lib/lib.es2019.d.ts","../node_modules/typescript/lib/lib.es2020.d.ts","../node_modules/typescript/lib/lib.es2021.d.ts","../node_modules/typescript/lib/lib.es2022.d.ts","../node_modules/typescript/lib/lib.es2023.d.ts","../node_modules/typescript/lib/lib.es2015.core.d.ts","../node_modules/typescript/lib/lib.es2015.collection.d.ts","../node_modules/typescript/lib/lib.es2015.generator.d.ts","../node_modules/typescript/lib/lib.es2015.iterable.d.ts","../node_modules/typescript/lib/lib.es2015.promise.d.ts","../node_modules/typescript/lib/lib.es2015.proxy.d.ts","../node_modules/typescript/lib/lib.es2015.reflect.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.d.ts","../node_modules/typescript/lib/lib.es2015.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2016.array.include.d.ts","../node_modules/typescript/lib/lib.es2016.intl.d.ts","../node_modules/typescript/lib/lib.es2017.arraybuffer.d.ts","../node_modules/typescript/lib/lib.es2017.date.d.ts","../node_modules/typescript/lib/lib.es2017.object.d.ts","../node_modules/typescript/lib/lib.es2017.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2017.string.d.ts","../node_modules/typescript/lib/lib.es2017.intl.d.ts","../node_modules/typescript/lib/lib.es2017.typedarrays.d.ts","../node_modules/typescript/lib/lib.es2018.asyncgenerator.d.ts","../node_modules/typescript/lib/lib.es2018.asynciterable.d.ts","../node_modules/typescript/lib/lib.es2018.intl.d.ts","../node_modules/typescript/lib/lib.es2018.promise.d.ts","../node_modules/typescript/lib/lib.es2018.regexp.d.ts","../node_modules/typescript/lib/lib.es2019.array.d.ts","../node_modules/typescript/lib/lib.es2019.object.d.ts","../node_modules/typescript/lib/lib.es2019.string.d.ts","../node_modules/typescript/lib/lib.es2019.symbol.d.ts","../node_modules/typescript/lib/lib.es2019.intl.d.ts","../node_modules/typescript/lib/lib.es2020.bigint.d.ts","../node_modules/typescript/lib/lib.es2020.date.d.ts","../node_modules/typescript/lib/lib.es2020.promise.d.ts","../node_modules/typescript/lib/lib.es2020.sharedmemory.d.ts","../node_modules/typescript/lib/lib.es2020.string.d.ts","../node_modules/typescript/lib/lib.es2020.symbol.wellknown.d.ts","../node_modules/typescript/lib/lib.es2020.intl.d.ts","../node_modules/typescript/lib/lib.es2020.number.d.ts","../node_modules/typescript/lib/lib.es2021.promise.d.ts","../node_modules/typescript/lib/lib.es2021.string.d.ts","../node_modules/typescript/lib/lib.es2021.weakref.d.ts","../node_modules/typescript/lib/lib.es2021.intl.d.ts","../node_modules/typescript/lib/lib.es2022.array.d.ts","../node_modules/typescript/lib/lib.es2022.error.d.ts","../node_modules/typescript/lib/lib.es2022.intl.d.ts","../node_modules/typescript/lib/lib.es2022.object.d.ts","../node_modules/typescript/lib/lib.es2022.string.d.ts","../node_modules/typescript/lib/lib.es2022.regexp.d.ts","../node_modules/typescript/lib/lib.es2023.array.d.ts","../node_modules/typescript/lib/lib.es2023.collection.d.ts","../node_modules/typescript/lib/lib.es2023.intl.d.ts","../node_modules/typescript/lib/lib.decorators.d.ts","../node_modules/typescript/lib/lib.decorators.legacy.d.ts","../node_modules/@netlify/open-api/dist/index.d.ts","../node_modules/@types/node/compatibility/disposable.d.ts","../node_modules/@types/node/compatibility/indexable.d.ts","../node_modules/@types/node/compatibility/iterators.d.ts","../node_modules/@types/node/compatibility/index.d.ts","../node_modules/@types/node/globals.typedarray.d.ts","../node_modules/@types/node/buffer.buffer.d.ts","../node_modules/buffer/index.d.ts","../node_modules/undici-types/header.d.ts","../node_modules/undici-types/readable.d.ts","../node_modules/undici-types/file.d.ts","../node_modules/undici-types/fetch.d.ts","../node_modules/undici-types/formdata.d.ts","../node_modules/undici-types/connector.d.ts","../node_modules/undici-types/client.d.ts","../node_modules/undici-types/errors.d.ts","../node_modules/undici-types/dispatcher.d.ts","../node_modules/undici-types/global-dispatcher.d.ts","../node_modules/undici-types/global-origin.d.ts","../node_modules/undici-types/pool-stats.d.ts","../node_modules/undici-types/pool.d.ts","../node_modules/undici-types/handlers.d.ts","../node_modules/undici-types/balanced-pool.d.ts","../node_modules/undici-types/agent.d.ts","../node_modules/undici-types/mock-interceptor.d.ts","../node_modules/undici-types/mock-agent.d.ts","../node_modules/undici-types/mock-client.d.ts","../node_modules/undici-types/mock-pool.d.ts","../node_modules/undici-types/mock-errors.d.ts","../node_modules/undici-types/proxy-agent.d.ts","../node_modules/undici-types/api.d.ts","../node_modules/undici-types/cookies.d.ts","../node_modules/undici-types/patch.d.ts","../node_modules/undici-types/filereader.d.ts","../node_modules/undici-types/diagnostics-channel.d.ts","../node_modules/undici-types/websocket.d.ts","../node_modules/undici-types/content-type.d.ts","../node_modules/undici-types/cache.d.ts","../node_modules/undici-types/interceptors.d.ts","../node_modules/undici-types/index.d.ts","../node_modules/@types/node/globals.d.ts","../node_modules/@types/node/assert.d.ts","../node_modules/@types/node/assert/strict.d.ts","../node_modules/@types/node/async_hooks.d.ts","../node_modules/@types/node/buffer.d.ts","../node_modules/@types/node/child_process.d.ts","../node_modules/@types/node/cluster.d.ts","../node_modules/@types/node/console.d.ts","../node_modules/@types/node/constants.d.ts","../node_modules/@types/node/crypto.d.ts","../node_modules/@types/node/dgram.d.ts","../node_modules/@types/node/diagnostics_channel.d.ts","../node_modules/@types/node/dns.d.ts","../node_modules/@types/node/dns/promises.d.ts","../node_modules/@types/node/domain.d.ts","../node_modules/@types/node/dom-events.d.ts","../node_modules/@types/node/events.d.ts","../node_modules/@types/node/fs.d.ts","../node_modules/@types/node/fs/promises.d.ts","../node_modules/@types/node/http.d.ts","../node_modules/@types/node/http2.d.ts","../node_modules/@types/node/https.d.ts","../node_modules/@types/node/inspector.d.ts","../node_modules/@types/node/module.d.ts","../node_modules/@types/node/net.d.ts","../node_modules/@types/node/os.d.ts","../node_modules/@types/node/path.d.ts","../node_modules/@types/node/perf_hooks.d.ts","../node_modules/@types/node/process.d.ts","../node_modules/@types/node/punycode.d.ts","../node_modules/@types/node/querystring.d.ts","../node_modules/@types/node/readline.d.ts","../node_modules/@types/node/readline/promises.d.ts","../node_modules/@types/node/repl.d.ts","../node_modules/@types/node/stream.d.ts","../node_modules/@types/node/stream/promises.d.ts","../node_modules/@types/node/stream/consumers.d.ts","../node_modules/@types/node/stream/web.d.ts","../node_modules/@types/node/string_decoder.d.ts","../node_modules/@types/node/test.d.ts","../node_modules/@types/node/timers.d.ts","../node_modules/@types/node/timers/promises.d.ts","../node_modules/@types/node/tls.d.ts","../node_modules/@types/node/trace_events.d.ts","../node_modules/@types/node/tty.d.ts","../node_modules/@types/node/url.d.ts","../node_modules/@types/node/util.d.ts","../node_modules/@types/node/v8.d.ts","../node_modules/@types/node/vm.d.ts","../node_modules/@types/node/wasi.d.ts","../node_modules/@types/node/worker_threads.d.ts","../node_modules/@types/node/zlib.d.ts","../node_modules/@types/node/index.d.ts","../node_modules/formdata-polyfill/esm.min.d.ts","../node_modules/fetch-blob/file.d.ts","../node_modules/fetch-blob/index.d.ts","../node_modules/fetch-blob/from.d.ts","../node_modules/node-fetch/@types/index.d.ts","../node_modules/@netlify/api/lib/types.d.ts","../node_modules/@netlify/api/lib/index.d.ts","../src/index.ts","../node_modules/@netlify/build-info/lib/logger.d.ts","../node_modules/@netlify/build-info/lib/file-system.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/primitive.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/typed-array.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/basic.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/observable-like.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/union-to-intersection.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/keys-of-union.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/distributed-omit.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/distributed-pick.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/empty-object.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/if-empty-object.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/optional-keys-of.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/required-keys-of.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/has-required-keys.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/is-never.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/if-never.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/unknown-array.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/internal/array.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/internal/characters.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/is-any.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/is-float.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/is-integer.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/numeric.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/is-literal.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/trim.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/is-equal.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/and.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/or.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/greater-than.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/greater-than-or-equal.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/less-than.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/internal/tuple.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/internal/string.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/internal/keys.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/internal/numeric.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/simplify.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/omit-index-signature.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/pick-index-signature.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/merge.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/if-any.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/internal/type.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/internal/object.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/internal/index.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/except.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/require-at-least-one.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/non-empty-object.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/non-empty-string.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/unknown-record.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/unknown-set.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/unknown-map.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/tagged-union.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/writable.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/writable-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/conditional-simplify.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/non-empty-tuple.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/array-tail.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/enforce-optional.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/simplify-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/merge-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/merge-exclusive.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/require-exactly-one.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/require-all-or-none.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/require-one-or-none.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/single-key-object.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/partial-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/required-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/subtract.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/paths.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/pick-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/array-splice.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/literal-union.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/union-to-tuple.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/omit-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/is-null.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/is-unknown.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/if-unknown.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/partial-on-undefined-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/undefined-on-partial-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/readonly-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/promisable.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/arrayable.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/tagged.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/invariant-of.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/set-optional.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/set-readonly.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/set-required.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/set-required-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/set-non-nullable.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/set-non-nullable-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/value-of.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/async-return-type.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/conditional-keys.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/conditional-except.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/conditional-pick.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/conditional-pick-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/stringified.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/join.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/sum.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/less-than-or-equal.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/array-slice.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/string-slice.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/fixed-length-array.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/multidimensional-array.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/multidimensional-readonly-array.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/iterable-element.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/entry.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/entries.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/set-return-type.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/set-parameter-type.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/asyncify.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/jsonify.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/jsonifiable.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/find-global-type.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/structured-cloneable.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/schema.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/literal-to-primitive.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/literal-to-primitive-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/string-key-of.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/exact.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/readonly-tuple.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/override-properties.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/has-optional-keys.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/writable-keys-of.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/readonly-keys-of.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/has-readonly-keys.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/has-writable-keys.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/spread.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/is-tuple.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/tuple-to-object.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/tuple-to-union.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/int-range.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/int-closed-range.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/array-indices.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/array-values.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/set-field-type.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/shared-union-fields.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/all-union-fields.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/shared-union-fields-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/if-null.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/words.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/camel-case.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/camel-cased-properties.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/camel-cased-properties-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/delimiter-case.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/kebab-case.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/delimiter-cased-properties.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/kebab-cased-properties.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/delimiter-cased-properties-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/kebab-cased-properties-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/pascal-case.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/pascal-cased-properties.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/pascal-cased-properties-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/snake-case.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/snake-cased-properties.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/snake-cased-properties-deep.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/screaming-snake-case.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/split.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/replace.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/string-repeat.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/includes.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/get.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/last-array-element.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/global-this.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/package-json.d.ts","../node_modules/read-pkg/node_modules/type-fest/source/tsconfig-json.d.ts","../node_modules/read-pkg/node_modules/type-fest/index.d.ts","../node_modules/@types/normalize-package-data/index.d.ts","../node_modules/read-pkg/index.d.ts","../node_modules/@types/semver/classes/semver.d.ts","../node_modules/@types/semver/functions/parse.d.ts","../node_modules/@types/semver/functions/valid.d.ts","../node_modules/@types/semver/functions/clean.d.ts","../node_modules/@types/semver/functions/inc.d.ts","../node_modules/@types/semver/functions/diff.d.ts","../node_modules/@types/semver/functions/major.d.ts","../node_modules/@types/semver/functions/minor.d.ts","../node_modules/@types/semver/functions/patch.d.ts","../node_modules/@types/semver/functions/prerelease.d.ts","../node_modules/@types/semver/functions/compare.d.ts","../node_modules/@types/semver/functions/rcompare.d.ts","../node_modules/@types/semver/functions/compare-loose.d.ts","../node_modules/@types/semver/functions/compare-build.d.ts","../node_modules/@types/semver/functions/sort.d.ts","../node_modules/@types/semver/functions/rsort.d.ts","../node_modules/@types/semver/functions/gt.d.ts","../node_modules/@types/semver/functions/lt.d.ts","../node_modules/@types/semver/functions/eq.d.ts","../node_modules/@types/semver/functions/neq.d.ts","../node_modules/@types/semver/functions/gte.d.ts","../node_modules/@types/semver/functions/lte.d.ts","../node_modules/@types/semver/functions/cmp.d.ts","../node_modules/@types/semver/functions/coerce.d.ts","../node_modules/@types/semver/classes/comparator.d.ts","../node_modules/@types/semver/classes/range.d.ts","../node_modules/@types/semver/functions/satisfies.d.ts","../node_modules/@types/semver/ranges/max-satisfying.d.ts","../node_modules/@types/semver/ranges/min-satisfying.d.ts","../node_modules/@types/semver/ranges/to-comparators.d.ts","../node_modules/@types/semver/ranges/min-version.d.ts","../node_modules/@types/semver/ranges/valid.d.ts","../node_modules/@types/semver/ranges/outside.d.ts","../node_modules/@types/semver/ranges/gtr.d.ts","../node_modules/@types/semver/ranges/ltr.d.ts","../node_modules/@types/semver/ranges/intersects.d.ts","../node_modules/@types/semver/ranges/simplify.d.ts","../node_modules/@types/semver/ranges/subset.d.ts","../node_modules/@types/semver/internals/identifiers.d.ts","../node_modules/@types/semver/index.d.ts","../node_modules/@bugsnag/core/types/event.d.ts","../node_modules/@bugsnag/core/types/session.d.ts","../node_modules/@bugsnag/core/types/client.d.ts","../node_modules/@bugsnag/core/types/common.d.ts","../node_modules/@bugsnag/core/types/breadcrumb.d.ts","../node_modules/@bugsnag/core/types/bugsnag.d.ts","../node_modules/@bugsnag/core/types/index.d.ts","../node_modules/@bugsnag/browser/types/bugsnag.d.ts","../node_modules/@bugsnag/node/types/bugsnag.d.ts","../node_modules/@bugsnag/js/types.d.ts","../node_modules/@netlify/build-info/lib/build-systems/build-system.d.ts","../node_modules/@netlify/build-info/lib/events.d.ts","../node_modules/@netlify/build-info/lib/metrics.d.ts","../node_modules/@netlify/build-info/lib/package-managers/detect-package-manager.d.ts","../node_modules/@netlify/build-info/lib/runtime/runtime.d.ts","../node_modules/@netlify/build-info/lib/settings/get-build-settings.d.ts","../node_modules/@netlify/build-info/lib/frameworks/analog.d.ts","../node_modules/@netlify/build-info/lib/frameworks/angular.d.ts","../node_modules/@netlify/build-info/lib/frameworks/assemble.d.ts","../node_modules/@netlify/build-info/lib/frameworks/astro.d.ts","../node_modules/@netlify/build-info/lib/frameworks/blitz.d.ts","../node_modules/@netlify/build-info/lib/frameworks/brunch.d.ts","../node_modules/@netlify/build-info/lib/frameworks/cecil.d.ts","../node_modules/@netlify/build-info/lib/frameworks/docpad.d.ts","../node_modules/@netlify/build-info/lib/frameworks/docusaurus.d.ts","../node_modules/@netlify/build-info/lib/frameworks/eleventy.d.ts","../node_modules/@netlify/build-info/lib/frameworks/ember.d.ts","../node_modules/@netlify/build-info/lib/frameworks/expo.d.ts","../node_modules/@netlify/build-info/lib/frameworks/gatsby.d.ts","../node_modules/@netlify/build-info/lib/frameworks/gridsome.d.ts","../node_modules/@netlify/build-info/lib/frameworks/grunt.d.ts","../node_modules/@netlify/build-info/lib/frameworks/gulp.d.ts","../node_modules/@netlify/build-info/lib/frameworks/harp.d.ts","../node_modules/@netlify/build-info/lib/frameworks/hexo.d.ts","../node_modules/@netlify/build-info/lib/frameworks/hugo.d.ts","../node_modules/@netlify/build-info/lib/frameworks/hydrogen.d.ts","../node_modules/@netlify/build-info/lib/frameworks/jekyll.d.ts","../node_modules/@netlify/build-info/lib/frameworks/metalsmith.d.ts","../node_modules/@netlify/build-info/lib/frameworks/middleman.d.ts","../node_modules/@netlify/build-info/lib/frameworks/next.d.ts","../node_modules/@netlify/build-info/lib/frameworks/nuxt.d.ts","../node_modules/@netlify/build-info/lib/frameworks/observable.d.ts","../node_modules/@netlify/build-info/lib/frameworks/parcel.d.ts","../node_modules/@netlify/build-info/lib/frameworks/phenomic.d.ts","../node_modules/@netlify/build-info/lib/frameworks/quasar.d.ts","../node_modules/@netlify/build-info/lib/frameworks/qwik.d.ts","../node_modules/@netlify/build-info/lib/frameworks/react-router.d.ts","../node_modules/@netlify/build-info/lib/frameworks/react-static.d.ts","../node_modules/@netlify/build-info/lib/frameworks/react.d.ts","../node_modules/@netlify/build-info/lib/frameworks/redwoodjs.d.ts","../node_modules/@netlify/build-info/lib/frameworks/remix.d.ts","../node_modules/@netlify/build-info/lib/frameworks/roots.d.ts","../node_modules/@netlify/build-info/lib/frameworks/sapper.d.ts","../node_modules/@netlify/build-info/lib/frameworks/solid-js.d.ts","../node_modules/@netlify/build-info/lib/frameworks/solid-start.d.ts","../node_modules/@netlify/build-info/lib/frameworks/stencil.d.ts","../node_modules/@netlify/build-info/lib/frameworks/svelte-kit.d.ts","../node_modules/@netlify/build-info/lib/frameworks/svelte.d.ts","../node_modules/@netlify/build-info/lib/frameworks/tanstack-router.d.ts","../node_modules/@netlify/build-info/lib/frameworks/tanstack-start.d.ts","../node_modules/@netlify/build-info/lib/frameworks/vite.d.ts","../node_modules/@netlify/build-info/lib/frameworks/vue.d.ts","../node_modules/@netlify/build-info/lib/frameworks/vuepress.d.ts","../node_modules/@netlify/build-info/lib/frameworks/wintersmith.d.ts","../node_modules/@netlify/build-info/lib/frameworks/wmr.d.ts","../node_modules/@netlify/build-info/lib/frameworks/zola.d.ts","../node_modules/@netlify/build-info/lib/frameworks/index.d.ts","../node_modules/@netlify/build-info/lib/workspaces/detect-workspace.d.ts","../node_modules/@netlify/build-info/lib/project.d.ts","../node_modules/@netlify/build-info/lib/frameworks/framework.d.ts","../node_modules/@netlify/build-info/lib/get-framework.d.ts","../node_modules/@netlify/build-info/lib/settings/get-toml-settings.d.ts","../node_modules/@netlify/build-info/lib/settings/netlify-toml.d.ts","../node_modules/@netlify/build-info/lib/index.d.ts","../node_modules/@netlify/build-info/lib/node/file-system.d.ts","../node_modules/@netlify/build-info/lib/node/get-build-info.d.ts","../node_modules/@netlify/build-info/lib/node/index.d.ts","../node_modules/@netlify/config/lib/events.d.ts","../node_modules/@netlify/config/lib/log/cleanup.d.ts","../node_modules/@netlify/config/lib/types/api.d.ts","../node_modules/@netlify/config/lib/types/options.d.ts","../node_modules/@netlify/config/lib/api/site_info.d.ts","../node_modules/@netlify/config/lib/main.d.ts","../node_modules/@netlify/config/lib/merge.d.ts","../node_modules/@netlify/config/lib/mutations/apply.d.ts","../node_modules/@netlify/config/lib/mutations/update.d.ts","../node_modules/@netlify/config/lib/index.d.ts","../node_modules/ci-info/index.d.ts","../node_modules/commander/typings/index.d.ts","../node_modules/commander/typings/esm.d.mts","../node_modules/@types/ms/index.d.ts","../node_modules/@types/debug/index.d.ts","../node_modules/locate-path/index.d.ts","../node_modules/find-up/index.d.ts","../node_modules/rxjs/dist/types/internal/subscription.d.ts","../node_modules/rxjs/dist/types/internal/subscriber.d.ts","../node_modules/rxjs/dist/types/internal/operator.d.ts","../node_modules/rxjs/dist/types/internal/observable.d.ts","../node_modules/rxjs/dist/types/internal/types.d.ts","../node_modules/rxjs/dist/types/internal/operators/audit.d.ts","../node_modules/rxjs/dist/types/internal/operators/audittime.d.ts","../node_modules/rxjs/dist/types/internal/operators/buffer.d.ts","../node_modules/rxjs/dist/types/internal/operators/buffercount.d.ts","../node_modules/rxjs/dist/types/internal/operators/buffertime.d.ts","../node_modules/rxjs/dist/types/internal/operators/buffertoggle.d.ts","../node_modules/rxjs/dist/types/internal/operators/bufferwhen.d.ts","../node_modules/rxjs/dist/types/internal/operators/catcherror.d.ts","../node_modules/rxjs/dist/types/internal/operators/combinelatestall.d.ts","../node_modules/rxjs/dist/types/internal/operators/combineall.d.ts","../node_modules/rxjs/dist/types/internal/operators/combinelatest.d.ts","../node_modules/rxjs/dist/types/internal/operators/combinelatestwith.d.ts","../node_modules/rxjs/dist/types/internal/operators/concat.d.ts","../node_modules/rxjs/dist/types/internal/operators/concatall.d.ts","../node_modules/rxjs/dist/types/internal/operators/concatmap.d.ts","../node_modules/rxjs/dist/types/internal/operators/concatmapto.d.ts","../node_modules/rxjs/dist/types/internal/operators/concatwith.d.ts","../node_modules/rxjs/dist/types/internal/operators/connect.d.ts","../node_modules/rxjs/dist/types/internal/operators/count.d.ts","../node_modules/rxjs/dist/types/internal/operators/debounce.d.ts","../node_modules/rxjs/dist/types/internal/operators/debouncetime.d.ts","../node_modules/rxjs/dist/types/internal/operators/defaultifempty.d.ts","../node_modules/rxjs/dist/types/internal/operators/delay.d.ts","../node_modules/rxjs/dist/types/internal/operators/delaywhen.d.ts","../node_modules/rxjs/dist/types/internal/operators/dematerialize.d.ts","../node_modules/rxjs/dist/types/internal/operators/distinct.d.ts","../node_modules/rxjs/dist/types/internal/operators/distinctuntilchanged.d.ts","../node_modules/rxjs/dist/types/internal/operators/distinctuntilkeychanged.d.ts","../node_modules/rxjs/dist/types/internal/operators/elementat.d.ts","../node_modules/rxjs/dist/types/internal/operators/endwith.d.ts","../node_modules/rxjs/dist/types/internal/operators/every.d.ts","../node_modules/rxjs/dist/types/internal/operators/exhaustall.d.ts","../node_modules/rxjs/dist/types/internal/operators/exhaust.d.ts","../node_modules/rxjs/dist/types/internal/operators/exhaustmap.d.ts","../node_modules/rxjs/dist/types/internal/operators/expand.d.ts","../node_modules/rxjs/dist/types/internal/operators/filter.d.ts","../node_modules/rxjs/dist/types/internal/operators/finalize.d.ts","../node_modules/rxjs/dist/types/internal/operators/find.d.ts","../node_modules/rxjs/dist/types/internal/operators/findindex.d.ts","../node_modules/rxjs/dist/types/internal/operators/first.d.ts","../node_modules/rxjs/dist/types/internal/subject.d.ts","../node_modules/rxjs/dist/types/internal/operators/groupby.d.ts","../node_modules/rxjs/dist/types/internal/operators/ignoreelements.d.ts","../node_modules/rxjs/dist/types/internal/operators/isempty.d.ts","../node_modules/rxjs/dist/types/internal/operators/last.d.ts","../node_modules/rxjs/dist/types/internal/operators/map.d.ts","../node_modules/rxjs/dist/types/internal/operators/mapto.d.ts","../node_modules/rxjs/dist/types/internal/notification.d.ts","../node_modules/rxjs/dist/types/internal/operators/materialize.d.ts","../node_modules/rxjs/dist/types/internal/operators/max.d.ts","../node_modules/rxjs/dist/types/internal/operators/merge.d.ts","../node_modules/rxjs/dist/types/internal/operators/mergeall.d.ts","../node_modules/rxjs/dist/types/internal/operators/mergemap.d.ts","../node_modules/rxjs/dist/types/internal/operators/flatmap.d.ts","../node_modules/rxjs/dist/types/internal/operators/mergemapto.d.ts","../node_modules/rxjs/dist/types/internal/operators/mergescan.d.ts","../node_modules/rxjs/dist/types/internal/operators/mergewith.d.ts","../node_modules/rxjs/dist/types/internal/operators/min.d.ts","../node_modules/rxjs/dist/types/internal/observable/connectableobservable.d.ts","../node_modules/rxjs/dist/types/internal/operators/multicast.d.ts","../node_modules/rxjs/dist/types/internal/operators/observeon.d.ts","../node_modules/rxjs/dist/types/internal/operators/onerrorresumenextwith.d.ts","../node_modules/rxjs/dist/types/internal/operators/pairwise.d.ts","../node_modules/rxjs/dist/types/internal/operators/partition.d.ts","../node_modules/rxjs/dist/types/internal/operators/pluck.d.ts","../node_modules/rxjs/dist/types/internal/operators/publish.d.ts","../node_modules/rxjs/dist/types/internal/operators/publishbehavior.d.ts","../node_modules/rxjs/dist/types/internal/operators/publishlast.d.ts","../node_modules/rxjs/dist/types/internal/operators/publishreplay.d.ts","../node_modules/rxjs/dist/types/internal/operators/race.d.ts","../node_modules/rxjs/dist/types/internal/operators/racewith.d.ts","../node_modules/rxjs/dist/types/internal/operators/reduce.d.ts","../node_modules/rxjs/dist/types/internal/operators/repeat.d.ts","../node_modules/rxjs/dist/types/internal/operators/repeatwhen.d.ts","../node_modules/rxjs/dist/types/internal/operators/retry.d.ts","../node_modules/rxjs/dist/types/internal/operators/retrywhen.d.ts","../node_modules/rxjs/dist/types/internal/operators/refcount.d.ts","../node_modules/rxjs/dist/types/internal/operators/sample.d.ts","../node_modules/rxjs/dist/types/internal/operators/sampletime.d.ts","../node_modules/rxjs/dist/types/internal/operators/scan.d.ts","../node_modules/rxjs/dist/types/internal/operators/sequenceequal.d.ts","../node_modules/rxjs/dist/types/internal/operators/share.d.ts","../node_modules/rxjs/dist/types/internal/operators/sharereplay.d.ts","../node_modules/rxjs/dist/types/internal/operators/single.d.ts","../node_modules/rxjs/dist/types/internal/operators/skip.d.ts","../node_modules/rxjs/dist/types/internal/operators/skiplast.d.ts","../node_modules/rxjs/dist/types/internal/operators/skipuntil.d.ts","../node_modules/rxjs/dist/types/internal/operators/skipwhile.d.ts","../node_modules/rxjs/dist/types/internal/operators/startwith.d.ts","../node_modules/rxjs/dist/types/internal/operators/subscribeon.d.ts","../node_modules/rxjs/dist/types/internal/operators/switchall.d.ts","../node_modules/rxjs/dist/types/internal/operators/switchmap.d.ts","../node_modules/rxjs/dist/types/internal/operators/switchmapto.d.ts","../node_modules/rxjs/dist/types/internal/operators/switchscan.d.ts","../node_modules/rxjs/dist/types/internal/operators/take.d.ts","../node_modules/rxjs/dist/types/internal/operators/takelast.d.ts","../node_modules/rxjs/dist/types/internal/operators/takeuntil.d.ts","../node_modules/rxjs/dist/types/internal/operators/takewhile.d.ts","../node_modules/rxjs/dist/types/internal/operators/tap.d.ts","../node_modules/rxjs/dist/types/internal/operators/throttle.d.ts","../node_modules/rxjs/dist/types/internal/operators/throttletime.d.ts","../node_modules/rxjs/dist/types/internal/operators/throwifempty.d.ts","../node_modules/rxjs/dist/types/internal/operators/timeinterval.d.ts","../node_modules/rxjs/dist/types/internal/operators/timeout.d.ts","../node_modules/rxjs/dist/types/internal/operators/timeoutwith.d.ts","../node_modules/rxjs/dist/types/internal/operators/timestamp.d.ts","../node_modules/rxjs/dist/types/internal/operators/toarray.d.ts","../node_modules/rxjs/dist/types/internal/operators/window.d.ts","../node_modules/rxjs/dist/types/internal/operators/windowcount.d.ts","../node_modules/rxjs/dist/types/internal/operators/windowtime.d.ts","../node_modules/rxjs/dist/types/internal/operators/windowtoggle.d.ts","../node_modules/rxjs/dist/types/internal/operators/windowwhen.d.ts","../node_modules/rxjs/dist/types/internal/operators/withlatestfrom.d.ts","../node_modules/rxjs/dist/types/internal/operators/zip.d.ts","../node_modules/rxjs/dist/types/internal/operators/zipall.d.ts","../node_modules/rxjs/dist/types/internal/operators/zipwith.d.ts","../node_modules/rxjs/dist/types/operators/index.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/action.d.ts","../node_modules/rxjs/dist/types/internal/scheduler.d.ts","../node_modules/rxjs/dist/types/internal/testing/testmessage.d.ts","../node_modules/rxjs/dist/types/internal/testing/subscriptionlog.d.ts","../node_modules/rxjs/dist/types/internal/testing/subscriptionloggable.d.ts","../node_modules/rxjs/dist/types/internal/testing/coldobservable.d.ts","../node_modules/rxjs/dist/types/internal/testing/hotobservable.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/asyncscheduler.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/timerhandle.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/asyncaction.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/virtualtimescheduler.d.ts","../node_modules/rxjs/dist/types/internal/testing/testscheduler.d.ts","../node_modules/rxjs/dist/types/testing/index.d.ts","../node_modules/rxjs/dist/types/internal/symbol/observable.d.ts","../node_modules/rxjs/dist/types/internal/observable/dom/animationframes.d.ts","../node_modules/rxjs/dist/types/internal/behaviorsubject.d.ts","../node_modules/rxjs/dist/types/internal/replaysubject.d.ts","../node_modules/rxjs/dist/types/internal/asyncsubject.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/asapscheduler.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/asap.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/async.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/queuescheduler.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/queue.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/animationframescheduler.d.ts","../node_modules/rxjs/dist/types/internal/scheduler/animationframe.d.ts","../node_modules/rxjs/dist/types/internal/util/identity.d.ts","../node_modules/rxjs/dist/types/internal/util/pipe.d.ts","../node_modules/rxjs/dist/types/internal/util/noop.d.ts","../node_modules/rxjs/dist/types/internal/util/isobservable.d.ts","../node_modules/rxjs/dist/types/internal/lastvaluefrom.d.ts","../node_modules/rxjs/dist/types/internal/firstvaluefrom.d.ts","../node_modules/rxjs/dist/types/internal/util/argumentoutofrangeerror.d.ts","../node_modules/rxjs/dist/types/internal/util/emptyerror.d.ts","../node_modules/rxjs/dist/types/internal/util/notfounderror.d.ts","../node_modules/rxjs/dist/types/internal/util/objectunsubscribederror.d.ts","../node_modules/rxjs/dist/types/internal/util/sequenceerror.d.ts","../node_modules/rxjs/dist/types/internal/util/unsubscriptionerror.d.ts","../node_modules/rxjs/dist/types/internal/observable/bindcallback.d.ts","../node_modules/rxjs/dist/types/internal/observable/bindnodecallback.d.ts","../node_modules/rxjs/dist/types/internal/anycatcher.d.ts","../node_modules/rxjs/dist/types/internal/observable/combinelatest.d.ts","../node_modules/rxjs/dist/types/internal/observable/concat.d.ts","../node_modules/rxjs/dist/types/internal/observable/connectable.d.ts","../node_modules/rxjs/dist/types/internal/observable/defer.d.ts","../node_modules/rxjs/dist/types/internal/observable/empty.d.ts","../node_modules/rxjs/dist/types/internal/observable/forkjoin.d.ts","../node_modules/rxjs/dist/types/internal/observable/from.d.ts","../node_modules/rxjs/dist/types/internal/observable/fromevent.d.ts","../node_modules/rxjs/dist/types/internal/observable/fromeventpattern.d.ts","../node_modules/rxjs/dist/types/internal/observable/generate.d.ts","../node_modules/rxjs/dist/types/internal/observable/iif.d.ts","../node_modules/rxjs/dist/types/internal/observable/interval.d.ts","../node_modules/rxjs/dist/types/internal/observable/merge.d.ts","../node_modules/rxjs/dist/types/internal/observable/never.d.ts","../node_modules/rxjs/dist/types/internal/observable/of.d.ts","../node_modules/rxjs/dist/types/internal/observable/onerrorresumenext.d.ts","../node_modules/rxjs/dist/types/internal/observable/pairs.d.ts","../node_modules/rxjs/dist/types/internal/observable/partition.d.ts","../node_modules/rxjs/dist/types/internal/observable/race.d.ts","../node_modules/rxjs/dist/types/internal/observable/range.d.ts","../node_modules/rxjs/dist/types/internal/observable/throwerror.d.ts","../node_modules/rxjs/dist/types/internal/observable/timer.d.ts","../node_modules/rxjs/dist/types/internal/observable/using.d.ts","../node_modules/rxjs/dist/types/internal/observable/zip.d.ts","../node_modules/rxjs/dist/types/internal/scheduled/scheduled.d.ts","../node_modules/rxjs/dist/types/internal/config.d.ts","../node_modules/rxjs/dist/types/index.d.ts","../node_modules/@types/through/index.d.ts","../node_modules/@types/inquirer/lib/objects/choice.d.ts","../node_modules/@types/inquirer/lib/objects/separator.d.ts","../node_modules/@types/inquirer/lib/objects/choices.d.ts","../node_modules/@types/inquirer/lib/utils/screen-manager.d.ts","../node_modules/@types/inquirer/lib/prompts/base.d.ts","../node_modules/@types/inquirer/lib/utils/paginator.d.ts","../node_modules/@types/inquirer/lib/prompts/checkbox.d.ts","../node_modules/@types/inquirer/lib/prompts/confirm.d.ts","../node_modules/@types/inquirer/lib/prompts/editor.d.ts","../node_modules/@types/inquirer/lib/prompts/expand.d.ts","../node_modules/@types/inquirer/lib/prompts/input.d.ts","../node_modules/@types/inquirer/lib/prompts/list.d.ts","../node_modules/@types/inquirer/lib/prompts/number.d.ts","../node_modules/@types/inquirer/lib/prompts/password.d.ts","../node_modules/@types/inquirer/lib/prompts/rawlist.d.ts","../node_modules/@types/inquirer/lib/ui/baseui.d.ts","../node_modules/@types/inquirer/lib/ui/bottom-bar.d.ts","../node_modules/@types/inquirer/lib/ui/prompt.d.ts","../node_modules/@types/inquirer/lib/utils/events.d.ts","../node_modules/@types/inquirer/lib/utils/readline.d.ts","../node_modules/@types/inquirer/index.d.ts","../node_modules/@types/inquirer-autocomplete-prompt/index.d.ts","../node_modules/@types/lodash/common/common.d.ts","../node_modules/@types/lodash/common/array.d.ts","../node_modules/@types/lodash/common/collection.d.ts","../node_modules/@types/lodash/common/date.d.ts","../node_modules/@types/lodash/common/function.d.ts","../node_modules/@types/lodash/common/lang.d.ts","../node_modules/@types/lodash/common/math.d.ts","../node_modules/@types/lodash/common/number.d.ts","../node_modules/@types/lodash/common/object.d.ts","../node_modules/@types/lodash/common/seq.d.ts","../node_modules/@types/lodash/common/string.d.ts","../node_modules/@types/lodash/common/util.d.ts","../node_modules/@types/lodash/index.d.ts","../node_modules/@types/lodash/merge.d.ts","../node_modules/@types/lodash/pick.d.ts","../node_modules/https-proxy-agent/node_modules/agent-base/dist/helpers.d.ts","../node_modules/https-proxy-agent/node_modules/agent-base/dist/index.d.ts","../node_modules/https-proxy-agent/dist/index.d.ts","../node_modules/wait-port/index.d.ts","../node_modules/chalk/source/vendor/ansi-styles/index.d.ts","../node_modules/chalk/source/vendor/supports-color/index.d.ts","../node_modules/chalk/source/index.d.ts","../node_modules/anymatch/index.d.ts","../node_modules/chokidar/types/index.d.ts","../node_modules/decache/decache.d.ts","../node_modules/is-wsl/index.d.ts","../node_modules/@types/lodash/debounce.d.ts","../node_modules/terminal-link/index.d.ts","../node_modules/picocolors/types.d.ts","../node_modules/nanospinner/dist/index.d.ts","../src/lib/spinner.ts","../node_modules/dot-prop/node_modules/type-fest/index.d.ts","../node_modules/dot-prop/index.d.ts","../node_modules/uuid/dist/esm/types.d.ts","../node_modules/uuid/dist/esm/max.d.ts","../node_modules/uuid/dist/esm/nil.d.ts","../node_modules/uuid/dist/esm/parse.d.ts","../node_modules/uuid/dist/esm/stringify.d.ts","../node_modules/uuid/dist/esm/v1.d.ts","../node_modules/uuid/dist/esm/v1tov6.d.ts","../node_modules/uuid/dist/esm/v35.d.ts","../node_modules/uuid/dist/esm/v3.d.ts","../node_modules/uuid/dist/esm/v4.d.ts","../node_modules/uuid/dist/esm/v5.d.ts","../node_modules/uuid/dist/esm/v6.d.ts","../node_modules/uuid/dist/esm/v6tov1.d.ts","../node_modules/uuid/dist/esm/v7.d.ts","../node_modules/uuid/dist/esm/validate.d.ts","../node_modules/uuid/dist/esm/version.d.ts","../node_modules/uuid/dist/esm/index.d.ts","../node_modules/@types/write-file-atomic/index.d.ts","../node_modules/env-paths/index.d.ts","../src/lib/settings.ts","../src/utils/get-global-config-store.ts","../src/utils/get-cli-package-json.ts","../node_modules/execa/index.d.ts","../src/utils/execa.ts","../src/utils/telemetry/utils.ts","../src/utils/telemetry/report-error.ts","../src/utils/cli-state.ts","../src/utils/types.ts","../node_modules/@netlify/build/lib/core/constants.d.ts","../node_modules/@netlify/build/lib/types/utils/many.d.ts","../node_modules/@netlify/build/lib/types/config/build.d.ts","../node_modules/@netlify/build/lib/types/config/functions.d.ts","../node_modules/@netlify/build/lib/types/utils/json_value.d.ts","../node_modules/@netlify/build/lib/types/config/inputs.d.ts","../node_modules/@netlify/build/lib/types/config/netlify_config.d.ts","../node_modules/@netlify/build/lib/plugins_core/types.d.ts","../node_modules/@netlify/build/node_modules/execa/index.d.ts","../node_modules/@netlify/build/lib/plugins/node_version.d.ts","../node_modules/@netlify/build/lib/plugins/spawn.d.ts","../node_modules/@netlify/build/lib/log/stream.d.ts","../node_modules/@netlify/build/lib/log/output_flusher.d.ts","../node_modules/@netlify/build/lib/log/logger.d.ts","../node_modules/@netlify/build/lib/core/types.d.ts","../node_modules/@netlify/build/lib/core/main.d.ts","../node_modules/@netlify/build/lib/types/options/netlify_plugin_build_util.d.ts","../node_modules/@netlify/build/lib/types/options/netlify_plugin_cache_util.d.ts","../node_modules/zod/lib/helpers/typealiases.d.ts","../node_modules/zod/lib/helpers/util.d.ts","../node_modules/zod/lib/zoderror.d.ts","../node_modules/zod/lib/locales/en.d.ts","../node_modules/zod/lib/errors.d.ts","../node_modules/zod/lib/helpers/parseutil.d.ts","../node_modules/zod/lib/helpers/enumutil.d.ts","../node_modules/zod/lib/helpers/errorutil.d.ts","../node_modules/zod/lib/helpers/partialutil.d.ts","../node_modules/zod/lib/standard-schema.d.ts","../node_modules/zod/lib/types.d.ts","../node_modules/zod/lib/external.d.ts","../node_modules/zod/lib/index.d.ts","../node_modules/zod/index.d.ts","../node_modules/@netlify/zip-it-and-ship-it/dist/types/utils.d.ts","../node_modules/@netlify/zip-it-and-ship-it/dist/archive.d.ts","../node_modules/@netlify/zip-it-and-ship-it/dist/feature_flags.d.ts","../node_modules/@netlify/zip-it-and-ship-it/dist/rate_limit.d.ts","../node_modules/@netlify/zip-it-and-ship-it/dist/utils/cache.d.ts","../node_modules/@netlify/zip-it-and-ship-it/dist/utils/logger.d.ts","../node_modules/esbuild/lib/main.d.ts","../node_modules/@netlify/zip-it-and-ship-it/dist/runtimes/node/utils/module_format.d.ts","../node_modules/@netlify/zip-it-and-ship-it/dist/runtimes/node/bundlers/types.d.ts","../node_modules/@babel/types/lib/index.d.ts","../node_modules/@netlify/zip-it-and-ship-it/dist/utils/routes.d.ts","../node_modules/@netlify/zip-it-and-ship-it/dist/runtimes/node/in_source_config/index.d.ts","../node_modules/@netlify/zip-it-and-ship-it/dist/runtimes/runtime.d.ts","../node_modules/@netlify/zip-it-and-ship-it/dist/function.d.ts","../node_modules/@netlify/zip-it-and-ship-it/dist/config.d.ts","../node_modules/@netlify/zip-it-and-ship-it/dist/utils/format_result.d.ts","../node_modules/@netlify/zip-it-and-ship-it/dist/zip.d.ts","../node_modules/@netlify/zip-it-and-ship-it/dist/manifest.d.ts","../node_modules/@netlify/zip-it-and-ship-it/dist/main.d.ts","../node_modules/@netlify/build/lib/types/options/netlify_plugin_functions_util.d.ts","../node_modules/@netlify/build/lib/types/options/netlify_plugin_git_util.d.ts","../node_modules/@netlify/build/lib/types/options/netlify_plugin_run_util.d.ts","../node_modules/@netlify/build/lib/types/options/netlify_plugin_status_util.d.ts","../node_modules/@netlify/build/lib/types/options/netlify_plugin_utils.d.ts","../node_modules/@netlify/build/lib/types/netlify_plugin_options.d.ts","../node_modules/@netlify/build/lib/types/netlify_event_handler.d.ts","../node_modules/@netlify/build/lib/types/netlify_plugin.d.ts","../node_modules/@netlify/build/lib/core/dev.d.ts","../node_modules/@netlify/build/lib/steps/run_core_steps.d.ts","../node_modules/@netlify/build/lib/index.d.ts","../node_modules/@netlify/headers-parser/lib/types.d.ts","../node_modules/@netlify/headers-parser/lib/all.d.ts","../node_modules/@netlify/headers-parser/lib/index.d.ts","../src/utils/feature-flags.ts","../node_modules/@netlify/edge-functions/node/dist/version.d.mts","../src/lib/edge-functions/bootstrap.ts","../src/lib/edge-functions/consts.ts","../node_modules/@netlify/edge-bundler/node_modules/execa/index.d.ts","../node_modules/@netlify/edge-bundler/dist/node/logger.d.ts","../node_modules/@netlify/edge-bundler/dist/node/bridge.d.ts","../node_modules/@netlify/edge-bundler/dist/node/edge_function.d.ts","../node_modules/@import-maps/resolve/types/src/types.d.ts","../node_modules/@import-maps/resolve/types/src/parser.d.ts","../node_modules/@import-maps/resolve/types/src/resolver.d.ts","../node_modules/@import-maps/resolve/types/index.d.ts","../node_modules/@netlify/edge-bundler/dist/node/import_map.d.ts","../node_modules/@netlify/edge-bundler/dist/node/rate_limit.d.ts","../node_modules/@netlify/edge-bundler/dist/node/config.d.ts","../node_modules/@netlify/edge-bundler/dist/node/feature_flags.d.ts","../node_modules/@netlify/edge-bundler/dist/node/declaration.d.ts","../node_modules/@netlify/edge-bundler/dist/node/bundle.d.ts","../node_modules/@netlify/edge-bundler/dist/node/layer.d.ts","../node_modules/@netlify/edge-bundler/dist/node/manifest.d.ts","../node_modules/@netlify/edge-bundler/dist/node/bundler.d.ts","../node_modules/@netlify/edge-bundler/dist/node/finder.d.ts","../node_modules/@netlify/edge-bundler/dist/node/vendor/module_graph/media_type.d.ts","../node_modules/@netlify/edge-bundler/dist/node/vendor/module_graph/module_graph.d.ts","../node_modules/@netlify/edge-bundler/dist/node/server/server.d.ts","../node_modules/@netlify/edge-bundler/dist/node/validation/manifest/error.d.ts","../node_modules/@netlify/edge-bundler/dist/node/validation/manifest/index.d.ts","../node_modules/@netlify/edge-bundler/dist/node/index.d.ts","../node_modules/get-port/index.d.ts","../src/utils/frameworks-api.ts","../src/commands/types.d.ts","../node_modules/@netlify/blobs/dist/server.d.ts","../src/lib/blobs/blobs.ts","../src/lib/geo-location.ts","../src/lib/edge-functions/headers.ts","../src/utils/multimap.ts","../src/lib/edge-functions/registry.ts","../src/lib/edge-functions/proxy.ts","../src/lib/build.ts","../src/utils/command-helpers.ts","../src/lib/http-agent.ts","../src/utils/get-site.ts","../node_modules/open/index.d.ts","../node_modules/is-docker/index.d.ts","../src/utils/open-browser.ts","../src/utils/telemetry/validation.ts","../src/utils/telemetry/telemetry.ts","../src/utils/telemetry/index.ts","../src/commands/base-command.ts","../node_modules/@types/envinfo/index.d.ts","../node_modules/fastest-levenshtein/mod.d.ts","../src/utils/nodejs-compile-cache.ts","../src/commands/api/api.ts","../src/commands/api/index.ts","../src/utils/hooks/requires-site-info.ts","../node_modules/@netlify/blobs/dist/main.d.ts","../src/utils/prompts/confirm-prompt.ts","../src/utils/prompts/prompt-messages.ts","../src/utils/prompts/blob-delete-prompts.ts","../src/commands/blobs/blobs-delete.ts","../src/commands/blobs/blobs-get.ts","../src/commands/blobs/blobs-list.ts","../src/utils/prompts/blob-set-prompt.ts","../src/commands/blobs/blobs-set.ts","../src/commands/blobs/blobs.ts","../src/utils/env/index.ts","../node_modules/fuzzy/lib/fuzzy.d.ts","../src/utils/build-info.ts","../src/commands/build/build.ts","../src/commands/build/index.ts","../src/commands/clone/option_values.ts","../node_modules/@types/parse-github-url/index.d.ts","../src/utils/normalize-repo-url.ts","../src/utils/run-git.ts","../node_modules/@types/lodash/isempty.d.ts","../src/lib/api.ts","../node_modules/git-repo-info/index.d.ts","../node_modules/@types/gitconfiglocal/index.d.ts","../src/utils/get-repo-data.ts","../node_modules/@types/parse-gitignore/index.d.ts","../src/lib/fs.ts","../src/utils/gitignore.ts","../src/commands/link/option_values.ts","../src/commands/link/link.ts","../src/commands/clone/clone.ts","../src/commands/clone/index.ts","../node_modules/@pnpm/tabtab/types/constants.d.ts","../node_modules/@pnpm/tabtab/types/index.d.ts","../src/lib/completion/constants.ts","../src/lib/completion/generate-autocompletion.ts","../src/lib/completion/index.ts","../src/commands/completion/completion.ts","../src/commands/completion/index.ts","../src/commands/deploy/option_values.ts","../node_modules/@types/lodash/isobject.d.ts","../node_modules/@netlify/redirect-parser/lib/all.d.ts","../node_modules/@netlify/redirect-parser/lib/index.d.ts","../node_modules/@types/prettyjson/index.d.ts","../src/lib/functions/config.ts","../src/lib/log.ts","../src/utils/deploy/constants.ts","../node_modules/clean-deep/index.d.ts","../src/lib/edge-functions/deploy.ts","../src/utils/deploy/hash-config.ts","../node_modules/@types/folder-walker/index.d.ts","../node_modules/@types/parallel-transform/index.d.ts","../node_modules/p-timeout/index.d.ts","../node_modules/p-wait-for/index.d.ts","../src/utils/deploy/util.ts","../src/utils/deploy/status-cb.ts","../src/utils/deploy/hasher-segments.ts","../src/utils/deploy/hash-files.ts","../src/utils/functions/functions.ts","../src/utils/deploy/hash-fns.ts","../node_modules/@types/backoff/index.d.ts","../node_modules/p-map/index.d.ts","../src/utils/deploy/upload-files.ts","../src/utils/temporary-file.ts","../src/utils/deploy/deploy-site.ts","../src/utils/functions/constants.ts","../src/utils/functions/get-functions.ts","../src/utils/functions/index.ts","../node_modules/before-after-hook/index.d.ts","../node_modules/@octokit/types/dist-types/requestmethod.d.ts","../node_modules/@octokit/types/dist-types/url.d.ts","../node_modules/@octokit/types/dist-types/fetch.d.ts","../node_modules/@octokit/types/dist-types/requestrequestoptions.d.ts","../node_modules/@octokit/types/dist-types/requestheaders.d.ts","../node_modules/@octokit/types/dist-types/requestparameters.d.ts","../node_modules/@octokit/types/dist-types/endpointoptions.d.ts","../node_modules/@octokit/types/dist-types/responseheaders.d.ts","../node_modules/@octokit/types/dist-types/octokitresponse.d.ts","../node_modules/@octokit/types/dist-types/endpointdefaults.d.ts","../node_modules/@octokit/types/dist-types/requestoptions.d.ts","../node_modules/@octokit/types/dist-types/route.d.ts","../node_modules/@octokit/openapi-types/types.d.ts","../node_modules/@octokit/types/dist-types/generated/endpoints.d.ts","../node_modules/@octokit/types/dist-types/endpointinterface.d.ts","../node_modules/@octokit/types/dist-types/requestinterface.d.ts","../node_modules/@octokit/types/dist-types/authinterface.d.ts","../node_modules/@octokit/types/dist-types/requesterror.d.ts","../node_modules/@octokit/types/dist-types/strategyinterface.d.ts","../node_modules/@octokit/types/dist-types/version.d.ts","../node_modules/@octokit/types/dist-types/getresponsetypefromendpointmethod.d.ts","../node_modules/@octokit/types/dist-types/index.d.ts","../node_modules/@octokit/request/dist-types/index.d.ts","../node_modules/@octokit/graphql/dist-types/types.d.ts","../node_modules/@octokit/graphql/dist-types/error.d.ts","../node_modules/@octokit/graphql/dist-types/index.d.ts","../node_modules/@octokit/request-error/dist-types/types.d.ts","../node_modules/@octokit/request-error/dist-types/index.d.ts","../node_modules/@octokit/core/dist-types/types.d.ts","../node_modules/@octokit/core/dist-types/index.d.ts","../node_modules/@octokit/plugin-paginate-rest/dist-types/generated/paginating-endpoints.d.ts","../node_modules/@octokit/plugin-paginate-rest/dist-types/types.d.ts","../node_modules/@octokit/plugin-paginate-rest/dist-types/compose-paginate.d.ts","../node_modules/@octokit/plugin-paginate-rest/dist-types/paginating-endpoints.d.ts","../node_modules/@octokit/plugin-paginate-rest/dist-types/index.d.ts","../node_modules/@octokit/plugin-rest-endpoint-methods/dist-types/generated/parameters-and-response-types.d.ts","../node_modules/@octokit/plugin-rest-endpoint-methods/dist-types/generated/method-types.d.ts","../node_modules/@octokit/plugin-rest-endpoint-methods/dist-types/types.d.ts","../node_modules/@octokit/plugin-rest-endpoint-methods/dist-types/index.d.ts","../node_modules/@octokit/rest/dist-types/index.d.ts","../src/utils/create-deferred.ts","../src/utils/gh-auth.ts","../src/lib/path.ts","../src/utils/init/plugins.ts","../src/utils/init/utils.ts","../src/utils/init/config-github.ts","../src/utils/init/config-manual.ts","../src/utils/init/config.ts","../src/commands/sites/sites-create.ts","../node_modules/boxen/node_modules/type-fest/index.d.ts","../node_modules/cli-boxes/index.d.ts","../node_modules/boxen/index.d.ts","../src/commands/deploy/deploy.ts","../src/commands/deploy/index.ts","../src/utils/validation.ts","../src/commands/recipes/common.ts","../src/commands/recipes/recipes.ts","../src/lib/edge-functions/editor-helper.ts","../node_modules/@types/range-parser/index.d.ts","../node_modules/@types/qs/index.d.ts","../node_modules/@types/express-serve-static-core/index.d.ts","../node_modules/@types/mime/index.d.ts","../node_modules/@types/serve-static/index.d.ts","../node_modules/@types/connect/index.d.ts","../node_modules/@types/body-parser/index.d.ts","../node_modules/@types/express/index.d.ts","../node_modules/jwt-decode/build/esm/index.d.ts","../src/lib/account.ts","../node_modules/dotenv/lib/main.d.ts","../src/utils/dot-env.ts","../src/utils/dev.ts","../src/utils/headers.ts","../node_modules/cron-parser/types/common.d.ts","../node_modules/cron-parser/types/index.d.ts","../src/lib/functions/memoized-build.ts","../node_modules/lambda-local/build/lambdalocal.d.ts","../node_modules/@netlify/local-functions-proxy/dist/index.d.ts","../src/lib/functions/local-proxy.ts","../src/lib/functions/runtimes/go/index.ts","../node_modules/read-package-up/node_modules/type-fest/index.d.ts","../node_modules/read-package-up/index.d.ts","../node_modules/source-map/source-map.d.ts","../node_modules/@types/source-map-support/index.d.ts","../src/lib/functions/runtimes/js/builders/zisi.ts","../src/lib/functions/runtimes/js/constants.ts","../node_modules/is-stream/index.d.ts","../src/lib/functions/runtimes/js/worker.ts","../src/lib/functions/runtimes/js/index.ts","../node_modules/toml/index.d.ts","../src/lib/functions/runtimes/rust/index.ts","../src/lib/functions/runtimes/index.ts","../src/lib/functions/netlify-function.ts","../src/lib/functions/utils.ts","../src/lib/functions/background.ts","../node_modules/@types/content-type/index.d.ts","../node_modules/@types/multiparty/index.d.ts","../node_modules/raw-body/index.d.ts","../src/lib/string.ts","../node_modules/@types/yauzl/index.d.ts","../node_modules/extract-zip/index.d.ts","../src/lib/functions/registry.ts","../src/lib/functions/form-submissions-handler.ts","../node_modules/ansi-to-html/lib/ansi_to_html.d.ts","../src/lib/functions/scheduled.ts","../src/lib/render-error-template.ts","../src/lib/functions/synchronous.ts","../src/lib/functions/server.ts","../src/utils/dev-server-banner.ts","../src/commands/dev/types.d.ts","../src/utils/detect-server-settings.ts","../node_modules/gh-release-fetch/dist/index.d.ts","../node_modules/isexe/dist/mjs/posix.d.ts","../node_modules/isexe/dist/mjs/win32.d.ts","../node_modules/isexe/dist/mjs/options.d.ts","../node_modules/isexe/dist/mjs/index.d.ts","../src/lib/exec-fetcher.ts","../src/utils/live-tunnel.ts","../node_modules/cookie/dist/index.d.ts","../node_modules/@types/etag/index.d.ts","../node_modules/@types/http-proxy/index.d.ts","../node_modules/http-proxy-middleware/dist/types.d.ts","../node_modules/http-proxy-middleware/dist/handlers/response-interceptor.d.ts","../node_modules/http-proxy-middleware/dist/handlers/fix-request-body.d.ts","../node_modules/http-proxy-middleware/dist/handlers/public.d.ts","../node_modules/http-proxy-middleware/dist/handlers/index.d.ts","../node_modules/http-proxy-middleware/dist/index.d.ts","../node_modules/@types/lodash/throttle.d.ts","../node_modules/p-filter/index.d.ts","../node_modules/sharp/lib/index.d.ts","../node_modules/image-meta/dist/index.d.ts","../node_modules/svgo/lib/types.d.ts","../node_modules/svgo/plugins/plugins-types.d.ts","../node_modules/svgo/lib/svgo.d.ts","../node_modules/ufo/dist/index.d.ts","../node_modules/h3/node_modules/crossws/dist/shared/crossws.bqxma5bh.d.mts","../node_modules/h3/node_modules/crossws/dist/index.d.mts","../node_modules/cookie-es/dist/index.d.cts","../node_modules/iron-webcrypto/dist/index.d.cts","../node_modules/h3/dist/index.d.ts","../node_modules/ipx/node_modules/unstorage/dist/shared/unstorage.ca7r4ql2.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/azure-app-configuration.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/azure-cosmos.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/azure-key-vault.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/azure-storage-blob.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/azure-storage-table.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/capacitor-preferences.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/cloudflare-kv-binding.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/cloudflare-kv-http.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/cloudflare-r2-binding.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/db0.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/deno-kv-node.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/deno-kv.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/fs-lite.d.ts","../node_modules/readdirp/index.d.ts","../node_modules/ipx/node_modules/chokidar/handler.d.ts","../node_modules/ipx/node_modules/chokidar/index.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/fs.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/github.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/http.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/indexedb.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/localstorage.d.ts","../node_modules/lru-cache/dist/commonjs/index.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/lru-cache.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/mongodb.d.ts","../node_modules/ipx/node_modules/@netlify/blobs/dist/main.d.cts","../node_modules/ipx/node_modules/unstorage/drivers/netlify-blobs.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/overlay.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/planetscale.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/redis.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/s3.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/session-storage.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/uploadthing.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/upstash.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/vercel-blob.d.ts","../node_modules/ipx/node_modules/unstorage/drivers/vercel-kv.d.ts","../node_modules/ipx/node_modules/unstorage/dist/index.d.ts","../node_modules/ipx/dist/index.d.mts","../src/lib/images/proxy.ts","../src/utils/create-stream-promise.ts","../node_modules/ulid/dist/types.d.ts","../node_modules/ulid/dist/ulid.d.ts","../node_modules/ulid/dist/uuid.d.ts","../node_modules/ulid/dist/crockford.d.ts","../node_modules/ulid/dist/error.d.ts","../node_modules/ulid/dist/constants.d.ts","../node_modules/ulid/dist/index.d.ts","../src/utils/request-id.ts","../src/utils/redirects.ts","../src/utils/rules-proxy.ts","../node_modules/@types/jsonwebtoken/index.d.ts","../src/utils/sign-redirect.ts","../src/utils/proxy.ts","../src/utils/proxy-server.ts","../src/utils/shell.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/node_modules/fast-uri/types/index.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/compile/codegen/code.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/compile/codegen/scope.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/compile/codegen/index.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/compile/rules.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/compile/util.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/compile/validate/subschema.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/compile/errors.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/compile/validate/index.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/compile/validate/datatype.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/applicator/additionalitems.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/applicator/items2020.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/applicator/contains.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/applicator/dependencies.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/applicator/propertynames.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/applicator/additionalproperties.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/applicator/not.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/applicator/anyof.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/applicator/oneof.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/applicator/if.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/applicator/index.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/validation/limitnumber.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/validation/multipleof.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/validation/pattern.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/validation/required.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/validation/uniqueitems.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/validation/const.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/validation/enum.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/validation/index.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/format/format.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/unevaluated/unevaluatedproperties.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/unevaluated/unevaluateditems.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/validation/dependentrequired.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/discriminator/types.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/discriminator/index.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/errors.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/types/json-schema.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/types/jtd-schema.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/runtime/validation_error.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/compile/ref_error.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/core.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/compile/resolve.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/compile/index.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/types/index.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/ajv.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/jtd/error.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/jtd/type.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/jtd/enum.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/jtd/elements.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/jtd/properties.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/jtd/discriminator.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/jtd/values.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/vocabularies/jtd/index.d.ts","../node_modules/@fastify/ajv-compiler/node_modules/ajv/dist/jtd.d.ts","../node_modules/@fastify/ajv-compiler/types/index.d.ts","../node_modules/@fastify/error/types/index.d.ts","../node_modules/fast-json-stringify/node_modules/ajv/dist/ajv.d.ts","../node_modules/fast-json-stringify/types/index.d.ts","../node_modules/@fastify/fast-json-stringify-compiler/types/index.d.ts","../node_modules/find-my-way/index.d.ts","../node_modules/light-my-request/types/index.d.ts","../node_modules/fastify/types/utils.d.ts","../node_modules/fastify/types/schema.d.ts","../node_modules/fastify/types/type-provider.d.ts","../node_modules/fastify/types/reply.d.ts","../node_modules/pino-std-serializers/index.d.ts","../node_modules/pino/node_modules/sonic-boom/types/index.d.ts","../node_modules/pino/pino.d.ts","../node_modules/fastify/types/logger.d.ts","../node_modules/fastify/types/plugin.d.ts","../node_modules/fastify/types/register.d.ts","../node_modules/fastify/types/instance.d.ts","../node_modules/fastify/types/hooks.d.ts","../node_modules/fastify/types/route.d.ts","../node_modules/fastify/types/context.d.ts","../node_modules/fastify/types/request.d.ts","../node_modules/fastify/types/content-type-parser.d.ts","../node_modules/fastify/types/errors.d.ts","../node_modules/fastify/types/serverfactory.d.ts","../node_modules/fastify/fastify.d.ts","../node_modules/@fastify/static/types/index.d.ts","../src/utils/static-server.ts","../src/utils/framework-server.ts","../src/utils/run-build.ts","../src/lib/extensions.ts","../src/commands/init/constants.ts","../src/commands/init/init.ts","../src/commands/dev/dev.ts","../src/commands/dev/index.ts","../src/commands/dev-exec/dev-exec.ts","../src/commands/dev-exec/index.ts","../src/commands/env/env-get.ts","../src/commands/env/env-import.ts","../node_modules/ansi-escapes/base.d.ts","../node_modules/ansi-escapes/index.d.ts","../node_modules/log-update/index.d.ts","../src/commands/env/env-list.ts","../src/utils/prompts/env-set-prompts.ts","../src/commands/env/env-set.ts","../src/utils/prompts/env-unset-prompts.ts","../src/commands/env/env-unset.ts","../src/utils/prompts/env-clone-prompt.ts","../src/commands/env/env-clone.ts","../src/commands/env/env.ts","../src/commands/env/index.ts","../src/commands/functions/functions-build.ts","../src/utils/addons/prepare.ts","../node_modules/readdirp/esm/index.d.ts","../src/utils/copy-template-dir/copy-template-dir.ts","../src/utils/read-repo-url.ts","../src/commands/functions/functions-create.ts","../src/commands/functions/functions-invoke.ts","../src/commands/functions/functions-list.ts","../src/commands/functions/functions-serve.ts","../src/commands/functions/functions.ts","../src/commands/functions/index.ts","../src/recipes/ai-context/context.ts","../src/recipes/ai-context/index.ts","../src/utils/mcp-utils.ts","../src/commands/init/ai-rules.ts","../src/commands/init/index.ts","../src/commands/link/index.ts","../src/commands/login/login.ts","../src/commands/login/index.ts","../src/commands/logout/logout.ts","../src/commands/logout/index.ts","../src/commands/logs/log-levels.ts","../node_modules/@types/ws/index.d.mts","../src/utils/websockets/index.ts","../src/commands/logs/build.ts","../src/commands/logs/functions.ts","../src/commands/logs/index.ts","../src/commands/open/open-admin.ts","../src/commands/open/open-site.ts","../src/commands/open/open.ts","../src/commands/open/index.ts","../src/commands/recipes/recipes-list.ts","../src/commands/recipes/index.ts","../src/commands/serve/serve.ts","../src/commands/serve/index.ts","../src/utils/sites/utils.ts","../src/utils/sites/create-template.ts","../src/commands/sites/sites-create-template.ts","../src/commands/sites/sites-list.ts","../src/commands/sites/sites-delete.ts","../src/commands/sites/sites.ts","../src/commands/sites/index.ts","../src/commands/status/status-hooks.ts","../src/commands/status/status.ts","../src/commands/status/index.ts","../src/commands/switch/switch.ts","../src/commands/switch/index.ts","../src/commands/unlink/unlink.ts","../src/commands/unlink/index.ts","../src/commands/watch/watch.ts","../src/commands/watch/index.ts","../src/commands/database/constants.ts","../src/commands/database/utils.ts","../src/commands/database/drizzle.ts","../src/commands/database/init.ts","../src/commands/database/status.ts","../src/commands/database/database.ts","../src/commands/database/index.ts","../src/commands/main.ts","../src/commands/index.ts","../src/lib/completion/get-autocompletion.ts","../src/lib/completion/script.ts","../src/recipes/blobs-migrate/index.ts","../node_modules/comment-json/index.d.ts","../src/recipes/vscode/settings.ts","../src/recipes/vscode/index.ts","../src/utils/parse-raw-flags.ts","../src/utils/scripted-commands.ts","../src/utils/run-program.ts","../src/utils/telemetry/request.ts","../node_modules/@types/configstore/index.d.ts","../node_modules/@types/eslint-config-prettier/index.d.ts","../node_modules/@types/estree/index.d.ts","../node_modules/@types/http-cache-semantics/index.d.ts","../node_modules/@types/istanbul-lib-coverage/index.d.ts","../node_modules/@types/istanbul-lib-report/index.d.ts","../node_modules/@types/istanbul-reports/index.d.ts","../node_modules/@types/json-schema/index.d.ts","../node_modules/@types/lodash.shuffle/index.d.ts","../node_modules/form-data/index.d.ts","../node_modules/@types/node-fetch/externals.d.ts","../node_modules/@types/node-fetch/index.d.ts","../node_modules/@types/picomatch/lib/constants.d.ts","../node_modules/@types/picomatch/lib/parse.d.ts","../node_modules/@types/picomatch/lib/scan.d.ts","../node_modules/@types/picomatch/lib/picomatch.d.ts","../node_modules/@types/picomatch/index.d.ts","../node_modules/@types/retry/index.d.ts","../node_modules/@types/serialize-javascript/index.d.ts","../node_modules/type-fest/source/primitive.d.ts","../node_modules/type-fest/source/typed-array.d.ts","../node_modules/type-fest/source/basic.d.ts","../node_modules/type-fest/source/observable-like.d.ts","../node_modules/type-fest/source/internal.d.ts","../node_modules/type-fest/source/except.d.ts","../node_modules/type-fest/source/simplify.d.ts","../node_modules/type-fest/source/writable.d.ts","../node_modules/type-fest/source/mutable.d.ts","../node_modules/type-fest/source/merge.d.ts","../node_modules/type-fest/source/merge-exclusive.d.ts","../node_modules/type-fest/source/require-at-least-one.d.ts","../node_modules/type-fest/source/require-exactly-one.d.ts","../node_modules/type-fest/source/require-all-or-none.d.ts","../node_modules/type-fest/source/remove-index-signature.d.ts","../node_modules/type-fest/source/partial-deep.d.ts","../node_modules/type-fest/source/partial-on-undefined-deep.d.ts","../node_modules/type-fest/source/readonly-deep.d.ts","../node_modules/type-fest/source/literal-union.d.ts","../node_modules/type-fest/source/promisable.d.ts","../node_modules/type-fest/source/opaque.d.ts","../node_modules/type-fest/source/invariant-of.d.ts","../node_modules/type-fest/source/set-optional.d.ts","../node_modules/type-fest/source/set-required.d.ts","../node_modules/type-fest/source/set-non-nullable.d.ts","../node_modules/type-fest/source/value-of.d.ts","../node_modules/type-fest/source/promise-value.d.ts","../node_modules/type-fest/source/async-return-type.d.ts","../node_modules/type-fest/source/conditional-keys.d.ts","../node_modules/type-fest/source/conditional-except.d.ts","../node_modules/type-fest/source/conditional-pick.d.ts","../node_modules/type-fest/source/union-to-intersection.d.ts","../node_modules/type-fest/source/stringified.d.ts","../node_modules/type-fest/source/fixed-length-array.d.ts","../node_modules/type-fest/source/multidimensional-array.d.ts","../node_modules/type-fest/source/multidimensional-readonly-array.d.ts","../node_modules/type-fest/source/iterable-element.d.ts","../node_modules/type-fest/source/entry.d.ts","../node_modules/type-fest/source/entries.d.ts","../node_modules/type-fest/source/set-return-type.d.ts","../node_modules/type-fest/source/asyncify.d.ts","../node_modules/type-fest/source/numeric.d.ts","../node_modules/type-fest/source/jsonify.d.ts","../node_modules/type-fest/source/schema.d.ts","../node_modules/type-fest/source/literal-to-primitive.d.ts","../node_modules/type-fest/source/string-key-of.d.ts","../node_modules/type-fest/source/exact.d.ts","../node_modules/type-fest/source/readonly-tuple.d.ts","../node_modules/type-fest/source/optional-keys-of.d.ts","../node_modules/type-fest/source/has-optional-keys.d.ts","../node_modules/type-fest/source/required-keys-of.d.ts","../node_modules/type-fest/source/has-required-keys.d.ts","../node_modules/type-fest/source/spread.d.ts","../node_modules/type-fest/source/split.d.ts","../node_modules/type-fest/source/camel-case.d.ts","../node_modules/type-fest/source/camel-cased-properties.d.ts","../node_modules/type-fest/source/camel-cased-properties-deep.d.ts","../node_modules/type-fest/source/delimiter-case.d.ts","../node_modules/type-fest/source/kebab-case.d.ts","../node_modules/type-fest/source/delimiter-cased-properties.d.ts","../node_modules/type-fest/source/kebab-cased-properties.d.ts","../node_modules/type-fest/source/delimiter-cased-properties-deep.d.ts","../node_modules/type-fest/source/kebab-cased-properties-deep.d.ts","../node_modules/type-fest/source/pascal-case.d.ts","../node_modules/type-fest/source/pascal-cased-properties.d.ts","../node_modules/type-fest/source/pascal-cased-properties-deep.d.ts","../node_modules/type-fest/source/snake-case.d.ts","../node_modules/type-fest/source/snake-cased-properties.d.ts","../node_modules/type-fest/source/snake-cased-properties-deep.d.ts","../node_modules/type-fest/source/includes.d.ts","../node_modules/type-fest/source/screaming-snake-case.d.ts","../node_modules/type-fest/source/join.d.ts","../node_modules/type-fest/source/trim.d.ts","../node_modules/type-fest/source/replace.d.ts","../node_modules/type-fest/source/get.d.ts","../node_modules/type-fest/source/last-array-element.d.ts","../node_modules/type-fest/source/package-json.d.ts","../node_modules/type-fest/source/tsconfig-json.d.ts","../node_modules/type-fest/index.d.ts","../node_modules/@types/update-notifier/node_modules/boxen/index.d.ts","../node_modules/@types/update-notifier/update-notifier.d.ts","../node_modules/@types/update-notifier/index.d.ts","../node_modules/@types/ws/index.d.ts","../node_modules/@types/yargs-parser/index.d.ts","../node_modules/@types/yargs/index.d.ts","../types/ascii-table/index.d.ts","../types/express-logging/index.d.ts","../types/lambda-local/index.d.ts","../types/maxstache/index.d.ts","../types/maxstache-stream/index.d.ts","../types/netlify-redirector/index.d.ts","../types/tomlify-j04/index.d.ts"],"fileIdsList":[[68,106],[68,106,378],[68,106,375],[68,106,374,375],[68,106,372,373,375,376],[68,106,372,373,374,376],[68,106,375,376],[68,106,372,373,374,375,376,377],[68,106,379,380],[68,106,1124,1125,1129,1156,1157,1159,1160,1161,1163,1164],[68,106,1122,1123],[68,106,1122],[68,106,1124,1164],[68,106,1124,1125,1161,1162,1164],[68,106,1164],[68,106,1121,1164,1165],[68,106,1124,1125,1163,1164],[68,106,1124,1125,1127,1128,1163,1164],[68,106,1124,1125,1126,1163,1164],[68,106,1124,1125,1129,1156,1157,1158,1159,1160,1163,1164],[68,106,1124,1129,1158,1159,1160,1161,1163,1164,1173],[68,106,1121,1124,1125,1129,1161,1163],[68,106,1129,1164],[68,106,1131,1132,1133,1134,1135,1136,1137,1138,1139,1140,1164],[68,106,1154,1164],[68,106,1130,1141,1149,1150,1151,1152,1153,1155],[68,106,1154,1164,1166],[68,106,1164,1166],[68,106,1164,1167,1168,1169,1170,1171,1172],[68,106,1129,1164,1166],[68,106,1134,1164],[68,106,1142,1143,1144,1145,1146,1147,1148,1164],[68,106,1161,1165,1174],[68,106,1178],[68,106,119,154,1200],[68,106,812,813,814],[68,106,812],[68,106,160],[62,68,106,119,159],[68,106,440],[68,106,163],[68,106,441],[68,106,331,371,440],[68,106,388,389,390,391,392,393,394,395,396,397,398,399,400,401,402,403,404,405,406,407,408,409,410,411,412,413,414,415,416,417,418,419,420,421,422,423,424,425,426,427,428,429,430,431,432,433,434,435,436,437,441],[68,106,438,440,441],[68,106,163,164,387,439,440,441,442,443,444],[68,106,381],[68,106,164],[68,106,163,381,385,387,439,441],[68,106,446,447],[68,106,371,440],[68,106,163,164,331,371,381,382,383,384,385,386,387,439,441],[68,106,440,441],[68,106,164,387,440],[68,106,331,438,440],[68,106,752],[68,106,752,753],[68,106,800],[68,106,739,745,754,790,794,795,796,797,798,799],[68,106,746,751],[68,106,136,750],[68,106,749,751,752],[68,106,747,748,752,800],[68,106,739,745,752],[68,106,753],[68,106,743],[68,106,740,741,742,744],[68,106,744,795],[68,106,744,796],[68,106,739,743,744,745,794],[68,106,740],[68,106,789],[68,106,747],[68,106,755,756,790,791,792,793],[68,106,107,136],[68,106,161,451,452],[68,106,449,450,454,455,456,457],[68,106,453],[68,106,119,747,809],[68,106,809,810,811,819,820,823],[68,106,809,810,811,816,817],[68,106,818,819],[68,106,811],[68,106,809,815],[68,106,810,811,818,820,823,824,825,827,828,830],[68,106,811,818,819,820,821,822],[68,106,119,809,810,811,818,819,827],[68,106,819,829],[68,106,826],[68,106,801],[68,106,802],[68,106,899],[68,106,119,136,771],[68,106,770,784],[68,106,119,771,783,785],[68,106,772,773,774,778,779,781,783,785,786,787,788],[68,106,774,781,784,786],[68,106,770],[68,106,770,773,775,776,777,778,784,785],[68,106,770,778,780,781,784,785],[68,106,770,771,773],[68,106,771,772,773,774,775,776,779,782,784,785,789],[68,106,119],[68,106,781,783,784],[68,106,772,773,776,785,786],[68,106,926,949,952,955],[68,106,948,954,956],[68,106,948,950],[68,106,949,950,951],[68,106,948],[68,106,958],[68,106,956,958,959,960],[68,106,957],[68,106,948,956,957],[68,106,948,962],[68,106,956,962,964],[68,106,948,963],[68,106,948,953],[68,106,956,961,965],[68,106,932,933,935,938,942],[68,106,927,928,931,932],[68,106,932,936,937,938,940],[68,106,927,928,932],[68,106,930,931,935,939],[68,106,927,928,929,930,931,932,933,934,935,936,937,938,940,941,942,943,944,945,946,947],[68,106,928,934],[68,106,932,935,938,940,941],[68,106,927,928,930,931],[68,106,928,930,931],[68,106,929],[68,106,943],[68,106,890],[68,106,118,154],[68,106,121,154,990],[68,106,121,154],[68,106,462],[68,106,154],[68,106,118,121,154,985,986],[68,106,986,987,989,991],[68,106,119,154],[68,106,118,121,123,126,136,147,154],[68,106,133,658,660,661,676],[68,106,133,654,655,656,657,658,659,660,661,662,663,664,665,666,667,668,669,670,671,672,673,674,675],[68,106,676],[68,106,656,657,676],[68,106,133,654,659,676],[68,106,133,660,661,676],[68,106,133,660,676],[68,106,133,654,660,676],[68,106,133,666,676],[68,106,133,676],[68,106,133,654],[68,106,659],[68,106,133],[68,106,1300],[68,106,1301],[68,106,111,154,462],[68,106,690],[68,106,678,680,681,682,683,684,685,686,687,688,689,690],[68,106,678,679,681,682,683,684,685,686,687,688,689,690],[68,106,679,680,681,682,683,684,685,686,687,688,689,690],[68,106,678,679,680,682,683,684,685,686,687,688,689,690],[68,106,678,679,680,681,683,684,685,686,687,688,689,690],[68,106,678,679,680,681,682,684,685,686,687,688,689,690],[68,106,678,679,680,681,682,683,685,686,687,688,689,690],[68,106,678,679,680,681,682,683,684,686,687,688,689,690],[68,106,678,679,680,681,682,683,684,685,687,688,689,690],[68,106,678,679,680,681,682,683,684,685,686,688,689,690],[68,106,678,679,680,681,682,683,684,685,686,687,689,690],[68,106,678,679,680,681,682,683,684,685,686,687,688,690],[68,106,678,679,680,681,682,683,684,685,686,687,688,689],[68,106,118,121,136,154],[68,106,121,147,154,1305,1306],[68,103,106],[68,105,106],[106],[68,106,111,139],[68,106,107,118,119,126,136,147],[68,106,107,108,118,126],[63,64,65,68,106],[68,106,109,148],[68,106,110,111,119,127],[68,106,111,136,144],[68,106,112,114,118,126],[68,105,106,113],[68,106,114,115],[68,106,118],[68,106,116,118],[68,105,106,118],[68,106,118,119,120,136,147],[68,106,118,119,120,133,136,139],[68,101,106,152],[68,106,114,118,121,126,136,147],[68,106,118,119,121,122,126,136,144,147],[68,106,121,123,136,144,147],[66,67,68,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,149,150,151,152,153],[68,106,118,124],[68,106,125,147,152],[68,106,114,118,126,136],[68,106,127],[68,106,128],[68,105,106,129],[68,106,130,146,152],[68,106,131],[68,106,132],[68,106,118,133,134],[68,106,133,135,148,150],[68,106,118,136,137,139],[68,106,138,139],[68,106,136,137],[68,106,139],[68,106,140],[68,106,136],[68,106,118,142,143],[68,106,142,143],[68,106,111,126,136,144],[68,106,145],[68,106,126,146],[68,106,121,132,147],[68,106,111,148],[68,106,136,149],[68,106,125,150],[68,106,151],[68,106,111,118,120,129,136,147,150,152],[68,106,136,153],[68,106,136,154],[68,106,147,154],[68,106,1311],[68,106,1308,1309,1310],[68,106,332,371],[68,106,332,356,371],[68,106,371],[68,106,332],[68,106,332,357,371],[68,106,332,333,334,335,336,337,338,339,340,341,342,343,344,345,346,347,348,349,350,351,352,353,354,355,356,357,358,359,360,361,362,363,364,365,366,367,368,369,370],[68,106,357,371],[68,106,121,154,988],[68,106,1008],[68,106,1395],[68,106,977,1393],[68,106,1296,1394],[68,106,118,121,123,126,136,144,147,153,154],[68,106,1398],[68,106,118,136,154],[68,106,1214],[68,106,329,977],[68,106,165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,183,184,185,186,187,188,189,190,191,192,193,194,199,200,201,202,203,207,208,209,210,211,212,213,214,215,216,218,219,221,222,223,224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255,256,257,258,259,260,261,262,263,264,265,266,267,268,269,270,271,272,273,274,275,276,277,278,279,280,281,282,283,284,285,286,287,288,289,290,291,292,293,294,295,296,297,298,299,300,301,302,303,304,305,306,307,308,309,310,311,312,313,314,315,316,317,318,319,320,321,322,323,324,325,326,327,328],[68,106,697,698],[68,106,146],[68,106,118,119,154,700],[68,106,460],[68,106,999],[68,106,329],[68,106,107,136,154],[68,106,1025],[68,106,1165],[68,106,121,122,123,126,1175,1176,1179,1180,1181,1182,1183,1184,1185,1189,1190,1191,1192,1193,1194,1195,1196,1197,1198,1199],[68,106,1182,1183,1184,1194,1196],[68,106,1182,1194],[68,106,1176],[68,106,136,1176,1182,1183,1184,1185,1189,1190,1191,1192,1194,1196],[68,106,121,126,1176,1180,1181,1182,1183,1184,1185,1189,1191,1193,1194,1196,1197],[68,106,1176,1182,1183,1184,1185,1188,1192,1194,1196],[68,106,1182,1184,1189,1192],[68,106,1182,1189,1190,1192,1200],[68,106,1182,1183,1184,1189,1192,1194,1195,1196],[68,106,1175,1182,1183,1184,1189,1192,1194,1195],[68,106,1176,1180,1182,1183,1184,1185,1189,1192,1193,1195,1196],[68,106,1175,1179,1200],[68,106,121,122,123,1182],[68,106,1182,1183,1194],[68,106,121,122,123],[68,106,156,157],[68,106,121,122],[68,106,464],[68,106,121,136,154],[68,106,126,154],[68,106,123,154,159],[68,106,121,136,1060,1062,1063,1064],[68,106,1061],[68,106,1050],[68,106,1048,1049],[68,106,1047,1051],[68,106,121,126,147,154,992,1046],[68,106,121,126,144,147,154,694],[68,106,121,123,136,154],[68,106,121,126,136,144,154,693],[68,106,1055,1056,1059,1065,1102],[68,106,119,1080,1082],[68,106,118,119,1080,1081],[68,106,1066,1067,1068,1069,1070,1071,1072,1073,1074,1075,1076,1077,1078,1079,1083,1084,1085,1086,1087,1089,1090,1092,1093,1094,1095,1096,1097,1098,1099,1100,1101],[68,106,1102],[68,106,1082,1102],[68,106,1088,1102],[68,106,1091],[68,106,1087,1102],[68,106,1038,1039,1040],[68,106,121,136],[68,106,706],[68,106,121,154,155,158],[68,106,107],[68,106,919],[68,106,910],[68,106,118,152,1186,1187],[68,106,329,331],[68,106,329,330],[68,106,170,180,199,206,299],[68,106,189],[68,106,186,189,190,192,193,206,233,261,262],[68,106,180,193,206,230],[68,106,180,206],[68,106,271],[68,106,206,303],[68,106,180,206,304],[68,106,206,304],[68,106,207,255],[68,106,179],[68,106,173,189,206,211,217,256],[68,106,255],[68,106,187,202,206,303],[68,106,180,206,303,307],[68,106,206,303,307],[68,106,170],[68,106,199],[68,106,269],[68,106,165,170,189,206,238],[68,106,189,206],[68,106,206,231,234,281,320],[68,106,192],[68,106,186,189,190,191,206],[68,106,175],[68,106,287],[68,106,176],[68,106,286],[68,106,183],[68,106,173],[68,106,178],[68,106,237],[68,106,238],[68,106,261,294],[68,106,206,230],[68,106,179,180],[68,106,181,182,195,196,197,198,204,205],[68,106,183,187,196],[68,106,178,180,186,196],[68,106,170,175,176,179,180,189,196,197,199,202,203,204],[68,106,182,186,188,195],[68,106,180,186,192,194],[68,106,165,178,183],[68,106,184,186,206],[68,106,165,178,179,186,206],[68,106,179,180,203,206],[68,106,167],[68,106,166,167,173,178,180,183,186,206,238],[68,106,206,303,307,311],[68,106,206,303,307,309],[68,106,169],[68,106,193],[68,106,200,279],[68,106,165],[68,106,180,200,201,202,206,211,217,218,219,220,221],[68,106,199,200,201],[68,106,189,230],[68,106,177,208],[68,106,184,185],[68,106,178,180,189,206,221,231,233,234,235],[68,106,202],[68,106,167,234],[68,106,178,206],[68,106,202,206,239],[68,106,206,304,313],[68,106,173,180,183,192,206,230],[68,106,169,178,180,199,206,231],[68,106,206],[68,106,179,203,206],[68,106,179,203,206,207],[68,106,179,203,206,224],[68,106,206,303,307,316],[68,106,199,206],[68,106,180,199,206,231,235,251],[68,106,199,206,207],[68,106,180,206,238],[68,106,180,183,206,221,229,231,235,249],[68,106,175,180,199,206,207],[68,106,178,180,206],[68,106,178,180,199,206],[68,106,206,217],[68,106,174,206],[68,106,187,190,191,206],[68,106,176,199],[68,106,186,187],[68,106,206,260,263],[68,106,166,276],[68,106,186,194,206],[68,106,186,206,230],[68,106,180,203,291],[68,106,169,178],[68,106,199,207],[68,106,119,136],[68,106,466,467,468,469,470,471,472,473,474,475,476,477,478,479,480,482,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,511,512,513,514,515,516,517,518,519,520,522,523,524,525,526,527,528,529,530,531,532,533,535,536,537,538,539,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,585,586,587,589,598,600,601,602,603,604,605,607,608,610,612,613,614,615,616,617,618,619,620,621,622,623,624,625,626,628,629,630,631,632,633,634,635,636,637,638,639,640,641,642,643,644,645,646,647,648,649,650,651,652,653],[68,106,511],[68,106,467,470],[68,106,469],[68,106,469,470],[68,106,466,467,468,470],[68,106,467,469,470,627],[68,106,470],[68,106,466,469,511],[68,106,469,470,627],[68,106,469,635],[68,106,467,469,470],[68,106,479],[68,106,502],[68,106,523],[68,106,469,470,511],[68,106,470,518],[68,106,469,470,511,529],[68,106,469,470,529],[68,106,470,570],[68,106,470,511],[68,106,466,470,588],[68,106,466,470,589],[68,106,611],[68,106,595,597],[68,106,606],[68,106,595],[68,106,466,470,588,595,596],[68,106,588,589,597],[68,106,609],[68,106,466,470,595,596,597],[68,106,468,469,470],[68,106,466,470],[68,106,467,469,589,590,591,592],[68,106,511,589,590,591,592],[68,106,589,591],[68,106,469,590,591,593,594,598],[68,106,466,469],[68,106,470,613],[68,106,471,472,473,474,475,476,477,478,479,480,481,482,483,484,485,486,487,488,489,490,491,492,493,494,495,496,497,498,499,500,501,502,503,504,505,506,507,508,509,510,512,513,514,515,516,517,519,520,521,522,523,524,525,526,527,528,530,531,532,533,534,535,536,537,538,539,540,541,542,543,544,545,546,547,548,549,550,551,552,553,554,555,556,557,558,559,560,561,562,563,564,565,566,567,568,569,570,571,572,573,574,575,576,577,578,579,580,581,582,583,584,585,586],[68,106,599],[68,106,1057,1058],[68,106,1057],[68,106,1315,1316,1317,1318,1320,1321,1322,1323,1324,1325,1326,1327,1328,1329,1330,1331,1332,1333,1334,1335,1336,1337,1338,1339,1340,1341,1342,1343,1344,1345,1346,1347,1348,1349,1350,1351,1352,1353,1354,1355,1356,1357,1358,1359,1360,1361,1362,1363,1364,1365,1366,1367,1368,1369,1370,1371,1372,1373,1374,1375,1376,1377,1378,1379,1380,1381,1382,1383,1384,1385,1386,1387,1388,1389,1390,1391,1392],[68,106,1341],[68,106,1341,1354],[68,106,1319,1368],[68,106,1369],[68,106,1320,1343],[68,106,1343],[68,106,1319],[68,106,1372],[68,106,1352],[68,106,1319,1360,1368],[68,106,1363],[68,106,1365],[68,106,1315],[68,106,1335],[68,106,1316,1317,1356],[68,106,1376],[68,106,1374],[68,106,1320,1321],[68,106,1322],[68,106,1333],[68,106,1319,1324],[68,106,1378],[68,106,1320],[68,106,1372,1381,1384],[68,106,1320,1321,1365],[68,106,1106,1107,1108,1109,1110,1111],[68,106,1106],[68,106,111,1106],[68,78,82,106,147],[68,78,106,136,147],[68,73,106],[68,75,78,106,144,147],[68,106,126,144],[68,73,106,154],[68,75,78,106,126,147],[68,70,71,74,77,106,118,136,147],[68,70,76,106],[68,74,78,106,139,147,154],[68,94,106,154],[68,72,73,106,154],[68,78,106],[68,72,73,74,75,76,77,78,79,80,82,83,84,85,86,87,88,89,90,91,92,93,95,96,97,98,99,100,106],[68,78,85,86,106],[68,76,78,86,87,106],[68,77,106],[68,70,73,78,106],[68,78,82,86,87,106],[68,82,106],[68,76,78,81,106,147],[68,70,75,76,78,82,85,106],[68,73,78,94,106,152,154],[68,106,711,712,713,714,715,716,717,719,720,721,722,723,724,725,726],[68,106,711],[68,106,711,718],[68,106,769],[68,106,759,760],[68,106,757,758,759,761,762,767],[68,106,758,759],[68,106,768],[68,106,759],[68,106,757,758,759,762,763,764,765,766],[68,106,757,758,769],[68,106,161,461,843,852,1400],[68,106,843,852,856],[68,106,119,128,130,148,161,445,448,458,459,461,463,465,676,677,691,692,731,737,804,833,834,842,843,844,845,848,851],[68,106,843,859,862],[68,106,119,128,461,843,852,859],[68,106,461,843,852,859,1400],[68,106,119,128,461,843,852,859,866],[68,106,461,705,852,858,863,864,865,867],[68,106,461,842,843,852,869,871],[68,106,130,705,852,869,872],[68,106,676,708,843,852,874,876,877,887],[68,106,705,852,874,888],[68,106,852],[68,106,119,127,128,147,461,676,843,852,891,894],[68,106,461,852,895],[68,106,461,676,852,1280,1281],[68,106,120,128,676,852,1277,1278],[68,106,1282],[68,106,843,852,901,1277,1278,1279,1282],[68,106,461,843,852,901,1277,1278,1282],[68,106,107,119,120,125,128,676,852,1277,1282],[68,106,119,120,128,161,676,705,708,738,800,803,806,807,834,842,843,848,852,869,871,878,879,887,897,898,900,901,902,903,904,922,925,975,978],[68,106,130,461,705,843,852,897,979],[68,106,461,733,852,869,997],[68,106,461,852,869,1210],[68,106,130,161,458,461,738,834,836,843,848,852,869,885,984,997,1033,1034,1035,1036,1043,1118,1119,1204,1205,1206,1207],[68,106,461,705,843,852,869,981,1208],[68,106,445],[68,106,461,843,852,1222],[68,106,461,843,852,869],[68,106,120,461,843,852,869,995,1400],[68,106,459,461,676,738,843,852,869,1215,1216,1400],[68,106,461,843,852,869,1218],[68,106,461,843,852,869,1220],[68,106,461,705,852,869,1212,1213,1217,1219,1221,1223],[68,106,1224],[68,106,120,461,789,843,852,925],[68,106,107,119,120,125,128,130,147,159,461,465,676,707,734,843,852,870,884,997,1227,1229,1230],[68,106,119,125,128,159,461,676,843,852,925],[68,106,461,843,852,925,1400],[68,106,128,461,836,852,925,997,1033,1034,1118],[68,106,461,705,843,852,858,1226,1231,1232,1233,1234],[68,106,1235],[68,106,852,1284],[68,106,119,128,161,676,708,738,843,852,876,877,1237,1238,1239],[68,106,461,705,852,1207,1240],[68,106,461,676,738,843,851,852,878,882,885,887,971,974,975,1206],[68,106,705,852,886,887],[68,103,106,161,676,708,738,843,851,852,878,879,882,885,886],[68,106,461,705,852,1243],[68,106,461,738,843,852],[68,106,461,852,1245],[68,106,461,843,851,852],[68,106,461,676,843,852,1249],[68,106,461,676,843,852,1247,1249],[68,106,461,852,1247,1250,1251],[68,106,130,461,676,705,731,732,734,834,843,851,852,853,854,855,857,868,873,889,896,980,1209,1211,1225,1236,1241,1242,1244,1246,1252,1256,1258,1260,1267,1270,1272,1274,1276,1283],[68,106,461,852,858,1253,1254,1255],[68,106,843,848,852],[68,106,461,843,848,852],[68,106,461,843,852,1253,1254],[68,106,120,128,147],[68,106,461,852,983,1257],[68,106,982,1400],[68,106,128,461,676,843,852,854,982],[68,106,461,852,869,981,1259],[68,106,130,461,738,833,836,843,848,852,869,885,916,984,997,1033,1034,1035,1036,1119,1204],[68,106,1266],[68,106,128,147,461,676,692,727,734,738,843,851,852,882,901,972,974,975,1261,1262],[68,106,461,676,692,738,843,851,852,882,887,901,974],[68,106,461,676,843,852],[68,106,461,708,738,843,852,879],[68,106,461,852,975,1263,1264,1265],[68,106,461,852,858,1268,1269],[68,106,461,843,852,901],[68,106,461,843,852,901,905],[68,106,461,852,1271],[68,106,461,676,843,852,1243],[68,106,161,737,738,833,842,843],[68,106,461,705,852,1273],[68,106,461,852,1275],[68,106,161,708,843,852,901,911,1207],[68,106,161],[68,106,997],[68,106,161,738,843],[68,106,128,727,730,835,843],[68,106,119,130,461,738,800,803,804,806,807,841,1406],[68,106,730],[68,106,119,128,843,892],[68,106,891],[68,106,893],[68,106,119,130,891,892,1286],[68,106,130,805,843],[68,106,120,128,730,807],[68,106,130,676,983],[68,106,120,121,128,708,730,738,804,806,807,831,832,834,836,837,838,840,843,852],[68,106,120,128,147,701,730,804,807,831,839,843,852],[68,106,128,130,734,843,1037,1041],[68,106,445,738,834,878],[68,106,119,120],[68,106,843,992,1018,1019],[68,106,789,800],[68,106,136,843,925,992,1017,1018,1021,1022,1023,1024,1027],[68,106,130,734,1003],[68,106,128,130,371,738,789,836,843,924,1000,1001,1017],[68,106,120,125,128,130,730,738,789,833,836,843,903,916,1001,1017,1018,1026],[68,106,128,130,734,921,1004,1017,1402],[68,106,789,843,1001,1005,1014,1016,1018],[68,106,120,125,128,702,730,773,789,843,902,916,1001,1007,1009,1014,1017,1018],[68,106,126,128,147,152,836,1010,1011,1013,1017,1018,1402],[68,106,126,130,152,1009,1012,1402],[68,106,120,128,130,465,730,734,916,1004,1015,1017,1018,1402],[68,106,121,925,992,1018,1019,1029,1402],[68,106,119,121,128,738,804,834,836,837,838,843,852,925,992,993,997,998,1019,1020,1027,1028,1030,1032,1401],[68,106,148,843,992,1012,1018,1019,1031,1402],[68,106,843,903,1018],[68,106,159],[68,106,120,695,696,843],[68,106,121,738,843,992,1103,1118],[68,106,843],[68,106,127,128,729],[68,106,707],[68,106,119,128,371,843,983],[68,106,128,676,733,843,983,1237],[68,106,676,843,852,859,919],[68,106,128,676,733,831,843,1290],[68,106,120,128,1289],[68,106,445,459,676,842,843,852,870],[68,106,119,128,130,465,710,728,730],[68,106,118,119,127,130,148,161,699,701,702,703,704,705,708,731,732,736,738,842],[68,106,119,128,136,148,1228,1403,1404],[68,106,121],[68,106,120,834,843,852,904,905,906,907,912,913,915,917,920,921],[68,106,111,1406],[68,106,137,834,908,914],[68,106,120,128,136,137,789,834,852,914,916],[68,106,111,119,136,137,909,912,913],[68,106,119,904,918,919],[68,106,128,904,911],[68,106,120,127,128,445,461,738,832,842,843,852,871,971,997,1035],[68,106,843,978],[68,106,130,161,738,832,843,878,994,996],[68,106,120,128,843,884,995],[68,106,130,733],[68,106,120,696,708,738,843,1120,1202],[68,106,120,128,458,834],[68,106,119,128,461,730,843,884],[68,106,789,884],[68,106,916,923,924],[68,106,120,128,147,330],[68,106,119,120,128,710,727,728,730],[68,106,128,148,465,843,875,880,881],[68,106,121,130,676,832,843,848,966,967],[68,106,120,128,843,883,884],[68,106,803,843],[68,106,461,843,852],[68,106,161,738,843,966,968,971,1285],[68,106,676,843,852,882,971],[68,106,843,852,882,972,973],[68,106,738,843],[68,106,120,128,161,445,676,738,843,852,871,884,905,969,970],[68,106,130,159,727,730,734,737,843,911,1042],[68,106,119,127,128,843,1237],[68,106,125,459],[68,106,875],[68,106,130,843,846,847],[68,106,843,860,861],[68,106,676,843],[68,106,738,843,860,861],[68,106,737,738,834,836,843,852,1027,1118],[68,106,118,120,121,123,126,128,130,136,147,148,153,464,710,738,832,834,841,843,884,993,998,1021,1027,1028,1031,1044,1045,1046,1052,1053,1054,1104,1105,1113,1115,1117,1285,1405],[68,106,147,159],[68,106,843,900],[68,106,1112],[68,106,128,701,738,843,884,1044,1054,1114,1405],[68,106,119,128,730,738,800,804,806,807,834,843,852,925,1203],[68,106,734],[68,106,1284,1285,1293],[68,106,130,459],[68,106,130,136,148,708,733,843,997],[68,106,1116],[68,106,461,676,738,843,875,1261],[68,106,159,733,738,843],[68,106,128,843,1200,1201],[68,106,736,850],[68,106,127,128,130,147,459,731,734,735],[68,106,130,159,732],[68,106,128,130,147,459,731,734,735,849],[68,106,732],[68,106,111,119,127,128],[68,106,121,445,731,737,1405],[68,106,1248],[68,106,992]],"fileInfos":[{"version":"69684132aeb9b5642cbcd9e22dff7818ff0ee1aa831728af0ecf97d3364d5546","affectsGlobalScope":true,"impliedFormat":1},{"version":"45b7ab580deca34ae9729e97c13cfd999df04416a79116c3bfb483804f85ded4","impliedFormat":1},{"version":"3facaf05f0c5fc569c5649dd359892c98a85557e3e0c847964caeb67076f4d75","impliedFormat":1},{"version":"e44bb8bbac7f10ecc786703fe0a6a4b952189f908707980ba8f3c8975a760962","impliedFormat":1},{"version":"5e1c4c362065a6b95ff952c0eab010f04dcd2c3494e813b493ecfd4fcb9fc0d8","impliedFormat":1},{"version":"68d73b4a11549f9c0b7d352d10e91e5dca8faa3322bfb77b661839c42b1ddec7","impliedFormat":1},{"version":"5efce4fc3c29ea84e8928f97adec086e3dc876365e0982cc8479a07954a3efd4","impliedFormat":1},{"version":"feecb1be483ed332fad555aff858affd90a48ab19ba7272ee084704eb7167569","impliedFormat":1},{"version":"ee7bad0c15b58988daa84371e0b89d313b762ab83cb5b31b8a2d1162e8eb41c2","impliedFormat":1},{"version":"27bdc30a0e32783366a5abeda841bc22757c1797de8681bbe81fbc735eeb1c10","impliedFormat":1},{"version":"c57796738e7f83dbc4b8e65132f11a377649c00dd3eee333f672b8f0a6bea671","affectsGlobalScope":true,"impliedFormat":1},{"version":"dc2df20b1bcdc8c2d34af4926e2c3ab15ffe1160a63e58b7e09833f616efff44","affectsGlobalScope":true,"impliedFormat":1},{"version":"515d0b7b9bea2e31ea4ec968e9edd2c39d3eebf4a2d5cbd04e88639819ae3b71","affectsGlobalScope":true,"impliedFormat":1},{"version":"0559b1f683ac7505ae451f9a96ce4c3c92bdc71411651ca6ddb0e88baaaad6a3","affectsGlobalScope":true,"impliedFormat":1},{"version":"0dc1e7ceda9b8b9b455c3a2d67b0412feab00bd2f66656cd8850e8831b08b537","affectsGlobalScope":true,"impliedFormat":1},{"version":"ce691fb9e5c64efb9547083e4a34091bcbe5bdb41027e310ebba8f7d96a98671","affectsGlobalScope":true,"impliedFormat":1},{"version":"8d697a2a929a5fcb38b7a65594020fcef05ec1630804a33748829c5ff53640d0","affectsGlobalScope":true,"impliedFormat":1},{"version":"4ff2a353abf8a80ee399af572debb8faab2d33ad38c4b4474cff7f26e7653b8d","affectsGlobalScope":true,"impliedFormat":1},{"version":"936e80ad36a2ee83fc3caf008e7c4c5afe45b3cf3d5c24408f039c1d47bdc1df","affectsGlobalScope":true,"impliedFormat":1},{"version":"d15bea3d62cbbdb9797079416b8ac375ae99162a7fba5de2c6c505446486ac0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"68d18b664c9d32a7336a70235958b8997ebc1c3b8505f4f1ae2b7e7753b87618","affectsGlobalScope":true,"impliedFormat":1},{"version":"eb3d66c8327153d8fa7dd03f9c58d351107fe824c79e9b56b462935176cdf12a","affectsGlobalScope":true,"impliedFormat":1},{"version":"38f0219c9e23c915ef9790ab1d680440d95419ad264816fa15009a8851e79119","affectsGlobalScope":true,"impliedFormat":1},{"version":"69ab18c3b76cd9b1be3d188eaf8bba06112ebbe2f47f6c322b5105a6fbc45a2e","affectsGlobalScope":true,"impliedFormat":1},{"version":"fef8cfad2e2dc5f5b3d97a6f4f2e92848eb1b88e897bb7318cef0e2820bceaab","affectsGlobalScope":true,"impliedFormat":1},{"version":"2f11ff796926e0832f9ae148008138ad583bd181899ab7dd768a2666700b1893","affectsGlobalScope":true,"impliedFormat":1},{"version":"4de680d5bb41c17f7f68e0419412ca23c98d5749dcaaea1896172f06435891fc","affectsGlobalScope":true,"impliedFormat":1},{"version":"954296b30da6d508a104a3a0b5d96b76495c709785c1d11610908e63481ee667","affectsGlobalScope":true,"impliedFormat":1},{"version":"ac9538681b19688c8eae65811b329d3744af679e0bdfa5d842d0e32524c73e1c","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a969edff4bd52585473d24995c5ef223f6652d6ef46193309b3921d65dd4376","affectsGlobalScope":true,"impliedFormat":1},{"version":"9e9fbd7030c440b33d021da145d3232984c8bb7916f277e8ffd3dc2e3eae2bdb","affectsGlobalScope":true,"impliedFormat":1},{"version":"811ec78f7fefcabbda4bfa93b3eb67d9ae166ef95f9bff989d964061cbf81a0c","affectsGlobalScope":true,"impliedFormat":1},{"version":"717937616a17072082152a2ef351cb51f98802fb4b2fdabd32399843875974ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"d7e7d9b7b50e5f22c915b525acc5a49a7a6584cf8f62d0569e557c5cfc4b2ac2","affectsGlobalScope":true,"impliedFormat":1},{"version":"71c37f4c9543f31dfced6c7840e068c5a5aacb7b89111a4364b1d5276b852557","affectsGlobalScope":true,"impliedFormat":1},{"version":"576711e016cf4f1804676043e6a0a5414252560eb57de9faceee34d79798c850","affectsGlobalScope":true,"impliedFormat":1},{"version":"89c1b1281ba7b8a96efc676b11b264de7a8374c5ea1e6617f11880a13fc56dc6","affectsGlobalScope":true,"impliedFormat":1},{"version":"74f7fa2d027d5b33eb0471c8e82a6c87216223181ec31247c357a3e8e2fddc5b","affectsGlobalScope":true,"impliedFormat":1},{"version":"d6d7ae4d1f1f3772e2a3cde568ed08991a8ae34a080ff1151af28b7f798e22ca","affectsGlobalScope":true,"impliedFormat":1},{"version":"063600664504610fe3e99b717a1223f8b1900087fab0b4cad1496a114744f8df","affectsGlobalScope":true,"impliedFormat":1},{"version":"934019d7e3c81950f9a8426d093458b65d5aff2c7c1511233c0fd5b941e608ab","affectsGlobalScope":true,"impliedFormat":1},{"version":"52ada8e0b6e0482b728070b7639ee42e83a9b1c22d205992756fe020fd9f4a47","affectsGlobalScope":true,"impliedFormat":1},{"version":"3bdefe1bfd4d6dee0e26f928f93ccc128f1b64d5d501ff4a8cf3c6371200e5e6","affectsGlobalScope":true,"impliedFormat":1},{"version":"59fb2c069260b4ba00b5643b907ef5d5341b167e7d1dbf58dfd895658bda2867","affectsGlobalScope":true,"impliedFormat":1},{"version":"639e512c0dfc3fad96a84caad71b8834d66329a1f28dc95e3946c9b58176c73a","affectsGlobalScope":true,"impliedFormat":1},{"version":"368af93f74c9c932edd84c58883e736c9e3d53cec1fe24c0b0ff451f529ceab1","affectsGlobalScope":true,"impliedFormat":1},{"version":"af3dd424cf267428f30ccfc376f47a2c0114546b55c44d8c0f1d57d841e28d74","affectsGlobalScope":true,"impliedFormat":1},{"version":"995c005ab91a498455ea8dfb63aa9f83fa2ea793c3d8aa344be4a1678d06d399","affectsGlobalScope":true,"impliedFormat":1},{"version":"959d36cddf5e7d572a65045b876f2956c973a586da58e5d26cde519184fd9b8a","affectsGlobalScope":true,"impliedFormat":1},{"version":"965f36eae237dd74e6cca203a43e9ca801ce38824ead814728a2807b1910117d","affectsGlobalScope":true,"impliedFormat":1},{"version":"3925a6c820dcb1a06506c90b1577db1fdbf7705d65b62b99dce4be75c637e26b","affectsGlobalScope":true,"impliedFormat":1},{"version":"0a3d63ef2b853447ec4f749d3f368ce642264246e02911fcb1590d8c161b8005","affectsGlobalScope":true,"impliedFormat":1},{"version":"b5ce7a470bc3628408429040c4e3a53a27755022a32fd05e2cb694e7015386c7","affectsGlobalScope":true,"impliedFormat":1},{"version":"8444af78980e3b20b49324f4a16ba35024fef3ee069a0eb67616ea6ca821c47a","affectsGlobalScope":true,"impliedFormat":1},{"version":"3287d9d085fbd618c3971944b65b4be57859f5415f495b33a6adc994edd2f004","affectsGlobalScope":true,"impliedFormat":1},{"version":"b4b67b1a91182421f5df999988c690f14d813b9850b40acd06ed44691f6727ad","affectsGlobalScope":true,"impliedFormat":1},{"version":"df83c2a6c73228b625b0beb6669c7ee2a09c914637e2d35170723ad49c0f5cd4","affectsGlobalScope":true,"impliedFormat":1},{"version":"436aaf437562f276ec2ddbee2f2cdedac7664c1e4c1d2c36839ddd582eeb3d0a","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e3c06ea092138bf9fa5e874a1fdbc9d54805d074bee1de31b99a11e2fec239d","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e65f4f2962cfc839bc4eec207a153c9c5fcfe793f1477fa38c974c69d0f0546","impliedFormat":1},{"version":"6c7176368037af28cb72f2392010fa1cef295d6d6744bca8cfb54985f3a18c3e","affectsGlobalScope":true,"impliedFormat":1},{"version":"ab41ef1f2cdafb8df48be20cd969d875602483859dc194e9c97c8a576892c052","affectsGlobalScope":true,"impliedFormat":1},{"version":"437e20f2ba32abaeb7985e0afe0002de1917bc74e949ba585e49feba65da6ca1","affectsGlobalScope":true,"impliedFormat":1},{"version":"21d819c173c0cf7cc3ce57c3276e77fd9a8a01d35a06ad87158781515c9a438a","impliedFormat":1},{"version":"a79e62f1e20467e11a904399b8b18b18c0c6eea6b50c1168bf215356d5bebfaf","affectsGlobalScope":true,"impliedFormat":1},{"version":"24f2d3933a63f7b5a951f6ec564df690ef462aca63bb12e6345d0d271bf3e319","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e9c23ba78aabc2e0a27033f18737a6df754067731e69dc5f52823957d60a4b6","impliedFormat":1},{"version":"5929864ce17fba74232584d90cb721a89b7ad277220627cc97054ba15a98ea8f","impliedFormat":1},{"version":"7180c03fd3cb6e22f911ce9ba0f8a7008b1a6ddbe88ccf16a9c8140ef9ac1686","impliedFormat":1},{"version":"25c8056edf4314820382a5fdb4bb7816999acdcb929c8f75e3f39473b87e85bc","impliedFormat":1},{"version":"54cb85a47d760da1c13c00add10d26b5118280d44d58e6908d8e89abbd9d7725","impliedFormat":1},{"version":"3e4825171442666d31c845aeb47fcd34b62e14041bb353ae2b874285d78482aa","impliedFormat":1},{"version":"c6fd2c5a395f2432786c9cb8deb870b9b0e8ff7e22c029954fabdd692bff6195","impliedFormat":1},{"version":"a967bfe3ad4e62243eb604bf956101e4c740f5921277c60debaf325c1320bf88","impliedFormat":1},{"version":"e9775e97ac4877aebf963a0289c81abe76d1ec9a2a7778dbe637e5151f25c5f3","impliedFormat":1},{"version":"471e1da5a78350bc55ef8cef24eb3aca6174143c281b8b214ca2beda51f5e04a","impliedFormat":1},{"version":"cadc8aced301244057c4e7e73fbcae534b0f5b12a37b150d80e5a45aa4bebcbd","impliedFormat":1},{"version":"385aab901643aa54e1c36f5ef3107913b10d1b5bb8cbcd933d4263b80a0d7f20","impliedFormat":1},{"version":"9670d44354bab9d9982eca21945686b5c24a3f893db73c0dae0fd74217a4c219","impliedFormat":1},{"version":"db3435f3525cd785bf21ec6769bf8da7e8a776be1a99e2e7efb5f244a2ef5fee","impliedFormat":1},{"version":"c3b170c45fc031db31f782e612adf7314b167e60439d304b49e704010e7bafe5","impliedFormat":1},{"version":"40383ebef22b943d503c6ce2cb2e060282936b952a01bea5f9f493d5fb487cc7","impliedFormat":1},{"version":"4893a895ea92c85345017a04ed427cbd6a1710453338df26881a6019432febdd","impliedFormat":1},{"version":"3a84b7cb891141824bd00ef8a50b6a44596aded4075da937f180c90e362fe5f6","impliedFormat":1},{"version":"13f6f39e12b1518c6650bbb220c8985999020fe0f21d818e28f512b7771d00f9","impliedFormat":1},{"version":"9b5369969f6e7175740bf51223112ff209f94ba43ecd3bb09eefff9fd675624a","impliedFormat":1},{"version":"4fe9e626e7164748e8769bbf74b538e09607f07ed17c2f20af8d680ee49fc1da","impliedFormat":1},{"version":"24515859bc0b836719105bb6cc3d68255042a9f02a6022b3187948b204946bd2","impliedFormat":1},{"version":"33203609eba548914dc83ddf6cadbc0bcb6e8ef89f6d648ca0908ae887f9fcc5","impliedFormat":1},{"version":"0db18c6e78ea846316c012478888f33c11ffadab9efd1cc8bcc12daded7a60b6","impliedFormat":1},{"version":"89167d696a849fce5ca508032aabfe901c0868f833a8625d5a9c6e861ef935d2","impliedFormat":1},{"version":"e53a3c2a9f624d90f24bf4588aacd223e7bec1b9d0d479b68d2f4a9e6011147f","impliedFormat":1},{"version":"339dc5265ee5ed92e536a93a04c4ebbc2128f45eeec6ed29f379e0085283542c","impliedFormat":1},{"version":"9f0a92164925aa37d4a5d9dd3e0134cff8177208dba55fd2310cd74beea40ee2","impliedFormat":1},{"version":"8bfdb79bf1a9d435ec48d9372dc93291161f152c0865b81fc0b2694aedb4578d","impliedFormat":1},{"version":"2e85db9e6fd73cfa3d7f28e0ab6b55417ea18931423bd47b409a96e4a169e8e6","impliedFormat":1},{"version":"c46e079fe54c76f95c67fb89081b3e399da2c7d109e7dca8e4b58d83e332e605","impliedFormat":1},{"version":"d32275be3546f252e3ad33976caf8c5e842c09cb87d468cb40d5f4cf092d1acc","impliedFormat":1},{"version":"4a0c3504813a3289f7fb1115db13967c8e004aa8e4f8a9021b95285502221bd1","impliedFormat":1},{"version":"5d4ba56f688207f1a47cf761ebe8987973e5bf9db6506edc160e211aa9f1dd51","affectsGlobalScope":true,"impliedFormat":1},{"version":"2aadab4729954c700a3ae50977f5611a8487dc3e3dc0e7f8fcd57f40475260a8","impliedFormat":1},{"version":"7394959e5a741b185456e1ef5d64599c36c60a323207450991e7a42e08911419","impliedFormat":1},{"version":"39b1a50d543770780b0409a4caacb87f3ff1d510aedfeb7dc06ed44188256f89","impliedFormat":1},{"version":"ea653f5686e3c9a52ad6568e05ddf07f048cc8469bb1a211931253f0491378a4","affectsGlobalScope":true,"impliedFormat":1},{"version":"51bb58ef3a22fdc49a2d338a852050855d1507f918d4d7fa77a68d72fee9f780","impliedFormat":1},{"version":"9b8d21812a10cba340a3e8dfacd5e883f6ccec7603eae4038fa90a0684fa9a07","impliedFormat":1},{"version":"cef8931bc129687165253f0642427c2a72705a4613b3ac461b9fa78c7cdaef32","affectsGlobalScope":true,"impliedFormat":1},{"version":"5524481e56c48ff486f42926778c0a3cce1cc85dc46683b92b1271865bcf015a","impliedFormat":1},{"version":"47b62c294beb69daa5879f052e416b02e6518f3e4541ae98adbfb27805dd6711","impliedFormat":1},{"version":"f8375506002c556ec412c7e2a5a9ece401079ee5d9eb2c1372e9f5377fac56c7","impliedFormat":1},{"version":"1c611ff373ce1958aafc40b328048ac2540ba5c7f373cf2897e0d9aeaabe90a0","impliedFormat":1},{"version":"548d9051fd6a3544216aec47d3520ce922566c2508df667a1b351658b2e46b8d","impliedFormat":1},{"version":"c175f4dd3b15b38833abfe19acb8ee38c6be2f80f5964b01a4354cafb676a428","impliedFormat":1},{"version":"b9a4824bb83f25d6d227394db2ed99985308cf2a3a35f0d6d39aa72b15473982","impliedFormat":1},{"version":"ee1ee365d88c4c6c0c0a5a5701d66ebc27ccd0bcfcfaa482c6e2e7fe7b98edf7","affectsGlobalScope":true,"impliedFormat":1},{"version":"b84f34005e497dbc0c1948833818cdb38e8c01ff4f88d810b4d70aa2e6c52916","affectsGlobalScope":true,"impliedFormat":1},{"version":"64eaa8ae36f494f21ffc6c911fa0f59a7ef4db2f0f98d816c4850cd5ba487a27","impliedFormat":1},{"version":"bdf415e4d75aabe69d58f4e5e13b2ccfe105b650679c6eff6cd6e61285f1fba8","impliedFormat":1},{"version":"0c5c23cfcfdf8f74c51593b0679d793edf656a134288cbcfb9c55258ab19bf69","impliedFormat":1},{"version":"6b3c4aa0ce6eb9cf6187e61d352cd269ff0e492f333ae102dda121e76f90285c","impliedFormat":1},{"version":"565fda33feca88f4b5db23ba8e605da1fd28b6d63292d276bdbd2afe6cd4c490","impliedFormat":1},{"version":"e822320b448edce0c7ede9cbeada034c72e1f1c8c8281974817030564c63dcb1","impliedFormat":1},{"version":"ebfc5ac063aa88ab26982757a8a9e6e9299306a5f9ea3e03ea5fd78c23dc5d79","affectsGlobalScope":true,"impliedFormat":1},{"version":"16bc7fc733bade239218d2f4351b0b53d7482c5aa917e5e12cf294c688f2e1b3","impliedFormat":1},{"version":"821c79b046e40d54a447bebd9307e70b86399a89980a87bbc98114411169e274","impliedFormat":1},{"version":"17bc38afc78d40b2f54af216c0cc31a4bd0c6897a5945fa39945dfc43260be2c","impliedFormat":1},{"version":"0e6726f7ab7649f3c668f4eadb45461dcfaab2c5899dd7db1e08f8a63905eb94","affectsGlobalScope":true,"impliedFormat":1},{"version":"d44445141f204d5672c502a39c1124bcf1df225eba05df0d2957f79122be87b5","affectsGlobalScope":true,"impliedFormat":1},{"version":"de905bc5f7e7a81cb420e212b95ab5e3ab840f93e0cfa8ce879f6e7fa465d4a2","impliedFormat":1},{"version":"91b64f6b37cfe86783b9a24d366f4c6c331c3ffb82926c60107cbc09960db804","impliedFormat":1},{"version":"bede3143eeddca3b8ec3592b09d7eb02042f9e195251040c5146eac09b173236","impliedFormat":1},{"version":"64a40cf4ec8a7a29db2b4bc35f042e5be8537c4be316e5221f40f30ca8ed7051","impliedFormat":1},{"version":"294c082d609e6523520290db4f1d54114ebc83643fb42abd965be5bcc5d9416b","impliedFormat":1},{"version":"5a64238d944ada60d4bec0f91ba970a064618ae3795cff27bb163c84b811284a","impliedFormat":1},{"version":"37ba7b45141a45ce6e80e66f2a96c8a5ab1bcef0fc2d0f56bb58df96ec67e972","impliedFormat":1},{"version":"125d792ec6c0c0f657d758055c494301cc5fdb327d9d9d5960b3f129aff76093","impliedFormat":1},{"version":"ce2fd18db93f879d300db4ae7738c28f3eefc7c2d9274ab7d22046f1d71ccd6f","affectsGlobalScope":true,"impliedFormat":1},{"version":"b85151402164ab7cb665e58df5c1a29aa25ea4ed3a367f84a15589e7d7a9c8ca","impliedFormat":1},{"version":"5d8cd11d44a41a6966a04e627d38efce8d214edb36daf494153ec15b2b95eee2","affectsGlobalScope":true,"impliedFormat":1},{"version":"bc6cb10764a82f3025c0f4822b8ad711c16d1a5c75789be2d188d553b69b2d48","affectsGlobalScope":true,"impliedFormat":1},{"version":"41d510caf7ed692923cb6ef5932dc9cf1ed0f57de8eb518c5bab8358a21af674","impliedFormat":1},{"version":"b1a9bf3c14dd2bac9784aaffbeabd878f5f6618a4fd3bfc1633a2758b0e96f32","impliedFormat":1},{"version":"dc058956a93388aab38307b7b3b9b6379e1021e73a244aab6ac9427dc3a252a7","impliedFormat":1},{"version":"f33302cf240672359992c356f2005d395b559e176196d03f31a28cc7b01e69bc","impliedFormat":1},{"version":"3ce25041ff6ae06c08fcaccd5fcd9baf4ca6e80e6cb5a922773a1985672e74c2","affectsGlobalScope":true,"impliedFormat":1},{"version":"652c0de14329a834ff06af6ad44670fac35849654a464fd9ae36edb92a362c12","affectsGlobalScope":true,"impliedFormat":1},{"version":"3b1e178016d3fc554505ae087c249b205b1c50624d482c542be9d4682bab81fc","impliedFormat":1},{"version":"f47fc200a9cad1976d5d046aa27b821918e93c82a2fd63cf06b47c9d0f88aaae","impliedFormat":1},{"version":"cf45d0510b661f1da461479851ff902f188edb111777c37055eff12fa986a23a","impliedFormat":1},{"version":"cb41c174db409193c4b26e1e02b39a80f3050318a6af120cc304323f29e1ec1b","affectsGlobalScope":true,"impliedFormat":1},{"version":"37bef1064b7d015aeaa7c0716fe23a0b3844abe2c0a3df7144153ca8445fe0da","impliedFormat":1},{"version":"1a013cfc1fa53be19899330926b9e09ccdb6514b3635ef80471ad427b1bbf817","impliedFormat":1},{"version":"d782e571cb7d6ec0f0645957ed843d00e3f8577e08cc2940f400c931bc47a8df","impliedFormat":99},{"version":"9167246623f181441e6116605221268d94e33a1ebd88075e2dc80133c928ae7e","impliedFormat":99},{"version":"dc1a838d8a514b6de9fbce3bd5e6feb9ccfe56311e9338bb908eb4d0d966ecaf","impliedFormat":99},{"version":"186f09ed4b1bc1d5a5af5b1d9f42e2d798f776418e82599b3de16423a349d184","impliedFormat":99},{"version":"d692ae73951775d2448df535ce8bc8abf162dc343911fedda2c37b8de3b20d8e","impliedFormat":99},{"version":"a3de3941348d3e889a279cdb5bf0e56703587bb816abef248a5d23dd7c5c08cb","impliedFormat":99},{"version":"826f6410781d98bb48fb55bf0b9b3875b6688642da7d7e92ff835d28de5a2fce","impliedFormat":99},{"version":"256a5d5389469510323f283d116992868db133016fcbb19756390321e7fb2ed6","signature":"29bc9df3ec76c35effcf8dad1e7d64fee4a8b386a2647bfe401c6f738e799b8c","impliedFormat":99},{"version":"e3ab429051d2f3e833752bdb0b9c9c0cc63399d9b001f401e39e18b7fae811f7","impliedFormat":99},{"version":"a82a6d492fb3f86da2d551de9eab088b9bf290ff081eae482ce614db6590eaa9","impliedFormat":99},{"version":"cd51ceafea7762ad639afb3ca5b68e1e4ffeaacaa402d7ef2cae17016e29e098","impliedFormat":1},{"version":"1b8357b3fef5be61b5de6d6a4805a534d68fe3e040c11f1944e27d4aec85936a","impliedFormat":1},{"version":"130ec22c8432ade59047e0225e552c62a47683d870d44785bee95594c8d65408","impliedFormat":1},{"version":"4f24c2781b21b6cd65eede543669327d68a8cf0c6d9cf106a1146b164a7c8ef9","affectsGlobalScope":true,"impliedFormat":1},{"version":"928f96b9948742cbaec33e1c34c406c127c2dad5906edb7df08e92b963500a41","impliedFormat":1},{"version":"56613f2ebdd34d4527ca1ee969ab7e82333c3183fc715e5667c999396359e478","impliedFormat":1},{"version":"d9720d542df1d7feba0aa80ed11b4584854951f9064232e8d7a76e65dc676136","impliedFormat":1},{"version":"d0fb3d0c64beba3b9ab25916cc018150d78ccb4952fac755c53721d9d624ba0d","impliedFormat":1},{"version":"86b484bcf6344a27a9ee19dd5cef1a5afbbd96aeb07708cc6d8b43d7dfa8466c","impliedFormat":1},{"version":"ba93f0192c9c30d895bee1141dd0c307b75df16245deef7134ac0152294788cc","impliedFormat":1},{"version":"fca7cd7512b19d38254171fb5e35d2b16ac56710b7915b7801994612953da16c","impliedFormat":1},{"version":"7e43693f6ea74c3866659265e0ce415b4da6ed7fabd2920ad7ea8a5e746c6a94","impliedFormat":1},{"version":"eb31477c87de3309cbe4e9984fa74a052f31581edb89103f8590f01874b4e271","impliedFormat":1},{"version":"4e251317bb109337e4918e5d7bcda7ef2d88f106cac531dcea03f7eee1dd2240","impliedFormat":1},{"version":"0f2c77683296ca2d0e0bee84f8aa944a05df23bc4c5b5fef31dda757e75f660f","impliedFormat":1},{"version":"1a67ba5891772a62706335b59a50720d89905196c90719dad7cec9c81c2990e6","impliedFormat":1},{"version":"cf41091fcbf45daff9aba653406b83d11a3ec163ff9d7a71890035117e733d98","impliedFormat":1},{"version":"aa514fadda13ad6ddadc2342e835307b962254d994f45a0cb495cc76eca13eff","impliedFormat":1},{"version":"ce92e662f86a36fc38c5aaa2ec6e6d6eed0bc6cf231bd06a9cb64cc652487550","impliedFormat":1},{"version":"3821c8180abb683dcf4ba833760764a79e25bc284dc9b17d32e138c34ada1939","impliedFormat":1},{"version":"0ef2a86ec84da6b2b06f830b441889c5bb8330a313691d4edbe85660afa97c44","impliedFormat":1},{"version":"b2a793bde18962a2e1e0f9fa5dce43dd3e801331d36d3e96a7451727185fb16f","impliedFormat":1},{"version":"9d8fc1d9b6b4b94127eec180183683a6ef4735b0e0a770ba9f7e2d98dd571e0c","impliedFormat":1},{"version":"8504003e88870caa5474ab8bd270f318d0985ba7ede4ee30fe37646768b5362a","impliedFormat":1},{"version":"892abbe1081799073183bab5dc771db813938e888cf49eb166f0e0102c0c1473","impliedFormat":1},{"version":"65465a64d5ee2f989ad4cf8db05f875204a9178f36b07a1e4d3a09a39f762e2e","impliedFormat":1},{"version":"2878f694f7d3a13a88a5e511da7ac084491ca0ddde9539e5dad76737ead9a5a9","impliedFormat":1},{"version":"d21c5f692d23afa03113393088bcb1ef90a69272a774950a9f69c58131ac5b7e","impliedFormat":1},{"version":"0915ce92bb54e905387b7907e98982620cb7143f7b44291974fb2e592602fe00","impliedFormat":1},{"version":"9dfb317a36a813f4356dc1488e26a36d95e3ac7f38a05fbf9dda97cfd13ef6ea","impliedFormat":1},{"version":"7c0a4d3819fb911cdb5a6759c0195c72b0c54094451949ebaa89ffceadd129ca","impliedFormat":1},{"version":"4733c832fb758f546a4246bc62f2e9d68880eb8abf0f08c6bec484decb774dc9","impliedFormat":1},{"version":"58d91c410f31f4dd6fa8d50ad10b4ae9a8d1789306e73a5fbe8abea6a593099b","impliedFormat":1},{"version":"3aea7345c25f1060791fc83a6466b889924db87389e5c344fa0c27b75257ebe4","impliedFormat":1},{"version":"a8289d1d525cf4a3a2d5a8db6b8e14e19f43d122cc47f8fb6b894b0aa2e2bde6","impliedFormat":1},{"version":"e6804515ba7c8f647e145ecc126138dd9d27d3e6283291d0f50050700066a0ea","impliedFormat":1},{"version":"9420a04edbe321959de3d1aab9fa88b45951a14c22d8a817f75eb4c0a80dba02","impliedFormat":1},{"version":"6927ceeb41bb451f47593de0180c8ff1be7403965d10dc9147ee8d5c91372fff","impliedFormat":1},{"version":"d9c6f10eebf03d123396d4fee1efbe88bc967a47655ec040ffe7e94271a34fc7","impliedFormat":1},{"version":"f2a392b336e55ccbeb8f8a07865c86857f1a5fc55587c1c7d79e4851b0c75c9a","impliedFormat":1},{"version":"fd53e2a54dae7bb3a9c3b061715fff55a0bb3878472d4a93b2da6f0f62262c9f","impliedFormat":1},{"version":"1f129869a0ee2dcb7ea9a92d6bc8ddf2c2cdaf2d244eec18c3a78efeb5e05c83","impliedFormat":1},{"version":"554962080d3195cae300341a8b472fb0553f354f658344ae181b9aa02d351dbd","impliedFormat":1},{"version":"89cd9ab3944b306e790b148dd0a13ca120daf7379a98729964ea6288a54a1beb","impliedFormat":1},{"version":"28fa41063a242eafcf51e1a62013fccdd9fd5d6760ded6e3ff5ce10a13c2ab31","impliedFormat":1},{"version":"e53a8b6e43f20fa792479f8069c41b1a788a15ffdfd56be1ab8ef46ea01bd43e","impliedFormat":1},{"version":"ada60ff3698e7fd0c7ed0e4d93286ee28aed87f648f6748e668a57308fde5a67","impliedFormat":1},{"version":"f65e0341f11f30b47686efab11e1877b1a42cf9b1a232a61077da2bdeee6d83e","impliedFormat":1},{"version":"e6918b864e3c2f3a7d323f1bb31580412f12ab323f6c3a55fb5dc532c827e26d","impliedFormat":1},{"version":"5d6f919e1966d45ea297c2478c1985d213e41e2f9a6789964cdb53669e3f7a6f","impliedFormat":1},{"version":"d7735a9ccd17767352ab6e799d76735016209aadd5c038a2fc07a29e7b235f02","impliedFormat":1},{"version":"843e98d09268e2b5b9e6ff60487cf68f4643a72c2e55f7c29b35d1091a4ee4e9","impliedFormat":1},{"version":"ef4c9ef3ec432ccbf6508f8aa12fbb8b7f4d535c8b484258a3888476de2c6c36","impliedFormat":1},{"version":"77ff2aeb024d9e1679c00705067159c1b98ccac8310987a0bdaf0e38a6ca7333","impliedFormat":1},{"version":"8f9effea32088f37d15858a890e1a7ccf9af8d352d47fea174f6b95448072956","impliedFormat":1},{"version":"952c4a8d2338e19ef26c1c0758815b1de6c082a485f88368f5bece1e555f39d4","impliedFormat":1},{"version":"1d953cb875c69aeb1ec8c58298a5226241c6139123b1ff885cedf48ac57b435c","impliedFormat":1},{"version":"1a80e164acd9ee4f3e2a919f9a92bfcdb3412d1fe680b15d60e85eadbaa460f8","impliedFormat":1},{"version":"f981ffdbd651f67db134479a5352dac96648ca195f981284e79dc0a1dbc53fd5","impliedFormat":1},{"version":"019c29de7d44d84684e65bdabb53ee8cc08f28b150ac0083d00e31a8fe2727d8","impliedFormat":1},{"version":"e35738485bf670f13eab658ea34d27ef2b875f3aae8fc00fb783d29e5737786d","impliedFormat":1},{"version":"bcd951d1a489d00e432c73760ce7f39adb0ef4e6a9c8ffef5dd7f093325a8377","impliedFormat":1},{"version":"672c1ebc4fa15a1c9b4911f1c68de2bc889f4d166a68c5be8f1e61f94014e9d8","impliedFormat":1},{"version":"b0378c1bc3995a1e7b40528dcd81670b2429d8c1dcc1f8d1dc8f76f33d3fc1b8","impliedFormat":1},{"version":"5a0d920468aa4e792285943cadad77bcb312ba2acf1c665e364ada1b1ee56264","impliedFormat":1},{"version":"c27c5144d294ba5e38f0cd483196f911047500a735490f85f318b4d5eb8ac2cc","impliedFormat":1},{"version":"900d1889110107cea3e40b30217c6e66f19db8683964a57afd9a72ecc821fe21","impliedFormat":1},{"version":"a2e4333bf0c330ae26b90c68e395ad0a8af06121f1c977979c75c4a5f9f6bc29","impliedFormat":1},{"version":"08c027d3d6e294b5607341125d1c4689b4fece03bdb9843bd048515fe496a73e","impliedFormat":1},{"version":"2cbf557a03f80df74106cb7cfb38386db82725b720b859e511bdead881171c32","impliedFormat":1},{"version":"918956b37f3870f02f0659d14bba32f7b0e374fd9c06a241db9da7f5214dcd79","impliedFormat":1},{"version":"260e6d25185809efc852e9c002600ad8a85f8062fa24801f30bead41de98c609","impliedFormat":1},{"version":"dd9694eecd70a405490ad23940ccd8979a628f1d26928090a4b05a943ac61714","impliedFormat":1},{"version":"42ca885a3c8ffdffcd9df252582aef9433438cf545a148e3a5e7568ca8575a56","impliedFormat":1},{"version":"309586820e31406ed70bb03ea8bca88b7ec15215e82d0aa85392da25d0b68630","impliedFormat":1},{"version":"db436ca96e762259f14cb74d62089c7ca513f2fc725e7dcfbac0716602547898","impliedFormat":1},{"version":"1410d60fe495685e97ed7ca6ff8ac6552b8c609ebe63bd97e51b7afe3c75b563","impliedFormat":1},{"version":"c6843fd4514c67ab4caf76efab7772ceb990fbb1a09085fbcf72b4437a307cf7","impliedFormat":1},{"version":"03ed68319c97cd4ce8f1c4ded110d9b40b8a283c3242b9fe934ccfa834e45572","impliedFormat":1},{"version":"956618754d139c7beb3c97df423347433473163d424ff8248af18851dd7d772a","impliedFormat":1},{"version":"7d8f40a7c4cc81db66ac8eaf88f192996c8a5542c192fdebb7a7f2498c18427d","impliedFormat":1},{"version":"c69ecf92a8a9fb3e4019e6c520260e4074dc6cb0044a71909807b8e7cc05bb65","impliedFormat":1},{"version":"07d0370c85ac112aa6f1715dc88bafcee4bcea1483bc6b372be5191d6c1a15c7","impliedFormat":1},{"version":"7fb0164ebb34ead4b1231eca7b691f072acf357773b6044b26ee5d2874c5f296","impliedFormat":1},{"version":"9e4fc88d0f62afc19fa5e8f8c132883378005c278fdb611a34b0d03f5eb6c20c","impliedFormat":1},{"version":"cc9bf8080004ee3d8d9ef117c8df0077d6a76b13cb3f55fd3eefbb3e8fcd1e63","impliedFormat":1},{"version":"1f0ee5ddb64540632c6f9a5b63e242b06e49dd6472f3f5bd7dfeb96d12543e15","impliedFormat":1},{"version":"b6aa8c6f2f5ebfb17126492623691e045468533ec2cc7bd47303ce48de7ab8aa","impliedFormat":1},{"version":"18b86125c67d99150f54225df07349ddd07acde086b55f3eeac1c34c81e424d8","impliedFormat":1},{"version":"68434152ef6e484df25a9bd0f4c9abdfb0d743f5a39bff2b2dc2a0f94ed5f391","impliedFormat":1},{"version":"b848b40bfeb73dfe2e782c5b7588ef521010a3d595297e69386670cbde6b4d82","impliedFormat":1},{"version":"aa79b64f5b3690c66892f292e63dfe3e84eb678a886df86521f67c109d57a0c5","impliedFormat":1},{"version":"a692e092c3b9860c9554698d84baf308ba51fc8f32ddd6646e01a287810b16c6","impliedFormat":1},{"version":"18076e7597cd9baa305cd85406551f28e3450683a699b7152ce7373b6b4a1db7","impliedFormat":1},{"version":"1848ebe5252ccb5ca1ca4ff52114516bdbbc7512589d6d0839beeea768bfb400","impliedFormat":1},{"version":"d2e3a1de4fde9291f9fb3b43672a8975a83e79896466f1af0f50066f78dbf39e","impliedFormat":1},{"version":"d0d03f7d2ba2cf425890e0f35391f1904d0d152c77179ddfc28dfad9d4a09c03","impliedFormat":1},{"version":"e37650b39727a6cf036c45a2b6df055e9c69a0afdd6dbab833ab957eb7f1a389","impliedFormat":1},{"version":"c58d6d730e95e67a62ebd7ba324e04bcde907ef6ba0f41922f403097fe54dd78","impliedFormat":1},{"version":"0f5773d0dd61aff22d2e3223be3b4b9c4a8068568918fb29b3f1ba3885cf701f","impliedFormat":1},{"version":"31073e7d0e51f33b1456ff2ab7f06546c95e24e11c29d5b39a634bc51f86d914","impliedFormat":1},{"version":"9ce0473b0fbaf7287afb01b6a91bd38f73a31093e59ee86de1fd3f352f3fc817","impliedFormat":1},{"version":"6f0d708924c3c4ee64b0fef8f10ad2b4cb87aa70b015eb758848c1ea02db0ed7","impliedFormat":1},{"version":"6addbb18f70100a2de900bace1c800b8d760421cdd33c1d69ee290b71e28003d","impliedFormat":1},{"version":"37569cc8f21262ca62ec9d3aa8eb5740f96e1f325fad3d6aa00a19403bd27b96","impliedFormat":1},{"version":"e0ef70ca30cdc08f55a9511c51a91415e814f53fcc355b14fc8947d32ce9e1aa","impliedFormat":1},{"version":"14be139e0f6d380a3d24aaf9b67972add107bea35cf7f2b1b1febac6553c3ede","impliedFormat":1},{"version":"23195b09849686462875673042a12b7f4cd34b4e27d38e40ca9c408dae8e6656","impliedFormat":1},{"version":"ff1731974600a4dad7ec87770e95fc86ca3d329b1ce200032766340f83585e47","impliedFormat":1},{"version":"91bc53a57079cf32e1a10ccf1a1e4a068e9820aa2fc6abc9af6bd6a52f590ffb","impliedFormat":1},{"version":"8dd284442b56814717e70f11ca22f4ea5b35feeca680f475bfcf8f65ba4ba296","impliedFormat":1},{"version":"a304e0af52f81bd7e6491e890fd480f3dc2cb0541dec3c7bd440dba9fea5c34e","impliedFormat":1},{"version":"c60fd0d7a1ba07631dfae8b757be0bffd5ef329e563f9a213e4a5402351c679f","impliedFormat":1},{"version":"02687b095a01969e6e300d246c9566a62fa87029ce2c7634439af940f3b09334","impliedFormat":1},{"version":"e79e530a8216ee171b4aca8fc7b99bd37f5e84555cba57dc3de4cd57580ff21a","impliedFormat":1},{"version":"ceb2c0bc630cca2d0fdd48b0f48915d1e768785efaabf50e31c8399926fee5b1","impliedFormat":1},{"version":"f351eaa598ba2046e3078e5480a7533be7051e4db9212bb40f4eeb84279aa24d","impliedFormat":1},{"version":"12aeda564ee3f1d96ac759553d6749534fafeb2e5142ea2867f22ed39f9d3260","impliedFormat":1},{"version":"4ce53edb8fb1d2f8b2f6814084b773cdf5846f49bf5a426fbe4029327bda95bf","impliedFormat":1},{"version":"85d63aaff358e8390b666a6bc68d3f56985f18764ab05f750cb67910f7bccb1a","impliedFormat":1},{"version":"0a0bf0cb43af5e0ac1703b48325ebc18ad86f6bf796bdbe96a429c0e95ca4486","impliedFormat":1},{"version":"563573a23a61b147358ddee42f88f887817f0de1fc5dbc4be7603d53cbd467ad","impliedFormat":1},{"version":"dd0cad0db617f71019108686cf5caabcad13888b2ae22f889a4c83210e4ba008","impliedFormat":1},{"version":"f08d2151bd91cdaa152532d51af04e29201cfc5d1ea40f8f7cfca0eb4f0b7cf3","impliedFormat":1},{"version":"b9c889d8a4595d02ebb3d3a72a335900b2fe9e5b5c54965da404379002b4ac44","impliedFormat":1},{"version":"a3cd30ebae3d0217b6b3204245719fc2c2f29d03b626905cac7127e1fb70e79c","impliedFormat":1},{"version":"bd56c2399a7eadccfca7398ca2244830911bdbb95b8ab7076e5a9210e9754696","impliedFormat":1},{"version":"f52fb387ac45e7b8cdc98209714c4aedc78d59a70f92e9b5041309b6b53fc880","impliedFormat":1},{"version":"1502a23e43fd7e9976a83195dc4eaf54acaff044687e0988a3bd4f19fc26b02b","impliedFormat":1},{"version":"5faa3d4b828440882a089a3f8514f13067957f6e5e06ec21ddd0bc2395df1c33","impliedFormat":1},{"version":"f0f95d40b0b5a485b3b97bd99931230e7bf3cbbe1c692bd4d65c69d0cdd6fa9d","impliedFormat":1},{"version":"380b4fe5dac74984ac6a58a116f7726bede1bdca7cec5362034c0b12971ac9c1","impliedFormat":1},{"version":"00de72aa7abede86b016f0b3bfbf767a08b5cff060991b0722d78b594a4c2105","impliedFormat":1},{"version":"965759788855797f61506f53e05c613afb95b16002c60a6f8653650317870bc3","impliedFormat":1},{"version":"f70a315e029dacf595f025d13fa7599e8585d5ccfc44dd386db2aa6596aaf553","impliedFormat":1},{"version":"f385a078ad649cc24f8c31e4f2e56a5c91445a07f25fbdc4a0a339c964b55679","impliedFormat":1},{"version":"08599363ef46d2c59043a8aeec3d5e0d87e32e606c7b1acf397e43f8acadc96a","impliedFormat":1},{"version":"4f5bbef956920cfd90f2cbffccb3c34f8dfc64faaba368d9d41a46925511b6b0","impliedFormat":1},{"version":"0ae9d5bbf4239616d06c50e49fc21512278171c1257a1503028fc4a95ada3ed0","impliedFormat":1},{"version":"cba49e77f6c1737f7a3ce9a50b484d21980665fff93c1c64e0ee0b5086ea460a","impliedFormat":1},{"version":"9c686df0769cca468ebf018749df4330d5ff9414e0d226c1956ebaf45c85ff61","impliedFormat":1},{"version":"89d5970d28f207d30938563e567e67395aa8c1789c43029fe03fe1d07893c74c","impliedFormat":1},{"version":"869e789f7a8abcc769f08ba70b96df561e813a4001b184d3feb8c3d13b095261","impliedFormat":1},{"version":"392f3eb64f9c0f761eb7a391d9fbef26ffa270351d451d11bd70255664170acc","impliedFormat":1},{"version":"f829212a0e8e4fd1b079645d4e97e6ec73734dd21aae4dfc921d2958774721d0","impliedFormat":1},{"version":"5e20af039b2e87736fd7c9e4b47bf143c46918856e78ce21da02a91c25d817e8","impliedFormat":1},{"version":"f321514602994ba6e0ab622ef52debd4e9f64a7b4494c03ee017083dc1965753","impliedFormat":1},{"version":"cc8734156129aa6230a71987d94bdfac723045459da707b1804ecec321e60937","impliedFormat":1},{"version":"bb89466514349b86260efdee9850e497d874e4098334e9b06a146f1e305fca3f","impliedFormat":1},{"version":"fc0ee9d0476dec3d1b37a0f968e371a3d23aac41742bc6706886e1c6ac486749","impliedFormat":1},{"version":"f7da03d84ce7121bc17adca0af1055021b834e861326462a90dbf6154cf1e106","impliedFormat":1},{"version":"fed8c2c205f973bfb03ef3588750f60c1f20e2362591c30cd2c850213115163b","impliedFormat":1},{"version":"32a2b99a3aacda16747447cc9589e33c363a925d221298273912ecf93155e184","impliedFormat":1},{"version":"07bfa278367913dd253117ec68c31205825b2626e1cb4c158f2112e995923ee8","impliedFormat":1},{"version":"6a76e6141ff2fe28e88e63e0d06de686f31184ab68b04ae16f0f92103295cc2a","impliedFormat":1},{"version":"f05d5d16d85abe57eb713bc12efefc00675c09016e3292360e2de0790f51fa48","impliedFormat":1},{"version":"2e3ceed776a470729c084f3a941101d681dd1867babbaf6e1ca055d738dd3878","impliedFormat":1},{"version":"3d9fb85cc7089ca54873c9924ff47fcf05d570f3f8a3a2349906d6d953fa2ccf","impliedFormat":1},{"version":"d82c245bfb76da44dd573948eca299ff75759b9714f8410468d2d055145a4b64","impliedFormat":1},{"version":"6b5b31af3f5cfcf5635310328f0a3a94f612902024e75dc484eb79123f5b8ebe","impliedFormat":1},{"version":"db08c1807e3ae065930d88a3449d926273816d019e6c2a534e82da14e796686d","impliedFormat":1},{"version":"9e5c7463fc0259a38938c9afbdeda92e802cff87560277fd3e385ad24663f214","impliedFormat":1},{"version":"ef83477cca76be1c2d0539408c32b0a2118abcd25c9004f197421155a4649c37","impliedFormat":1},{"version":"2c3936b0f811f38ab1a4f0311993bf599c27c2da5750e76aa5dfbed8193c9922","impliedFormat":1},{"version":"c253c7ea2877126b1c3311dc70b7664fe4d696cb09215857b9d7ea8b7fdce1f0","impliedFormat":1},{"version":"22293bd6fa12747929f8dfca3ec1684a3fe08638aa18023dd286ab337e88a592","impliedFormat":1},{"version":"46c4a7b98171add588d6a8ea324e11c47cc7a717711da44e79d8307f82d98786","impliedFormat":99},{"version":"cf3d384d082b933d987c4e2fe7bfb8710adfd9dc8155190056ed6695a25a559e","impliedFormat":1},{"version":"9871b7ee672bc16c78833bdab3052615834b08375cb144e4d2cba74473f4a589","impliedFormat":1},{"version":"c863198dae89420f3c552b5a03da6ed6d0acfa3807a64772b895db624b0de707","impliedFormat":1},{"version":"8b03a5e327d7db67112ebbc93b4f744133eda2c1743dbb0a990c61a8007823ef","impliedFormat":1},{"version":"86c73f2ee1752bac8eeeece234fd05dfcf0637a4fbd8032e4f5f43102faa8eec","impliedFormat":1},{"version":"42fad1f540271e35ca37cecda12c4ce2eef27f0f5cf0f8dd761d723c744d3159","impliedFormat":1},{"version":"ff3743a5de32bee10906aff63d1de726f6a7fd6ee2da4b8229054dfa69de2c34","impliedFormat":1},{"version":"83acd370f7f84f203e71ebba33ba61b7f1291ca027d7f9a662c6307d74e4ac22","impliedFormat":1},{"version":"1445cec898f90bdd18b2949b9590b3c012f5b7e1804e6e329fb0fe053946d5ec","impliedFormat":1},{"version":"0e5318ec2275d8da858b541920d9306650ae6ac8012f0e872fe66eb50321a669","impliedFormat":1},{"version":"cf530297c3fb3a92ec9591dd4fa229d58b5981e45fe6702a0bd2bea53a5e59be","impliedFormat":1},{"version":"c1f6f7d08d42148ddfe164d36d7aba91f467dbcb3caa715966ff95f55048b3a4","impliedFormat":1},{"version":"f4e9bf9103191ef3b3612d3ec0044ca4044ca5be27711fe648ada06fad4bcc85","impliedFormat":1},{"version":"0c1ee27b8f6a00097c2d6d91a21ee4d096ab52c1e28350f6362542b55380059a","impliedFormat":1},{"version":"7677d5b0db9e020d3017720f853ba18f415219fb3a9597343b1b1012cfd699f7","impliedFormat":1},{"version":"bc1c6bc119c1784b1a2be6d9c47addec0d83ef0d52c8fbe1f14a51b4dfffc675","impliedFormat":1},{"version":"52cf2ce99c2a23de70225e252e9822a22b4e0adb82643ab0b710858810e00bf1","impliedFormat":1},{"version":"770625067bb27a20b9826255a8d47b6b5b0a2d3dfcbd21f89904c731f671ba77","impliedFormat":1},{"version":"d1ed6765f4d7906a05968fb5cd6d1db8afa14dbe512a4884e8ea5c0f5e142c80","impliedFormat":1},{"version":"799c0f1b07c092626cf1efd71d459997635911bb5f7fc1196efe449bba87e965","impliedFormat":1},{"version":"2a184e4462b9914a30b1b5c41cf80c6d3428f17b20d3afb711fff3f0644001fd","impliedFormat":1},{"version":"9eabde32a3aa5d80de34af2c2206cdc3ee094c6504a8d0c2d6d20c7c179503cc","impliedFormat":1},{"version":"397c8051b6cfcb48aa22656f0faca2553c5f56187262135162ee79d2b2f6c966","impliedFormat":1},{"version":"a8ead142e0c87dcd5dc130eba1f8eeed506b08952d905c47621dc2f583b1bff9","impliedFormat":1},{"version":"a02f10ea5f73130efca046429254a4e3c06b5475baecc8f7b99a0014731be8b3","impliedFormat":1},{"version":"c2576a4083232b0e2d9bd06875dd43d371dee2e090325a9eac0133fd5650c1cb","impliedFormat":1},{"version":"4c9a0564bb317349de6a24eb4efea8bb79898fa72ad63a1809165f5bd42970dd","impliedFormat":1},{"version":"f40ac11d8859092d20f953aae14ba967282c3bb056431a37fced1866ec7a2681","impliedFormat":1},{"version":"cc11e9e79d4746cc59e0e17473a59d6f104692fd0eeea1bdb2e206eabed83b03","impliedFormat":1},{"version":"b444a410d34fb5e98aa5ee2b381362044f4884652e8bc8a11c8fe14bbd85518e","impliedFormat":1},{"version":"c35808c1f5e16d2c571aa65067e3cb95afeff843b259ecfa2fc107a9519b5392","impliedFormat":1},{"version":"14d5dc055143e941c8743c6a21fa459f961cbc3deedf1bfe47b11587ca4b3ef5","impliedFormat":1},{"version":"a3ad4e1fc542751005267d50a6298e6765928c0c3a8dce1572f2ba6ca518661c","impliedFormat":1},{"version":"f237e7c97a3a89f4591afd49ecb3bd8d14f51a1c4adc8fcae3430febedff5eb6","impliedFormat":1},{"version":"3ffdfbec93b7aed71082af62b8c3e0cc71261cc68d796665faa1e91604fbae8f","impliedFormat":1},{"version":"662201f943ed45b1ad600d03a90dffe20841e725203ced8b708c91fcd7f9379a","impliedFormat":1},{"version":"c9ef74c64ed051ea5b958621e7fb853fe3b56e8787c1587aefc6ea988b3c7e79","impliedFormat":1},{"version":"2462ccfac5f3375794b861abaa81da380f1bbd9401de59ffa43119a0b644253d","impliedFormat":1},{"version":"34baf65cfee92f110d6653322e2120c2d368ee64b3c7981dff08ed105c4f19b0","impliedFormat":1},{"version":"844ab83672160ca57a2a2ea46da4c64200d8c18d4ebb2087819649cad099ff0e","impliedFormat":1},{"version":"d3711654b0698b84e59ee40159d8bd56ac8ae01075313ed049a3fc310bfe8a80","impliedFormat":1},{"version":"cf4ff96698b4147c6ce07915d5fea830391a7bd0e934af5fc3f8b04dc1fa57ca","impliedFormat":1},{"version":"25b6dc46fda19aa5db804152ab8463eab7d8815999f5dbf7f27739bd05525952","impliedFormat":1},{"version":"841ace225afa08b17d709351f762b0a33f186f175786a4626da31194a052e160","impliedFormat":1},{"version":"f0291f25990e92d99828fa19af7bc8875ae5c116229e79abbd01ff5c4a0c27fd","impliedFormat":1},{"version":"5fb9bcba24bb23cd81fdc06952f445581a97ee10388a8ebf1fcd80800e0f44be","impliedFormat":1},{"version":"33ab997f5db0f07003187deeefdf24f72993f4f6bc4145d9716bae37bbdfde33","impliedFormat":1},{"version":"3867e3767bf5edaf8dc7c95ebd9740acba587c3db801d07902656be6ec253bf5","impliedFormat":1},{"version":"ccb10029bcb21a73d372c0f98a6caa854741a8c21295d358be4786e28e5f5f4e","impliedFormat":1},{"version":"bded69a38f56b2370216f42adab029be54020d3e965c67d7e5987ba606284150","impliedFormat":1},{"version":"cf165b358efb5c98924a8b37cc744ecc80fc84251dfe15820c6b656df12f14f5","impliedFormat":99},{"version":"7dec66b19493298068b5dab4e096eb67694313092114e650a28e8ca9c18c1a7e","impliedFormat":99},{"version":"082de38879df9e9f885667802f1e010356d92c0b5c10dbf45bba45c7e76f542b","impliedFormat":99},{"version":"7b3e7e0f76ddb0ab449439e36f02a6c5c610a67f51bc0176626012d2aea6de4e","impliedFormat":99},{"version":"7e0e423724b3a32aa2a340ed1bbd0cc76af68bcb0642fddd273c213a9d7cda53","impliedFormat":99},{"version":"70d78a4c1c1fabc691fba1b285497d08212bfdd439b3ada3d8ef13cfcf12c35c","impliedFormat":99},{"version":"666d7d9057b078510a0551be3c630a52136ba743794af739ed71478b1f89487a","impliedFormat":99},{"version":"a3c319269e8848888f59db5ae261e0a386a01181f86d5d67635496c7bff9b4f0","impliedFormat":99},{"version":"edaaa3f32cf45bfb2befb4a3a950ef7c50055b80fa935956d7e22f5cc2970b48","impliedFormat":99},{"version":"8162ba59b729d4cb27d16d1e255e4c44c5d75236fa923e4b31b2a112a3a8a0bc","impliedFormat":99},{"version":"59d138ba95f31b7b7274684997239676d5713c168c190861905c4da358b53088","impliedFormat":99},{"version":"2022508d7a52e265c7f59bb8cd31717d3d15c24c4fabbe1dfa49011aee76920f","impliedFormat":99},{"version":"51a70d5108cf372d6ca3e010252b359e1d42fe92a974f4476a0d183d21989f5a","impliedFormat":99},{"version":"70f70c2d8d84371662db477849dd6c2c99186c577e561e39536a6a8d0dce4294","impliedFormat":99},{"version":"8639fa2ae8c672117030afc3f6f373402f30da0245dcbd07b1f39e226dbf3708","impliedFormat":99},{"version":"90efc9bd684353edd81ad09b546d4964bb062b13a9e53445d3d2f362373ab566","impliedFormat":99},{"version":"4b2cef0bb6805951990b68fdf43ba0a731b1ccbc15d28dec56c4e4b0e20b9b68","impliedFormat":99},{"version":"30ae496902d8005831668fc6451700dec4e31abfbb2e72df8789528c0127ad74","impliedFormat":99},{"version":"b243c9ab8279fd3718f8d883b4a127b66d48e2dd4e5baf3a8afba9bf991eedca","impliedFormat":99},{"version":"6eeab8f71354b2b1f59315300d75914a4301ac9aa21c5a532a1c83f58618aaab","impliedFormat":99},{"version":"1bc7cbad17459ec5a3e343f804f38c11aaecee40145d8351e25172060fe4b971","impliedFormat":99},{"version":"1df70179bc4778f0016589cab5e7ae337bfcbd4ce98b94cf30519271ffe51f9b","impliedFormat":99},{"version":"2423420e653bbfd25d9f958c925de99a1a42770447f9fa581912de35f1858847","impliedFormat":99},{"version":"4883b8ac4f59c12031ae1b8f7aaef99a359819cdceb99051a7b1059224c7738e","impliedFormat":99},{"version":"43cf865b516e67eabd492df11977c8fd053632d459dc77493ccc4c2cf1815f43","impliedFormat":99},{"version":"197da6667c6fa703ef9031a77ce69ccb97439e4a106c52988acd0e51e69c2c6a","impliedFormat":99},{"version":"0b236bfca94f558acc8dd928aad1a0a9a60524bd74cde66841654f140170a61c","impliedFormat":99},{"version":"4da6db2484f97314a98165f44580a26addfb22ed8002cc2343a82cbce7b0bdfa","impliedFormat":99},{"version":"d66a66d1b2dd805296b95800015034965909ea022746ec42f1034a72cbefc5ea","impliedFormat":99},{"version":"2b1f07ff4fcd3b34969c890e1d9460e70850baa8f66ec5aad3d32d2b2d6f6aca","impliedFormat":99},{"version":"4300446fd38797cdb552cbdd2c1e4b44deffad011d84f0dd297f47c0cc1b3deb","impliedFormat":99},{"version":"88c033983f03d5d35d576780ea04652238c1f695ebf3eb096a7ae97d09bf61ea","impliedFormat":99},{"version":"cf77d5355a6c30f4d8ee15313c5d18d708f621217fb86c7fd3b28742c62043ca","impliedFormat":99},{"version":"e1fedd099f845bbed38bdee5401140010fd3725f5b7a97cd5c6bac06e3eed798","impliedFormat":99},{"version":"27031e170bde0662936131facc3c9c28063f689d6fae0e8866820cbaa55e568d","impliedFormat":99},{"version":"fbd8e9e313bf1ce4ce6dec3fa9a1541fb25062bf95778fcf74701762226d5efb","impliedFormat":99},{"version":"f1f6d08caf846fb1d560fbf4750fb9b9e2b32ccfcebc16731c54022fbc5095aa","impliedFormat":99},{"version":"a2d6e24b3784045cc489a28f8a6219d9055e98f1eef9e6f4fcd58c59c7c70979","impliedFormat":99},{"version":"47f554381b939c2ff42643e14a7a3531563b4a18b92a50192a602e4cfde09abb","impliedFormat":99},{"version":"50c87e6213ced9d49bb61c27b0deee6f7ba2cdb222d3b84beffc8056a1c0090e","impliedFormat":99},{"version":"a34f1cbe8931616ba065462ba0426e8738101a553530841a17f46501431c89c9","impliedFormat":99},{"version":"cd4fced0d09c1d60bfe9414a2b907a381c6e28fa3464f199fd4ea65e49df5ddd","impliedFormat":99},{"version":"4d225d589e40bd0977468adebae28cffbf914bea0ad4a1487eaeaeb8d6bdf20f","impliedFormat":99},{"version":"5bbb159b5fe6e0bbc894f1c2b932736facec0a037ffea654c1104aa9e6664d14","impliedFormat":99},{"version":"fcdb11ac16978aab95cc676ade6e2da5b5a50d425c3b768e5d419d57efd9fce1","impliedFormat":99},{"version":"dc6eed55650a33bd1e2572fe55936e35ef8b8f2c71d9ae27365d07a8b23ec811","impliedFormat":99},{"version":"8f6c76c7d79194dc8acb28469ed89767ae0e411eb431b7bcddc4abeee396c3f4","impliedFormat":99},{"version":"d6be06d85f77744ce9cc79f2c9d0dae7eb68523ddf5e2949d1c9a59bca7e41df","impliedFormat":99},{"version":"ac3cff165847106bb5d767271e4e225c12b928629c2838621877af38b36ebb64","impliedFormat":99},{"version":"11922a20dd508545ed34ef22b12660b040692ce49adf9a6a8f8cd6addaf9a420","impliedFormat":99},{"version":"45fed9566b49458cdc51126f0b110bddd5e9d87ee5654addc6855d160f644cc1","impliedFormat":99},{"version":"ca44ec138c9e576ab28667328c957b3b5ca6d37d6f474f4bd524765b5236834c","impliedFormat":99},{"version":"487d9550ce19bd8dac662bb3a242fcb38dbd1826698d59319ca9cc47b1c0faa7","impliedFormat":99},{"version":"ed11cb3e229bfa109cbe1cd84a1407e734a14db158e251f4b460c599e232fb8d","impliedFormat":99},{"version":"3861b9505140d5008ea0387b6279e5c082b114e751c3dab1fae47febd7336c41","impliedFormat":99},{"version":"3a66dc1ac4955d8134eaab18e79453f017fadd3527fe15143e00e79cd34e285a","impliedFormat":99},{"version":"925a7637b162db37c4f62579bcdbbb1b3d83280f5beeaa60ea14977446ea1082","impliedFormat":99},{"version":"babf709bb03eed9007ec60db615227b61843f529e0332ec2bf0a6446d20a1ce0","impliedFormat":99},{"version":"be709fc51e1cb1fec7edf324a6c9ece4be3f815bc6e135a9730435387953b75d","impliedFormat":99},{"version":"2fb988354ced2e79ee82fd3a56c434037c2d9ed253fda7cd02628d1a45ac882f","impliedFormat":99},{"version":"85e5df0910674b826ca6b38c129a1a76a99404b031ae0bcce249bffcf0f24aa5","impliedFormat":99},{"version":"35a01b628282746e6aea7b8100b7442cdad5531a5ee030d42a63eb2bafdc235d","impliedFormat":99},{"version":"cc812fdcaf798f4db9395e1166965b8ab905840c7bd7440bbe7e71b47fe00388","impliedFormat":99},{"version":"ab8ee0714ccf7ff42ae26c0253ff984fdddf5a1c436f71c3419061cbd5b87921","impliedFormat":99},{"version":"2a568d2dab0fd4f5fd1a4c0ec50d69435281e239a84b4ed7453d0b4f251d9d19","impliedFormat":99},{"version":"fc0239d0f1e569c74191f8546176ed26d81c136e33de2900117f02493463cf75","impliedFormat":99},{"version":"b07cc3a486403ccd18a44e6efa65fb4c9b1b06b11c228a6e8ff3eca9c704080c","impliedFormat":99},{"version":"b633e8a76ad3f057924c34795190fbce14a77559f9f0f90a600d9d80dc187971","impliedFormat":99},{"version":"86090ad80066a4c71b403deaabcf972be656690bf167fc48ede2fc9e1b363689","impliedFormat":99},{"version":"631f68ec813eb2fe7505df6523ffe2b56fb82de85dc824414d1e67fc6cac09db","impliedFormat":99},{"version":"79a6947ef7a22c54d92eda98a9ef73e8f21c9995fdd44910404bc8953f56a9a8","impliedFormat":99},{"version":"c4037e427556291251a9dc92eeafa5c73a61949fb254aa2d6efc620b3af217b5","impliedFormat":99},{"version":"462bad60450aba304a6280a0255b3f0b7767acb14d3e41afa8c9ac0b56d0ab75","impliedFormat":99},{"version":"f59b7411bf15a049c5595083b205c165db7b453e04ed467acdae37d1e00ff1e3","impliedFormat":99},{"version":"c6b5e47c0f7fea6ad2cb10736f2ec3391252f8b49f9fec7f1abcb18a98fd7663","impliedFormat":99},{"version":"7a632c16e91f29590756fd94309c4bb0db0ff54dfd8df75e0f9d0f7754ad1c1c","impliedFormat":99},{"version":"bc907403c9999797139324c73372e0289b03cff5ee6bb21069a6330c320d1587","impliedFormat":99},{"version":"8d0bb3e7403e4c24e3f8ba965d2b1825a9b8ccc83e3ed12f3094f2fd00feb2d6","impliedFormat":1},{"version":"a722a71d8f3cb0028857b12579c7eca55acc76bf34e5db7eaf6fe817b985f9c3","impliedFormat":1},{"version":"b124c0624b15412ace7d54644ade38d7a69db7e25488a1a4d2a8df6e11696538","impliedFormat":99},{"version":"fb893a0dfc3c9fb0f9ca93d0648694dd95f33cbad2c0f2c629f842981dfd4e2e","impliedFormat":1},{"version":"3eb11dbf3489064a47a2e1cf9d261b1f100ef0b3b50ffca6c44dd99d6dd81ac1","impliedFormat":1},{"version":"51cac533b4031fe5d4fecef5635afac9c0dca87c11f5b325e49e1600a9c51117","impliedFormat":99},{"version":"3657ccb355f52a6ccfb2ae731e7e789e619d220858a522e4108479797cd2ab53","impliedFormat":99},{"version":"073ca26c96184db9941b5ec0ddea6981c9b816156d9095747809e524fdd90e35","impliedFormat":1},{"version":"e41d17a2ec23306d953cda34e573ed62954ca6ea9b8c8b74e013d07a6886ce47","impliedFormat":1},{"version":"241bd4add06f06f0699dcd58f3b334718d85e3045d9e9d4fa556f11f4d1569c1","impliedFormat":1},{"version":"2ae3787e1498b20aad1b9c2ee9ea517ec30e89b70d242d8e3e52d1e091039695","impliedFormat":1},{"version":"c7c72c4cffb1bc83617eefed71ed68cc89df73cab9e19507ccdecb3e72b4967e","affectsGlobalScope":true,"impliedFormat":1},{"version":"b8bff8a60af0173430b18d9c3e5c443eaa3c515617210c0c7b3d2e1743c19ecb","impliedFormat":1},{"version":"38b38db08e7121828294dec10957a7a9ff263e33e2a904b346516d4a4acca482","impliedFormat":1},{"version":"a76ebdf2579e68e4cfe618269c47e5a12a4e045c2805ed7f7ab37af8daa6b091","impliedFormat":1},{"version":"8a2aaea564939c22be05d665cc955996721bad6d43148f8fa21ae8f64afecd37","impliedFormat":1},{"version":"e59d36b7b6e8ba2dd36d032a5f5c279d2460968c8b4e691ca384f118fb09b52a","impliedFormat":1},{"version":"e96885c0684c9042ec72a9a43ef977f6b4b4a2728f4b9e737edcbaa0c74e5bf6","impliedFormat":1},{"version":"95950a187596e206d32d5d9c7b932901088c65ed8f9040e614aa8e321e0225ef","impliedFormat":1},{"version":"89e061244da3fc21b7330f4bd32f47c1813dd4d7f1dc3d0883d88943f035b993","impliedFormat":1},{"version":"e46558c2e04d06207b080138678020448e7fc201f3d69c2601b0d1456105f29a","impliedFormat":1},{"version":"71549375db52b1163411dba383b5f4618bdf35dc57fa327a1c7d135cf9bf67d1","impliedFormat":1},{"version":"7e6b2d61d6215a4e82ea75bc31a80ebb8ad0c2b37a60c10c70dd671e8d9d6d5d","impliedFormat":1},{"version":"78bea05df2896083cca28ed75784dde46d4b194984e8fc559123b56873580a23","impliedFormat":1},{"version":"5dd04ced37b7ea09f29d277db11f160df7fd73ba8b9dba86cb25552e0653a637","impliedFormat":1},{"version":"f74b81712e06605677ae1f061600201c425430151f95b5ef4d04387ad7617e6a","impliedFormat":1},{"version":"9a72847fcf4ac937e352d40810f7b7aec7422d9178451148296cf1aa19467620","impliedFormat":1},{"version":"3ae18f60e0b96fa1e025059b7d25b3247ba4dcb5f4372f6d6e67ce2adac74eac","impliedFormat":1},{"version":"2b9260f44a2e071450ae82c110f5dc8f330c9e5c3e85567ed97248330f2bf639","impliedFormat":1},{"version":"4f196e13684186bda6f5115fc4677a87cf84a0c9c4fc17b8f51e0984f3697b6d","impliedFormat":1},{"version":"61419f2c5822b28c1ea483258437c1faab87d00c6f84481aa22afb3380d8e9a4","impliedFormat":1},{"version":"64479aee03812264e421c0bf5104a953ca7b02740ba80090aead1330d0effe91","impliedFormat":1},{"version":"0521108c9f8ddb17654a0a54dae6ba9667c99eddccfd6af5748113e022d1c37a","impliedFormat":1},{"version":"c5570e504be103e255d80c60b56c367bf45d502ca52ee35c55dec882f6563b5c","impliedFormat":1},{"version":"ee764e6e9a7f2b987cc1a2c0a9afd7a8f4d5ebc4fdb66ad557a7f14a8c2bd320","impliedFormat":1},{"version":"0520b5093712c10c6ef23b5fea2f833bf5481771977112500045e5ea7e8e2b69","impliedFormat":1},{"version":"5c3cf26654cf762ac4d7fd7b83f09acfe08eef88d2d6983b9a5a423cb4004ca3","impliedFormat":1},{"version":"e60fa19cf7911c1623b891155d7eb6b7e844e9afdf5738e3b46f3b687730a2bd","impliedFormat":1},{"version":"b1fd72ff2bb0ba91bb588f3e5329f8fc884eb859794f1c4657a2bfa122ae54d0","impliedFormat":1},{"version":"6cf42a4f3cfec648545925d43afaa8bb364ac10a839ffed88249da109361b275","impliedFormat":1},{"version":"d7058e75920120b142a9d57be25562a3cd9a936269fd52908505f530105f2ec4","impliedFormat":1},{"version":"6df52b70d7f7702202f672541a5f4a424d478ee5be51a9d37b8ccbe1dbf3c0f2","impliedFormat":1},{"version":"0ca7f997e9a4d8985e842b7c882e521b6f63233c4086e9fe79dd7a9dc4742b5e","impliedFormat":1},{"version":"91046b5c6b55d3b194c81fd4df52f687736fad3095e9d103ead92bb64dc160ee","impliedFormat":1},{"version":"db5704fdad56c74dfc5941283c1182ed471bd17598209d3ac4a49faa72e43cfc","impliedFormat":1},{"version":"758e8e89559b02b81bc0f8fd395b17ad5aff75490c862cbe369bb1a3d1577c40","impliedFormat":1},{"version":"2ee64342c077b1868f1834c063f575063051edd6e2964257d34aad032d6b657c","impliedFormat":1},{"version":"6f6b4b3d670b6a5f0e24ea001c1b3d36453c539195e875687950a178f1730fa7","impliedFormat":1},{"version":"a472a1d3f25ce13a1d44911cd3983956ac040ce2018e155435ea34afb25f864c","impliedFormat":1},{"version":"b48b83a86dd9cfe36f8776b3ff52fcd45b0e043c0538dc4a4b149ba45fe367b9","impliedFormat":1},{"version":"792de5c062444bd2ee0413fb766e57e03cce7cdaebbfc52fc0c7c8e95069c96b","impliedFormat":1},{"version":"a79e3e81094c7a04a885bad9b049c519aace53300fb8a0fe4f26727cb5a746ce","impliedFormat":1},{"version":"93181bac0d90db185bb730c95214f6118ae997fe836a98a49664147fbcaf1988","impliedFormat":1},{"version":"8a4e89564d8ea66ad87ee3762e07540f9f0656a62043c910d819b4746fc429c5","impliedFormat":1},{"version":"b9011d99942889a0f95e120d06b698c628b0b6fdc3e6b7ecb459b97ed7d5bcc6","impliedFormat":1},{"version":"4d639cbbcc2f8f9ce6d55d5d503830d6c2556251df332dc5255d75af53c8a0e7","impliedFormat":1},{"version":"cdb48277f600ab5f429ecf1c5ea046683bc6b9f73f3deab9a100adac4b34969c","impliedFormat":1},{"version":"75be84956a29040a1afbe864c0a7a369dfdb739380072484eff153905ef867ee","impliedFormat":1},{"version":"b06b4adc2ae03331a92abd1b19af8eb91ec2bf8541747ee355887a167d53145e","impliedFormat":1},{"version":"c54166a85bd60f86d1ebb90ce0117c0ecb850b8a33b366691629fdf26f1bbbd8","impliedFormat":1},{"version":"0d417c15c5c635384d5f1819cc253a540fe786cc3fda32f6a2ae266671506a21","impliedFormat":1},{"version":"80f23f1d60fbed356f726b3b26f9d348dddbb34027926d10d59fad961e70a730","impliedFormat":1},{"version":"cb59317243a11379a101eb2f27b9df1022674c3df1df0727360a0a3f963f523b","impliedFormat":1},{"version":"cc20bb2227dd5de0aab0c8d697d1572f8000550e62c7bf5c92f212f657dd88c5","impliedFormat":1},{"version":"06b8a7d46195b6b3980e523ef59746702fd210b71681a83a5cf73799623621f9","impliedFormat":1},{"version":"860e4405959f646c101b8005a191298b2381af8f33716dc5f42097e4620608f8","impliedFormat":1},{"version":"f7e32adf714b8f25d3c1783473abec3f2e82d5724538d8dcf6f51baaaff1ca7a","impliedFormat":1},{"version":"d0da80c845999a16c24d0783033fb5366ada98df17867c98ad433ede05cd87fd","impliedFormat":1},{"version":"bfbf80f9cd4558af2d7b2006065340aaaced15947d590045253ded50aabb9bc5","impliedFormat":1},{"version":"fd9a991b51870325e46ebb0e6e18722d313f60cd8e596e645ec5ac15b96dbf4e","impliedFormat":1},{"version":"c3bd2b94e4298f81743d92945b80e9b56c1cdfb2bef43c149b7106a2491b1fc9","impliedFormat":1},{"version":"a246cce57f558f9ebaffd55c1e5673da44ea603b4da3b2b47eb88915d30a9181","impliedFormat":1},{"version":"d993eacc103c5a065227153c9aae8acea3a4322fe1a169ee7c70b77015bf0bb2","impliedFormat":1},{"version":"fc2b03d0c042aa1627406e753a26a1eaad01b3c496510a78016822ef8d456bb6","impliedFormat":1},{"version":"063c7ebbe756f0155a8b453f410ca6b76ffa1bbc1048735bcaf9c7c81a1ce35f","impliedFormat":1},{"version":"314e402cd481370d08f63051ae8b8c8e6370db5ee3b8820eeeaaf8d722a6dac6","impliedFormat":1},{"version":"9669075ac38ce36b638b290ba468233980d9f38bdc62f0519213b2fd3e2552ec","impliedFormat":1},{"version":"4d123de012c24e2f373925100be73d50517ac490f9ed3578ac82d0168bfbd303","impliedFormat":1},{"version":"656c9af789629aa36b39092bee3757034009620439d9a39912f587538033ce28","impliedFormat":1},{"version":"3ac3f4bdb8c0905d4c3035d6f7fb20118c21e8a17bee46d3735195b0c2a9f39f","impliedFormat":1},{"version":"1f453e6798ed29c86f703e9b41662640d4f2e61337007f27ac1c616f20093f69","impliedFormat":1},{"version":"af43b7871ff21c62bf1a54ec5c488e31a8d3408d5b51ff2e9f8581b6c55f2fc7","impliedFormat":1},{"version":"70550511d25cbb0b6a64dcac7fffc3c1397fd4cbeb6b23ccc7f9b794ab8a6954","impliedFormat":1},{"version":"af0fbf08386603a62f2a78c42d998c90353b1f1d22e05a384545f7accf881e0a","impliedFormat":1},{"version":"cefc20054d20b85b534206dbcedd509bb74f87f3d8bc45c58c7be3a76caa45e1","impliedFormat":1},{"version":"ad6eee4877d0f7e5244d34bc5026fd6e9cf8e66c5c79416b73f9f6ebf132f924","impliedFormat":1},{"version":"4888fd2bcfee9a0ce89d0df860d233e0cee8ee9c479b6bd5a5d5f9aae98342fe","impliedFormat":1},{"version":"f4749c102ced952aa6f40f0b579865429c4869f6d83df91000e98005476bee87","impliedFormat":1},{"version":"56654d2c5923598384e71cb808fac2818ca3f07dd23bb018988a39d5e64f268b","impliedFormat":1},{"version":"8b6719d3b9e65863da5390cb26994602c10a315aa16e7d70778a63fee6c4c079","impliedFormat":1},{"version":"05f56cd4b929977d18df8f3d08a4c929a2592ef5af083e79974b20a063f30940","impliedFormat":1},{"version":"547d3c406a21b30e2b78629ecc0b2ddaf652d9e0bdb2d59ceebce5612906df33","impliedFormat":1},{"version":"b3a4f9385279443c3a5568ec914a9492b59a723386161fd5ef0619d9f8982f97","impliedFormat":1},{"version":"3fe66aba4fbe0c3ba196a4f9ed2a776fe99dc4d1567a558fb11693e9fcc4e6ed","impliedFormat":1},{"version":"140eef237c7db06fc5adcb5df434ee21e81ee3a6fd57e1a75b8b3750aa2df2d8","impliedFormat":1},{"version":"0944ec553e4744efae790c68807a461720cff9f3977d4911ac0d918a17c9dd99","impliedFormat":1},{"version":"cb46b38d5e791acaa243bf342b8b5f8491639847463ac965b93896d4fb0af0d9","impliedFormat":1},{"version":"7c7d9e116fe51100ff766703e6b5e4424f51ad8977fe474ddd8d0959aa6de257","impliedFormat":1},{"version":"af70a2567e586be0083df3938b6a6792e6821363d8ef559ad8d721a33a5bcdaf","impliedFormat":1},{"version":"006cff3a8bcb92d77953f49a94cd7d5272fef4ab488b9052ef82b6a1260d870b","impliedFormat":1},{"version":"7d44bfdc8ee5e9af70738ff652c622ae3ad81815e63ab49bdc593d34cb3a68e5","impliedFormat":1},{"version":"339814517abd4dbc7b5f013dfd3b5e37ef0ea914a8bbe65413ecffd668792bc6","impliedFormat":1},{"version":"34d5bc0a6958967ec237c99f980155b5145b76e6eb927c9ffc57d8680326b5d8","impliedFormat":1},{"version":"9eae79b70c9d8288032cbe1b21d0941f6bd4f315e14786b2c1d10bccc634e897","impliedFormat":1},{"version":"18ce015ed308ea469b13b17f99ce53bbb97975855b2a09b86c052eefa4aa013a","impliedFormat":1},{"version":"5a931bc4106194e474be141e0bc1046629510dc95b9a0e4b02a3783847222965","impliedFormat":1},{"version":"5e5f371bf23d5ced2212a5ff56675aefbd0c9b3f4d4fdda1b6123ac6e28f058c","impliedFormat":1},{"version":"907c17ad5a05eecb29b42b36cc8fec6437be27cc4986bb3a218e4f74f606911c","impliedFormat":1},{"version":"ce60a562cd2a92f37a88f2ddd99a3abfbc5848d7baf38c48fb8d3243701fcb75","impliedFormat":1},{"version":"a726ad2d0a98bfffbe8bc1cd2d90b6d831638c0adc750ce73103a471eb9a891c","impliedFormat":1},{"version":"f44c0c8ce58d3dacac016607a1a90e5342d830ea84c48d2e571408087ae55894","impliedFormat":1},{"version":"75a315a098e630e734d9bc932d9841b64b30f7a349a20cf4717bf93044eff113","impliedFormat":1},{"version":"9131d95e32b3d4611d4046a613e022637348f6cebfe68230d4e81b691e4761a1","impliedFormat":1},{"version":"b03aa292cfdcd4edc3af00a7dbd71136dd067ec70a7536b655b82f4dd444e857","impliedFormat":1},{"version":"b6e2b0448ced813b8c207810d96551a26e7d7bb73255eea4b9701698f78846d6","impliedFormat":1},{"version":"8ae10cd85c1bd94d2f2d17c4cbd25c068a4b2471c70c2d96434239f97040747a","impliedFormat":1},{"version":"9ed5b799c50467b0c9f81ddf544b6bcda3e34d92076d6cab183c84511e45c39f","impliedFormat":1},{"version":"b4fa87cc1833839e51c49f20de71230e259c15b2c9c3e89e4814acc1d1ef10de","impliedFormat":1},{"version":"e90ac9e4ac0326faa1bc39f37af38ace0f9d4a655cd6d147713c653139cf4928","impliedFormat":1},{"version":"ea27110249d12e072956473a86fd1965df8e1be985f3b686b4e277afefdde584","impliedFormat":1},{"version":"8776a368617ce51129b74db7d55c3373dadcce5d0701e61d106e99998922a239","impliedFormat":1},{"version":"5666075052877fe2fdddd5b16de03168076cf0f03fbca5c1d4a3b8f43cba570c","impliedFormat":1},{"version":"9108ab5af05418f599ab48186193b1b07034c79a4a212a7f73535903ba4ca249","impliedFormat":1},{"version":"bb4e2cdcadf9c9e6ee2820af23cee6582d47c9c9c13b0dca1baaffe01fbbcb5f","impliedFormat":1},{"version":"6e30d0b5a1441d831d19fe02300ab3d83726abd5141cbcc0e2993fa0efd33db4","impliedFormat":1},{"version":"423f28126b2fc8d8d6fa558035309000a1297ed24473c595b7dec52e5c7ebae5","impliedFormat":1},{"version":"fb30734f82083d4790775dae393cd004924ebcbfde49849d9430bf0f0229dd16","impliedFormat":1},{"version":"2c92b04a7a4a1cd9501e1be338bf435738964130fb2ad5bd6c339ee41224ac4c","impliedFormat":1},{"version":"c5c5f0157b41833180419dacfbd2bcce78fb1a51c136bd4bcba5249864d8b9b5","impliedFormat":1},{"version":"02ae43d5bae42efcd5a00d3923e764895ce056bca005a9f4e623aa6b4797c8af","impliedFormat":1},{"version":"db6e01f17012a9d7b610ae764f94a1af850f5d98c9c826ad61747dca0fb800bd","impliedFormat":1},{"version":"8a44b424edee7bb17dc35a558cc15f92555f14a0441205613e0e50452ab3a602","impliedFormat":1},{"version":"24a00d0f98b799e6f628373249ece352b328089c3383b5606214357e9107e7d5","impliedFormat":1},{"version":"33637e3bc64edd2075d4071c55d60b32bdb0d243652977c66c964021b6fc8066","impliedFormat":1},{"version":"0f0ad9f14dedfdca37260931fac1edf0f6b951c629e84027255512f06a6ebc4c","impliedFormat":1},{"version":"16ad86c48bf950f5a480dc812b64225ca4a071827d3d18ffc5ec1ae176399e36","impliedFormat":1},{"version":"8cbf55a11ff59fd2b8e39a4aa08e25c5ddce46e3af0ed71fb51610607a13c505","impliedFormat":1},{"version":"d5bc4544938741f5daf8f3a339bfbf0d880da9e89e79f44a6383aaf056fe0159","impliedFormat":1},{"version":"97f9169882d393e6f303f570168ca86b5fe9aab556e9a43672dae7e6bb8e6495","impliedFormat":1},{"version":"7c9adb3fcd7851497818120b7e151465406e711d6a596a71b807f3a17853cb58","impliedFormat":1},{"version":"6752d402f9282dd6f6317c8c048aaaac27295739a166eed27e00391b358fed9a","impliedFormat":1},{"version":"9fd7466b77020847dbc9d2165829796bf7ea00895b2520ff3752ffdcff53564b","impliedFormat":1},{"version":"fbfc12d54a4488c2eb166ed63bab0fb34413e97069af273210cf39da5280c8d6","impliedFormat":1},{"version":"85a84240002b7cf577cec637167f0383409d086e3c4443852ca248fc6e16711e","impliedFormat":1},{"version":"84794e3abd045880e0fadcf062b648faf982aa80cfc56d28d80120e298178626","impliedFormat":1},{"version":"053d8b827286a16a669a36ffc8ccc8acdf8cc154c096610aa12348b8c493c7b8","impliedFormat":1},{"version":"3cce4ce031710970fe12d4f7834375f5fd455aa129af4c11eb787935923ff551","impliedFormat":1},{"version":"8f62cbd3afbd6a07bb8c934294b6bfbe437021b89e53a4da7de2648ecfc7af25","impliedFormat":1},{"version":"62c3621d34fb2567c17a2c4b89914ebefbfbd1b1b875b070391a7d4f722e55dc","impliedFormat":1},{"version":"c05ac811542e0b59cb9c2e8f60e983461f0b0e39cea93e320fad447ff8e474f3","impliedFormat":1},{"version":"8e7a5b8f867b99cc8763c0b024068fb58e09f7da2c4810c12833e1ca6eb11c4f","impliedFormat":1},{"version":"132351cbd8437a463757d3510258d0fa98fd3ebef336f56d6f359cf3e177a3ce","impliedFormat":1},{"version":"df877050b04c29b9f8409aa10278d586825f511f0841d1ec41b6554f8362092b","impliedFormat":1},{"version":"33d1888c3c27d3180b7fd20bac84e97ecad94b49830d5dd306f9e770213027d1","impliedFormat":1},{"version":"ee942c58036a0de88505ffd7c129f86125b783888288c2389330168677d6347f","impliedFormat":1},{"version":"a3f317d500c30ea56d41501632cdcc376dae6d24770563a5e59c039e1c2a08ec","impliedFormat":1},{"version":"eb21ddc3a8136a12e69176531197def71dc28ffaf357b74d4bf83407bd845991","impliedFormat":1},{"version":"0c1651a159995dfa784c57b4ea9944f16bdf8d924ed2d8b3db5c25d25749a343","impliedFormat":1},{"version":"aaa13958e03409d72e179b5d7f6ec5c6cc666b7be14773ae7b6b5ee4921e52db","impliedFormat":1},{"version":"0a86e049843ad02977a94bb9cdfec287a6c5a0a4b6b5391a6648b1a122072c5a","impliedFormat":1},{"version":"40f06693e2e3e58526b713c937895c02e113552dc8ba81ecd49cdd9596567ddb","impliedFormat":1},{"version":"4ed5e1992aedb174fb8f5aa8796aa6d4dcb8bd819b4af1b162a222b680a37fa0","impliedFormat":1},{"version":"d7f4bd46a8b97232ea6f8c28012b8d2b995e55e729d11405f159d3e00c51420a","impliedFormat":1},{"version":"d604d413aff031f4bfbdae1560e54ebf503d374464d76d50a2c6ded4df525712","impliedFormat":1},{"version":"e4f4f9cf1e3ac9fd91ada072e4d428ecbf0aa6dc57138fb797b8a0ca3a1d521c","impliedFormat":1},{"version":"12bfd290936824373edda13f48a4094adee93239b9a73432db603127881a300d","impliedFormat":1},{"version":"340ceb3ea308f8e98264988a663640e567c553b8d6dc7d5e43a8f3b64f780374","impliedFormat":1},{"version":"c5a769564e530fba3ec696d0a5cff1709b9095a0bdf5b0826d940d2fc9786413","impliedFormat":1},{"version":"7124ef724c3fc833a17896f2d994c368230a8d4b235baed39aa8037db31de54f","impliedFormat":1},{"version":"5de1c0759a76e7710f76899dcae601386424eab11fb2efaf190f2b0f09c3d3d3","impliedFormat":1},{"version":"9c5ee8f7e581f045b6be979f062a61bf076d362bf89c7f966b993a23424e8b0d","impliedFormat":1},{"version":"1a11df987948a86aa1ec4867907c59bdf431f13ed2270444bf47f788a5c7f92d","impliedFormat":1},{"version":"8018dd2e95e7ce6e613ddd81672a54532614dc745520a2f9e3860ff7fb1be0ca","impliedFormat":1},{"version":"b756781cd40d465da57d1fc6a442c34ae61fe8c802d752aace24f6a43fedacee","impliedFormat":1},{"version":"0fe76167c87289ea094e01616dcbab795c11b56bad23e1ef8aba9aa37e93432a","impliedFormat":1},{"version":"3a45029dba46b1f091e8dc4d784e7be970e209cd7d4ff02bd15270a98a9ba24b","impliedFormat":1},{"version":"032c1581f921f8874cf42966f27fd04afcabbb7878fa708a8251cac5415a2a06","impliedFormat":1},{"version":"69c68ed9652842ce4b8e495d63d2cd425862104c9fb7661f72e7aa8a9ef836f8","impliedFormat":1},{"version":"0e704ee6e9fd8b6a5a7167886f4d8915f4bc22ed79f19cb7b32bd28458f50643","impliedFormat":1},{"version":"06f62a14599a68bcde148d1efd60c2e52e8fa540cc7dcfa4477af132bb3de271","impliedFormat":1},{"version":"904a96f84b1bcee9a7f0f258d17f8692e6652a0390566515fe6741a5c6db8c1c","impliedFormat":1},{"version":"11f19ce32d21222419cecab448fa335017ebebf4f9e5457c4fa9df42fa2dcca7","impliedFormat":1},{"version":"2e8ee2cbb5e9159764e2189cf5547aebd0e6b0d9a64d479397bb051cd1991744","impliedFormat":1},{"version":"1b0471d75f5adb7f545c1a97c02a0f825851b95fe6e069ac6ecaa461b8bb321d","impliedFormat":1},{"version":"1d157c31a02b1e5cca9bc495b3d8d39f4b42b409da79f863fb953fbe3c7d4884","impliedFormat":1},{"version":"07baaceaec03d88a4b78cb0651b25f1ae0322ac1aa0b555ae3749a79a41cba86","impliedFormat":1},{"version":"619a132f634b4ebe5b4b4179ea5870f62f2cb09916a25957bff17b408de8b56d","impliedFormat":1},{"version":"f60fa446a397eb1aead9c4e568faf2df8068b4d0306ebc075fb4be16ed26b741","impliedFormat":1},{"version":"f3cb784be4d9e91f966a0b5052a098d9b53b0af0d341f690585b0cc05c6ca412","impliedFormat":1},{"version":"350f63439f8fe2e06c97368ddc7fb6d6c676d54f59520966f7dbbe6a4586014e","impliedFormat":1},{"version":"eba613b9b357ac8c50a925fa31dc7e65ff3b95a07efbaa684b624f143d8d34ba","impliedFormat":1},{"version":"45b74185005ed45bec3f07cac6e4d68eaf02ead9ff5a66721679fb28020e5e7c","impliedFormat":1},{"version":"0f6199602df09bdb12b95b5434f5d7474b1490d2cd8cc036364ab3ba6fd24263","impliedFormat":1},{"version":"c8ca7fd9ec7a3ec82185bfc8213e4a7f63ae748fd6fced931741d23ef4ea3c0f","impliedFormat":1},{"version":"5c6a8a3c2a8d059f0592d4eab59b062210a1c871117968b10797dee36d991ef7","impliedFormat":1},{"version":"ad77fd25ece8e09247040826a777dc181f974d28257c9cd5acb4921b51967bd8","impliedFormat":1},{"version":"08323a8971cb5b2632b532cba1636ad4ca0d76f9f7d0b8d1a0c706fdf5c77b45","impliedFormat":1},{"version":"06fc6fbc8eb2135401cf5adce87655790891ca22ad4f97dfccd73c8cf8d8e6b5","impliedFormat":99},{"version":"1cce0c01dd7e255961851cdb9aa3d5164ec5f0e7f0fefc61e28f29afedda374f","impliedFormat":99},{"version":"7778598dfac1b1f51b383105034e14a0e95bc7b2538e0c562d5d315e7d576b76","impliedFormat":99},{"version":"b14409570c33921eb797282bb7f9c614ccc6008bf3800ba184e950cdfc54ab5c","impliedFormat":99},{"version":"2f0357257a651cc1b14e77b57a63c7b9e4e10ec2bb57e5fdccf83be0efb35280","impliedFormat":99},{"version":"866e63a72a9e85ed1ec74eaebf977be1483f44aa941bcae2ba9b9e3b39ca4395","impliedFormat":99},{"version":"6865d0d503a5ad6775339f6b5dcfa021d72d2567027943b52679222411ad2501","impliedFormat":99},{"version":"dc2be4768bcf96e5d5540ed06fdfbddb2ee210227556ea7b8114ad09d06d35a5","impliedFormat":99},{"version":"e86813f0b7a1ada681045a56323df84077c577ef6351461d4fff4c4afdf79302","impliedFormat":99},{"version":"b3ace759b8242cc742efb6e54460ed9b8ceb9e56ce6a9f9d5f7debe73ed4e416","impliedFormat":99},{"version":"1c4d715c5b7545acecd99744477faa8265ca3772b82c3fa5d77bfc8a27549c7e","impliedFormat":99},{"version":"8f92dbdd3bbc8620e798d221cb7c954f8e24e2eed31749dfdb5654379b031c26","impliedFormat":99},{"version":"f30bfef33d69e4d0837e9e0bbf5ea14ca148d73086dc95a207337894fde45c6b","impliedFormat":99},{"version":"82230238479c48046653e40a6916e3c820b947cb9e28b58384bc4e4cea6a9e92","impliedFormat":99},{"version":"3a6941ff3ea7b78017f9a593d0fd416feb45defa577825751c01004620b507d3","impliedFormat":99},{"version":"481c38439b932ef9e87e68139f6d03b0712bc6fc2880e909886374452a4169b5","impliedFormat":99},{"version":"64054d6374f7b8734304272e837aa0edcf4cfa2949fa5810971f747a0f0d9e9e","impliedFormat":99},{"version":"267498893325497596ff0d99bfdb5030ab4217c43801221d2f2b5eb5734e8244","impliedFormat":99},{"version":"d2ec89fb0934a47f277d5c836b47c1f692767511e3f2c38d00213c8ec4723437","impliedFormat":99},{"version":"475e411f48f74c14b1f6e50cc244387a5cc8ce52340dddfae897c96e03f86527","impliedFormat":99},{"version":"c1022a2b86fadc3f994589c09331bdb3461966fb87ebb3e28c778159a300044e","impliedFormat":99},{"version":"3abdd3e99f8e6d465c3d6cc49582d197cb5ba5847fefc8d2d33b90d6eb3d5552","impliedFormat":99},{"version":"7220461ab7f6d600b313ce621346c315c3a0ebc65b5c6f268488c5c55b68d319","impliedFormat":1},{"version":"f90d4c1ae3af9afb35920b984ba3e41bdd43f0dc7bae890b89fbd52b978f0cac","impliedFormat":1},{"version":"fcf79300e5257a23ed3bacaa6861d7c645139c6f7ece134d15e6669447e5e6db","impliedFormat":1},{"version":"187119ff4f9553676a884e296089e131e8cc01691c546273b1d0089c3533ce42","impliedFormat":1},{"version":"aa2c18a1b5a086bbcaae10a4efba409cc95ba7287d8cf8f2591b53704fea3dea","impliedFormat":1},{"version":"b88749bdb18fc1398370e33aa72bc4f88274118f4960e61ce26605f9b33c5ba2","impliedFormat":1},{"version":"0aaef8cded245bf5036a7a40b65622dd6c4da71f7a35343112edbe112b348a1e","impliedFormat":1},{"version":"00baffbe8a2f2e4875367479489b5d43b5fc1429ecb4a4cc98cfc3009095f52a","impliedFormat":1},{"version":"a873c50d3e47c21aa09fbe1e2023d9a44efb07cc0cb8c72f418bf301b0771fd3","impliedFormat":1},{"version":"7c14ccd2eaa82619fffc1bfa877eb68a012e9fb723d07ee98db451fadb618906","impliedFormat":1},{"version":"49c36529ee09ea9ce19525af5bb84985ea8e782cb7ee8c493d9e36d027a3d019","impliedFormat":1},{"version":"df996e25faa505f85aeb294d15ebe61b399cf1d1e49959cdfaf2cc0815c203f9","impliedFormat":1},{"version":"4f6a12044ee6f458db11964153830abbc499e73d065c51c329ec97407f4b13dd","impliedFormat":1},{"version":"b6f9de62790db96554ad17ff5ff2b37e18e9eecca311430bb200b8318e282113","impliedFormat":1},{"version":"4807f4518f03c61ee6909977fe98d21e753e698c94c1d84202636d4f3954d024","impliedFormat":1},{"version":"b541d22eb72e9c9b3330f9c9c931b57fece701e8fb3685ed031b8b777913ee72","impliedFormat":1},{"version":"79fb4e39cede8f2ebb8b540ae1e7469ae60080d913220f0635040ef57aa0aa56","impliedFormat":1},{"version":"c5f3b1f5a2df5d78c73a3563e789b77fb71035c81e2d739b28b708fcfeac98be","impliedFormat":1},{"version":"7bc0ac39181dd7d35e3b2b2ac22daf45320ba62e973c6847513a4767abc69606","impliedFormat":1},{"version":"acfed6cc001e7f7f26d2ba42222a180ba669bb966d4dd9cb4ad5596516061b13","impliedFormat":99},{"version":"f61a4dc92450609c353738f0a2daebf8cae71b24716dbd952456d80b1e1a48b6","impliedFormat":99},{"version":"f3f76db6e76bc76d13cc4bfa10e1f74390b8ebe279535f62243e8d8acd919314","impliedFormat":99},{"version":"eac647a94fb1f09789e12dfecb52dcd678d05159a4796b4e415aa15892f3b103","impliedFormat":1},{"version":"0744807211f8cd16343fb1a796f53a8f7b7f95d4bd278c48febf657679bf28e6","impliedFormat":1},{"version":"e276ef2a884a3052e2448440c128e07d5d06b29be44fbb6aed70edfeb51af88d","impliedFormat":1},{"version":"bcb876739b4dd7777c2b156401d81158234a356438b67817dde85fdeaed82e4d","impliedFormat":99},{"version":"a5f9563c1315cffbc1e73072d96dcd42332f4eebbdffd7c3e904f545c9e9fe24","impliedFormat":1},{"version":"d4eafe01f9155d8bd7749971480789bd46f14a47544ce6ac3c79ad0950c6429e","impliedFormat":99},{"version":"590595c1230ebb7c43ebac51b2b2da956a719b213355b4358e2a6b16a8b5936c","impliedFormat":1},{"version":"608cbb7c90cbf935dbd968efd5216b6236f882099647eb1f111e3f5805670cd5","impliedFormat":1},{"version":"f95bb79909136681416172da0163edc81bcba15f9548c23211780225e4b74250","signature":"6edbb6947100d98c2475891ff725ccc9f1c836bea487c8e61581e51e54b149a2","impliedFormat":99},{"version":"c253c7ea2877126b1c3311dc70b7664fe4d696cb09215857b9d7ea8b7fdce1f0","impliedFormat":1},{"version":"5c1e4e5796363f74432c44dd416134c42fcec370fec5910125cda17fda1b6949","impliedFormat":99},{"version":"cff399d99c68e4fafdd5835d443a980622267a39ac6f3f59b9e3d60d60c4f133","impliedFormat":99},{"version":"6ada175c0c585e89569e8feb8ff6fc9fc443d7f9ca6340b456e0f94cbef559bf","impliedFormat":99},{"version":"e56e4d95fad615c97eb0ae39c329a4cda9c0af178273a9173676cc9b14b58520","impliedFormat":99},{"version":"73e8dfd5e7d2abc18bdb5c5873e64dbdd1082408dd1921cad6ff7130d8339334","impliedFormat":99},{"version":"fc820b2f0c21501f51f79b58a21d3fa7ae5659fc1812784dbfbb72af147659ee","impliedFormat":99},{"version":"4f041ef66167b5f9c73101e5fd8468774b09429932067926f9b2960cc3e4f99d","impliedFormat":99},{"version":"31501b8fc4279e78f6a05ca35e365e73c0b0c57d06dbe8faecb10c7254ce7714","impliedFormat":99},{"version":"7bc76e7d4bbe3764abaf054aed3a622c5cdbac694e474050d71ce9d4ab93ea4b","impliedFormat":99},{"version":"ff4e9db3eb1e95d7ba4b5765e4dc7f512b90fb3b588adfd5ca9b0d9d7a56a1ae","impliedFormat":99},{"version":"f205fd03cd15ea054f7006b7ef8378ef29c315149da0726f4928d291e7dce7b9","impliedFormat":99},{"version":"d683908557d53abeb1b94747e764b3bd6b6226273514b96a942340e9ce4b7be7","impliedFormat":99},{"version":"7c6d5704e2f236fddaf8dbe9131d998a4f5132609ef795b78c3b63f46317f88a","impliedFormat":99},{"version":"d05bd4d28c12545827349b0ac3a79c50658d68147dad38d13e97e22353544496","impliedFormat":99},{"version":"b6436d90a5487d9b3c3916b939f68e43f7eaca4b0bb305d897d5124180a122b9","impliedFormat":99},{"version":"04ace6bedd6f59c30ea6df1f0f8d432c728c8bc5c5fd0c5c1c80242d3ab51977","impliedFormat":99},{"version":"57a8a7772769c35ba7b4b1ba125f0812deec5c7102a0d04d9e15b1d22880c9e8","impliedFormat":99},{"version":"badcc9d59770b91987e962f8e3ddfa1e06671b0e4c5e2738bbd002255cad3f38","impliedFormat":99},{"version":"444634b6bb516121294ceaf6494bd8509a5a1a82f161d241855d372ff9efda61","impliedFormat":1},{"version":"32b191427ab4b739866e8df699b71490cd8640312be03f08df897b5a248d60f6","impliedFormat":99},{"version":"3e72fa7fe2d190ba0f334cbd500c2be2ba133a0ff6a983e04ba2cb2cb1b3f31a","signature":"2d91a5d4c0bcbc101afdaf788e1e7a16ac92011dd73ad17290561bff00939bfd","impliedFormat":99},{"version":"5901e698c1f23d7b91d0896e56ebfb88fc5e3c02ba2153c93c7a9d05c209eed1","signature":"f28aef59c8a2745acefe5a9bc51537b4daf71c094698a0a998dab1aa5a014ac3","impliedFormat":99},{"version":"eb4f83ec48c1eb9c6c8f0e290b6cd6f8769696c3496a26379bb6d896e673b351","signature":"6d221d441a45c854a7f53bb570acd150e7412b3dbf33a18b2ad72c45ef43ee19","impliedFormat":99},{"version":"088703b7810394a5af823ac753cca116931df81a97183725ae1e2c4e6038268d","impliedFormat":1},{"version":"2b9eaefcb439dbbcd6c87366fc534616e9aa9917ecc84f144f66ca23db44c147","signature":"4c4f5aba09fd8ec96a72c3177906388157e043f3851f6685ecba0cea503a4421","impliedFormat":99},{"version":"f773253b3fd22940e637224996d7af120d9b4ff2bc5011ee6c2b606bb3e2c8f4","signature":"e242f6533ce421763609310879e5e51f4288d662a50afabdf565c6b005b94833","impliedFormat":99},{"version":"d4ac9c78bef7437993f2e83bf08e59afcad2997067f38db3eaf53fea7fc0463f","signature":"227018354afcc7019818e5f72ab3200cdcd16a854aa3cd7167d51c061964125e","impliedFormat":99},{"version":"a09b80d28d3e36e90d7104a6a4de37da9dd11516abb1052b7705fe27a0579246","signature":"4fe26304b5557ae38534fdf7d3f6c38cb30df8d5bbc22cbfff5c151dd7e63d14","impliedFormat":99},{"version":"760627ece0ce3b45df7fd09b8d137c26c045fe7e039865d65122400682c670ec","signature":"61fcaf8674d3f0659d4bd5c338a6fcce1bb991db41425c961fd4742889035c18","impliedFormat":99},{"version":"052fe7a6d6c4447d99be2ccf6472aa41398265f63a77ea3a1799782666ff8de3","impliedFormat":99},{"version":"ce7f045680863a8c6943e4a546a25f428fe6cc4c406969f243c9e8b2ce05c278","impliedFormat":99},{"version":"25a5fc314ecb103cb21f1db89958be139c055fa6244cce937065b628f19d2fbc","impliedFormat":99},{"version":"dbdb18be06b306d30323b3ba7b8f2966447cabf330aa02f574a7365a81bcfb92","impliedFormat":99},{"version":"db0cdbaf428affcefa26a6eb58b4258431b4a231c982366f15463d67902faad4","impliedFormat":99},{"version":"3718eb2e82cd01c29f2029e3a4de2361e83d8fa7a61fd03f15de103be3c6866d","impliedFormat":99},{"version":"a05eea02959d6335aa42e3cd1bf3262e851989893e24e84aa798aea27b466419","impliedFormat":99},{"version":"b1f2afedbcc29f0ee014f51e239201ef268e5be4b0a9f47938ea9048bb992921","impliedFormat":99},{"version":"32cbe201bfe8ed7f4c323fb8a3fcfdfb451f22e84d3c49da33ceda2fbf9230be","impliedFormat":99},{"version":"15dcf35edcb927f3720fc999dabfa873e0733afd69dbbfeb1c304d2b12155c1b","impliedFormat":99},{"version":"6b4b0db56e0f75c5cfa02a1121cfe4bc465aae8d8a9693ec7c8eeed9b28ca823","impliedFormat":99},{"version":"12f03afb493171b5f73f1dd407fefe8c59e17eaf2fb2d219016602363d2b761e","impliedFormat":99},{"version":"c860f12740e0396dfea15b99e42819659e5a3f6b34133e328adba4be7ebe1746","impliedFormat":99},{"version":"7500becb73606a5418a0de2fb8c6b670096c26efd37084ac779e37acd3ea171e","impliedFormat":99},{"version":"511a68fc5469470bced981ead81dbfdda005d21452fc42111c7129194cf95c63","impliedFormat":99},{"version":"6bd85b1142d9603859bf70b21a9df0b690bcdab604d1b2081d869719fabf3769","impliedFormat":99},{"version":"75367b9cf2854dbec67fcaa29f4cdb52be0fa281dcee2bc784ce22a51d2ea2b0","impliedFormat":99},{"version":"f86797e373d65f0da88dd3924e24074cb61894489f5625cfc47cd841d3019bcf","impliedFormat":99},{"version":"d3cfde44f8089768ebb08098c96d01ca260b88bccf238d55eee93f1c620ff5a5","impliedFormat":1},{"version":"b542939a35357458e62f8229c2d7578ae888d63d3ab837395d7bb8a3064c205e","impliedFormat":1},{"version":"3a5af4fba7b27b815bb40f52715aedebaa4b371da3e5a664e7e0798c9b638825","impliedFormat":1},{"version":"8485b6da53ec35637d072e516631d25dae53984500de70a6989058f24354666f","impliedFormat":1},{"version":"ebe80346928736532e4a822154eb77f57ef3389dbe2b3ba4e571366a15448ef2","impliedFormat":1},{"version":"49c632082dc8a916353288d3d8b2dc82b3471794249a381d090d960c8ceac908","impliedFormat":1},{"version":"f672c876c1a04a223cf2023b3d91e8a52bb1544c576b81bf64a8fec82be9969c","impliedFormat":1},{"version":"71addb585c2db7b8e53dc1b0bcfa58c6c67c6e4fa2b968942046749d66f82e7e","impliedFormat":1},{"version":"c76b0c5727302341d0bdfa2cc2cee4b19ff185b554edb6e8543f0661d8487116","impliedFormat":1},{"version":"25b3f581e12ede11e5739f57a86e8668fbc0124f6649506def306cad2c59d262","impliedFormat":1},{"version":"e703cfacb9965c4d4155346c65a0091ecded90ea98874ed6b3f36286577c4dde","impliedFormat":1},{"version":"f5ef066942e4f0bd98200aa6a6694b831e73200c9b3ade77ad0aa2409e8fe1b1","impliedFormat":1},{"version":"b9e99cd94f4166a245f5158f7286c05406e2a4c694619bceb7a4f3519d1d768e","impliedFormat":1},{"version":"5568d7c32e5cf5f35e092649f4e5e168c3114c800b1d7545b7ae5e0415704802","impliedFormat":1},{"version":"e568aeba150fa2739d6f703ceee6e32f5cd72eadf4ae9a7df57df6706e5d712c","impliedFormat":99},{"version":"c9327c23edd11a6ba747b268d87075b62e2f3c99ab7fe2f73cb2d730a45029cd","impliedFormat":99},{"version":"a56240a422eba940abc675374704cc76e1f6378742b962cd526691d955b7f8c0","impliedFormat":99},{"version":"1c6611982d2b6a9593b869968251df88fa968ce69541e9480e40a6e737741e55","impliedFormat":99},{"version":"a6d2d3749d40bb80cc1db4cef4f6403e62818e8e76dadfb2802dae74159d2447","impliedFormat":99},{"version":"925d23745a2e0c630005cf10b93b142ad84a85a130ad49ed6dbc334b25f0b08a","impliedFormat":99},{"version":"dd7ca4f0ef3661dac7043fb2cdf1b99e008d2b6bc5cd998dd1fa5a2968034984","affectsGlobalScope":true,"impliedFormat":1},{"version":"09cb516d11a7c7113c24c1dd8f734869e9966746f379e9b88a925a87ad908fdf","impliedFormat":99},{"version":"a3c563eb0aad02108298a985c260ac725dfa4f12708ee2ed5227820943b59653","impliedFormat":99},{"version":"d88b3dc8b7055665059ea06ffafce9467fc4bdfa7cb2d7a6f4262556bb482b0d","impliedFormat":1},{"version":"b396c5f865111cb48f5b97e8573d759879ced04a1aef432f0750225aa9f8c6bd","impliedFormat":99},{"version":"c3deb025ee8e1c0f45d7d82b3f235218db3395d757441183b7be69c872785f5e","impliedFormat":99},{"version":"a377d52f042411e4a949ca05a79fbba1f8f455c8c6ba02634463f6ac997ec41d","impliedFormat":99},{"version":"200d11765347233df119c5aa3d048fe741e49e57e5c49d3c304c01c44fb8520e","impliedFormat":99},{"version":"00411f0238f39ae3bfa499e3fa10302988a3842e8a8f9e902cd292d630252bf6","impliedFormat":99},{"version":"3a4d30926f55c8ebc992d7001dd93db11d13eeb9dbfc74cc1d42a62c1847f8ad","impliedFormat":99},{"version":"2674642faa9c285f9b654758371ea7ace1153909c3126056e415693fd84ad1d4","impliedFormat":99},{"version":"81828984e8f5063510622ccb36c7f68016e3effa5e7ebfb6ac7e24b8dbfa9b09","impliedFormat":99},{"version":"ae908ed59b40d4df5ed42f34512feecdfce72b6d21b667706542cefbaddf970a","impliedFormat":99},{"version":"36cfa4d25d2575040649e85e0c8385856adb33154ff3560d8a5aafb68b964ff2","impliedFormat":99},{"version":"3f69633602105a1fae36023d252e056dbcff9d7581c577d19437fdbb69f58d03","impliedFormat":99},{"version":"2f15333f5c888aee06009b1a6c4e2c4d2f765d7bc31135fa14ca530a948f3037","impliedFormat":99},{"version":"88066857eb61d0f068588dde29aebf0c18327a5b5d7d8fc1f3dcbcb36d97bc38","impliedFormat":99},{"version":"d814047ff5c496bbd6820e128b360ccc2a56acd203ddfcfb507c4e25edfc9d48","impliedFormat":99},{"version":"0c5c49b6322739e4656d5956201e5cae674963783abf1338395d83f64d9f507b","impliedFormat":99},{"version":"a93cff2a27753839b793729d963937d67834345ec38b6ff6c560dc40de0f88c2","impliedFormat":99},{"version":"6bea577855853cc48a12d8f038de1157cce727a93b9301b6428830c58c561525","impliedFormat":99},{"version":"5926e552082af4082c58bbe2b8489e9f5e826b868456cc00b053a6a954d5a593","impliedFormat":99},{"version":"1b28c4df57b1a7f6f9b052a6ce145caceaa78339af9d608b17912f45de324f58","impliedFormat":99},{"version":"d535fe6a9a49fa49a927e2e9f4a068f372dbbe3f2df777b9a028d82c8aadf55d","impliedFormat":99},{"version":"0596c56fa73772ed5dc19cc31bc4eba6b57b416fe6b0e307e0cc083d5c3ed10c","impliedFormat":99},{"version":"bca5f946bf7ec8c2c65a8b7602a7526958c2f2ac4ddc86407eee3b8013b94533","impliedFormat":99},{"version":"e66135d88eb6f7482692c939709310ae0afb4abf089320497595c088f187b0c9","impliedFormat":99},{"version":"a154d4648ab1cbac7379d4bf3a67b629b7c053020c9ca81d1c5a7f8a3855fc86","signature":"3b7747c033b16152091eb3156a58056a45eb7ea085351e8d942a007cf1a43051","impliedFormat":99},{"version":"c7144a87481d39621d3d178c17c0372322a48d11869aa72aa617518b41180e21","impliedFormat":99},{"version":"e1bfbebe69689cab72e5ac213f1cbaa07671dbd337aa8697df8ea13d2980f678","signature":"46ac83e312603c145c53535233a15dce194a9f12a43a415bc112963cad455aee","impliedFormat":99},{"version":"12db781c43f06a5030645d62fb616470bbdd2e17dee91500e09d098d5159ab62","signature":"ad733ba3f11c96c8c5047c8033cdf49c8667ff53046f14e06d72a3e1599f6caf","impliedFormat":99},{"version":"32cbe201bfe8ed7f4c323fb8a3fcfdfb451f22e84d3c49da33ceda2fbf9230be","impliedFormat":99},{"version":"d31a436a784a6ccde7acd3e937f7f45f66aa3ab856af69388e9b2b5a96dadb94","impliedFormat":99},{"version":"aadac50bfbeb25e2ff5f0456049bca54ce8a932d16537922528e7f4680175af7","impliedFormat":99},{"version":"d3c678f189964e8f54df90c5d2646b6a231bfb42a0e7757fe4830055217c0f94","impliedFormat":99},{"version":"0ac55506dd203a9cae98e8405830783bd3f233f26a0dec0fc0b279fae2f2a46e","impliedFormat":1},{"version":"3aa259091b1174b817f471d1fa9802cf79d53199092b0af1ed3cebba728a2982","impliedFormat":1},{"version":"71ba1647b9450b0fa13e6d53c05b83908468f6a4c0d8f438ce48871d1b0e320a","impliedFormat":1},{"version":"b69d4563828891cacfbaee8667592e3522ff3ff05dd59eac518a3048ebe21c79","impliedFormat":1},{"version":"8fa6a68b088bfd88bbe4dd80e610983e8736127be06559d72689acfda595588c","impliedFormat":99},{"version":"93c838304a7b3f9eb4fd6b3d9993f4a4234694a8c9f76a21b3a9a6c04c981363","impliedFormat":99},{"version":"84e27c83d339870a01f752e4ae9cac486d7501da1ed029a52d09931b38af3430","impliedFormat":99},{"version":"5c464901af7ec9420762859ef27366a0908dcee01c299bb4d5a9b60cff67551d","impliedFormat":99},{"version":"845bcc38db960753c28dc96ee9cd459926dbb2f274c1aba768abe0ff5a5d494c","impliedFormat":99},{"version":"4d32e16a44c01df68f57c3a112fc3bea1fd4cd7cf2b7150e3bb923162d10b6e2","impliedFormat":99},{"version":"aa9f2a39d99e2376556fab4d95b7bc697f036c67068eccd9cf09fe87c5f229a1","impliedFormat":99},{"version":"5ab7690385b948ce9fa789f6b0377e28bb4e91a843b34a2d171648f2c6315be3","impliedFormat":99},{"version":"c961b20d7a385200f6047c538b03892000d601567314f39220a0cd305705f18b","impliedFormat":99},{"version":"a272330aea88b18305639508dcd0cc9b7b12642f6856a5b0fcd0889e257d2f09","impliedFormat":99},{"version":"65f0e4035624223d79d6f82f1e090f8115793784d57bebe50ea0c80609ab86ad","impliedFormat":99},{"version":"623c6f0c41c459a4454d7993cb49e1e9b4f6b920ea0a3a11ac8b9f6ceb65b90a","impliedFormat":99},{"version":"18d5e4245385f6e9aa1cc032577608447dad65ed2dd7f76803895e619dda93c6","impliedFormat":99},{"version":"65fc1b07f81f3ceffa96b4db9881c0c165384b895410da457a7ec1e17c821613","impliedFormat":99},{"version":"319de222e317ec333f02742b9aff1a0912a8840c6a101f8d4cee262d7f7a5b04","impliedFormat":99},{"version":"c117a320873762f461712acab7a6708dcab2c1c279382c7392ac0e70b8609fe5","impliedFormat":99},{"version":"58ca66ecec099ab769ce4fef62f4cc93718d93c9d0d4b67dfa7ba20c9a7c50ed","impliedFormat":1},{"version":"8e9f6c8948e6f0335ec146c229bc4941c0728bcb5d7efae2e2d5fd46341942f1","signature":"0cbd38c2780cf7b22aedf79df8298399bda1baee4e4cf09e05a8602251a759be","impliedFormat":99},{"version":"a7acade0df0ffa5b5208e45521030dca3f0092737c56e3d8482327934f1f6c81","impliedFormat":99},{"version":"8b5367f0d7e40c91efe7e921f69d1bf4b71c22dceef29d5506728e401d50d367","impliedFormat":99},{"version":"0cc6cd165f7f24bc8c559d998a85cedb90ec56eb1cb2465da247e4c3f40274fa","signature":"ed3a9c5f12843eb92677d66b27d28ca8b898e894334514511489d589f8716139","impliedFormat":99},{"version":"b9640002a4df53ad3b6146ce3e37af79908b7bbd48ddd20d3fe21e342f11b3d1","signature":"4e823455d3a1c3f89e94524dfd2b45d6db24252e0594d90fa9a5faa8b99eb351","impliedFormat":99},{"version":"2c72514446b137c1c8506095b74204a324e31a60a3283edfda62c0cbf24384b1","signature":"87110d2e1e78a17db6253d493f857c55d79ecaafcb63c572ba0eefe8328e0b16","impliedFormat":99},{"version":"fdd4f294363e754a24baecacdbf77344705dace9d22658d9689530e4892a126a","signature":"dae1ca59dd60d6abcb0b88744ba4ea36cae0668b6723020c50796a514231eeb3","impliedFormat":99},{"version":"7c0046fa1022ae3f38dc67f4b453dd0899cc633129cbb74e4ec37afcb3cdff98","signature":"61d7ff71ffecdbc63b1e4d7f0132fb13fd458d6104d886327e6d457166f0f0aa","impliedFormat":99},{"version":"7487336664c47a177534c6a26cc1dfedaeb6b34064dc1123b077ee678fc6b79d","signature":"ef2c3467e3e0b763ecc60595500a8f5627dd541008c8e91f4d869f9f4161b642","impliedFormat":99},{"version":"15b85f6acf4369171c752b6cffba86e933242ca105c93c97d5f984543a98b920","signature":"7873b28b5772b4be365569ab58f7aeea7cb41408b6cd48ca5f3a8235b1769835","impliedFormat":99},{"version":"6ab0129aecbe71d87206c162e71d82463d9fcac7b55860c7e44b8a7ad9dccf31","signature":"e3c8629bf250b7d7adaed3e6277e8eb0604b7654ecaaa86ae7ac03e24195e40a","impliedFormat":99},{"version":"eeb0164ded2d4d35481eb923f078af02b3cc747b1b69cf0b5ac3eee0baac474f","signature":"f8428205e98c54325741e1292ce3c1672548755d3d71fda72bb169a196509e4c","impliedFormat":99},{"version":"39ff6f3e5e6c45da321f80f8abf94e17cfe511080e8ed05bdf2bd4deb118065b","signature":"764bcd5e672fd89a8f82d62b6f46657e7a9503d31a25c6b3d84ff6b5fbebb780","impliedFormat":99},{"version":"93a98ba747d8637f2e65250461ff910355f755caf6a29744def94b1c0636843d","impliedFormat":99},{"version":"c7b726233b40a362211795f661be875227e3cd76965c550ec35637e5506dcc27","impliedFormat":99},{"version":"bdd213e4f878029eed842c8551fb3072c5ca626eff5e7b60c3950bbfb9b62b59","signature":"f20312f46230feae2511930e70b45ca96538b3afef0ca2d7f1d4f8951d16cb29","impliedFormat":99},{"version":"5bcc5451c9baec3af6c6dbd2d58b1678103d218af3db41f3631aed87d8c0d769","signature":"ebce6e335c44c22cb3170690d0fd07a17c3ab01be85c7c28f95ff9ee6f843039","impliedFormat":99},{"version":"1198ee17e5f1edba6d170dbedb6db9359e7870e7aad46396280061caac97ef9e","signature":"d9c60f043b9147b4e899af3b5ad81f09cab9b42b2157c6d6514d7523f3fe2eb1","impliedFormat":99},{"version":"be9620d9dae645eac815cd7609f8dd48fe13ca6560189e4bdea242af4ab126da","signature":"81215018a4aa0ac2c57cee49294022843a3853f45fcc2291be7fddbbe41dd000","impliedFormat":99},{"version":"ee3b54c20c7192f572311d45ee7f791c1ec4d315ece2c0927e377c142dcc2b65","signature":"390a9391b282edeb3474ac2d8224071cbfa125e2c32e50361e82656c3a7e4869","impliedFormat":99},{"version":"9558d5260a87eda3be2117ade944f767c4637134e01c42d885b1cbb010eb4569","impliedFormat":1},{"version":"b7eece07762a9a944f097ee05d6f6b642b1e2dd87e6fc1b09600d881e5475377","impliedFormat":1},{"version":"bd27645ebb8287ce3c07470af310a3f8d9c36b7d9bf8c8d84a160945481396cd","signature":"2b0ef1515612423fdee8fb0ee475519ff744165f11dca8cf776e421bde1c7f81","impliedFormat":99},{"version":"2e5086d4ab92ed1e865df8ac953291b312e2ae44fd49a88e0e6fe44ac1d436be","signature":"aa2f48eeb1c0286bf8d7c515626cfe5a0a0bd0a0e099738ef23308585338a242","impliedFormat":99},{"version":"bd130eb2dd14aa8606ad74fc7ed9fc87371bb01a1e32f9ba4f5b41a342fa98f5","signature":"70aaca8a17249aeb1e16235f79cdefce7c12644fc745dd94bf49f345739a7744","impliedFormat":99},{"version":"229d15f176a73f5dde18998ec5c50786193964a68bc65e0fa096be09223d9fb5","signature":"264ad8cd8b68988a8d7c5967bed399f182d9df7ce2c94cbd2a7f8e59c0a8d019","impliedFormat":99},{"version":"6c4de9221562677475a35d76f4980a2d9e84d8b4eca033a7912a8f8246b3d58e","affectsGlobalScope":true,"impliedFormat":99},{"version":"bd4f37eaa93cb3de27616c9958a3fead822a4198e48b27e057d862a66e1193cd","signature":"c57e0c5d8672758d118b640436cc55673d68d5f89c0930f54a80716756290979","impliedFormat":99},{"version":"018d327d03bdef669d35264756cc2e7affa62bef04eca676a776678c27be5137","signature":"6a0e23bc892b9a0743fd9c1d5ca89efab60dfc02d8d21f0c3bbdf8c73690c9a6","impliedFormat":99},{"version":"fc84cfcdc9a8671402b106dadacd5b804c9188b8c6daba9f75941916d787502b","signature":"aa1b461c9e058df00772b4fb36540b8d855eb5a6f6db1c2b643c4f46d59fc590","impliedFormat":99},{"version":"ad44db40ce9ab86f10ec26dfbecf5826268dfd9e50177a128273c23faa46eab7","signature":"4283ed01271d5a2212c4416f87689b8ca4c5c24e8e4aefd16c64eb864545e95d","impliedFormat":99},{"version":"b402dbdfa81ddde4565152aa1456a14cffc5d9c4ef2118ed9762e2813bcd5e10","signature":"1bdf835bb54ed21d249b8d47e44fe483a617cd74b7d3d9963d6db0c42d371ee3","impliedFormat":99},{"version":"864dab6ea50d8a860a8dfbc29843a320181f1f3c5a3290dafd11bcf4a8f7b8aa","signature":"9c000e1b409396425cc8316ed6b91a0e29483f0bfee0614a3409c59fddf3513e","impliedFormat":99},{"version":"491d6345718f300b5c5a87063820ba34eb516e33347caba9b7042afea90facca","signature":"8133fb7c7bedca4b7fb9cbb44b335568967dc8cc4a16f705c6580228912c9014","impliedFormat":99},{"version":"5f4702498650704cc30dda96c390abca62d82407a9fbadc6339ab5852b861c54","signature":"76e42734b94e2890b49617c72ee87f06bf1dea92a16b77931967ae579bbd8152","impliedFormat":99},{"version":"04159fcc2d58286e527be2d8b274cdc9d39f80401ed75cf3412460ce522300cc","signature":"2c1c389a2c6548055c63fe47df579f197d1c2f013302b082fe2c0793898ce4d4","impliedFormat":99},{"version":"b41cc328072fcf73a02feee5dfcd92c6ffc8cef623ceb7948dd8ed4f564c8c09","signature":"8cb9c50a92c7c04714cb21fcc012b887fa782de80baa23e08f966836ed82935f","impliedFormat":99},{"version":"dfefdcf01b5764302755cdcbc15dc91057eaa6204e2386cefe82a8687896eae9","impliedFormat":1},{"version":"b81e7f124707b5991f4138414cec31c66d6dbf570618ee0511e64ebd36f94dcd","signature":"559e687f961fd95f93696791f18ebef01b9d859c95c63a7c05cb1fcc27a941a8","impliedFormat":99},{"version":"ac85d847ff195c65b05951dfd537f53a8d7d8037aaa9fb8acfcee52e28f813f7","signature":"29fff4eb517aae2f117b4ac5354be36a668b0bb278f5aa0022446ec22b899287","impliedFormat":99},{"version":"cab0e34c211ca425b3999094d594a4f85093798e292aa5403533a85edadc85bf","signature":"c4cce11c9178bf0deaf768f4f10e6982c9312b8e2b59aec79623cd74f10fcd6d","impliedFormat":99},{"version":"4d55a12b9de7ea95b66577eab248b4f2a015ff6b020e8e055b4a4e4b3afc15f5","signature":"fa0e8744308947256174327055a0ec64d9803e37b0594c64359e00f9118eee62","impliedFormat":99},{"version":"375825a745145deeb084162d9aa19e3c0b1d06874da706c5bb2d85523628b5c2","impliedFormat":1},{"version":"1e96e451edd3cd721c203110bf320aa152b189ea91ab52eb9473f6647c3d9c3f","signature":"6b6f501f0b296dc138c625d0073b8bcab2f779a4733fd7790156e2a8a4689114","impliedFormat":99},{"version":"3d51c96ee5f781ed1636e07ddddd0a1d3ae42027b823a6d2585199487c6d824d","signature":"c067cb34eb5531bb63d34c1081d409df9afc2af21f251334220f20d1be7537bb","impliedFormat":99},{"version":"8dcd8273655aef81be9c273e532a55f56032c7907b20f8ed4d069f7eec44ace8","impliedFormat":1},{"version":"76a3606c21eda1bcc4ec732fc09a400f6a0c692f447c9e1f5cd0e516b483f023","signature":"8092a36eeee8108648c03e0c41db56afe9a58172c88c9f053902c857d6d1b202","impliedFormat":99},{"version":"061abd7e8ced01353f8ee103a1b1ca69bedba64acd7a743de6c53c4466fed025","impliedFormat":1},{"version":"54a0b0a65bda993e314d67abdfec183b3d96f8d4de70b8f0554baff14c2a35c5","impliedFormat":1},{"version":"9e41ac0e33d32c2e369005a17b746c793c1e09b8f7d9feb2417b41eda2d7f359","signature":"585d05583c0a2c55f440ce97ab31f787165491ecd2db9ec194f40b41992a9c89","impliedFormat":99},{"version":"322630a0e2127a4f73a864fb4df1771b77b982681e261ea58af6780b39314880","impliedFormat":1},{"version":"036c64d75e44c63070bdbd4fb718303563c77bef1b835a7408601347ab709dd8","signature":"1fe4967de32a23ab01d65ae734df18ec9b94658cbf60146919820ddc2b8971e3","impliedFormat":99},{"version":"64fffbdecf3df8f02dc2084fe9c6d53eafd11b16dc569f98e468f085be2e3e1c","signature":"7836b6425c105eb7ff2534b978536c1e7b51e1805d06e90db6b25f7d1ce6a9b7","impliedFormat":99},{"version":"a69b069dadc7074ed5a77d2fa0740bb1d2189ffab26e765260e8030117344ab8","signature":"31cb7e3c866b7c9c90cb60b95ff50192a5e05eea2eff3951ca4a94ca6e25b95c","impliedFormat":99},{"version":"2741cab8e67115bfdb858bbfadd524de9799b8f7fbd4cc379901cdf4b57a6dae","signature":"5c10084cdffee0896388190f7ad532d6506f9d1abe4d92451850f87219967521","impliedFormat":99},{"version":"3374c31ecd9fe6c1e2892bdd55decd044c06d1640d23660fe94a121c9db976e0","signature":"abf52e5f1670de7beacff9ed50a2f7c63fcb35e7d74d3807bee7fdcfddd31e98","impliedFormat":99},{"version":"1df367a39e32672bf15d16c7300a3248a3443c9d7c94cf6f9e649aff14cfaa2c","signature":"e297b7e463d554a3db2c0acd2d45cba29b8b73fa86a23a9dfa63420183ee87e8","impliedFormat":99},{"version":"ab670041d468aff737b658e35c521eb19ffe96316cd1a83f28883a5c2f62c50a","impliedFormat":1},{"version":"6aa0561bd73dd1760cf264a0ada7cb32b8019a5158ee262defd52f2848cdd430","impliedFormat":1},{"version":"93fffbb7f1c5d526d530852862b2fb2a3d5713deeaf22fa9032fb5b7a88dec80","signature":"2c1b6ba5a26c69d256932a17432edf27ab30cee3292667096e7d98926ca2bdd3","impliedFormat":99},{"version":"618579e08df40af42bc41b3e968f60828cf6318297da92dbfe56594c4bb9efcd","signature":"770350c951aa440d6fea800710fd3b6e91552b1a553f4435472761ab0c9d1fe5","impliedFormat":99},{"version":"b43e3942142e872865fd559662e3accccb51675fba579751d54b91cc4f518538","signature":"5b7f764b8d510cc6cc080260177682033d8f4e315504e4e22d7794d31d25d566","impliedFormat":99},{"version":"6fc774fef0592c111d665092ad5f162cee104235742eeeb7d8df6e4f6ebf285a","signature":"25b8ecdfa770270679aa94d87fef3a1430b883b9edb37f5eaf6eaf151ef3a9fe","impliedFormat":99},{"version":"5047f26687088843cacc1d1651bfefb3cd8960fb90705039df26a806fb24bc84","signature":"9463ad5ec3b8cff62ee9319aa5b94ca23f826b5344b0d219dbf50950ce17f3f3","impliedFormat":99},{"version":"dae63e28c932e4f39f9f0263d66b7082d6b1476267a7796b88d1984324ac0ba7","signature":"9662d9c3296009dbb7bbf59cbd82e84abd25eb2e60db84bb7e3a69b9dae7a342","impliedFormat":99},{"version":"08906ca4df290e78211120ae722953b460e978096c01ab2d42a682088fd1203e","impliedFormat":1},{"version":"38daf8c02f6266564eb289bd38d4067cc3219389d6a8a24c55c79ff762df2da2","impliedFormat":99},{"version":"6d9462d5f3a93784b618a8e22b3aba6dec7cd510234706893fa61d251373cb5f","impliedFormat":99},{"version":"f16e9e6df71bf32a8f96ee061b515437fbc2b2d7bf278208972e795de1b1a355","impliedFormat":1},{"version":"20f604414287e25bb5046a7d3b9156e12a2d29aa4b4f6d74a6e69538c51298a0","signature":"f167a0971f8611c0b8261278e167cca8ff523c7dd13a44cf498298d722dac950","impliedFormat":99},{"version":"f067d812736cf4a1ba81c5dba28d64e6f2f49ce45af71905e3392db33436e534","signature":"67551824999cb45b593f86a4f2e728ce0aee30d2f217727f1b0f4a36b08ca216","impliedFormat":99},{"version":"a150d1c3d1fdeac449c52e0e682ce7c1b06bf2d9285c6f75bd05994a49534363","signature":"08900fd4eec6298307329a8a4462fe742f7d52ed832e6382201447b651be5c09","impliedFormat":99},{"version":"0f791e7d9e5609d6557a8ac627c24fb33aa6d43ab6633e3a6103b341836c590a","impliedFormat":1},{"version":"8174e1355f5239021c966e7ac481046afa09feaa8c26b2e50983a9fd0dd0c765","signature":"faa88903bb6dc90f7225733cb0bed7d0c47bc94e9e8887c7c0640968fa11e574","impliedFormat":99},{"version":"f3c9e0a66385922f234524ccc38835db7e14ac6412ab118b9d34f6ff79ff765f","signature":"37da4e6c195d20ee5fd50633dcf58ea8d03177732b803623ccd46aa49acb9d17","impliedFormat":99},{"version":"0aad15b592e469f55e1f446bcb3dedd27ae063345cf273b80bb3d54cd3113442","impliedFormat":1},{"version":"f7ab6a9b1299e3e69ffa5cab9accb5d1cb9611038ee915eec43ca0b25ee0237e","impliedFormat":1},{"version":"91764b36fe5e1c5d688f5f90eeea47703a059ab9a81bf80f7bbc9b04507b7bd3","impliedFormat":99},{"version":"adb5ad16c19ff8dbfa9daa3a7dc8e1b039c381a2b94383144a53368681ad8ca0","impliedFormat":99},{"version":"e48896ad27523790c68aa6ef341c815d874a927204b5fc77b6295c5d225d98af","signature":"29be9856a593eb1ec25c4fd0eb9d2c103c107a01646d38347ebeb718f5c6266d","impliedFormat":99},{"version":"9bbbe72d3d4caea7b6266a4e87c0247eea9ad6418ae56d224c8ea888eef92a1b","signature":"a1c0ca064df0ea7e94390f534d27f874d705eb2e97681bf6099e1027d798d692","impliedFormat":99},{"version":"822f38e7d348d3db3101c6a53f7ca4ab5432717caff45a7b5b252b0b521786cb","signature":"915fd3d5a9761b960423bf435a05cc5992f51aa0a5b03f25b589e7f95fbe702c","impliedFormat":99},{"version":"96696cd73d30d52a634e3cefde8f60610e077b308bba9eb7705c5f9fa7ecc5cb","signature":"e72e7166272ce753994c3951f3a92d072e183a41b36ec97fcc217b86fe00807f","impliedFormat":99},{"version":"670d9739b234b46489e0fa6043269c662b6ee7a62b5f5da920356e1363b9b4be","signature":"a6e24b1b2dd15efd676b10ba8e65286734073a1b4c241616040c4dd5b12d47bf","impliedFormat":99},{"version":"fe8a6e4803f203d23ee447902eb264f478f16ecb41ac4ddc721bbc8aa440a004","signature":"05ecfcca613118f830fa58992cde0c052d02b77049411dd5bff86f05427c5624","impliedFormat":99},{"version":"1325ca02fb4ff76f9b0b3c5ab8f04a48ee99c50242f9571d6f7f22dddde81eba","impliedFormat":1},{"version":"ab8ec3826df18259ea79e2a8ca9a6374bb552d9454697d5f6f18afc3f3179943","impliedFormat":99},{"version":"53b44081fe1aaeb5f4fed7ea16c8b1d561d71b8fe15744d36a15094952a8b695","signature":"9ef0105c67a8027b37c194afc4234010a5bf0aa0d8d20dcdb16090876f3b4e12","impliedFormat":99},{"version":"78be24de2c24b43a255c0ae273ccd54253023f4a505ed43195490df36049823b","signature":"cc62e2fecccc39d65e6bf742d0f0a94021ef8f482869ea65f9443e9a1e2229b3","impliedFormat":99},{"version":"cbeff352adef9c201ec8ec46cbdd822833843b8ec5d881894f7bea23f51ef324","signature":"47bbfa3d08b01cdd4be3f20df55f2cd9eabfe47f14b6c232f0f4d02e9d542586","impliedFormat":99},{"version":"881b163cc037810f9d3dab7ec671df9d0939d8588cecaeccf10d9614bd14a422","signature":"bb8ad18dc4fc662b049a8c322ee2c728e8c87eff04aa814469c1c94aa569fd01","impliedFormat":99},{"version":"c1103635a53654c31c29be2a16f15f9e2e7d4dd45c85e879675fadb9ccfa4faa","signature":"1a6bb8499657c69f64f246316fc3f5e646dd5eb18e63434f668d1fdec835ff33","impliedFormat":99},{"version":"d16e7a35a7d2de9dcb27d1f20ef0d66b14ee0a36c7d9f8d5da3b3e38325f3403","signature":"736eb0dfe3634bcc0e0bfd9fc59970c1dafc02362475d84174f023b225ed5b07","impliedFormat":99},{"version":"fb1853fc6e52955d4b8abad35a2de9929c6721ce9134a93880af9818ca2ae691","impliedFormat":99},{"version":"1257ee54981d320653568ebc2bd84cf1ef6ccd42c6fb301a76b1faf87a54dbd5","impliedFormat":1},{"version":"9ab0a0c34faa1a3dd97f2f3350be4ecf195d0e8a41b92e534f6d9c910557a2e6","impliedFormat":1},{"version":"45d8db9ee4ddbc94861cf9192b30305ba7d72aea6a593961b17e7152c5916bd0","impliedFormat":1},{"version":"899a53848def7a9e4d3d33621d3002b983bd37cc93670401bc3593435c86d3e5","impliedFormat":1},{"version":"5da94e87e7ddce31c028d6b1211c5c4e9b5b82e5a4b5caeb6cf7c5d071d6e0f3","impliedFormat":1},{"version":"b483a639ff4c3ae66f35ce2e8f5942fbda4ca5687c1c8ef599dca54a3b870527","impliedFormat":1},{"version":"4aa311d7da4493cfba71da8c62b3b5c8c6b0b71fbb3c1dc0ccece6cae33cd452","impliedFormat":1},{"version":"2288693289db1068cfc1092082d1f572afb456e2c82e0d2d91d82842f219bab9","impliedFormat":1},{"version":"a6b5dea55f228fa87c3f316f8c91af07d01a2080a437eba452f1d1ea1be8abff","impliedFormat":1},{"version":"06197e656f2756de6c786d6d81e7ea2e4c8f04c53e7fd804f1dc4db58bdc2a35","impliedFormat":1},{"version":"29efb0f7665d433c62af9c053152ab900295a7077661a8b82ae8872289c9d777","impliedFormat":1},{"version":"5180a1a33602d0eb1ff18a8370eab0bc98f81060f4c64dcbbfab9d8db0075379","impliedFormat":1},{"version":"5a2cd1d19a6e09f2ea10f1a7ad4f8ac00b88117d208bf6aa491f621f7e960884","impliedFormat":1},{"version":"128deb6e1215c99a54eac934035d5be70ea52bc31278441d8716cada6d3be51b","impliedFormat":1},{"version":"b96ffc470b9199b8d4f4a0c8da2f35381800dc8982d531657965dcb67da8b6ca","impliedFormat":1},{"version":"297fbca2836d78ba85abe9d26ef0844d7edd0fd61759040eaed4070a989e7dfd","impliedFormat":1},{"version":"c884d560430256ab7765cdad72f9e466e9e65db61a245c2310490b5ced3abe76","impliedFormat":1},{"version":"b6f2a56a96124f9d919e98532b4d0299d1c0798881bc30da196845d4f0d9a374","impliedFormat":1},{"version":"1c34c2ca74699b26ac7025304600240c5ab570acf6d4cad4519c8c306164ada9","impliedFormat":1},{"version":"bd8397055fbcbca1be43962df4c7aeb2a052970280c846bcad224a1922eae2bf","impliedFormat":1},{"version":"a4c07340daf98bb36410874a47a9c6f8de19fa54b015505f173bffb802fd110a","impliedFormat":1},{"version":"e9af2804e0d79776e63796d14bcb32804d7d7fb4d043d70df74288eb42a1f4eb","impliedFormat":1},{"version":"758e92a92871b11a9aede1787106be4764ae6a32f6c76bb29f072bfa28d9f69a","impliedFormat":99},{"version":"1694f761640dd96d805157f64c826748860207f375b0a4ccf255cb672daf0f83","impliedFormat":99},{"version":"2fea489e3c5f8d4134f54efc5bda5ec68e419e7ec3d190161f78bac4b8396c0b","impliedFormat":99},{"version":"b2eadc9b2db171f930beddf847a4e064a2985b83bf344beb44d65a8f016f08aa","impliedFormat":99},{"version":"1ead895650e6ca37ea8abcc05e9a9752b73e8008a7985d73a5e3816f4a1df3a6","impliedFormat":99},{"version":"929288672d6b91a25b82e047ee87bf37e03f38d3602aaf3a4fba53e028675264","impliedFormat":99},{"version":"649a01dcc990910ab52e35967b38fdc7c16095b54a9189dea18c9e3e4e40ec95","impliedFormat":99},{"version":"d2b70053822fdb37df76b171956ef3ed0341d08ffcf89d3a9021f7fb301fb2ab","impliedFormat":99},{"version":"e892b406cc200ff1a1cc550a9a667d83fff38fff7169a570ad49dfc3d43bbb87","impliedFormat":99},{"version":"c66d62d7e0f918751ae576b4567ea04ce2538abdcccdd83459e559ab74416ecc","impliedFormat":99},{"version":"c2bbbdad520259f1b029852cf29d8a19c886c4b9a965ead205e354678a4a222b","impliedFormat":99},{"version":"7812a1bb9b5475ab4216005fdb6332d5b57c5c96696dec1eddeafe87d04b69de","impliedFormat":99},{"version":"e91d958316d91eca21850be2d86d01995e6ee5071ca51483bbd9bd61692a22b8","impliedFormat":99},{"version":"81c9f06132556fc6c89595f624ce2b6b15be515be15fd77c3eddda4de58778ba","impliedFormat":99},{"version":"0aafe1b9144616994247e80fe2c9dfbf2fb1f64fca4795479dfe8e0b5db9c588","impliedFormat":99},{"version":"62accaae04a3db14c5ef4033231408edb801d983c8a355c5e03f56c90bec8648","impliedFormat":99},{"version":"78b64de15366b18545ec6a3dcc3e78078f47d7d4adaf5cdc39b5960c1f93a19c","impliedFormat":99},{"version":"3b210aa55ec4b8a3a740e8426f79cd8e177777d528750f1da11cd611f36f3e44","impliedFormat":99},{"version":"5eced0dd56654336846bc6606dcbaf3c5a253bd1bc614e1644f3c0ee1731b633","signature":"e6b48e703e398f63d80105f4dbf74bd22dd269d218ffb8ee560c4e1ddb415562","impliedFormat":99},{"version":"a8e4c9e8b8fe15a0b86845a01d6fc9948e345088590d0b9680b3fa9f29b2c39d","signature":"4600c69435a964d18707640aa1cdc67f03b01c3dc293543e2dacdeb856316453","impliedFormat":99},{"version":"00419c51598e7d4e3fff7579b25daa1bedda3374b799461de077126c32a38259","signature":"4dfd8432215a84ce9617c17b1247afdaefce3ef404793495ae065aaf50fd2eda","impliedFormat":99},{"version":"44dcc9f6f83c9f479819dd7db4997d85db49270b34798329748b27a4500f2511","signature":"0860e21274a4e36b524d73a9678db23d0bd5dc61de4dd72cdba60cac292a0017","impliedFormat":99},{"version":"7ef424250895bfa7f7d6ea800a51cda7394457df728187cc57c295f8c0affee2","signature":"662aa1c08f8aaa6d062eb8e18d5398c237dc81661703c2b36d9214e4081a4491","impliedFormat":99},{"version":"26dc6208720beb589f4ab9669a0a0b3de9fdc34b5547c534d78e13122696b4bf","signature":"21f101b1a5db05f23da3e3b878edac309f45ad420792b27c874b978a4026ab4e","impliedFormat":99},{"version":"607cc53eb9a2b308e480e584235c9c68bae48c9b2f5a35e6136228202d02dee6","signature":"4f4b2ba70599c24438e339aa9a1df6951496514f72abc3bac786f7335de72b03","impliedFormat":99},{"version":"8f82e49493baaaeaf639ec4680e76be75cc0fc4e9efc69213a65e70239b8f58b","signature":"6389a543e40fde1473f68a9c5e8299023c25d106e55a87f0f14b4dc54e94ed69","impliedFormat":99},{"version":"920869cecad3bed07a61051af4e3eba9602dc493f62ccfb9b3e14c64f4f222c8","signature":"64af3c656288ca32bb50cbb7ac04bc847894c88bd3fce02920ab831e8ea83bd6","impliedFormat":99},{"version":"c253c7ea2877126b1c3311dc70b7664fe4d696cb09215857b9d7ea8b7fdce1f0","impliedFormat":1},{"version":"cbb45afef9f2e643592d99a4a514fbe1aaf05a871a00ea8e053f938b76deeeb9","impliedFormat":1},{"version":"5728fd6e79e51c877314783a38af0316f6da7ddc662f090ca816b9aa0199720d","impliedFormat":99},{"version":"7ca190853b0c3a30b7a781a785653345b181d04284d56010b5db73ce5faa3edc","signature":"6fcf910d0f36ddf05267fd68267b0a2c2a7b8555eb2b059560db548fac2be53a","impliedFormat":99},{"version":"2f304c34d3743473654c8f5f932d2cbfdd7cdeb37f5296b22ad67bec178c3f29","signature":"b1e84ffe9b64af7a9345743875201899dd3e94cf62061d9444725ada22c04d2e","impliedFormat":99},{"version":"8643039bfa16bb150dd85d716d01de043321351a288554bb0c573b2ca4dc6386","signature":"ba4ac13ad8c31c6dfba4ea6fa438b41a7617c45a7212cceb998ba871aea4a392","impliedFormat":99},{"version":"de2259fc54113bf98f08c9adfe7482ca7835d953c660e17ac3c365bf53b39512","signature":"76aff3bef9d7cacf5a736ac110499a19bd217bef6c3ed7259acdee93acff8a58","impliedFormat":99},{"version":"e983a835ce13996b6de22ad2610e040dbeb0afd433a294a7d163ce7c457e8268","signature":"1395c4a9c15fcf2e68c1cae4d4afd6d95fb2d64d250655a695a1c0e824976d33","impliedFormat":99},{"version":"62105d7740785e82c0af10035da2d8832b669dbe032dc7da4256d327fcb9986d","signature":"39d32c1a5065d7413889ed9a07d65127e8a4f79e5dd3c1a0119774b25b9ddcb5","impliedFormat":99},{"version":"16d51f964ec125ad2024cf03f0af444b3bc3ec3614d9345cc54d09bab45c9a4c","impliedFormat":1},{"version":"ba601641fac98c229ccd4a303f747de376d761babb33229bb7153bed9356c9cc","impliedFormat":1},{"version":"d2f7baf43dfa349d4010cbd9d64d84cdf3ec26c65fa5f44c8f74f052bedd0b49","affectsGlobalScope":true,"impliedFormat":1},{"version":"84e3bbd6f80983d468260fdbfeeb431cc81f7ea98d284d836e4d168e36875e86","impliedFormat":1},{"version":"0b85cb069d0e427ba946e5eb2d86ef65ffd19867042810516d16919f6c1a5aec","impliedFormat":1},{"version":"6d829824ead8999f87b6df21200df3c6150391b894b4e80662caa462bd48d073","impliedFormat":1},{"version":"afc559c1b93df37c25aef6b3dfa2d64325b0e112e887ee18bf7e6f4ec383fc90","impliedFormat":1},{"version":"15c88bfd1b8dc7231ff828ae8df5d955bae5ebca4cf2bcb417af5821e52299ae","impliedFormat":1},{"version":"6d575d93896c413b308c3726eed99ddd17e821a00bdd2cc5929510b46fe64de4","impliedFormat":99},{"version":"b426f3f04c96acdb64a805c559330678cf7d50da593ffcaf629a6b135ad39fa8","signature":"fab7d38045df1360e998afa23834aaac9fb60f565fcbd27c07354c4d4ec9f473","impliedFormat":99},{"version":"f634e4c7d5cdba8e092d98098033b311c8ef304038d815c63ffdb9f78f3f7bb7","impliedFormat":1},{"version":"c3a1a51e33468f28fc1dea4bdff4c0838daff8622ffce280117f9ffc3b2944d9","signature":"56f5956abad224a1a4fcb2711e29597eeadf7ccdba212fbf2a9fe9a2521e9958","impliedFormat":99},{"version":"61e58db6672209c4cedcb6d30e518924a1c306e717b2069575cbf73fb1ec63c9","signature":"083fe62bef0b10f093d7b572fd9617c0c5c8571d5d8d48de90a6523068acc600","impliedFormat":99},{"version":"f5131aa7365b4265b391e3187ef67e3c63723ed20de6c646ef8618831e96e76c","signature":"5f92ebe9401610b25459229350fe555fdeaa6940542600dcc99be7467678aa28","impliedFormat":99},{"version":"827eb54656695635a6e25543f711f0fe86d1083e5e1c0e84f394ffc122bd3ad7","impliedFormat":1},{"version":"2309cee540edc190aa607149b673b437cb8807f4e8d921bf7f5a50e6aa8d609c","impliedFormat":1},{"version":"f161105ffdb65b7b01a9e1a8b066d17644f3163a2ca371fd1881d06440dbc956","signature":"5b2cda3c8817e1b61b626df7759b883749160cfec11f4c073f3f472efac22346","impliedFormat":99},{"version":"a2a94f6468093fa35dbb953dce2ff5caa0677bff2730d21c5e2de142d0ce33b2","impliedFormat":1},{"version":"9de2ec15f6a63e6a4e926e0ae865af226d486094382a53412e62cf2ef0f43b5c","impliedFormat":99},{"version":"43e0d9a5565c7ac15e697b5b22b68dda2dbcdd5e4308e7880b9db97e29392279","signature":"a9d7a0ab9ea827df3b838efd13789d20f8dcf83eccbb9a4be54c9d82a8d341bf","impliedFormat":99},{"version":"21c7a6c6631fb9bc2fa3fac282755116ed27033febd89166fa766f6e6df9cfc9","signature":"16d47ae5639b4245ed445a7ba1bfc5e104e11d05dce2745822552ddef0a8ca11","impliedFormat":99},{"version":"c253c7ea2877126b1c3311dc70b7664fe4d696cb09215857b9d7ea8b7fdce1f0","impliedFormat":1},{"version":"52131aa8ca7e64f2d26812ac0eb1b0ebf3a312e2716192d2c37d8d3c91eeeab8","impliedFormat":99},{"version":"2887592574fcdfd087647c539dcb0fbe5af2521270dad4a37f9d17c16190d579","impliedFormat":1},{"version":"f5858a3e4621139b8a375fb79a482c633d5f31d744f3674e3d51a4ae291c8f2b","impliedFormat":1},{"version":"ac7bb3cadcdff93a1b79ce38968fb242f20336d2191ce4330927b2e2aa8999ac","signature":"a8f82c3fb0c942f901bb7c520ca99da0cdcd132343a000219a40d8db0f0a8381","impliedFormat":99},{"version":"45d4d2497474a680b8d0324fca816980988c4c2535a673d62ba795c1d4c5a668","signature":"d12ae6f691e9f9ed4f2d7fcdb47d908d3476a378230e6e0f7ad6e472c9ef9d1a","impliedFormat":99},{"version":"af3b1b4a00b5e4e190b0585b239d9589c86fcb3a6c464c9fb9b387d9bc8ae481","impliedFormat":99},{"version":"e66a29eb40c2538cd4718648a3f684cc28066fd462da52ae487fb2035f2d4d74","signature":"1dc24e3af717f901c5363eb235b673878dd4502ce3eee68576f9e51e8632506f","impliedFormat":99},{"version":"7201f57570153d563333652ef563eebbea46b7c83a54f08d6ea2c2f4946e617a","signature":"4d6ba281896c15db9161222b6b2bc07ec9911fe70cfe2471e64347142c00ac41","impliedFormat":99},{"version":"a7fe7e88c50608567af53c49d3c59ea5f33bf5f59126d67b2a25f85eb41297ba","impliedFormat":1},{"version":"e30cb0c13b84721d7b9072d9f7ac75b808987c5198b532988369c68ac1f6d4e7","signature":"3704fb76b0d0053b26e5d1eedd3c49a6e0623a075ede3c77b4fb1adb821eec64","impliedFormat":99},{"version":"eeafceea12dc9e0a160058d6455039246a9996914ea3c56b2ffd7d5fcaa4478c","signature":"eb7012287602066466cd320664e3a177cef6982da7bdcf524fe04f0eeca79529","impliedFormat":99},{"version":"85ed9c356fb336539d5ed433263e2f27b869f01743275ce8b8fbcc2c1809ef42","signature":"016aa6157139388cf6737c1bfa7aa3004ffde61d9847a87a3959cf4e4e0b0a61","impliedFormat":99},{"version":"1c47ecb87c85161fe6f328dd5dd3b1cb24a6085a50404cd874ff74e6f75d2672","signature":"20f163818f7827c2535e3775f9105fba66aa8b4ed6bc1a10a2ff5d06bd1e40a6","impliedFormat":99},{"version":"1c3735b4f33b59df671faf04d2e19ae7dd834f3cb4ad903d91d16b7618118c00","signature":"a7f5d4824fd44ab2b3da71147fca7f3ffd62f81febdf237ae0a232bd8f91d160","impliedFormat":99},{"version":"7a0f7320d37408a3d03ae6a0cd710615bc999d5db203146028365caa38fc8219","impliedFormat":1},{"version":"a89ff1fb3de5205b6f810e11e0dea4a529bf35c3b257f23fe0ee3f097f1a6dd8","impliedFormat":1},{"version":"f85855c94b112d97977bdaa00665c01779e47416bfb73ce6dc1a949b13e5aa0f","impliedFormat":1},{"version":"0db68e8d0389334fdce5c3dc899bd7175ff8f1b1c5d4b440692889b59cc341d3","signature":"040703024d69aa7d6917b5de305dbf825021fa819cf9a91da2ea038d39e4d9fc","impliedFormat":99},{"version":"65dfa4bc49ccd1355789abb6ae215b302a5b050fdee9651124fe7e826f33113c","impliedFormat":1},{"version":"60550aec61b6b7012420824782afdf1b2d7e0ebe566ab5c7fd6aa6d4bae55dfa","impliedFormat":1},{"version":"b2b3d71a8707e7da656213079b85678da8cce0a8f367914573fa9483b03b5fac","signature":"6ac13362193d7b243eb9bbc74f4458a52c85bb90f660a1ff6a234707d254bdd8","impliedFormat":99},{"version":"8b2064762c4c9956683f61835bac52cbe9c32c3a2eb95f6537e87503227e8888","signature":"70d0822c96fcc77e3d2bd898a6d87cec4728a504fe5df05ab8d6c77e1cf94b37","impliedFormat":99},{"version":"49883e6cbacd0674bcc5a05df073f3d5ebc73ff6b5f5d329ed077326510d31e1","impliedFormat":1},{"version":"79cd047baeee940762c303c6f57f98465077545acd6d74ab064c4b1e03bd4e31","signature":"80f632f2607533fcf926fd6f6d96c19cb1c660cb4ce755996946a55af70f7329","impliedFormat":99},{"version":"08873721e55c3c1de4d7219dc735fa8448374500c2a3db44f349605efcb66156","signature":"06c1cc3941693562eacb9cedca9c2e41bab7a95741210c6a92f3a424198409e6","impliedFormat":99},{"version":"7baa971ea053c588860348709d82b49b41e1d1a9669e0b634054daf23c7f9f16","signature":"4115b39aecab7feceffbe9bac130b33a6097d2bd1f2befd4bbb7816f96dbb01f","impliedFormat":99},{"version":"f749dc5f1584d6d9214b2799a2e12ee2ffa3a1fdc348fff511eb0e945327ab82","signature":"2f10897f2a4105319ddc6392480812a980ee21af079bb2fe87016fd039c422a8","impliedFormat":99},{"version":"17785650990d608d2324b5dff8eb29daf4f180a0176c99d027ee286295845647","signature":"29878d66789aa68c8928cc5de86724b50ef37f04180412c3a23aff77b42960f9","impliedFormat":99},{"version":"a189fbb95c63978f2ec5179451f485c4bfcaff829ebe3a3854c2ae7882fb0e17","impliedFormat":99},{"version":"39bcfff55a376c270088dd88806d10e6e1d4d280e9905e6458e08cee4b594ba3","signature":"bc468b92c7c4ec1c6cf6b84f7cf249dd4c730da67cce564676bf660bcb58ff6a","impliedFormat":99},{"version":"dd78263a47e5657ae925527fa32cc643931ccc725c2e30a705032987e68730c4","impliedFormat":99},{"version":"c5d2c7cb2c50332aec1be9c65353efb8308b7088280a729763e2141bec107bf9","impliedFormat":99},{"version":"6f61a0bcf3d46341cb05413028bf00301aad728231d417a7f42e2b331dd39a8f","impliedFormat":99},{"version":"291424805ddd10bb51d3ec9efe48e83b3bf791f12dc4f114867889079f1ca43d","impliedFormat":99},{"version":"72032aed69c98ff9d94b1e1515dd7569bf06564f66725c53c0d1d20df277efe9","impliedFormat":99},{"version":"4b61b2cb308a7a6b01dc8ceb7a1efb4ac6fc1d0afe2d42c98ae60fa3c53c90aa","signature":"c9afe6c021bb642610b94d2a078e6c10c0f4a373af78ef4f685930c5d35ab340","impliedFormat":99},{"version":"b63e381581c45c783928598c41fb6117bf3c581fef6a052392bb64148e819f90","signature":"cff87d5bca26a2ddc08ecb6ed71c6358972454851d256c4ef97da33331b4696c","impliedFormat":99},{"version":"5a7ebcf5fe8ac590dd03af1bbe426dfed639a3490fb1e5d6b934e45643b8ea1b","impliedFormat":1},{"version":"537bd81394de1d3d6dfb9af22259559a93aac90f03bb80811de354c6603bb34b","impliedFormat":1},{"version":"e4b4326b61261bf5ffd6de8b4825f00eb11ebb89a51bd92663dd6e660abf4210","impliedFormat":1},{"version":"43a4860173cec933ed8380e55f7a4473dd0df38b43e706b492f443cd8612bd87","impliedFormat":1},{"version":"f90d85d4cb38445499bdb7e7b013e4f64d99d157a6fa0843e998495ceb27b520","impliedFormat":1},{"version":"2e178a87e7bf03a067cfb1cf5573e7c4899fcbc9f462a0b0c67d238e39b794a4","impliedFormat":1},{"version":"901becb8779e1089442378fda5623e607ee4588762a32e7692436f1ea81cf848","impliedFormat":1},{"version":"8286d84d2567b713fd6a1fdfbb1a0abc8cfa668ee1e0e83d7dd4ade5761f2750","impliedFormat":1},{"version":"f28dffc6bf9bbd8b9dc156aadb74d11de7faabf547eb9f0aebb8cd03e8750a6c","impliedFormat":1},{"version":"a05ebc3674deb77908d5a9385c5b246edd6eeb042d9b83d828fbc4fea7a4d7a1","impliedFormat":1},{"version":"97402596b68e028aeaf4779c609a1ee35fb98be9c7ed9f2d9870a844970a0042","impliedFormat":99},{"version":"eb5a18ff81309fcfc307dcb798f0e6dab4a3918928e49c314037cd8c9bc56dda","impliedFormat":1},{"version":"7f482f96309e3865d7295a829643500f196ec423782b64ad008b19596bf10799","impliedFormat":99},{"version":"fbea5e651cb86ad689d30cf0963878b207baf65cdc00cedb58b15b6e09064910","impliedFormat":1},{"version":"a6add645e43d9899dbbc657157b436e29653c9d1d230dea0cfb9ff1f053a266d","impliedFormat":1},{"version":"56a50d5cb6f9068a247132b8a48a1b3d72b4d8a82f3bb5bb0210cac21341ba48","impliedFormat":1},{"version":"646483c3da2908cb01be25636e7b6bb3164db2e2aaf4249b8f5ae8af654bdc1d","impliedFormat":1},{"version":"8722f197f77b724af76856d3a5ce4bce80073f6be5403f3ac551f029d950f25e","impliedFormat":99},{"version":"c4d23227ea6621366b7328e9d8dab5611f98a588354aeec5602aed88d5951b60","impliedFormat":99},{"version":"72c0c2d2a621ee1c9c8676da0fb95d60da2fac306ff69c28e77815d192a4d05f","impliedFormat":1},{"version":"b3f5c18e3f40c78ac6cb98be36789242e0c218f2ad23d1121dfc6164546a9b4c","impliedFormat":1},{"version":"90f1590c7d131ef31e4e1e104f920444613b72e30e72ffe1e24468753f74ba8f","impliedFormat":1},{"version":"18c5f42dfca20a5ea2f3c4484bb269ed593648a46fbb5339408972fe13c69803","impliedFormat":1},{"version":"b5ae41485ee77239d98bc1de2fe0885fdf38ece68044976711733957e599a1a0","impliedFormat":1},{"version":"77ba35cd38d1444c3acebb37bcc65cd0940e1375e3fe9d620af82318498a46d2","impliedFormat":1},{"version":"200444013098e1101ebcedd1ed7e066005edcdd79c2a3b4639e6c31afc6d16b4","impliedFormat":1},{"version":"65d08b51e495dea476672f6425e867165faa7e810b0f79246bd7b254fdda394c","impliedFormat":1},{"version":"6957c30f4e63a04f729f0ce8c29fb4e7c1c2007a537055a0e9a7851d5c62d64b","impliedFormat":1},{"version":"7158569b18767ca4b75eb1f6be88fdb7d1affc0a3d49604a66821b6c34e40881","impliedFormat":1},{"version":"11112e9608dd55e8bbb833466c7d3d594caa50f2ebf6b25cdaef5c7de58d107a","impliedFormat":1},{"version":"3e3984aea990ced29e2cf141c7122077cb9c4a666a60b4f68c17c27e257985a2","impliedFormat":1},{"version":"b0a944320d1f135103b89cbc1abf7b8cca2e8d19cbce7e521b68469153c56476","impliedFormat":1},{"version":"04d95cc745a0ade65cb097898f678efae5b98f34cb7d87cac3f3a20942a8c473","impliedFormat":1},{"version":"664261afc0e1327bb2699b7041cd4f04b7aaba73909034073c4dd85ae2160e19","impliedFormat":1},{"version":"8b51734f81cb942e0df48448c959b7a9a94b5ad976c79f952e4dae18794b746d","impliedFormat":1},{"version":"f1e5ae130c5897d7a3d652003dbebf222fef33fbe0f375e6dbce2a5c6c1adfad","impliedFormat":1},{"version":"d3a6e1ff56a0a760b1b36eb34925042a8148d8e0ab4c2d28fcbdbf40fb5a8acc","impliedFormat":1},{"version":"839114ddc4236b8304df6a6c7cc6784913b7c69a63afd4ecb36fc5c9c57276fc","impliedFormat":1},{"version":"cc4ecb6238b32248c6b58577a2ac2a6223c002c1a9e3f1f9424a89f44aa84f0a","impliedFormat":1},{"version":"43d6a5d2e16da096be6d33fe3c362056de879491b05d488dfdebde8897515fba","impliedFormat":1},{"version":"2a95739f4682f791166b7b6295e81ca94c51d0aa238d552daf18eda8164eeebf","impliedFormat":1},{"version":"4aae1d39abff5fed49e7a564cebf72d16c927d3f88740c06b1c99326094cf752","impliedFormat":1},{"version":"e7508e6530bb3cf4a0b2cfed3f7fe3af36883df699fddab087d2fa25269cc363","impliedFormat":1},{"version":"92950fac48e0ffcc3b7c084638a03ae3529421ad165b49879893b60907ad563a","impliedFormat":1},{"version":"0838507efff4f479c6f603ec812810ddfe14ab32abf8f4a8def140be970fe439","impliedFormat":1},{"version":"428567adcb151876f14ba36e3ed7deb476a74257a4819d09fc7804963d09878f","impliedFormat":1},{"version":"14fcc596b21f06cbfe0b9970f3a6c0672fa5448a677c468df2f05a5954ed97dc","impliedFormat":1},{"version":"1340e1709862ade7206176e131ab1abebb6bb72bd2974e3f0236b4dc4ec5a4f5","affectsGlobalScope":true,"impliedFormat":1},{"version":"e6771a79205706eec980e1b0cc9ba358a2847a500da1e44486dfcdccc4e24933","impliedFormat":1},{"version":"6c70ad7d9cb6a020e24ce1863c3ab26a966615d386db1df4030df6ae6df4aae4","impliedFormat":1},{"version":"edccbf47ffb11281dc4245515258b5a26153b816dac3e0606f482875de684626","impliedFormat":1},{"version":"3876ed22278c447fa9fbabe490370d9dfbd94ae3efbf393a42d00478514a8d07","impliedFormat":1},{"version":"b3a44ce274a8baf75469f42e990184673480b5970327b34522a8f05b6b4a7a97","impliedFormat":1},{"version":"56363e59268f7fd3575b2c76ba0ba60a1d6a205feebe8ab080b53c1a06913858","impliedFormat":1},{"version":"53e0ccd8974edb4d10060ef5f94eef4092c06333fc2a27de9e969d0d26693315","impliedFormat":1},{"version":"53b5b818a4ce42a022112107f5a01924affd6ee908e999ba278351556793caeb","impliedFormat":1},{"version":"c3e89152965e4e5fa3c217653f97c633083cf968a61d9d81b41347c4aaba65f4","impliedFormat":1},{"version":"6bbafdd9fa51bcc33f013b6267eec5c13ddbd01206fdb2cb333f8656aff85140","impliedFormat":1},{"version":"2d0f051ead6ad8becb7e6f7da769a6cbb1fb0d4614e8e979f90cbc4793a83864","impliedFormat":1},{"version":"baa73823ce303e21dd69fd8709b03c6de066ca0ac782fb3e6f6be1ef2366748c","impliedFormat":99},{"version":"e28de435f283adb192e578884149ffe28f99d09a3c3cfcad4940abc2e706e667","signature":"f9962b1961b6ee3cd39f641fbf4dbccc190c8056f3f75b36c6cb7f36fa3c0a30","impliedFormat":99},{"version":"5622dd1eddbc31e2f4385a1d59072460cc8228d7bc9c9ca3e4dc772c80a77617","signature":"bd0688b0df0b7190a7b58652c29c0f7aa6db579a2f214a2c050705b2b2dacae0","impliedFormat":99},{"version":"0828dd60d0ea50ec9edc32fedd4ac30dc4af97fc1b3e3ce07c9640ce1103d92a","impliedFormat":99},{"version":"607819aaa6c0016edc1760e120070a00689114a0e2812bfc8fc8d892a6c75c9a","impliedFormat":99},{"version":"76150b701d3d784a30b1fd081ed8e0a34b6da836129ba5539dc0c8221a9338d6","impliedFormat":99},{"version":"22960e9371a7d32f0a1c4492e3ff6c7ca6fdba7e2e73b0cbc7ab73e479e63d6a","impliedFormat":99},{"version":"d866d597fb9fb5c1361c12e3defcdc8b3166ac1c65f1ba6c653ed98513dcf522","impliedFormat":99},{"version":"b8b0748b78f316e47137b598294e78e815d8b5f87ddbf376dbefdda89435091d","impliedFormat":99},{"version":"c69bde68870dfad4077824357acfc599c564b063232d740229ca61b9fb3c1ccb","impliedFormat":99},{"version":"7aeaf75b6aaaa8ae0532837e27e8f773737a471d5e0225b762ea11df1e5ee6dc","signature":"e3d604bd1eccccc54b60e5a26209db83ce4e456bf37556600091704ced5f3623","impliedFormat":99},{"version":"3fb1a6a42b681d8c85d28a69199100ee06be1388d76f00c47f5f5e74f26de225","signature":"d1bfbb57afb862c91ad1c370218ca4223bd02156fbbd95490bc0e2f4fa986ed9","impliedFormat":99},{"version":"9980f3ae56a6a50f4e6d05d3d02e5c5738388b7812e93539898e815dea97eab4","signature":"d97c2de5b74c1f6c50188dfc15f0a5f7bc7d73661734881dbe5de6cf65d20824","impliedFormat":99},{"version":"818e7c86776c67f49dbd781d445e13297b59aa7262e54b065b1332d7dcc6f59a","impliedFormat":1},{"version":"46bf7e45f200db6e4957ee86ef935063de356e832d02ce8a8935ed62a10ea2ad","signature":"ea75b1d0307c103f73052280ece702a40405ab97794c1c1e5a0657041ce62b10","impliedFormat":99},{"version":"5246d792554f17390e74ecd495b183844005e58430e1184cb125b10a246c960d","signature":"9e34dcf3a97aa02c644854e5a3e1c31e765f83fdf545ddb2545c91cec914f5d8","impliedFormat":99},{"version":"799160d7cdf0152a5495a050eb837470efad3cc23289db87f88275dcc59d9064","signature":"bd11d7a3ac4baab1da52d4c181bda933eb7441f34a8f23c29094db8e3b8a2b1f","impliedFormat":99},{"version":"c953181aa8e2c8f90afd0977ebff709cf2315aa6d3e20411cfedb077e6aa4945","signature":"e760cbbb97deedaf4fa4776768ab394337afd9aec2256698256ad8b8003d58c8","impliedFormat":99},{"version":"c68eb17ea7b2ff7f8bcfe1a9e82b8210c3112820d9e74b56b0fbecaab5ce8866","impliedFormat":1},{"version":"2d225e7bda2871c066a7079c88174340950fb604f624f2586d3ea27bb9e5f4ff","impliedFormat":1},{"version":"6a785f84e63234035e511817dd48ada756d984dd8f9344e56eb8b2bdcd8fd001","impliedFormat":1},{"version":"c1422d016f7df2ccd3594c06f2923199acd09898f2c42f50ea8159f1f856f618","impliedFormat":1},{"version":"2973b1b7857ca144251375b97f98474e9847a890331e27132d5a8b3aea9350a8","impliedFormat":1},{"version":"0eb6152d37c84d6119295493dfcc20c331c6fda1304a513d159cdaa599dcb78b","impliedFormat":1},{"version":"237df26f8c326ca00cd9d2deb40214a079749062156386b6d75bdcecc6988a6b","impliedFormat":1},{"version":"cd44995ee13d5d23df17a10213fed7b483fabfd5ea08f267ab52c07ce0b6b4da","impliedFormat":1},{"version":"58ce1486f851942bd2d3056b399079bc9cb978ec933fe9833ea417e33eab676e","impliedFormat":1},{"version":"7557d4d7f19f94341f4413575a3453ba7f6039c9591015bcf4282a8e75414043","impliedFormat":1},{"version":"a3b2cc16f3ce2d882eca44e1066f57a24751545f2a5e4a153d4de31b4cac9bb5","impliedFormat":1},{"version":"ac2b3b377d3068bfb6e1cb8889c99098f2c875955e2325315991882a74d92cc8","impliedFormat":1},{"version":"8deb39d89095469957f73bd194d11f01d9894b8c1f1e27fbf3f6e8122576b336","impliedFormat":1},{"version":"a38a9c41f433b608a0d37e645a31eecf7233ef3d3fffeb626988d3219f80e32f","impliedFormat":1},{"version":"8e1428dcba6a984489863935049893631170a37f9584c0479f06e1a5b1f04332","impliedFormat":1},{"version":"1fce9ecb87a2d3898941c60df617e52e50fb0c03c9b7b2ba8381972448327285","impliedFormat":1},{"version":"5ef0597b8238443908b2c4bf69149ed3894ac0ddd0515ac583d38c7595b151f1","impliedFormat":1},{"version":"ac52b775a80badff5f4ac329c5725a26bd5aaadd57afa7ad9e98b4844767312a","impliedFormat":1},{"version":"6ae5b4a63010c82bf2522b4ecfc29ffe6a8b0c5eea6b2b35120077e9ac54d7a1","impliedFormat":1},{"version":"dd7109c49f416f218915921d44f0f28975df78e04e437c62e1e1eb3be5e18a35","impliedFormat":1},{"version":"eee181112e420b345fc78422a6cc32385ede3d27e2eaf8b8c4ad8b2c29e3e52e","impliedFormat":1},{"version":"25fbe57c8ee3079e2201fe580578fab4f3a78881c98865b7c96233af00bf9624","impliedFormat":1},{"version":"62cc8477858487b4c4de7d7ae5e745a8ce0015c1592f398b63ee05d6e64ca295","impliedFormat":1},{"version":"cc2a9ec3cb10e4c0b8738b02c31798fad312d21ef20b6a2f5be1d077e9f5409d","impliedFormat":1},{"version":"4b4fadcda7d34034737598c07e2dca5d7e1e633cb3ba8dd4d2e6a7782b30b296","impliedFormat":1},{"version":"360fdc8829a51c5428636f1f83e7db36fef6c5a15ed4411b582d00a1c2bd6e97","impliedFormat":1},{"version":"1cf0d15e6ab1ecabbf329b906ae8543e6b8955133b7f6655f04d433e3a0597ab","impliedFormat":1},{"version":"7c9f98fe812643141502b30fb2b5ec56d16aaf94f98580276ae37b7924dd44a4","impliedFormat":1},{"version":"b3547893f24f59d0a644c52f55901b15a3fa1a115bc5ea9a582911469b9348b7","impliedFormat":1},{"version":"596e5b88b6ca8399076afcc22af6e6e0c4700c7cd1f420a78d637c3fb44a885e","impliedFormat":1},{"version":"adddf736e08132c7059ee572b128fdacb1c2650ace80d0f582e93d097ed4fbaf","impliedFormat":1},{"version":"d4cad9dc13e9c5348637170ddd5d95f7ed5fdfc856ddca40234fa55518bc99a6","impliedFormat":1},{"version":"d70675ba7ba7d02e52b7070a369957a70827e4b2bca2c1680c38a832e87b61fd","impliedFormat":1},{"version":"3be71f4ce8988a01e2f5368bdd58e1d60236baf511e4510ee9291c7b3729a27e","impliedFormat":1},{"version":"423d2ccc38e369a7527988d682fafc40267bcd6688a7473e59c5eea20a29b64f","impliedFormat":1},{"version":"2f9fde0868ed030277c678b435f63fcf03d27c04301299580a4017963cc04ce6","impliedFormat":1},{"version":"feeb73d48cc41c6dd23d17473521b0af877751504c30c18dc84267c8eeea429a","impliedFormat":1},{"version":"25f1159094dc0bf3a71313a74e0885426af21c5d6564a254004f2cadf9c5b052","impliedFormat":1},{"version":"cde493e09daad4bb29922fe633f760be9f0e8e2f39cdca999cce3b8690b5e13a","impliedFormat":1},{"version":"3d7f9eb12aface876f7b535cc89dcd416daf77f0b3573333f16ec0a70bcf902a","impliedFormat":1},{"version":"b83139ae818dd20f365118f9999335ca4cd84ae518348619adc5728e7e0372d5","impliedFormat":1},{"version":"e0205f04611bea8b5b82168065b8ef1476a8e96236201494eb8c785331c43118","impliedFormat":1},{"version":"62d26d8ba4fa15ab425c1b57a050ed76c5b0ecbffaa53f182110aa3a02405a07","impliedFormat":1},{"version":"9941cbf7ca695e95d588f5f1692ab040b078d44a95d231fa9a8f828186b7b77d","impliedFormat":1},{"version":"41b8775befd7ded7245a627e9f4de6110236688ce4c124d2d40c37bc1a3bfe05","impliedFormat":1},{"version":"a6613ee552418429af38391e37389036654a882c342a1b81f2711e8ddac597f2","impliedFormat":1},{"version":"da47cb979ae4a849f9b983f43ef34365b7050c4f5ae2ebf818195858774e1d67","impliedFormat":1},{"version":"ac3bcb82d7280fc313a967f311764258d18caf33db6d2b1a0243cde607ff01a0","impliedFormat":1},{"version":"c9b5632d6665177030428d02603aeac3e920d31ec83ac500b55d44c7da74bd84","impliedFormat":1},{"version":"46456824df16d60f243a7e386562b27bac838aaba66050b9bc0f31e1ab34c1f2","impliedFormat":1},{"version":"b91034069e217212d8dda6c92669ee9f180b4c36273b5244c3be2c657f9286c7","impliedFormat":1},{"version":"0697277dd829ac2610d68fe1b457c9e758105bb52d40e149d9c15e5e2fe6dca4","impliedFormat":1},{"version":"b0d06dbb409369169143ede5df1fb58b2fca8d44588e199bd624b6f6d966bf08","impliedFormat":1},{"version":"88dfdb2a44912a28aea3ebb657dc7fcec6ba59f7233005e3405824995b713dac","impliedFormat":1},{"version":"67dd027877c83c46e74cde7ed6e7faacca148526cd9018ea0772aa7579fa0abc","impliedFormat":1},{"version":"d9aed3df3f4a1e42a18d442c85950f57decf2474a062f01ab9bf224c066a1d1e","impliedFormat":1},{"version":"41b8775befd7ded7245a627e9f4de6110236688ce4c124d2d40c37bc1a3bfe05","impliedFormat":1},{"version":"c3886d64fc80d215640d9fbffa90ebfd387d8eb012243dd044c9810d9f33b136","impliedFormat":1},{"version":"6e50b2017454705ff94359fc0a2daeba2fa19c133f2f204213d33deed52cf7b4","impliedFormat":1},{"version":"5ffe93378264ba2dba287bce8eabc389b0bfe2266016cc95bd66b64c5a6492a0","impliedFormat":1},{"version":"7ca788d6efb81cf64221b171bbeadc65491fe2e0fc2918efe3ecdaca395ea748","impliedFormat":1},{"version":"da35d6a8ee45e3349b4d577148bdd20c9b29862872e3c40f5d428c32557e5e0c","impliedFormat":1},{"version":"62941034216275e4541d6cfeeb80ae805fcc9639582a540bab4252554f3a613c","impliedFormat":1},{"version":"13aeadb616f9d2b44ea9da3cbfca62e70d30eb616c35425b78a2af3c3bc65b30","impliedFormat":1},{"version":"6ba418e319a0200ab67c2277d9354b6fa8755eed39ab9b584a3acaac6754ff7c","impliedFormat":1},{"version":"4fe80f12b1d5189384a219095c2eabadbb389c2d3703aae7c5376dbaa56061df","impliedFormat":1},{"version":"9eb1d2dceae65d1c82fc6be7e9b6b19cf3ca93c364678611107362b6ad4d2d41","impliedFormat":1},{"version":"cf1dc1d2914dd0f9462bc04c394084304dff5196cce7b725029c792e4e622a5b","impliedFormat":1},{"version":"4523dfd2dda07c1ab19f97034ba371f6553327b2a7189411a70a442546660fd6","impliedFormat":1},{"version":"2e5afb93fc3e6da3486a10effebc44f62bf9c11bec1eebe1d3b03cae91e4434c","impliedFormat":1},{"version":"a8a3779913ddff18d1f516d51bec89f5e3eb149928b859ad3684fae0e10fb2d3","impliedFormat":1},{"version":"a87090ce4dff0ec78b895d3a8803b864680e0b60c457f6bba961892a19954272","impliedFormat":1},{"version":"1991baf0ed3c21f4db584389462764d0519353ef477406f7e4e783c2b2408750","impliedFormat":1},{"version":"388ac09a64783588f92a7787237c2f8a417f402ef8605f154977c395a054b6bc","impliedFormat":1},{"version":"bbd0fce6da05dd72dc1f7c23e31cdcb5088e18f66a5e54450b28de31cfc27ce3","impliedFormat":1},{"version":"c059d7e5d3105a9067e0c0a9e392344a9a16b34d7ce7e41cea3ae9e50e0639f0","impliedFormat":1},{"version":"feeb4514da40bd3c50f6c884c607adb142002b3c8e6a3fe76db41ba8cce644ad","impliedFormat":1},{"version":"e3b0808e9afa9dce875873c2785b771a326e665276099380319637516d8d1aac","impliedFormat":1},{"version":"7247fd1853426de8fdc38a7027b488498bb00ea62c9a99037a760520e3944a26","impliedFormat":1},{"version":"0b6a84d1c3a325b7ed90153f5aad8bf6c8a6fba26f0b6385503218cae4080e25","impliedFormat":1},{"version":"e8284c9858c5d17dff0cb2de8139f8ff9fd2a3cf0de46b64fbcf37797e37ee0c","impliedFormat":1},{"version":"73e76d96bb4bc4a120be3964d6fd534b1ed4375acd2a90c2d054f365d42020c7","signature":"b0f67b0fd44bded8b846edc13c559b434334c1d91099689977df6893a3c7aa69","impliedFormat":99},{"version":"fa917a6fddb27bfbe0fefadc4a9b967dc971cbecbb03a74f390c7ee576e7d52e","signature":"e8fba48995e7f01cb22c646ebddfd80e9be8a6cfec7caeeb6e216b1bce3d9c24","impliedFormat":99},{"version":"0bdfe5c5c96248c7d5803e6b98ec9e78859654774ff5cf4c4fbabdd206ffb150","signature":"d906a63316f9682ff86661aef62ae49f9644e2edc04b5e6ab51794bf918ad1a3","impliedFormat":99},{"version":"b0b297fdd791bdf2c06f6afe219b75798c93bdde96c6fb14d5f5b6dae1ad95be","signature":"d247492f67cbd6cdcc3b156ad55d1e1b5885f7ad0702e203af28c2e2106c32c9","impliedFormat":99},{"version":"c29a3925af8957d6b3081fc198a0c7a54a1ad1c254f5fb9e7d13f80f58e9e017","signature":"57f2c16e7192e0a04846683fce2f398e822ffa145f4d48a65424d914561cb5ed","impliedFormat":99},{"version":"8f07a0ad81c1dd18e0892197c8e72aafbddf1cb41a2f4c559199b655b8e50ad9","signature":"71e122ee71057709a3bdfa8807fb13e4a8c208341b6157ef4921262de2660043","impliedFormat":99},{"version":"ee5b346e92e43090922b30dc884f465f02f8f074b29ab7e22b65059658253839","signature":"a28e8e7949f05cc86684e1fc2fef9fab6aa50d944ca8ba45318790229ea28000","impliedFormat":99},{"version":"3916a89ad61d307ab3d8ed08f629d6460661073294ee543b08486e3a5184b16e","signature":"875aa8b3d5711976a2af10b0ea7a069c5736ba57a05928cea204599b2177d43b","impliedFormat":99},{"version":"85ac68d57c4ff48c4fe90633f67588c6dfe2708f9b217fef8f2e8b93fe7e7630","signature":"923e3aced7d30c7da378fa70437e0837c6a46b832626dbe699382b71786479dc","impliedFormat":99},{"version":"32b0a5a003fa9a6031555be204ebd1c88d2a20604b90f0ca6e6edc59397ace18","signature":"9d305b1188e6baefb3d50ca7554a285fa32d9586a2cc66b57b67ac6c17453068","impliedFormat":99},{"version":"ab20e21190f321e605af04cca0d48653a6c012aebb54df0c6cc6519ae3538d7c","signature":"a6f40c2959adae4a494af140e00ead4703bddb5c0e2f1f1156328b36bf358907","impliedFormat":99},{"version":"cf01dd0c57a155f2f1d6aac59e75efa727df2fead3e51b607ace51522ea428fc","signature":"c72b2df3e7675f90742ef25a39241d6c18c0ba9b285baff4eaa6c0a0e5d7ad0f","impliedFormat":99},{"version":"bf729f952893415564c15f1eba8ad17191f8c5c2f712b8ad23b0fccc9891d90d","impliedFormat":99},{"version":"d1cc9289766f3874cb06fbc04c8292262e608db3b2ea3d78d8b797bf5965446a","impliedFormat":99},{"version":"c3cf88c859e1fcae00ee7935b56debee805b40381c8b8b266c6f7a62f30f7b38","impliedFormat":99},{"version":"283e38ce592ee0191d466574bd4d8ebc49bfd432db822575069db913a4225db2","signature":"452057bfe2057d7f23cf968cece993d21a311d68e5f04a0fa06a1b5635cc60f7","impliedFormat":99},{"version":"02c0ccfc1fbaae9cb58e12be3e0cbc70753284837bfbbfe669d1a0532b8aacc3","signature":"7911a8ca623edc3c077fb73c855cd4aaf937cbe4bc6735b16822e0a23a7d4422","impliedFormat":99},{"version":"1415a0576e9f30df33320de19cc5ecc76d12649d1420434f66e68862c051917c","signature":"f2513c23c7e007bc7abd5088288d425eecd6841883a6a1e18355d973c209f93e","impliedFormat":99},{"version":"78955fdf49f82c37464a905f7b562dba6d938b21c905775b230ab28646b6b0c9","signature":"5191d8882110d2c00430a0a278c0b382fe3afe48f2fadcf91c8bd1f10879f0df","impliedFormat":99},{"version":"99b8c0bd91c48a07d8b6937557134e7789f333d44e1034afd0fedc0ad739eb47","signature":"f664a5a4935f29c19f7a90981ade2091392985979694fa66e127af478099e66b","impliedFormat":99},{"version":"43f4d7f74308cdc0874df6d66c78ee5d670a5a248d81ea6e7d7c0c36029ea6ce","signature":"e92299916f8ff212ae5134b1dd662fd258430575ef6f14243f18e9bd6cfb4cfe","impliedFormat":99},{"version":"7e41e3d4b9549dd408bc53b6f146db3e41b80f35ff2abbc47ac44264e4c27e21","signature":"126e10ae570c24c4a871059355b027a84171f37d7b4dc6c854ea0b89756be1d4","impliedFormat":99},{"version":"5302241cd23345a0799b33d85f924f4be7f470295ba3f893a422c95d0a5c8ffe","signature":"0cf4f39e141c1a7b9a464a61d591b15d566aa90077f4a67bd2b20a9f317a6a38","impliedFormat":99},{"version":"16e6efa25d978c73710f33784e916c17125b0a61b966b4f4de95dc012a798c8e","signature":"98b9efebd8a41875ffc100ba176908cd1b0f44da02f0c0674e6bef54eb0af3eb","impliedFormat":99},{"version":"a4594b85b52b923c4c4149bde2edc707e1347fecad363c39c267f409073dc086","signature":"ca271618259dfdd908aa7b865682fdeea3a99e65dfa10da942f75964cb5dc803","impliedFormat":99},{"version":"028a119b3e689c709c0db8a7599b218b176a27af3a62305b36fd96340465e7a5","signature":"28f1252968fe14dc4f488292ac478a7bba679fd0f88b31ebea41048a080cb640","impliedFormat":99},{"version":"d3a6e1ff56a0a760b1b36eb34925042a8148d8e0ab4c2d28fcbdbf40fb5a8acc","impliedFormat":99},{"version":"1fe9584ff26dc79fec1b5d222ed7180b67e64329e0d31c4b3a283a916bc29215","signature":"a96d3c46c6cd06d8a6e43b76439c8ab81cce75110891b03095e1d1f3a1755477","impliedFormat":99},{"version":"023f723112b3d5d4b24222b63b99f1d41c5065329ec9a3437c13db014396705d","signature":"e8ea8b051488644aefc98a9231533c2efb6a508c4c39c818d16f1a2fc2f82a3c","impliedFormat":99},{"version":"d935a2313aa10130dacb6e016cdf0995a342956e90fadf4543e60e81e5d7e116","signature":"63015c136dcc6f181aaa4f60d2e630be70c90cde3abb89343dfb2bc34155e43c","impliedFormat":99},{"version":"56280c794cb85bb1dd96ecf623fb15bdf46f3afe41f2839309069fa9922bbc7a","signature":"a3bcec29aa5da3d41af23d836fd242aa13c8f3888cbe15ba17864ccca4ecdf84","impliedFormat":99},{"version":"8b8579501833f18b8296ced031fd83a9db782f910ae2f7466dce7dc9a7705da3","signature":"6a83d97da51c709443158a212d5c64ae554c02b8c32eb09ba1346b48dcd5c944","impliedFormat":99},{"version":"88f31fdebcda53c00b915cb030ad473e368fff3d37a4d3fe8c33489042ceb78f","signature":"6812c2460d8af53d35bb0e749f9b275138c60390128eb6c2b28f2c457fb2333f","impliedFormat":99},{"version":"273d1ec0626a59a62df0f92beb1af4953294d48e6217c2299943e1f28476a2fc","signature":"0277cdcca1e18da828ffa46585d688c60d5d81fc20a71f36144c5e1fe9f80d2a","impliedFormat":99},{"version":"66201fe6882924c4d3afd94691219f26e40441968d7c296bdde466ac7bf9ef7c","signature":"b1aa913654ad272b35a90787cdf8534487a251aab72da8505879f4c339a38111","impliedFormat":99},{"version":"a0d17a92aa1995044ba0ee7209fe6ff13b8d3e4d9451fe205569563652f5c410","signature":"267c0bb803b05fd009f2fafc7bbe28ea99d681e0bccd580fb19ef6af9562fd5a","impliedFormat":99},{"version":"ca287f58a2c82c24927f8e6cab7bbcf3849c70a6cf51fa94a2abfc9889392c1d","signature":"5d7014f89a44300336227e265698a691d349e0b5a3d5617e4dd45e81dbca3656","impliedFormat":99},{"version":"6d71e74429a8d8ddf60bff5ae1d64b2112490a5cf6db5cddeb82c06c612bb3a8","signature":"84e7d886a365816dbb2cae197e0d97e61be72a87f7cbb6547da20456e566b4bf","impliedFormat":99},{"version":"fb15c5214a6c7d10aec6674cbcf8c95538ffb399af3065964a0dff49e7187e60","signature":"55bba06b987ff8411525052f1941388bf2ac16c8f17716c607025387975cb8e8","impliedFormat":99},{"version":"67a4b2a424f900a2fa63b18c34a85540a18f37d74eef844610b837c49fe25640","signature":"972dcae528b64625600ddc9c25810172782cc29543de3b98708f2b0213d18593","impliedFormat":99},{"version":"735d32e8fbb51c36bbf026817a3daba706d3758448c6fb3ad84cec1dc7e04e0f","signature":"e604077d073fd2a5cf5a96f871dc8c063e21eb3d15e85c4eee154cc20fc5ffcd","impliedFormat":99},{"version":"47fd80549a6c1d4294b30109c725de4b3f907f5950faeb124f1b58ed6ad3f026","signature":"ff6d2920197446e537f52b1a13e72700ab50457969f8edd4e19b011aa3447691","impliedFormat":99},{"version":"7b0e1b6af1d1871d665633073b97a85aac4cbf0e42767cc9d6dc78e00e15b9fb","signature":"459b8e3ef1651003ecd15657a26f1c84ebc779ee416761215f63866e9d276707","impliedFormat":99},{"version":"d1443743c86b56a7c568630353ba4929d62461b97f441a70f8a4e867da513972","signature":"1969f112cc43626e1c499d63b51455d0ec1e6b68a9202037296756010995ede9","impliedFormat":99},{"version":"fdbe3cd15a74f69d711fbd56ddc68fd6ce0f39bc29d746a29024200ca82466f8","signature":"14f6261f2c2a8268a28c08d1dd57ab971cf44cb0570c367dec79249734dc2fad","impliedFormat":99},{"version":"90abb49f0312f41c13eb60b2817b9657912cbaa21d3bc6aedd84ec5cdba1b880","signature":"3ae0cc0109806096b20544ecff9a2a38a250e255402e1fb37b9d362294d47278","impliedFormat":99},{"version":"316f1486e15cbf7896425f0a16dfe12d447dd57cfb3244b8b119c77df870858f","impliedFormat":99},{"version":"bc0994681a66975c2076d735ddfbce95fc87912c058755f847a63a36c92e2378","signature":"054ab654a65dc0b8f43278955812c923d2e10e23b5afac6a3bd25942cc75c121","impliedFormat":99},{"version":"d0aa544490a30feaafb3268e731156a6891fb940ee037c626b1185203d7c1c16","signature":"ecd0e4089cf371f91f8db1a1910004be0f38ba0f0192f46046b6debe17756bd3","impliedFormat":99},{"version":"458a4f73948bc926c984a86b732e6ecab0fff1af06963d12c852dc0682f0e904","signature":"992f65cd010df4f00c623b57261607251d67d005a8cf16c8d76ba779959bc47a","impliedFormat":99},{"version":"257d484953a2d6386ecac05492a2b265268b9aa8d4ae6c5f50475121561eca59","signature":"e1eb8a76fc143c59ceb5048480b1e82eee2e97137f958f4f9d934ec8f5580c63","impliedFormat":99},{"version":"59a342215a967fc3e3430b01ea80dcefe5b4267e7f81828ed58364ba65ba9d91","signature":"e21693804007a8674a35701c3930fd9f121c3186ada60ce28542d25101bd88d4","impliedFormat":99},{"version":"b37f0a2d91d09897959e95a521439cd0b7ed5ade620be41a9406a9acf55475b5","signature":"1c6e67836ba3849eb60d543e74260e06173b0cba1b8a7ba33bf56cd5618dfa66","impliedFormat":99},{"version":"93eb5f9df788588c6709bad7b3232ad25d8df109d68a3b739060357c5d4d11f3","signature":"c3f89392130688c9a519fda32667b33fbba6dfb3f8a591f90b19ec58b9e23c84","impliedFormat":99},{"version":"ac71c1d519e90d1b6d99bf9bd34d3af51a39bac4c61c3eb31f4e8ab85d4749f7","signature":"e3d79d02542f15bcae454a48b2cf46586b5d5d85afbe184860fca2486ad98219","impliedFormat":99},{"version":"da0e74c1ea3622f48216d4ed421005eecd4002df4d308c0f6173a4bd646525c5","signature":"0775a4beb8375755d40b6ba40a23878469784dc44e5c1bf2be58e2e784b5b848","impliedFormat":99},{"version":"78618009b7957ae20a544e2ddea2acb3087109c690081e97a97be041f3bdaf81","signature":"387802c8b689571931db50d6add7f68ecfc2ab5f5b764d824a052ecc1240e819","impliedFormat":99},{"version":"efe5143e39e26bd230a442c87c04a39688f7fdc6ee275fbf5c5e48392db8a63c","signature":"6fb5c071b6ad819e30c8812d04ce9df586bb740622b88b0efe353b7d265653a3","impliedFormat":99},{"version":"793c23b10e57efcca2d2bb84c0d1ab05247fe49fb92072413b55275f4588f99a","signature":"a4f6a0c2ecd9674ad3079ef8906ed20ca1642b77ed9031500c7a7d3d3acb3185","impliedFormat":99},{"version":"5eaa7f93dd2024dfef113de0cae5a88608fceee446f5bf7e48db11785f62a1f2","signature":"248bcbf3ee36d6ac1671ec076d3af8b8ae92a0226f5af9d9943e0807282500f9","impliedFormat":99},{"version":"00f00e7701fc37764b444af233f6777c086c00207f17cbbb64bd1a6281d54583","signature":"350866711f5c087409adad05218955ee4df1da3871887c56965b04490448bc70","impliedFormat":99},{"version":"2291d8a312578de1f95391296ec5aba097fa1f5c99f71cca7a31807382ed70c4","signature":"de5ef6903c869281a93f4eac762ec11401f95cea614ba76a4ce8f985a0b75e79","impliedFormat":99},{"version":"807162a9f25ad1cd1298c4df4faf2eb6db3d2a9451a9db4689c65a04a74268bf","signature":"6b91e292a9aac41f5814206900ff8440f3b21b631bd4279a27aafc7d49723232","impliedFormat":99},{"version":"1ebcd3d6d0767e047134106ee1484b8a91ce14edbbcd58dd8bdb294d3dad22d2","signature":"fa01858ddd6f0f112978229070f51ccc3b98538df5d800041c601cb643692621","impliedFormat":99},{"version":"3f81a6f87024ec4a4ec394118c7f2723b11bc908528b39c5e964a4ed71ebaf51","signature":"e5cddb91baef22cba26fca4a0440f32edfca85be61075be449838343fbc61fdb","impliedFormat":99},{"version":"8fb0adee802d3aef19856226d9e1e409f7be4a4c214225e2f7096dbe0584bb37","signature":"055313d14f3b0a663b2f3b4f92ca9a16482b10e846a229473d5e581e18c9590c","impliedFormat":99},{"version":"38a22b4bc0352cf6264aaced65dc1871b127d2f688b7e0ab86a47d5b5956f94e","signature":"288b413ba71f39fd1ae74afaea6fb3832c83c201ab8021137c1388195257e31c","impliedFormat":99},{"version":"31cead56367b27141a8d748434123a57f1fc45948af17f326869586357e596fc","signature":"57f1250af74df454f4caac1f7f6bbae4e5e6fda9ddd13bc424e5ec94cbfc84c9","impliedFormat":99},{"version":"ae54a78693e3d48881254c2cf2d1524602ae44b33ac6aabcdad9aa00897de69f","signature":"22df250c6824416e8b576a76938793245851da5938c3350a12d9127b71819882","impliedFormat":99},{"version":"86fd64dae14d9489ddcae9529e5119c08d0aac6fe430c08fdc97f8ab10c44166","signature":"a0facf8a223d46bd7d3d9413042363d700b4f6b75ebaab89d44432c16af1e4aa","impliedFormat":99},{"version":"019c210c9772b5242c573a1b3bc3c30fe6ceafeb28476a106ce29975f008e1a8","signature":"50c9ed401386cfaad21fce4c088cc5c9a65dddab7b0478db85d777ad0a6e41d8","impliedFormat":99},{"version":"4c3ffe5088647d921bad20a93561b217633a0cf48f6b654e9232bacd8cccaeba","signature":"3972a6892b174e151afdb8bc24f295fee9d51f7d32858c93357cd61771ee362b","impliedFormat":99},{"version":"81060e2a5c25229de6599d660408d34beb0173cc6c1de90c36b2fd9e4d51dccc","signature":"a2ee2905f6601b02b6a1f99b11beb65c693433adb6456070ce8c9cd5914e5dc5","impliedFormat":99},{"version":"fd18943048d6b062ba58f2e0f7a9f9264659ceabb3544abb915b2effec1bcb28","signature":"6fc7fb299e85cdb4f96f7ff50fe3d6b445cee3929587754b72ef22c3f76811ed","impliedFormat":99},{"version":"f53d3b8419ac7e7ff5bb26af36e74fa141c3c563060081d6fec561e12133a890","signature":"e4aca6c2c014837dac6bcb293bd044ddc47e652ed9acc90c6365533dd82d5b2f","impliedFormat":99},{"version":"92a51840de5444c5408bca9251773711706509612a0da4ae3c67b4c6080c6c5c","signature":"6788e95153735c4d7db2d9cad283bd717a5393cf55b7d17995efb500a9aa2176","impliedFormat":99},{"version":"c3891d215a7b373c20d03d6789e5a44e52e46605792262dbb76fc6206a73f01f","signature":"4d70250aedebbf6536744a67daca8990950c550de6a351df620470334f319afd","impliedFormat":99},{"version":"aa6201310202fd21c2f4caab60025a2e5b0afe5488daab841cb293f9885ef928","signature":"640f110aed34c89bd087315e489c65bd0372908b0a62e5d2e30e57bd97d5ebf8","impliedFormat":99},{"version":"69432e548cc8c71f465546ea7fbbd52d48486529fdf8aec22ed65b24a8d664a6","signature":"b6ee83c039171af8ac20292a7d85ff5495953f261120b3049e7253d01b9ce575","impliedFormat":99},{"version":"88208d2db9d60c32e448faef1edb7a837a94292cd7506b8c3631161635280e1d","signature":"0607c7300dd22aa523f9e0aeeade6e3c38090cab64c09dd157bb28590e41d94e","impliedFormat":99},{"version":"4e21c02add6ec58d4f94b6a346fe0b6aadc344dcd77c8ff3cf1536f6f5c76d1b","signature":"a8585654210c5d18395b720746ae0d89ac726fc38ba5cd937c8f372770b67469","impliedFormat":99},{"version":"d1a8f7d914accecb515855fed071e7e0f43f255c6049c3d8602e3e74bebae759","signature":"8b10a863a709df868857be61cb417db2ff92fb4e8525e80e9d8d8d99cadf1aca","impliedFormat":99},{"version":"9255caabc4034d5b5442f13ea4c6a60d2fd8114bf61444c5bc3e2095f0b5c5f2","signature":"113e59967b9bf6c0850b7c26bc7766367c8a856bc07b8b9c7d034732e76a62e8","impliedFormat":99},{"version":"38b8c151ae031e9ab0f628724d0f4268425c7c5fa00fa3800ea52c20ff93c80d","signature":"7ed2679213800ed51ede2242be44bbacc20e50baf354754410037e8ff882eb6c","impliedFormat":99},{"version":"e8512b637d9eb7fefa7b899194ab2e75443f5e89565a44df23fd931492fb0573","signature":"21cd168e1fb134b20a11f4643598e5de06fb891cb9ec0369323be42c0c134d37","impliedFormat":99},{"version":"5acb9b052ec25e02f2e4ce9f45ca9299794b7eb0db5d238aee9209fbe0ca5350","signature":"43e818adf60173644896298637f47b01d5819b17eda46eaa32d0c7d64724d012","impliedFormat":99},{"version":"78b1676deb7fd87241190bd7aa64b9065ca6b8dcafba9ca0ca51c12b51336768","signature":"00fa34bb9a7d90328bd76553a6f69a709028668d1fbb3e913935b513d62ed5d4","impliedFormat":99},{"version":"60466353a3577a32124398adb7cc0affff682f2eba2dd1bae70c7da84ff1253f","impliedFormat":1},{"version":"e8171627727c5c91305360361cd412c3143e39ebe9f79189a158560ff5131212","signature":"d1ee790e8c768311aadaadad67d4030ecd08762096bf0c5478ef985ce658155c","impliedFormat":99},{"version":"75e21c16d517cfd1480b9e7fb7e0552eeb0133340222d6c9dd8c3b9537518729","signature":"0709edb0f0c91bc5cbe283cb546bf8542123ddbd202b5bf13a1eb2a838bd3ce0","impliedFormat":99},{"version":"0812499367ae09f0c2ab7aef2ce953e6e006d0a407dceb80434d303362747b1f","signature":"ed1a9a0b42f1060796a09f139c24f8e559703a80cc9ebd5217c9e28e81d79f11","impliedFormat":99},{"version":"bebba41ae293f23df1356bdaad71a8b1d8a2b85bd44fd4f04a570af3550d656d","signature":"d9897371094fd887e1305aee07c64f4a4bd4a3cf4097cf3200279fa47796d836","impliedFormat":99},{"version":"7e5c310428d174e5a66ca862cf5eaee800bdc35ad5cf1d26be3d463e697cda1e","signature":"eafd21a5cd4d4d4f43d3384a04d3456fd3f2b16a3475c89803362cf3c679dbbf","impliedFormat":99},{"version":"988f240b60e76987a15b21d7dd0aa019dfe7704a9caddcb0d77a18a5f773f040","signature":"8e609bb71c20b858c77f0e9f90bb1319db8477b13f9f965f1a1e18524bf50881","impliedFormat":99},{"version":"64050eb2791f5a4eac039e89d6e68ec40da8ba10348ce2419a6f260794374536","impliedFormat":99},{"version":"ee2d7785dbeed8881d14a147c744a2bcb01667b6748c7c5203142ffdb39e480d","impliedFormat":1},{"version":"e2b48abff5a8adc6bb1cd13a702b9ef05e6045a98e7cfa95a8779b53b6d0e69d","impliedFormat":1},{"version":"d7dbe0ad36bdca8a6ecf143422a48e72cc8927bab7b23a1a2485c2f78a7022c6","impliedFormat":1},{"version":"8b06ac3faeacb8484d84ddb44571d8f410697f98d7bfa86c0fda60373a9f5215","impliedFormat":1},{"version":"a4809f4d92317535e6b22b01019437030077a76fec1d93b9881c9ed4738fcc54","impliedFormat":1},{"version":"5f53fa0bd22096d2a78533f94e02c899143b8f0f9891a46965294ee8b91a9434","impliedFormat":1},{"version":"f3d8c757e148ad968f0d98697987db363070abada5f503da3c06aefd9d4248c1","impliedFormat":1},{"version":"d5816a8ceb0baf465f134e0018e57781be9a09dcc316976a6985bb658749aede","impliedFormat":1},{"version":"736097ddbb2903bef918bb3b5811ef1c9c5656f2a73bd39b22a91b9cc2525e50","impliedFormat":1},{"version":"4340936f4e937c452ae783514e7c7bbb7fc06d0c97993ff4865370d0962bb9cf","impliedFormat":1},{"version":"b70c7ea83a7d0de17a791d9b5283f664033a96362c42cc4d2b2e0bdaa65ef7d1","impliedFormat":1},{"version":"ff9590ea90db4a3c6d194f50582160b52ef78f83a93145a3d9d25541b03bccad","impliedFormat":1},{"version":"b90c23a457c16f77a282531a5caba5c911d2252eb097f3193a8ee2df6a3f21a2","impliedFormat":1},{"version":"18a78c980596d0c645668abcdeb14ea32b119f5535f0cb6ee28e7e16b61844e5","impliedFormat":1},{"version":"5ff1b426023eafdf4d725222cb5c111e612761735bca62ec7e22dde3e526f0af","impliedFormat":1},{"version":"d5be608b445099a10fdacb72200005012ac87982a1802eea12df7ac3c632f705","impliedFormat":1},{"version":"510616459e6edd01acbce333fb256e06bdffdad43ca233a9090164bf8bb83912","impliedFormat":1},{"version":"bd9875953696fb4654cafc980acb1ceced688de09927387f238ea68eeaedb4dc","impliedFormat":1},{"version":"cd51ceafea7762ad639afb3ca5b68e1e4ffeaacaa402d7ef2cae17016e29e098","impliedFormat":1},{"version":"1b8357b3fef5be61b5de6d6a4805a534d68fe3e040c11f1944e27d4aec85936a","impliedFormat":1},{"version":"4a15fc59b27b65b9894952048be2afc561865ec37606cd0f5e929ee4a102233b","impliedFormat":1},{"version":"744e7c636288493667d553c8f8ebd666ccbc0e715df445a4a7c4a48812f20544","affectsGlobalScope":true,"impliedFormat":1},{"version":"c05dcfbd5bd0abcefa3ad7d2931424d4d8090bc55bbe4f5c8acb8d2ca5886b2e","impliedFormat":1},{"version":"326da4aebf555d54b995854ff8f3432f63ba067be354fa16c6e1f50daa0667de","impliedFormat":1},{"version":"90748076a143bbeb455f8d5e8ad1cc451424c4856d41410e491268a496165256","impliedFormat":1},{"version":"76e3f3a30c533bf20840d4185ce2d143dc18ca955b64400ac09670a89d388198","impliedFormat":1},{"version":"144dfcee38ebc38aae93a85bc47211c9268d529b099127b74d61242ec5c17f35","impliedFormat":1},{"version":"2cf38989b23031694f04308b6797877534a49818b2f5257f4a5d824e7ea82a5a","impliedFormat":1},{"version":"f981ffdbd651f67db134479a5352dac96648ca195f981284e79dc0a1dbc53fd5","impliedFormat":1},{"version":"e4ace1cf5316aa7720e58c8dd511ba86bab1c981336996fb694fa64b8231d5f0","impliedFormat":1},{"version":"a1c85a61ff2b66291676ab84ae03c1b1ff7139ffde1942173f6aee8dc4ee357b","impliedFormat":1},{"version":"f35a727758da36dd885a70dd13a74d9167691aaff662d50eaaf66ed591957702","impliedFormat":1},{"version":"116205156fb819f2afe33f9c6378ea11b6123fa3090f858211c23f667fff75da","impliedFormat":1},{"version":"8fe68442c15f8952b8816fa4e7e6bd8d5c45542832206bd7bcf3ebdc77d1c3f3","impliedFormat":1},{"version":"3add9402f56a60e9b379593f69729831ac0fc9eae604b6fafde5fa86d2f8a4b9","impliedFormat":1},{"version":"cc28c8b188905e790de427f3cd00b96734c9c662fb849d68ff9d5f0327165c0d","impliedFormat":1},{"version":"da2aa652d2bf03cc042e2ff31e4194f4f18f042b8344dcb2568f761daaf7869f","impliedFormat":1},{"version":"03ed68319c97cd4ce8f1c4ded110d9b40b8a283c3242b9fe934ccfa834e45572","impliedFormat":1},{"version":"de2b56099545de410af72a7e430ead88894e43e4f959de29663d4d0ba464944d","impliedFormat":1},{"version":"eec9e706eef30b4f1c6ff674738d3fca572829b7fa1715f37742863dabb3d2f2","impliedFormat":1},{"version":"cec67731fce8577b0a90aa67ef0522ddb9f1fd681bece50cdcb80a833b4ed06f","impliedFormat":1},{"version":"a14679c24962a81ef24b6f4e95bbc31601551f150d91af2dc0bce51f7961f223","impliedFormat":1},{"version":"3f4d43bb3f61d173a4646c19557e090a06e9a2ec9415313a6d84af388df64923","impliedFormat":1},{"version":"18b86125c67d99150f54225df07349ddd07acde086b55f3eeac1c34c81e424d8","impliedFormat":1},{"version":"d5a5025f04e7a3264ecfa3030ca9a3cb0353450f1915a26d5b84f596240a11cd","impliedFormat":1},{"version":"03f4449c691dd9c51e42efd51155b63c8b89a5f56b5cf3015062e2f818be8959","impliedFormat":1},{"version":"23b213ec3af677b3d33ec17d9526a88d5f226506e1b50e28ce4090fb7e4050a8","impliedFormat":1},{"version":"f0abf96437a6e57b9751a792ba2ebb765729a40d0d573f7f6800b305691b1afb","impliedFormat":1},{"version":"7d30aee3d35e64b4f49c235d17a09e7a7ce2961bebb3996ee1db5aa192f3feba","impliedFormat":1},{"version":"eb1625bab70cfed00931a1e09ecb7834b61a666b0011913b0ec24a8e219023ef","impliedFormat":1},{"version":"1a923815c127b27f7f375c143bb0d9313ccf3c66478d5d2965375eeb7da72a4c","impliedFormat":1},{"version":"4f92df9d64e5413d4b34020ae6b382edda84347daec97099e7c008a9d5c0910b","impliedFormat":1},{"version":"fcc438e50c00c9e865d9c1777627d3fdc1e13a4078c996fb4b04e67e462648c8","impliedFormat":1},{"version":"d0f07efa072420758194c452edb3f04f8eabc01cd4b3884a23e7274d4e2a7b69","impliedFormat":1},{"version":"7086cca41a87b3bf52c6abfc37cda0a0ec86bb7e8e5ef166b07976abec73fa5e","impliedFormat":1},{"version":"4571a6886b4414403eacdd1b4cdbd854453626900ece196a173e15fb2b795155","impliedFormat":1},{"version":"c122227064c2ebf6a5bd2800383181395b56bb71fd6683d5e92add550302e45f","impliedFormat":1},{"version":"60f476f1c4de44a08d6a566c6f1e1b7de6cbe53d9153c9cc2284ca0022e21fba","impliedFormat":1},{"version":"84315d5153613eeb4b34990fb3bc3a1261879a06812ee7ae481141e30876d8dc","impliedFormat":1},{"version":"4f0781ec008bb24dc1923285d25d648ea48fb5a3c36d0786e2ee82eb00eff426","impliedFormat":1},{"version":"8fefaef4be2d484cdfc35a1b514ee7e7bb51680ef998fb9f651f532c0b169e6b","impliedFormat":1},{"version":"8be5c5be3dbf0003a628f99ad870e31bebc2364c28ea3b96231089a94e09f7a6","impliedFormat":1},{"version":"6626bbc69c25a92f6d32e6d2f25038f156b4c2380cbf29a420f7084fb1d2f7d7","impliedFormat":1},{"version":"f351eaa598ba2046e3078e5480a7533be7051e4db9212bb40f4eeb84279aa24d","impliedFormat":1},{"version":"5126032fe6e999f333827ee8e67f7ca1d5f3d6418025878aa5ebf13b499c2024","impliedFormat":1},{"version":"4ce53edb8fb1d2f8b2f6814084b773cdf5846f49bf5a426fbe4029327bda95bf","impliedFormat":1},{"version":"1edc9192dfc277c60b92525cdfa1980e1bfd161ae77286c96777d10db36be73c","impliedFormat":1},{"version":"1573cae51ae8a5b889ec55ecb58e88978fe251fd3962efa5c4fdb69ce00b23ba","impliedFormat":1},{"version":"75a7db3b7ddf0ca49651629bb665e0294fda8d19ba04fddc8a14d32bb35eb248","impliedFormat":1},{"version":"f2d1ac34b05bb6ce326ea1702befb0216363f1d5eccdd1b4b0b2f5a7e953ed8a","impliedFormat":1},{"version":"789665f0cd78bc675a31140d8f133ec6a482d753a514012fe1bb7f86d0a21040","impliedFormat":1},{"version":"bb30fb0534dceb2e41a884c1e4e2bb7a0c668dadd148092bba9ff15aafb94790","impliedFormat":1},{"version":"6ef829366514e4a8f75ce55fa390ebe080810b347e6f4a87bbeecb41e612c079","impliedFormat":1},{"version":"8f313aa8055158f08bd75e3a57161fa473a50884c20142f3318f89f19bfc0373","impliedFormat":1},{"version":"e789eb929b46299187312a01ff71905222f67907e546e491952c384b6f956a63","impliedFormat":1},{"version":"a0147b607f8c88a5433a5313cdc10443c6a45ed430e1b0a335a413dc2b099fd5","impliedFormat":1},{"version":"a86492d82baf906c071536e8de073e601eaa5deed138c2d9c42d471d72395d7e","impliedFormat":1},{"version":"6b1071c06abcbe1c9f60638d570fdbfe944b6768f95d9f28ebc06c7eec9b4087","impliedFormat":1},{"version":"92eb8a98444729aa61be5e6e489602363d763da27d1bcfdf89356c1d360484da","impliedFormat":1},{"version":"1285ddb279c6d0bc5fe46162a893855078ae5b708d804cd93bfc4a23d1e903d9","impliedFormat":1},{"version":"d729b8b400507b9b51ff40d11e012379dbf0acd6e2f66bf596a3bc59444d9bf1","impliedFormat":1},{"version":"fc3ee92b81a6188a545cba5c15dc7c5d38ee0aaca3d8adc29af419d9bdb1fdb9","impliedFormat":1},{"version":"a14371dc39f95c27264f8eb02ce2f80fd84ac693a2750983ac422877f0ae586d","impliedFormat":1},{"version":"755bcc456b4dd032244b51a8b4fe68ee3b2d2e463cf795f3fde970bb3f269fb1","impliedFormat":1},{"version":"c00b402135ef36fb09d59519e34d03445fd6541c09e68b189abb64151f211b12","impliedFormat":1},{"version":"e08e58ac493a27b29ceee80da90bb31ec64341b520907d480df6244cdbec01f8","impliedFormat":1},{"version":"c0fe2b1135ca803efa203408c953e1e12645b8065e1a4c1336ad8bb11ea1101b","impliedFormat":1},{"version":"f3dedc92d06e0fdc43e76c2e1acca21759dd63d2572c9ec78a5188249965d944","impliedFormat":1},{"version":"25b1108faedaf2043a97a76218240b1b537459bbca5ae9e2207c236c40dcfdef","impliedFormat":1},{"version":"a1d1e49ccd2ac07ed8a49a3f98dfd2f7357cf03649b9e348b58b97bb75116f18","impliedFormat":1},{"version":"7ad042f7d744ccfbcf6398216203c7712f01359d6fd4348c8bd8df8164e98096","impliedFormat":1},{"version":"0e0b8353d6d7f7cc3344adbabf3866e64f2f2813b23477254ba51f69e8fdf0eb","impliedFormat":1},{"version":"8e7653c13989dca094412bc4de20d5c449457fc92735546331d5e9cdd79ac16e","impliedFormat":1},{"version":"189dedb255e41c8556d0d61d7f1c18506501896354d0925cbd47060bcddccab1","impliedFormat":1},{"version":"48f0819c2e14214770232f1ab0058125bafdde1d04c4be84339d5533098bf60a","impliedFormat":1},{"version":"2641aff32336e35a5b702aa2d870a0891da29dc1c19ae48602678e2050614041","impliedFormat":1},{"version":"e133066d15e9e860ca96220a548dee28640039a8ac33a9130d0f83c814a78605","impliedFormat":1},{"version":"5728fd6e79e51c877314783a38af0316f6da7ddc662f090ca816b9aa0199720d","impliedFormat":99},{"version":"6e5a6f43aa773a978acb6e1b9eb9467ec74741f94d2ba5729955525a691b901f","impliedFormat":99},{"version":"da8b4bb72cd116416bf684f55d5f4c8fcb904747b23120290453320c1241def0","impliedFormat":99},{"version":"1ba59c8bbeed2cb75b239bb12041582fa3e8ef32f8d0bd0ec802e38442d3f317","impliedFormat":1},{"version":"bae8d023ef6b23df7da26f51cea44321f95817c190342a36882e93b80d07a960","impliedFormat":1},{"version":"c3e5b75e1af87b8e67e12e21332e708f7eccee6aac6261cfe98ca36652cdcb53","impliedFormat":1},{"version":"9e3a60f7c3ddfe66bb8e267dec2dc9e35e001f22a60859d69c5f674b949a99e3","impliedFormat":99},{"version":"15e3f5387dd31c1f90cf196e34a5d1d048a76196454974a05ec408f9b4a5e798","impliedFormat":99},{"version":"def775228f6b15050aa2333b1a46fcb17d357fe9b3f265bd1aadc24843607c13","impliedFormat":99},{"version":"377ce7c2d6c159d12401d32cdad77b97d7fdf21d8dc2958ce9347eda013d2f51","impliedFormat":99},{"version":"249d7b47f25a6c2066826d48a9714d6c7f3fcd4cc7361f16186d64e9a92daa2a","impliedFormat":99},{"version":"4edc6f7b9a4f9bf19bdb6c1be910a47add363f5e0f46cb39f4c516b705b31233","impliedFormat":99},{"version":"7149fffeca512eecb6856009d3f73608c96d0d5a1c952cdd7b0fee586db59e43","impliedFormat":99}],"root":[162,708,[730,732],[734,738],804,806,807,833,834,[836,845],[848,852],[855,858],[860,869],[871,874],876,877,879,882,[884,889],[892,897],[902,904],906,907,[912,917],[920,925],[967,975],[979,984],994,[996,998],1001,1004,1005,1010,1011,1013,1014,[1016,1020],1024,1027,1028,[1030,1036],1042,1043,1104,1105,[1113,1115],[1117,1120],[1202,1213],[1217,1227],[1229,1247],[1249,1288],[1290,1295]],"options":{"allowJs":true,"declaration":true,"declarationMap":true,"downlevelIteration":true,"esModuleInterop":true,"module":100,"outDir":"./","skipLibCheck":true,"sourceMap":true,"strict":true,"target":9},"referencedMap":[[780,1],[379,2],[376,3],[377,4],[374,5],[375,6],[372,7],[378,8],[373,3],[381,9],[380,2],[1165,10],[1122,1],[1124,11],[1123,12],[1128,13],[1163,14],[1160,15],[1162,16],[1125,15],[1126,17],[1130,17],[1129,18],[1127,19],[1161,20],[1174,21],[1159,15],[1164,22],[1157,1],[1158,1],[1131,23],[1136,15],[1138,15],[1133,15],[1134,23],[1140,15],[1141,24],[1132,15],[1137,15],[1139,15],[1135,15],[1155,25],[1154,15],[1156,26],[1150,15],[1171,27],[1169,28],[1168,15],[1166,13],[1173,29],[1170,30],[1167,28],[1172,28],[1152,15],[1151,15],[1147,15],[1153,31],[1148,15],[1149,32],[1142,15],[1143,15],[1144,15],[1145,15],[1146,15],[1121,1],[1175,33],[1176,1],[1179,34],[1201,35],[815,36],[813,37],[814,37],[812,1],[161,38],[160,39],[859,1],[835,1],[382,40],[383,1],[164,41],[388,42],[389,42],[390,42],[391,42],[392,42],[393,42],[394,42],[395,42],[396,42],[397,42],[398,42],[399,42],[441,43],[400,42],[401,42],[402,42],[403,42],[404,42],[405,42],[406,42],[407,42],[438,44],[408,42],[409,42],[410,42],[411,42],[412,42],[413,42],[414,42],[415,42],[416,42],[417,42],[418,42],[419,42],[420,42],[421,42],[422,42],[423,42],[424,42],[425,42],[426,42],[427,42],[428,42],[429,42],[430,42],[431,42],[432,42],[433,42],[434,42],[435,42],[436,42],[437,42],[442,45],[445,46],[163,1],[384,47],[446,48],[447,49],[448,50],[385,51],[440,52],[386,40],[387,53],[443,54],[444,1],[439,55],[739,1],[798,56],[754,57],[753,58],[800,59],[752,60],[751,61],[750,62],[748,1],[749,63],[746,64],[799,65],[741,1],[742,1],[744,66],[745,67],[796,68],[797,69],[795,70],[755,1],[756,71],[790,72],[791,1],[792,73],[793,1],[794,74],[743,1],[740,1],[747,75],[453,76],[449,1],[458,77],[450,1],[454,78],[455,1],[456,1],[457,1],[451,1],[452,1],[810,79],[821,1],[824,80],[818,81],[820,82],[811,1],[819,1],[825,83],[816,84],[831,85],[822,1],[809,1],[823,86],[817,1],[828,87],[829,1],[830,88],[826,1],[827,89],[808,75],[805,1],[802,90],[803,91],[801,1],[1003,1],[62,1],[899,1],[900,92],[772,93],[785,94],[773,1],[784,95],[789,96],[788,97],[774,98],[779,99],[782,100],[778,101],[783,102],[771,1],[775,103],[786,104],[776,1],[781,1],[787,105],[956,106],[955,107],[951,108],[952,109],[950,110],[939,1],[959,111],[957,110],[961,112],[960,113],[958,114],[963,115],[962,110],[965,116],[964,117],[954,118],[953,110],[949,110],[966,119],[943,120],[936,121],[941,122],[933,123],[929,1],[940,124],[947,1],[948,125],[935,126],[944,1],[931,1],[942,127],[927,1],[937,128],[932,129],[930,130],[934,1],[938,1],[945,131],[928,1],[946,1],[890,1],[891,132],[918,133],[991,134],[1296,1],[990,135],[1021,1],[463,136],[853,1],[1297,1],[1298,1],[1045,137],[987,138],[992,139],[908,140],[881,1],[1299,1],[1046,141],[677,142],[676,143],[656,144],[658,145],[657,144],[660,146],[662,147],[663,148],[664,149],[665,147],[666,148],[667,147],[668,150],[669,148],[670,147],[671,151],[672,144],[673,144],[674,152],[661,153],[675,154],[659,154],[1300,1],[1301,155],[1302,156],[1303,1],[1116,157],[1304,158],[679,159],[680,160],[678,161],[681,162],[682,163],[683,164],[684,165],[685,166],[686,167],[687,168],[688,169],[689,170],[704,158],[690,171],[878,158],[898,158],[691,158],[692,158],[1053,158],[988,1],[462,1],[1022,172],[1306,1],[1307,173],[103,174],[104,174],[105,175],[68,176],[106,177],[107,178],[108,179],[63,1],[66,180],[64,1],[65,1],[109,181],[110,182],[111,183],[112,184],[113,185],[114,186],[115,186],[117,187],[116,188],[118,189],[119,190],[120,191],[102,192],[67,1],[121,193],[122,194],[123,195],[154,196],[124,197],[125,198],[126,199],[127,200],[128,201],[129,202],[130,203],[131,204],[132,205],[133,206],[134,206],[135,207],[136,208],[138,209],[137,210],[139,211],[140,212],[141,213],[142,214],[143,215],[144,216],[145,217],[146,218],[147,219],[148,220],[149,221],[150,222],[151,223],[152,224],[153,225],[330,1],[909,226],[875,227],[883,137],[1312,228],[1308,1],[1309,1],[1311,229],[1310,1],[901,1],[986,1],[985,1],[1313,1],[356,230],[357,231],[332,232],[335,232],[354,230],[355,230],[345,230],[344,233],[342,230],[337,230],[350,230],[348,230],[352,230],[336,230],[349,230],[353,230],[338,230],[339,230],[351,230],[333,230],[340,230],[341,230],[343,230],[347,230],[358,234],[346,230],[334,230],[371,235],[370,1],[365,234],[367,236],[366,234],[359,234],[360,234],[362,234],[364,234],[368,236],[369,236],[361,236],[363,236],[1314,1],[989,237],[1009,238],[655,226],[1396,239],[1394,240],[1395,241],[728,137],[1248,242],[1397,242],[1398,1],[1399,243],[1025,244],[1214,1],[1215,245],[1029,1],[700,1],[926,1],[978,246],[976,247],[69,1],[699,248],[697,1],[698,249],[701,250],[459,1],[905,1],[977,1],[461,251],[460,1],[1289,1],[1063,1],[1044,1],[999,1],[1000,252],[702,1],[710,253],[709,247],[995,227],[729,1],[777,1],[733,254],[1026,255],[1177,10],[1178,256],[854,1],[1200,257],[1197,258],[1195,259],[1198,260],[1193,261],[1192,262],[1189,263],[1190,264],[1191,265],[1185,266],[1196,267],[1194,268],[1183,269],[1199,270],[1184,271],[1182,272],[156,1],[158,273],[157,1],[1180,274],[465,275],[1305,276],[155,1],[870,1],[832,277],[1037,278],[880,1],[1065,279],[1062,280],[1061,1],[1049,135],[1051,281],[1050,282],[1048,135],[1052,283],[1047,284],[695,285],[693,286],[694,287],[1056,1],[1103,288],[1091,1],[1081,289],[1082,290],[1102,291],[1066,1],[1067,292],[1068,292],[1069,292],[1070,292],[1071,292],[1072,292],[1073,292],[1074,292],[1075,292],[1076,292],[1077,292],[1078,292],[1079,292],[1083,293],[1084,292],[1085,1],[1086,292],[1087,292],[1089,294],[1090,292],[1092,295],[1093,292],[1094,292],[1095,292],[1096,292],[1097,296],[1098,292],[1099,292],[1100,292],[1101,292],[1064,1],[847,1],[1012,213],[703,1],[1041,297],[1040,1],[1038,1],[1039,1],[993,1],[1002,1],[1181,298],[464,1],[1216,1],[1088,1],[707,299],[159,300],[846,301],[1054,302],[919,1],[910,1],[911,303],[706,1],[1186,135],[1187,133],[1188,304],[1023,1],[1007,305],[1006,247],[331,306],[329,247],[300,307],[190,308],[296,1],[263,309],[233,310],[219,311],[297,1],[244,1],[254,1],[273,312],[167,1],[304,313],[306,314],[305,315],[256,316],[255,317],[258,318],[257,319],[217,1],[307,320],[311,321],[309,322],[171,323],[172,323],[173,1],[220,324],[270,325],[269,1],[282,326],[207,327],[276,1],[265,1],[324,328],[326,1],[193,329],[192,330],[285,331],[288,332],[177,333],[289,334],[203,335],[174,336],[179,337],[302,338],[239,339],[323,308],[295,340],[294,341],[181,342],[182,1],[206,343],[197,344],[198,345],[205,346],[196,347],[195,348],[204,349],[246,1],[183,1],[189,1],[184,1],[185,350],[187,351],[178,1],[237,1],[291,352],[238,338],[268,1],[260,1],[275,353],[274,354],[308,322],[312,355],[310,356],[170,357],[325,1],[262,329],[194,358],[280,359],[279,1],[234,360],[222,361],[223,1],[202,362],[266,363],[267,363],[209,364],[210,1],[218,1],[186,365],[168,1],[236,366],[200,1],[175,1],[191,308],[284,367],[327,368],[228,369],[240,370],[313,315],[315,371],[314,371],[231,372],[232,373],[201,1],[165,1],[243,1],[242,374],[287,334],[283,1],[321,374],[225,375],[208,376],[224,375],[226,377],[229,374],[176,331],[278,1],[319,378],[298,379],[252,380],[251,1],[247,381],[272,382],[248,381],[250,383],[249,384],[271,339],[301,385],[299,386],[221,387],[199,1],[227,388],[316,322],[318,355],[317,356],[320,389],[290,390],[281,1],[322,391],[264,392],[259,1],[277,393],[230,394],[261,395],[214,1],[245,1],[188,374],[328,1],[292,396],[293,1],[166,1],[241,374],[169,1],[235,397],[180,1],[213,1],[211,1],[212,1],[253,1],[303,374],[216,374],[286,308],[215,398],[1228,399],[1080,399],[654,400],[627,1],[605,401],[603,401],[653,402],[618,403],[617,403],[518,404],[469,405],[625,404],[626,404],[628,406],[629,404],[630,407],[529,408],[631,404],[602,404],[632,404],[633,409],[634,404],[635,403],[636,410],[637,404],[638,404],[639,404],[640,404],[641,403],[642,404],[643,404],[644,404],[645,404],[646,411],[647,404],[648,404],[649,404],[650,404],[651,404],[468,402],[471,407],[472,407],[473,407],[474,407],[475,407],[476,407],[477,407],[478,404],[480,412],[481,407],[479,407],[482,407],[483,407],[484,407],[485,407],[486,407],[487,407],[488,404],[489,407],[490,407],[491,407],[492,407],[493,407],[494,404],[495,407],[496,407],[497,407],[498,407],[499,407],[500,407],[501,404],[503,413],[502,407],[504,407],[505,407],[506,407],[507,407],[508,411],[509,404],[510,404],[524,414],[512,415],[513,407],[514,407],[515,404],[516,407],[517,407],[519,416],[520,407],[521,407],[522,407],[523,407],[525,407],[526,407],[527,407],[528,407],[530,417],[531,407],[532,407],[533,407],[534,404],[535,407],[536,418],[537,418],[538,418],[539,404],[540,407],[541,407],[542,407],[547,407],[543,407],[544,404],[545,407],[546,404],[548,407],[549,407],[550,407],[551,407],[552,407],[553,407],[554,404],[555,407],[556,407],[557,407],[558,407],[559,407],[560,407],[561,407],[562,407],[563,407],[564,407],[565,407],[566,407],[567,407],[568,407],[569,407],[570,407],[571,419],[572,407],[573,407],[574,407],[575,407],[576,407],[577,407],[578,404],[579,404],[580,404],[581,404],[582,404],[583,407],[584,407],[585,407],[586,407],[604,420],[652,404],[589,421],[588,422],[612,423],[611,424],[607,425],[606,424],[608,426],[597,427],[595,428],[610,429],[609,426],[596,1],[598,430],[511,431],[467,432],[466,407],[601,1],[593,433],[594,434],[591,1],[592,435],[590,407],[599,436],[470,437],[619,1],[620,1],[613,1],[616,403],[615,1],[621,1],[622,1],[614,438],[623,1],[624,1],[587,439],[600,440],[1055,226],[1008,1],[1059,441],[1057,1],[1058,442],[705,1],[1015,1],[1393,443],[1342,444],[1355,445],[1317,1],[1369,446],[1371,447],[1370,447],[1344,448],[1343,1],[1345,449],[1372,450],[1376,451],[1374,451],[1353,452],[1352,1],[1361,450],[1320,450],[1348,1],[1389,453],[1364,454],[1366,455],[1384,450],[1319,456],[1336,457],[1351,1],[1386,1],[1357,458],[1373,451],[1377,459],[1375,460],[1390,1],[1359,1],[1333,456],[1325,1],[1324,461],[1349,450],[1350,450],[1323,462],[1356,1],[1318,1],[1335,1],[1363,1],[1391,463],[1330,450],[1331,464],[1378,447],[1380,465],[1379,465],[1315,1],[1334,1],[1341,1],[1332,450],[1362,1],[1329,1],[1388,1],[1328,1],[1326,466],[1327,1],[1365,1],[1358,1],[1385,467],[1339,461],[1337,461],[1338,461],[1354,1],[1321,1],[1381,451],[1383,459],[1382,460],[1368,1],[1367,468],[1360,1],[1347,1],[1387,1],[1392,1],[1316,1],[1346,1],[1340,1],[1322,461],[60,1],[61,1],[12,1],[11,1],[2,1],[13,1],[14,1],[15,1],[16,1],[17,1],[18,1],[19,1],[20,1],[3,1],[21,1],[22,1],[4,1],[23,1],[27,1],[24,1],[25,1],[26,1],[28,1],[29,1],[30,1],[5,1],[31,1],[32,1],[33,1],[34,1],[6,1],[38,1],[35,1],[36,1],[37,1],[39,1],[7,1],[40,1],[45,1],[46,1],[41,1],[42,1],[43,1],[44,1],[8,1],[50,1],[47,1],[48,1],[49,1],[51,1],[9,1],[52,1],[53,1],[54,1],[56,1],[55,1],[57,1],[58,1],[10,1],[59,1],[1,1],[1060,1],[1111,1],[1109,1],[1110,1],[1112,469],[1106,1],[1107,470],[1108,471],[85,472],[92,473],[84,472],[99,474],[76,475],[75,476],[98,137],[93,477],[96,478],[78,479],[77,480],[73,481],[72,137],[95,482],[74,483],[79,484],[80,1],[83,484],[70,1],[101,485],[100,484],[87,486],[88,487],[90,488],[86,489],[89,490],[94,137],[81,491],[82,492],[91,493],[71,213],[97,494],[727,495],[712,1],[713,1],[714,1],[715,1],[711,1],[716,496],[717,1],[719,497],[718,496],[720,496],[721,497],[722,496],[723,1],[724,496],[725,1],[726,1],[696,1],[770,498],[761,499],[768,500],[763,1],[764,1],[762,501],[765,498],[757,1],[758,1],[769,502],[760,503],[766,1],[767,504],[759,505],[856,506],[857,507],[852,508],[863,509],[864,510],[865,511],[867,512],[868,513],[872,514],[873,515],[888,516],[889,517],[874,518],[895,519],[896,520],[1277,1],[1282,521],[1279,522],[1283,523],[1280,524],[1281,525],[1278,526],[979,527],[980,528],[897,518],[1210,529],[1211,530],[1208,531],[1209,532],[1035,533],[1223,534],[1212,535],[1213,536],[1217,537],[1219,538],[1221,539],[1224,540],[1225,541],[1226,542],[1231,543],[1232,544],[1233,545],[1234,546],[1235,547],[1236,548],[1285,549],[1240,550],[1206,1],[1241,551],[1207,552],[1242,553],[887,554],[886,518],[1244,555],[1243,556],[1246,557],[1245,558],[1250,559],[1251,560],[1252,561],[1247,1],[1284,562],[1256,563],[1253,564],[1254,565],[1255,566],[982,567],[1258,568],[1257,569],[983,570],[1260,571],[1259,572],[1267,573],[1263,574],[975,575],[1265,576],[1264,577],[1266,578],[1270,579],[1268,580],[1269,581],[1272,582],[1271,583],[834,584],[1274,585],[1273,558],[1276,586],[1275,587],[162,588],[994,589],[879,590],[836,591],[842,592],[892,593],[893,594],[1286,595],[894,596],[1287,597],[806,598],[807,1],[906,599],[984,600],[838,1],[841,601],[840,602],[1042,603],[1205,604],[884,605],[1020,606],[902,607],[1028,608],[1004,609],[1001,1],[1018,610],[1027,611],[1005,612],[1017,613],[1010,614],[1011,1],[1014,615],[1013,616],[1016,617],[1030,618],[1033,619],[1032,620],[1019,621],[837,622],[844,623],[1104,624],[903,625],[969,1],[1031,567],[730,626],[708,627],[1024,1],[1237,628],[1238,629],[1288,630],[1291,631],[1290,632],[1227,625],[871,633],[737,634],[843,635],[1229,636],[967,1],[1105,637],[904,1],[922,638],[907,639],[915,640],[917,641],[914,642],[913,1],[920,643],[912,644],[1036,645],[1034,646],[997,647],[996,648],[869,590],[734,649],[804,1],[1203,650],[833,651],[923,1],[916,652],[924,653],[925,654],[732,655],[731,656],[882,657],[845,590],[968,658],[885,659],[998,660],[858,661],[972,662],[973,663],[974,664],[970,665],[971,666],[1043,667],[1239,668],[839,1],[855,669],[876,670],[848,671],[1292,1],[862,672],[866,672],[860,673],[1222,674],[1218,672],[1220,672],[861,625],[1119,675],[1118,676],[1230,677],[1114,678],[1113,679],[1115,680],[1204,681],[877,682],[1294,683],[1293,684],[1120,685],[1117,686],[1262,687],[1261,688],[1202,689],[851,690],[736,691],[1295,692],[850,693],[735,694],[849,625],[921,695],[738,696],[981,625],[1249,697],[1400,1],[1401,698],[1402,1],[1404,213],[1403,1],[1405,1],[1406,1]],"version":"5.8.3"} \ No newline at end of file diff --git a/dist/utils/addons/prepare.d.ts b/dist/utils/addons/prepare.d.ts new file mode 100644 index 00000000000..a38ad6d1152 --- /dev/null +++ b/dist/utils/addons/prepare.d.ts @@ -0,0 +1,13 @@ +export declare const getCurrentAddon: ({ addonName, addons }: { + addonName: any; + addons: any; +}) => any; +export declare const getSiteData: ({ api, siteId }: { + api: any; + siteId: any; +}) => Promise; +export declare const getAddons: ({ api, siteId }: { + api: any; + siteId: any; +}) => Promise; +//# sourceMappingURL=prepare.d.ts.map \ No newline at end of file diff --git a/dist/utils/addons/prepare.d.ts.map b/dist/utils/addons/prepare.d.ts.map new file mode 100644 index 00000000000..a6e8c653221 --- /dev/null +++ b/dist/utils/addons/prepare.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"prepare.d.ts","sourceRoot":"","sources":["../../../src/utils/addons/prepare.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,eAAe,GAAI;;;CAAqB,QAA6D,CAAA;AAGlH,eAAO,MAAM,WAAW,GAAU;;;CAAe,iBAQhD,CAAA;AAGD,eAAO,MAAM,SAAS,GAAU;;;CAAe,iBAQ9C,CAAA"} \ No newline at end of file diff --git a/dist/utils/addons/prepare.js b/dist/utils/addons/prepare.js new file mode 100644 index 00000000000..43a0d47154c --- /dev/null +++ b/dist/utils/addons/prepare.js @@ -0,0 +1,26 @@ +import { logAndThrowError } from '../command-helpers.js'; +// @ts-expect-error TS(7031) FIXME: Binding element 'addonName' implicitly has an 'any... Remove this comment to see the full error message +export const getCurrentAddon = ({ addonName, addons }) => addons.find((addon) => addon.service_slug === addonName); +// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message +export const getSiteData = async ({ api, siteId }) => { + let siteData; + try { + siteData = await api.getSite({ siteId }); + } + catch (error_) { + return logAndThrowError(`Failed getting list of project data: ${error_.message}`); + } + return siteData; +}; +// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message +export const getAddons = async ({ api, siteId }) => { + let addons; + try { + addons = await api.listServiceInstancesForSite({ siteId }); + } + catch (error_) { + return logAndThrowError(`Failed getting list of addons: ${error_.message}`); + } + return addons; +}; +//# sourceMappingURL=prepare.js.map \ No newline at end of file diff --git a/dist/utils/addons/prepare.js.map b/dist/utils/addons/prepare.js.map new file mode 100644 index 00000000000..b9c732acd2b --- /dev/null +++ b/dist/utils/addons/prepare.js.map @@ -0,0 +1 @@ +{"version":3,"file":"prepare.js","sourceRoot":"","sources":["../../../src/utils/addons/prepare.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,gBAAgB,EAAE,MAAM,uBAAuB,CAAA;AAElE,2IAA2I;AAC3I,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,EAAE,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,YAAY,KAAK,SAAS,CAAC,CAAA;AAElH,2IAA2I;AAC3I,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE;IACnD,IAAI,QAAQ,CAAA;IACZ,IAAI,CAAC;QACH,QAAQ,GAAG,MAAM,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;IAC1C,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,OAAO,gBAAgB,CAAC,wCAAyC,MAAmB,CAAC,OAAO,EAAE,CAAC,CAAA;IACjG,CAAC;IACD,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED,2IAA2I;AAC3I,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,EAAE;IACjD,IAAI,MAAM,CAAA;IACV,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,GAAG,CAAC,2BAA2B,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;IAC5D,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,OAAO,gBAAgB,CAAC,kCAAmC,MAAmB,CAAC,OAAO,EAAE,CAAC,CAAA;IAC3F,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/build-info.d.ts b/dist/utils/build-info.d.ts new file mode 100644 index 00000000000..cb24f23c80e --- /dev/null +++ b/dist/utils/build-info.d.ts @@ -0,0 +1,21 @@ +import type { Settings } from '@netlify/build-info'; +import type BaseCommand from '../commands/base-command.js'; +import type { DefaultConfig } from '../lib/build.js'; +/** + * Detects and filters the build setting for a project and a command + */ +export declare function detectBuildSettings(command: BaseCommand): Promise; +/** + * Uses `@netlify/build-info` to detect the dev settings and port based on the framework + * and the build system that is used. + * @param command The base command + * @param type The type of command (dev or build) + */ +export declare const detectFrameworkSettings: (command: BaseCommand, type?: "dev" | "build") => Promise; +/** + * Generates a defaultConfig for @netlify/build based on the settings from the heuristics + * Returns the defaultConfig in the format that @netlify/build expects (json version of toml) + * @param settings The settings from the heuristics + */ +export declare const getDefaultConfig: (settings?: Settings) => DefaultConfig | undefined; +//# sourceMappingURL=build-info.d.ts.map \ No newline at end of file diff --git a/dist/utils/build-info.d.ts.map b/dist/utils/build-info.d.ts.map new file mode 100644 index 00000000000..dd682843662 --- /dev/null +++ b/dist/utils/build-info.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"build-info.d.ts","sourceRoot":"","sources":["../../src/utils/build-info.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAKnD,OAAO,KAAK,WAAW,MAAM,6BAA6B,CAAA;AAE1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAgCpD;;GAEG;AACH,wBAAsB,mBAAmB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,CAWnF;AAED;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAClC,SAAS,WAAW,EACpB,OAAM,KAAK,GAAG,OAAe,KAC5B,OAAO,CAAC,QAAQ,GAAG,SAAS,CA0D9B,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,WAAW,QAAQ,KAAG,aAAa,GAAG,SAoBtE,CAAA"} \ No newline at end of file diff --git a/dist/utils/build-info.js b/dist/utils/build-info.js new file mode 100644 index 00000000000..df69ca9d94a --- /dev/null +++ b/dist/utils/build-info.js @@ -0,0 +1,122 @@ +import { isCI } from 'ci-info'; +import fuzzy from 'fuzzy'; +import inquirer from 'inquirer'; +import { chalk, log } from './command-helpers.js'; +/** + * Filters the inquirer settings based on the input + */ +const filterSettings = function (scriptInquirerOptions, input) { + const filterOptions = scriptInquirerOptions.map((scriptInquirerOption) => scriptInquirerOption.name); + // TODO: remove once https://github.com/sindresorhus/eslint-plugin-unicorn/issues/1394 is fixed + const filteredSettings = fuzzy.filter(input, filterOptions); + const filteredSettingNames = new Set(filteredSettings.map((filteredSetting) => (input ? filteredSetting.string : filteredSetting))); + return scriptInquirerOptions.filter((t) => filteredSettingNames.has(t.name)); +}; +/** + * Formats the settings to present it as an array for the inquirer input so that it can choose one + */ +const formatSettingsArrForInquirer = function (settings, type = 'dev') { + return settings.map((setting) => { + const cmd = type === 'dev' ? setting.devCommand : setting.buildCommand; + return { + name: `[${chalk.yellow(setting.framework.name)}] '${cmd}'`, + value: { ...setting, commands: [cmd] }, + short: `${setting.name}-${cmd}`, + }; + }); +}; +/** + * Detects and filters the build setting for a project and a command + */ +export async function detectBuildSettings(command) { + const { project, workspacePackage } = command; + const buildSettings = await project.getBuildSettings(project.workspace ? workspacePackage : ''); + return buildSettings + .filter((setting) => { + if (project.workspace && project.relativeBaseDirectory && setting.packagePath) { + return project.relativeBaseDirectory.startsWith(setting.packagePath); + } + return true; + }) + .filter((setting) => setting.devCommand); +} +/** + * Uses `@netlify/build-info` to detect the dev settings and port based on the framework + * and the build system that is used. + * @param command The base command + * @param type The type of command (dev or build) + */ +export const detectFrameworkSettings = async (command, type = 'dev') => { + const { relConfigFilePath } = command.netlify; + const settings = await detectBuildSettings(command); + if (settings.length === 1) { + return settings[0]; + } + if (type === 'build' && command.netlify.config?.build?.command?.length) { + return { + ...settings[0], + buildCommand: command.netlify.config.build.command, + }; + } + if (type === 'dev' && command.netlify.config?.dev?.command?.length) { + return { + ...settings[0], + devCommand: command.netlify.config.dev.command, + }; + } + if (settings.length > 1) { + if (isCI) { + log(`Multiple possible ${type} commands found`); + throw new Error(`Detected commands for: ${settings + .map((setting) => setting.framework.name) + .join(', ')}. Update your settings to specify which to use. Refer to https://ntl.fyi/dev-monorepo for more information.`); + } + // multiple matching detectors, make the user choose + const scriptInquirerOptions = formatSettingsArrForInquirer(settings, type); + const { chosenSettings } = await inquirer.prompt({ + name: 'chosenSettings', + message: `Multiple possible ${type} commands found`, + // @ts-expect-error is not known by the types as it uses the autocomplete plugin + type: 'autocomplete', + source(_, input = '') { + if (!input) + return scriptInquirerOptions; + // only show filtered results + return filterSettings(scriptInquirerOptions, input); + }, + }); + log(` +Update your ${relConfigFilePath} to avoid this selection prompt next time: + +[build] +command = "${chosenSettings.buildCommand}" +publish = "${chosenSettings.dist}" + +[dev] +command = "${chosenSettings.devCommand}" +`); + return chosenSettings; + } +}; +/** + * Generates a defaultConfig for @netlify/build based on the settings from the heuristics + * Returns the defaultConfig in the format that @netlify/build expects (json version of toml) + * @param settings The settings from the heuristics + */ +export const getDefaultConfig = (settings) => { + if (!settings) { + return undefined; + } + const config = { build: {} }; + if (settings.buildCommand) { + config.build.command = settings.buildCommand; + config.build.commandOrigin = 'default'; + } + if (settings.dist) { + config.build.publish = settings.dist; + config.build.publishOrigin = 'default'; + } + config.plugins = settings.plugins_recommended?.map((plugin) => ({ package: plugin, origin: 'default' })) || []; + return config; +}; +//# sourceMappingURL=build-info.js.map \ No newline at end of file diff --git a/dist/utils/build-info.js.map b/dist/utils/build-info.js.map new file mode 100644 index 00000000000..dc67dc00b3a --- /dev/null +++ b/dist/utils/build-info.js.map @@ -0,0 +1 @@ +{"version":3,"file":"build-info.js","sourceRoot":"","sources":["../../src/utils/build-info.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/cli-state.d.ts b/dist/utils/cli-state.d.ts new file mode 100644 index 00000000000..1815f382df9 --- /dev/null +++ b/dist/utils/cli-state.d.ts @@ -0,0 +1,13 @@ +export default class CLIState { + private path; + constructor(cwd: string); + get all(): any; + set all(val: any); + get size(): number; + get(key: any): string | undefined; + set(...args: any[]): void; + has(key: any): boolean; + delete(key: any): void; + clear(): void; +} +//# sourceMappingURL=cli-state.d.ts.map \ No newline at end of file diff --git a/dist/utils/cli-state.d.ts.map b/dist/utils/cli-state.d.ts.map new file mode 100644 index 00000000000..4e520330cd4 --- /dev/null +++ b/dist/utils/cli-state.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"cli-state.d.ts","sourceRoot":"","sources":["../../src/utils/cli-state.ts"],"names":[],"mappings":"AA0BA,MAAM,CAAC,OAAO,OAAO,QAAQ;IAC3B,OAAO,CAAC,IAAI,CAAQ;gBAER,GAAG,EAAE,MAAM;IAIvB,IAAI,GAAG,QA2BN;IAED,IAAI,GAAG,CAAC,GAAG,KAAA,EAeV;IAED,IAAI,IAAI,WAEP;IAGD,GAAG,CAAC,GAAG,KAAA;IAUP,GAAG,CAAC,GAAG,IAAI,OAAA;IAgBX,GAAG,CAAC,GAAG,KAAA;IAKP,MAAM,CAAC,GAAG,KAAA;IAMV,KAAK;CAGN"} \ No newline at end of file diff --git a/dist/utils/cli-state.js b/dist/utils/cli-state.js new file mode 100644 index 00000000000..1b1489a0b3c --- /dev/null +++ b/dist/utils/cli-state.js @@ -0,0 +1,107 @@ +import fs from 'fs'; +import path from 'path'; +import process from 'process'; +import { deleteProperty, getProperty, hasProperty, setProperty } from 'dot-prop'; +import { findUpSync } from 'find-up'; +import writeFileAtomic from 'write-file-atomic'; +import { getPathInProject } from '../lib/settings.js'; +const STATE_PATH = getPathInProject(['state.json']); +const permissionError = "You don't have access to this file."; +/** + * Finds location of `.netlify/state.json` + */ +const findStatePath = (cwd) => { + const statePath = findUpSync([STATE_PATH], { cwd }); + if (!statePath) { + return path.join(cwd, STATE_PATH); + } + return statePath; +}; +export default class CLIState { + path; + constructor(cwd) { + this.path = findStatePath(cwd); + } + get all() { + try { + // @ts-expect-error TS(2345) FIXME: Argument of type 'Buffer' is not assignable to par... Remove this comment to see the full error message + return JSON.parse(fs.readFileSync(this.path)); + } + catch (error) { + // Don't create if it doesn't exist + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + if (error.code === 'ENOENT' || error.code === 'ENOTDIR') { + return {}; + } + // Improve the message of permission errors + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + if (error.code === 'EACCES') { + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + error.message = `${error.message}\n${permissionError}\n`; + } + // Empty the file if it encounters invalid JSON + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + if (error.name === 'SyntaxError') { + writeFileAtomic.sync(this.path, ''); + return {}; + } + throw error; + } + } + set all(val) { + try { + // Make sure the folder exists as it could have been deleted in the meantime + fs.mkdirSync(path.dirname(this.path), { recursive: true }); + writeFileAtomic.sync(this.path, JSON.stringify(val, null, '\t')); + } + catch (error) { + // Improve the message of permission errors + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + if (error.code === 'EACCES') { + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + error.message = `${error.message}\n${permissionError}\n`; + } + throw error; + } + } + get size() { + return Object.keys(this.all || {}).length; + } + // @ts-expect-error TS(7006) FIXME: Parameter 'key' implicitly has an 'any' type. + get(key) { + if (key === 'siteId' && process.env.NETLIFY_SITE_ID) { + // TODO figure out cleaner way of grabbing ENV vars + return process.env.NETLIFY_SITE_ID; + } + // eslint-disable-next-line @typescript-eslint/no-confusing-void-expression + return getProperty(this.all, key); + } + // @ts-expect-error TS(7019) FIXME: Rest parameter 'args' implicitly has an 'any[]' ty... Remove this comment to see the full error message + set(...args) { + const [key, val] = args; + const config = this.all; + if (args.length === 1) { + Object.entries(key).forEach(([keyPart, value]) => { + setProperty(config, keyPart, value); + }); + } + else { + setProperty(config, key, val); + } + this.all = config; + } + // @ts-expect-error TS(7006) FIXME: Parameter 'key' implicitly has an 'any' type. + has(key) { + return hasProperty(this.all, key); + } + // @ts-expect-error TS(7006) FIXME: Parameter 'key' implicitly has an 'any' type. + delete(key) { + const config = this.all; + deleteProperty(config, key); + this.all = config; + } + clear() { + this.all = {}; + } +} +//# sourceMappingURL=cli-state.js.map \ No newline at end of file diff --git a/dist/utils/cli-state.js.map b/dist/utils/cli-state.js.map new file mode 100644 index 00000000000..4d4a85bee75 --- /dev/null +++ b/dist/utils/cli-state.js.map @@ -0,0 +1 @@ +{"version":3,"file":"cli-state.js","sourceRoot":"","sources":["../../src/utils/cli-state.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/command-helpers.d.ts b/dist/utils/command-helpers.d.ts new file mode 100644 index 00000000000..7632e1a9122 --- /dev/null +++ b/dist/utils/command-helpers.d.ts @@ -0,0 +1,111 @@ +import type { NetlifyAPI } from '@netlify/api'; +import chokidar from 'chokidar'; +import type { TokenLocation } from './types.js'; +import type { CachedConfig } from '../lib/build.js'; +export declare const chalk: import("chalk").ChalkInstance; +/** + * Adds the filler to the start of the string + * @param {string} str + * @param {number} count + * @param {string} [filler] + * @returns {string} + */ +export declare const padLeft: (str: any, count: any, filler?: string) => any; +export declare const version: string; +export declare const USER_AGENT: string; +export declare const NETLIFY_CYAN: import("chalk").ChalkInstance; +export declare const NETLIFY_CYAN_HEX = "#28b5ac"; +export declare const NETLIFYDEVLOG: string; +export declare const NETLIFYDEVWARN: string; +export declare const NETLIFYDEVERR: string; +export declare const BANG: string; +/** + * Sorts two options so that the base flags are at the bottom of the list + * @param {import('commander').Option} optionA + * @param {import('commander').Option} optionB + * @returns {number} + * @example + * options.sort(sortOptions) + */ +export declare const sortOptions: (optionA: any, optionB: any) => any; +export declare const pollForToken: ({ api, ticket, }: { + api: NetlifyAPI; + ticket: { + id?: string; + client_id?: string; + authorized?: boolean; + created_at?: string; + }; +}) => Promise; +/** + * Get a netlify token + * @param {string} [tokenFromOptions] optional token from the provided --auth options + * @returns {Promise<[null|string, 'flag' | 'env' |'config' |'not found']>} + */ +export type TokenTuple = [string | null, TokenLocation]; +export declare const getToken: (tokenFromOptions?: string) => Promise; +/** + * logs a json message + */ +export declare const logJson: (message?: unknown) => void; +export declare const log: (message?: string, ...args: string[]) => void; +export declare const logPadded: (message?: string, ...args: string[]) => void; +/** + * logs a warning message + */ +export declare const warn: (message?: string) => void; +export declare const logAndThrowError: (message: unknown) => never; +export declare const logError: (message: unknown) => void; +export declare const exit: (code?: number) => never; +/** + * When `build.publish` is not set by the user, the CLI behavior differs in + * several ways. It detects it by checking if `build.publish` is `undefined`. + * However, `@netlify/config` adds a default value to `build.publish`. + * This removes 'publish' and 'publishOrigin' in this case. + * TODO(serhalp): Come up with a better name (or kill it?). This sucks but it's descriptive. + */ +export type NormalizedCachedConfigConfig = CachedConfig['config'] | (Omit & { + build: Omit; +}); +export declare const normalizeConfig: (config: CachedConfig["config"]) => NormalizedCachedConfigConfig; +interface WatchDebouncedOptions { + depth?: number; + ignored?: (string | RegExp)[]; + onAdd?: (paths: string[]) => void; + onChange?: (paths: string[]) => void; + onUnlink?: (paths: string[]) => void; +} +/** + * Adds a file watcher to a path or set of paths and debounces the events. + */ +export declare const watchDebounced: (target: string | string[], { depth, ignored, onAdd, onChange, onUnlink }: WatchDebouncedOptions) => Promise; +export declare const getTerminalLink: (text: string, url: string) => string; +export declare const isNodeError: (err: unknown) => err is NodeJS.ErrnoException; +export declare const nonNullable: (value: T) => value is NonNullable; +export declare const noOp: () => void; +export interface APIError extends Error { + status: number; + message: string; +} +export declare class GitHubAPIError extends Error { + status: string; + constructor(status: string, message: string); +} +export interface GitHubRepoResponse { + status?: string; + message?: string; + id?: number; + name?: string; + clone_url?: string; + full_name?: string; + private?: boolean; + default_branch?: string; + errors?: string[]; + is_template?: boolean; +} +export declare const checkFileForLine: (filename: string, line: string) => boolean; +export declare const TABTAB_CONFIG_LINE = "[[ -f ~/.config/tabtab/__tabtab.zsh ]] && . ~/.config/tabtab/__tabtab.zsh || true"; +export declare const AUTOLOAD_COMPINIT = "autoload -U compinit; compinit"; +export declare const netlifyCommand: () => "netlify" | "npx netlify" | "pnpm exec netlify" | "pnpx netlify"; +export {}; +//# sourceMappingURL=command-helpers.d.ts.map \ No newline at end of file diff --git a/dist/utils/command-helpers.d.ts.map b/dist/utils/command-helpers.d.ts.map new file mode 100644 index 00000000000..88b18ccd8eb --- /dev/null +++ b/dist/utils/command-helpers.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"command-helpers.d.ts","sourceRoot":"","sources":["../../src/utils/command-helpers.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAE9C,OAAO,QAAQ,MAAM,UAAU,CAAA;AAW/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAmBnD,eAAO,MAAM,KAAK,+BAAqC,CAAA;AAEvD;;;;;;GAMG;AAEH,eAAO,MAAM,OAAO,GAAI,QAAG,EAAE,UAAK,EAAE,eAAY,QAA6C,CAAA;AAO7F,eAAO,MAAM,OAAO,QAAiB,CAAA;AACrC,eAAO,MAAM,UAAU,QAAmE,CAAA;AAK1F,eAAO,MAAM,YAAY,+BAA0B,CAAA;AACnD,eAAO,MAAM,gBAAgB,YAAY,CAAA;AAIzC,eAAO,MAAM,aAAa,QAAyB,CAAA;AACnD,eAAO,MAAM,cAAc,QAA0B,CAAA;AACrD,eAAO,MAAM,aAAa,QAAuB,CAAA;AAEjD,eAAO,MAAM,IAAI,QAA2C,CAAA;AAE5D;;;;;;;GAOG;AAEH,eAAO,MAAM,WAAW,GAAI,YAAO,EAAE,YAAO,QAM3C,CAAA;AAKD,eAAO,MAAM,YAAY,GAAU,kBAGhC;IACD,GAAG,EAAE,UAAU,CAAA;IACf,MAAM,EAAE;QAAE,EAAE,CAAC,EAAE,MAAM,CAAC;QAAC,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,OAAO,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,CAAA;CACvF,oBAyBA,CAAA;AACD;;;;GAIG;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,MAAM,GAAG,IAAI,EAAE,aAAa,CAAC,CAAA;AAEvD,eAAO,MAAM,QAAQ,GAAU,mBAAmB,MAAM,KAAG,OAAO,CAAC,UAAU,CAkB5E,CAAA;AAMD;;GAEG;AACH,eAAO,MAAM,OAAO,GAAI,UAAS,OAAY,SAI5C,CAAA;AAED,eAAO,MAAM,GAAG,GAAI,gBAAY,EAAE,GAAG,MAAM,MAAM,EAAE,SAOlD,CAAA;AAED,eAAO,MAAM,SAAS,GAAI,gBAAY,EAAE,GAAG,MAAM,MAAM,EAAE,SAIxD,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,IAAI,GAAI,gBAAY,SAGhC,CAAA;AAUD,eAAO,MAAM,gBAAgB,GAAI,SAAS,OAAO,KAAG,KAInD,CAAA;AAED,eAAO,MAAM,QAAQ,GAAI,SAAS,OAAO,KAAG,IAS3C,CAAA;AAED,eAAO,MAAM,IAAI,GAAI,aAAQ,KAAG,KAE/B,CAAA;AAED;;;;;;GAMG;AACH,MAAM,MAAM,4BAA4B,GACpC,YAAY,CAAC,QAAQ,CAAC,GACtB,CAAC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC,GAAG;IACvC,KAAK,EAAE,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,EAAE,SAAS,GAAG,eAAe,CAAC,CAAA;CAC1E,CAAC,CAAA;AACN,eAAO,MAAM,eAAe,GAAI,QAAQ,YAAY,CAAC,QAAQ,CAAC,KAAG,4BAKhE,CAAA;AAID,UAAU,qBAAqB;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,OAAO,CAAC,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAA;IAC7B,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;IACjC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;IACpC,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,IAAI,CAAA;CACrC;AAED;;GAEG;AACH,eAAO,MAAM,cAAc,GACzB,QAAQ,MAAM,GAAG,MAAM,EAAE,EACzB,+CAAyE,qBAAqB,gCA6C/F,CAAA;AAED,eAAO,MAAM,eAAe,GAAI,MAAM,MAAM,EAAE,KAAK,MAAM,KAAG,MACK,CAAA;AAEjE,eAAO,MAAM,WAAW,GAAI,KAAK,OAAO,KAAG,GAAG,IAAI,MAAM,CAAC,cAAsC,CAAA;AAE/F,eAAO,MAAM,WAAW,GAAI,CAAC,EAAE,OAAO,CAAC,KAAG,KAAK,IAAI,WAAW,CAAC,CAAC,CAA0C,CAAA;AAE1G,eAAO,MAAM,IAAI,YAEhB,CAAA;AAED,MAAM,WAAW,QAAS,SAAQ,KAAK;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,qBAAa,cAAe,SAAQ,KAAK;IACvC,MAAM,EAAE,MAAM,CAAA;gBAEF,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK5C;AAED,MAAM,WAAW,kBAAkB;IACjC,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAA;IACjB,WAAW,CAAC,EAAE,OAAO,CAAA;CACtB;AAED,eAAO,MAAM,gBAAgB,GAAI,UAAU,MAAM,EAAE,MAAM,MAAM,YAQ9D,CAAA;AAED,eAAO,MAAM,kBAAkB,sFAAsF,CAAA;AACrH,eAAO,MAAM,iBAAiB,mCAAmC,CAAA;AASjE,eAAO,MAAM,cAAc,wEAoB1B,CAAA"} \ No newline at end of file diff --git a/dist/utils/command-helpers.js b/dist/utils/command-helpers.js new file mode 100644 index 00000000000..b7e0330ca3c --- /dev/null +++ b/dist/utils/command-helpers.js @@ -0,0 +1,274 @@ +import { once } from 'events'; +import os from 'os'; +import fs from 'fs'; +import process from 'process'; +import { format, inspect } from 'util'; +import { Chalk } from 'chalk'; +import chokidar from 'chokidar'; +import decache from 'decache'; +import WSL from 'is-wsl'; +import debounce from 'lodash/debounce.js'; +import terminalLink from 'terminal-link'; +import { startSpinner } from '../lib/spinner.js'; +import getGlobalConfigStore from './get-global-config-store.js'; +import getCLIPackageJson from './get-cli-package-json.js'; +import { reportError } from './telemetry/report-error.js'; +/** The parsed process argv without the binary only arguments and flags */ +const argv = process.argv.slice(2); +/** + * Chalk instance for CLI that can be initialized with no colors mode + * needed for json outputs where we don't want to have colors + * @param {boolean} noColors - disable chalk colors + * @return {import('chalk').ChalkInstance} - default or custom chalk instance + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'noColors' implicitly has an 'any' type. +const safeChalk = function (noColors) { + if (noColors) { + const colorlessChalk = new Chalk({ level: 0 }); + return colorlessChalk; + } + return new Chalk(); +}; +export const chalk = safeChalk(argv.includes('--json')); +/** + * Adds the filler to the start of the string + * @param {string} str + * @param {number} count + * @param {string} [filler] + * @returns {string} + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'str' implicitly has an 'any' type. +export const padLeft = (str, count, filler = ' ') => str.padStart(str.length + count, filler); +const platform = WSL ? 'wsl' : os.platform(); +const arch = os.arch() === 'ia32' ? 'x86' : os.arch(); +const { name, version: packageVersion } = await getCLIPackageJson(); +export const version = packageVersion; +export const USER_AGENT = `${name}/${version} ${platform}-${arch} node-${process.version}`; +/** A list of base command flags that needs to be sorted down on documentation and on help pages */ +const BASE_FLAGS = new Set(['--debug', '--http-proxy', '--http-proxy-certificate-filename']); +export const NETLIFY_CYAN = chalk.rgb(40, 180, 170); +export const NETLIFY_CYAN_HEX = '#28b5ac'; +// TODO(serhalp) I *think* this "dev" naming is a vestige of the predecessor of the CLI? Rename to avoid +// confusion with `netlify dev` command? +export const NETLIFYDEVLOG = chalk.greenBright('⬄'); +export const NETLIFYDEVWARN = chalk.yellowBright('⬄'); +export const NETLIFYDEVERR = chalk.redBright('⬄'); +export const BANG = process.platform === 'win32' ? 'Ā»' : '›'; +/** + * Sorts two options so that the base flags are at the bottom of the list + * @param {import('commander').Option} optionA + * @param {import('commander').Option} optionB + * @returns {number} + * @example + * options.sort(sortOptions) + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'optionA' implicitly has an 'any' type. +export const sortOptions = (optionA, optionB) => { + // base flags should be always at the bottom + if (BASE_FLAGS.has(optionA.long) || BASE_FLAGS.has(optionB.long)) { + return -1; + } + return optionA.long.localeCompare(optionB.long); +}; +// Poll Token timeout 5 Minutes +const TOKEN_TIMEOUT = 3e5; +export const pollForToken = async ({ api, ticket, }) => { + const spinner = startSpinner({ text: 'Waiting for authorization...' }); + try { + const accessToken = await api.getAccessToken(ticket, { timeout: TOKEN_TIMEOUT }); + if (!accessToken) { + return logAndThrowError('Could not retrieve access token'); + } + return accessToken; + } + catch (error_) { + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + if (error_.name === 'TimeoutError') { + return logAndThrowError(`Timed out waiting for authorization. If you do not have a ${chalk.bold.greenBright('Netlify')} account, please create one at ${chalk.magenta('https://app.netlify.com/signup')}, then run ${chalk.cyanBright('netlify login')} again.`); + } + else { + return logAndThrowError(error_); + } + } + finally { + spinner.stop(); + spinner.clear(); + } +}; +export const getToken = async (tokenFromOptions) => { + // 1. First honor command flag --auth + if (tokenFromOptions) { + return [tokenFromOptions, 'flag']; + } + // 2. then Check ENV var + const { NETLIFY_AUTH_TOKEN } = process.env; + if (NETLIFY_AUTH_TOKEN && NETLIFY_AUTH_TOKEN !== 'null') { + return [NETLIFY_AUTH_TOKEN, 'env']; + } + // 3. If no env var use global user setting + const globalConfig = await getGlobalConfigStore(); + const userId = globalConfig.get('userId'); + const tokenFromConfig = globalConfig.get(`users.${userId}.auth.token`); + if (tokenFromConfig) { + return [tokenFromConfig, 'config']; + } + return [null, 'not found']; +}; +// 'api' command uses JSON output by default +// 'functions:invoke' need to return the data from the function as is +const isDefaultJson = () => argv[0] === 'functions:invoke' || (argv[0] === 'api' && !argv.includes('--list')); +/** + * logs a json message + */ +export const logJson = (message = '') => { + if (argv.includes('--json') || isDefaultJson()) { + process.stdout.write(JSON.stringify(message, null, 2)); + } +}; +export const log = (message = '', ...args) => { + // If --silent or --json flag passed disable logger + if (argv.includes('--json') || argv.includes('--silent') || isDefaultJson()) { + return; + } + message = typeof message === 'string' ? message : inspect(message); + process.stdout.write(`${format(message, ...args)}\n`); +}; +export const logPadded = (message = '', ...args) => { + log(''); + log(message, ...args); + log(''); +}; +/** + * logs a warning message + */ +export const warn = (message = '') => { + const bang = chalk.yellow(BANG); + log(` ${bang} Warning: ${message}`); +}; +const toError = (val) => { + if (val instanceof Error) + return val; + if (typeof val === 'string') + return new Error(val); + const err = new Error(inspect(val)); + err.stack = undefined; + return err; +}; +export const logAndThrowError = (message) => { + const err = toError(message); + void reportError(err, { severity: 'error' }); + throw err; +}; +export const logError = (message) => { + const err = toError(message); + const bang = chalk.red(BANG); + if (process.env.DEBUG) { + process.stderr.write(` ${bang} Warning: ${err.stack?.split('\n').join(`\n ${bang} `)}\n`); + } + else { + process.stderr.write(` ${bang} ${chalk.red(`${err.name}:`)} ${err.message}\n`); + } +}; +export const exit = (code = 0) => { + process.exit(code); +}; +export const normalizeConfig = (config) => { + // Unused var here is in order to omit 'publish' from build config + const { publish, publishOrigin, ...build } = config.build; + return publishOrigin === 'default' ? { ...config, build } : config; +}; +const DEBOUNCE_WAIT = 100; +/** + * Adds a file watcher to a path or set of paths and debounces the events. + */ +export const watchDebounced = async (target, { depth, ignored = [], onAdd = noOp, onChange = noOp, onUnlink = noOp }) => { + const baseIgnores = [/\/(node_modules|.git)\//]; + const watcher = chokidar.watch(target, { depth, ignored: [...baseIgnores, ...ignored], ignoreInitial: true }); + await once(watcher, 'ready'); + let onChangeQueue = []; + let onAddQueue = []; + let onUnlinkQueue = []; + const debouncedOnChange = debounce(() => { + onChange(onChangeQueue); + onChangeQueue = []; + }, DEBOUNCE_WAIT); + const debouncedOnAdd = debounce(() => { + onAdd(onAddQueue); + onAddQueue = []; + }, DEBOUNCE_WAIT); + const debouncedOnUnlink = debounce(() => { + onUnlink(onUnlinkQueue); + onUnlinkQueue = []; + }, DEBOUNCE_WAIT); + watcher + .on('change', (path) => { + // @ts-expect-error + decache(path); + onChangeQueue.push(path); + debouncedOnChange(); + }) + .on('unlink', (path) => { + // @ts-expect-error + decache(path); + onUnlinkQueue.push(path); + debouncedOnUnlink(); + }) + .on('add', (path) => { + // @ts-expect-error + decache(path); + onAddQueue.push(path); + debouncedOnAdd(); + }); + return watcher; +}; +export const getTerminalLink = (text, url) => terminalLink(text, url, { fallback: () => `${text} (${url})` }); +export const isNodeError = (err) => err instanceof Error; +export const nonNullable = (value) => value !== null && value !== undefined; +export const noOp = () => { + // no-op +}; +export class GitHubAPIError extends Error { + status; + constructor(status, message) { + super(message); + this.status = status; + this.name = 'GitHubAPIError'; + } +} +export const checkFileForLine = (filename, line) => { + let filecontent = ''; + try { + filecontent = fs.readFileSync(filename, 'utf8'); + } + catch (error_) { + return logAndThrowError(error_); + } + return !!filecontent.match(line); +}; +export const TABTAB_CONFIG_LINE = '[[ -f ~/.config/tabtab/__tabtab.zsh ]] && . ~/.config/tabtab/__tabtab.zsh || true'; +export const AUTOLOAD_COMPINIT = 'autoload -U compinit; compinit'; +function pkgFromUserAgent(userAgent) { + if (!userAgent) + return undefined; + const pkgSpec = userAgent.split(' ')[0]; + const [pkgManagerName] = pkgSpec.split('/'); + return pkgManagerName; +} +export const netlifyCommand = () => { + const { npm_command, npm_config_user_agent, npm_lifecycle_event } = process.env; + // Captures both `npx netlify ...` and `npm exec netlify ...` + if (npm_lifecycle_event === 'npx') { + return `npx netlify`; + } + // Captures `pnpm exec netlify ...` + if (pkgFromUserAgent(npm_config_user_agent) === 'pnpm' && npm_command === 'exec') { + return `pnpm exec netlify`; + } + // Captures `pnpx netlify ...` + if (pkgFromUserAgent(npm_config_user_agent) === 'pnpm' && npm_command === 'run-script') { + return `pnpx netlify`; + } + // Default + return 'netlify'; +}; +//# sourceMappingURL=command-helpers.js.map \ No newline at end of file diff --git a/dist/utils/command-helpers.js.map b/dist/utils/command-helpers.js.map new file mode 100644 index 00000000000..2639210e82f --- /dev/null +++ b/dist/utils/command-helpers.js.map @@ -0,0 +1 @@ +{"version":3,"file":"command-helpers.js","sourceRoot":"","sources":["../../src/utils/command-helpers.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/copy-template-dir/copy-template-dir.d.ts b/dist/utils/copy-template-dir/copy-template-dir.d.ts new file mode 100644 index 00000000000..fc9183f8034 --- /dev/null +++ b/dist/utils/copy-template-dir/copy-template-dir.d.ts @@ -0,0 +1,2 @@ +export declare function copyTemplateDir(srcDir: string, outDir: string, vars: Record): Promise; +//# sourceMappingURL=copy-template-dir.d.ts.map \ No newline at end of file diff --git a/dist/utils/copy-template-dir/copy-template-dir.d.ts.map b/dist/utils/copy-template-dir/copy-template-dir.d.ts.map new file mode 100644 index 00000000000..90b50af032b --- /dev/null +++ b/dist/utils/copy-template-dir/copy-template-dir.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"copy-template-dir.d.ts","sourceRoot":"","sources":["../../../src/utils/copy-template-dir/copy-template-dir.ts"],"names":[],"mappings":"AAqDA,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CA2BrH"} \ No newline at end of file diff --git a/dist/utils/copy-template-dir/copy-template-dir.js b/dist/utils/copy-template-dir/copy-template-dir.js new file mode 100644 index 00000000000..70f74ac29f0 --- /dev/null +++ b/dist/utils/copy-template-dir/copy-template-dir.js @@ -0,0 +1,66 @@ +// License for copy-template-dir. +// Original repository: https://github.com/yoshuawuyts/copy-template-dir +// The MIT License (MIT) +// Copyright (c) 2015 Yoshua Wuyts +// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated +// documentation files (the "Software"), to deal in the Software without restriction, including without limitation the +// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit +// persons to whom the Software is furnished to do so, subject to the following conditions: +// The above copyright notice and this permission notice shall be included in all copies or substantial portions of the +// Software. +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE +// WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +import fs from 'fs'; +import path from 'path'; +import { pipeline } from 'stream'; +import { promisify } from 'util'; +import maxstache from 'maxstache'; +import maxstacheStream from 'maxstache-stream'; +import { readdirp } from 'readdirp'; +// Remove a leading underscore +function removeUnderscore(filepath) { + const parts = filepath.split(path.sep); + const filename = parts.pop()?.replace(/^_/, '') || ''; + return [...parts, filename].join(path.sep); +} +// Write a file to a directory +async function writeFile(outDir, vars, file) { + const fileName = file.path; + const inFile = file.fullPath; + const parentDir = path.dirname(file.path); + const outFile = path.join(outDir, maxstache(removeUnderscore(fileName), vars)); + await fs.promises.mkdir(path.join(outDir, maxstache(parentDir, vars)), { recursive: true }); + const rs = fs.createReadStream(inFile); + const ts = maxstacheStream(vars); + const ws = fs.createWriteStream(outFile); + await promisify(pipeline)(rs, ts, ws); +} +// High throughput template dir writes +export async function copyTemplateDir(srcDir, outDir, vars) { + await fs.promises.mkdir(outDir, { recursive: true }); + const rs = readdirp(srcDir); + const streams = []; + const createdFiles = []; + rs.on('data', (file) => { + createdFiles.push(path.join(outDir, maxstache(removeUnderscore(file.path), vars))); + streams.push(writeFile(outDir, vars, file)); + }); + await new Promise((resolve, reject) => { + rs.on('end', async () => { + try { + await Promise.all(streams); + resolve(); + } + catch (error) { + reject(error); + } + }); + rs.on('error', (error) => { + reject(error); + }); + }); + return createdFiles; +} +//# sourceMappingURL=copy-template-dir.js.map \ No newline at end of file diff --git a/dist/utils/copy-template-dir/copy-template-dir.js.map b/dist/utils/copy-template-dir/copy-template-dir.js.map new file mode 100644 index 00000000000..080b6d45708 --- /dev/null +++ b/dist/utils/copy-template-dir/copy-template-dir.js.map @@ -0,0 +1 @@ +{"version":3,"file":"copy-template-dir.js","sourceRoot":"","sources":["../../../src/utils/copy-template-dir/copy-template-dir.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,wEAAwE;AAExE,wBAAwB;AAExB,kCAAkC;AAElC,+GAA+G;AAC/G,sHAAsH;AACtH,yHAAyH;AACzH,2FAA2F;AAE3F,uHAAuH;AACvH,YAAY;AAEZ,uHAAuH;AACvH,wHAAwH;AACxH,mHAAmH;AACnH,mHAAmH;AAEnH,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAA;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,MAAM,CAAA;AAEhC,OAAO,SAAS,MAAM,WAAW,CAAA;AACjC,OAAO,eAAe,MAAM,kBAAkB,CAAA;AAC9C,OAAO,EAAE,QAAQ,EAA6B,MAAM,UAAU,CAAA;AAE9D,8BAA8B;AAC9B,SAAS,gBAAgB,CAAC,QAAgB;IACxC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;IACtC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAAG,EAAE,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,CAAA;IACrD,OAAO,CAAC,GAAG,KAAK,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;AAC5C,CAAC;AAED,8BAA8B;AAC9B,KAAK,UAAU,SAAS,CAAC,MAAc,EAAE,IAA4B,EAAE,IAAe;IACpF,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAA;IAC1B,MAAM,MAAM,GAAG,IAAI,CAAC,QAAQ,CAAA;IAC5B,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACzC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,gBAAgB,CAAC,QAAQ,CAAC,EAAE,IAAI,CAAC,CAAC,CAAA;IAE9E,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAE3F,MAAM,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACtC,MAAM,EAAE,GAAG,eAAe,CAAC,IAAI,CAAC,CAAA;IAChC,MAAM,EAAE,GAAG,EAAE,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAA;IAExC,MAAM,SAAS,CAAC,QAAQ,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAA;AACvC,CAAC;AAED,sCAAsC;AACtC,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,MAAc,EAAE,MAAc,EAAE,IAA4B;IAChG,MAAM,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAEpD,MAAM,EAAE,GAAmB,QAAQ,CAAC,MAAM,CAAC,CAAA;IAC3C,MAAM,OAAO,GAAoB,EAAE,CAAA;IACnC,MAAM,YAAY,GAAa,EAAE,CAAA;IAEjC,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAe,EAAE,EAAE;QAChC,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,CAAC,CAAC,CAAC,CAAA;QAClF,OAAO,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC,CAAA;IAC7C,CAAC,CAAC,CAAA;IAEF,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QAC1C,EAAE,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,IAAI,EAAE;YACtB,IAAI,CAAC;gBACH,MAAM,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAA;gBAC1B,OAAO,EAAE,CAAA;YACX,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,CAAC,KAAK,CAAC,CAAA;YACf,CAAC;QACH,CAAC,CAAC,CAAA;QACF,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,EAAE,EAAE;YACvB,MAAM,CAAC,KAAK,CAAC,CAAA;QACf,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;IAEF,OAAO,YAAY,CAAA;AACrB,CAAC"} \ No newline at end of file diff --git a/dist/utils/create-deferred.d.ts b/dist/utils/create-deferred.d.ts new file mode 100644 index 00000000000..161c2e3cd59 --- /dev/null +++ b/dist/utils/create-deferred.d.ts @@ -0,0 +1,7 @@ +declare const createDeferred: () => { + promise: Promise; + reject: (reason: unknown) => void; + resolve: (value: T) => void; +}; +export default createDeferred; +//# sourceMappingURL=create-deferred.d.ts.map \ No newline at end of file diff --git a/dist/utils/create-deferred.d.ts.map b/dist/utils/create-deferred.d.ts.map new file mode 100644 index 00000000000..e7e774d0630 --- /dev/null +++ b/dist/utils/create-deferred.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"create-deferred.d.ts","sourceRoot":"","sources":["../../src/utils/create-deferred.ts"],"names":[],"mappings":"AAAA,QAAA,MAAM,cAAc,GAAI,CAAC;;qBAEO,OAAO,KAAK,IAAI;qBADhB,CAAC,KAAK,IAAI;CAQzC,CAAA;AAED,eAAe,cAAc,CAAA"} \ No newline at end of file diff --git a/dist/utils/create-deferred.js b/dist/utils/create-deferred.js new file mode 100644 index 00000000000..a75a1883628 --- /dev/null +++ b/dist/utils/create-deferred.js @@ -0,0 +1,11 @@ +const createDeferred = () => { + let resolveDeferred; + let rejectDeferred; + const promise = new Promise((resolve, reject) => { + resolveDeferred = resolve; + rejectDeferred = reject; + }); + return { promise, reject: rejectDeferred, resolve: resolveDeferred }; +}; +export default createDeferred; +//# sourceMappingURL=create-deferred.js.map \ No newline at end of file diff --git a/dist/utils/create-deferred.js.map b/dist/utils/create-deferred.js.map new file mode 100644 index 00000000000..06d213bfd62 --- /dev/null +++ b/dist/utils/create-deferred.js.map @@ -0,0 +1 @@ +{"version":3,"file":"create-deferred.js","sourceRoot":"","sources":["../../src/utils/create-deferred.ts"],"names":[],"mappings":"AAAA,MAAM,cAAc,GAAG,GAAM,EAAE;IAC7B,IAAI,eAAoC,CAAA;IACxC,IAAI,cAA0C,CAAA;IAC9C,MAAM,OAAO,GAAG,IAAI,OAAO,CAAI,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACjD,eAAe,GAAG,OAAO,CAAA;QACzB,cAAc,GAAG,MAAM,CAAA;IACzB,CAAC,CAAC,CAAA;IAEF,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,cAAc,EAAE,OAAO,EAAE,eAAe,EAAE,CAAA;AACtE,CAAC,CAAA;AAED,eAAe,cAAc,CAAA"} \ No newline at end of file diff --git a/dist/utils/create-stream-promise.d.ts b/dist/utils/create-stream-promise.d.ts new file mode 100644 index 00000000000..e1af41c12f9 --- /dev/null +++ b/dist/utils/create-stream-promise.d.ts @@ -0,0 +1,5 @@ +import { Buffer } from 'buffer'; +import { IncomingMessage } from 'http'; +declare const createStreamPromise: (stream: IncomingMessage, timeoutSeconds: number, bytesLimit?: number) => Promise; +export default createStreamPromise; +//# sourceMappingURL=create-stream-promise.d.ts.map \ No newline at end of file diff --git a/dist/utils/create-stream-promise.d.ts.map b/dist/utils/create-stream-promise.d.ts.map new file mode 100644 index 00000000000..acc08436112 --- /dev/null +++ b/dist/utils/create-stream-promise.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"create-stream-promise.d.ts","sourceRoot":"","sources":["../../src/utils/create-stream-promise.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC/B,OAAO,EAAE,eAAe,EAAE,MAAM,MAAM,CAAA;AAOtC,QAAA,MAAM,mBAAmB,GACvB,QAAQ,eAAe,EACvB,gBAAgB,MAAM,EACtB,mBAAgC,KAC/B,OAAO,CAAC,MAAM,CAyChB,CAAA;AAED,eAAe,mBAAmB,CAAA"} \ No newline at end of file diff --git a/dist/utils/create-stream-promise.js b/dist/utils/create-stream-promise.js new file mode 100644 index 00000000000..a7041740be6 --- /dev/null +++ b/dist/utils/create-stream-promise.js @@ -0,0 +1,46 @@ +import { Buffer } from 'buffer'; +const SEC_TO_MILLISEC = 1e3; +// 6 MiB +const DEFAULT_BYTES_LIMIT = 6e6; +const createStreamPromise = function (stream, timeoutSeconds, bytesLimit = DEFAULT_BYTES_LIMIT) { + return new Promise(function streamPromiseFunc(resolve, reject) { + let data = []; + let dataLength = 0; + // @ts-expect-error TS(7034) FIXME: Variable 'timeoutId' implicitly has type 'any' in ... Remove this comment to see the full error message + let timeoutId = null; + if (timeoutSeconds != null && Number.isFinite(timeoutSeconds)) { + timeoutId = setTimeout(() => { + data = null; + reject(new Error('Request timed out waiting for body')); + }, timeoutSeconds * SEC_TO_MILLISEC); + } + stream.on('data', function onData(chunk) { + if (!Array.isArray(data)) { + // Stream harvesting closed + return; + } + dataLength += chunk.length; + if (dataLength > bytesLimit) { + data = null; + reject(new Error('Stream body too big')); + } + else { + data.push(chunk); + } + }); + stream.on('error', function onError(error) { + data = null; + reject(error); + clearTimeout(timeoutId); + }); + stream.on('end', function onEnd() { + clearTimeout(timeoutId); + if (data) { + // @ts-expect-error TS(7005) FIXME: Variable 'data' implicitly has an 'any[]' type. + resolve(Buffer.concat(data)); + } + }); + }); +}; +export default createStreamPromise; +//# sourceMappingURL=create-stream-promise.js.map \ No newline at end of file diff --git a/dist/utils/create-stream-promise.js.map b/dist/utils/create-stream-promise.js.map new file mode 100644 index 00000000000..942c4b8d657 --- /dev/null +++ b/dist/utils/create-stream-promise.js.map @@ -0,0 +1 @@ +{"version":3,"file":"create-stream-promise.js","sourceRoot":"","sources":["../../src/utils/create-stream-promise.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAG/B,MAAM,eAAe,GAAG,GAAG,CAAA;AAE3B,QAAQ;AACR,MAAM,mBAAmB,GAAG,GAAG,CAAA;AAE/B,MAAM,mBAAmB,GAAG,UAC1B,MAAuB,EACvB,cAAsB,EACtB,UAAU,GAAG,mBAAmB;IAEhC,OAAO,IAAI,OAAO,CAAC,SAAS,iBAAiB,CAAC,OAAO,EAAE,MAAM;QAC3D,IAAI,IAAI,GAAqB,EAAE,CAAA;QAC/B,IAAI,UAAU,GAAG,CAAC,CAAA;QAElB,2IAA2I;QAC3I,IAAI,SAAS,GAAmB,IAAI,CAAA;QACpC,IAAI,cAAc,IAAI,IAAI,IAAI,MAAM,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;YAC9D,SAAS,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC1B,IAAI,GAAG,IAAI,CAAA;gBACX,MAAM,CAAC,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC,CAAA;YACzD,CAAC,EAAE,cAAc,GAAG,eAAe,CAAC,CAAA;QACtC,CAAC;QAED,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,MAAM,CAAC,KAAK;YACrC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBACzB,2BAA2B;gBAC3B,OAAM;YACR,CAAC;YACD,UAAU,IAAI,KAAK,CAAC,MAAM,CAAA;YAC1B,IAAI,UAAU,GAAG,UAAU,EAAE,CAAC;gBAC5B,IAAI,GAAG,IAAI,CAAA;gBACX,MAAM,CAAC,IAAI,KAAK,CAAC,qBAAqB,CAAC,CAAC,CAAA;YAC1C,CAAC;iBAAM,CAAC;gBACN,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;YAClB,CAAC;QACH,CAAC,CAAC,CAAA;QAEF,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,SAAS,OAAO,CAAC,KAAK;YACvC,IAAI,GAAG,IAAI,CAAA;YACX,MAAM,CAAC,KAAK,CAAC,CAAA;YACb,YAAY,CAAC,SAAS,CAAC,CAAA;QACzB,CAAC,CAAC,CAAA;QACF,MAAM,CAAC,EAAE,CAAC,KAAK,EAAE,SAAS,KAAK;YAC7B,YAAY,CAAC,SAAS,CAAC,CAAA;YACvB,IAAI,IAAI,EAAE,CAAC;gBACT,mFAAmF;gBACnF,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAA;YAC9B,CAAC;QACH,CAAC,CAAC,CAAA;IACJ,CAAC,CAAC,CAAA;AACJ,CAAC,CAAA;AAED,eAAe,mBAAmB,CAAA"} \ No newline at end of file diff --git a/dist/utils/deploy/constants.d.ts b/dist/utils/deploy/constants.d.ts new file mode 100644 index 00000000000..e5e578de00d --- /dev/null +++ b/dist/utils/deploy/constants.d.ts @@ -0,0 +1,10 @@ +export declare const DEFAULT_DEPLOY_TIMEOUT = 1200000; +export declare const DEFAULT_CONCURRENT_HASH = 100; +export declare const DEFAULT_CONCURRENT_UPLOAD = 5; +export declare const DEFAULT_SYNC_LIMIT = 100; +export declare const DEFAULT_MAX_RETRY = 5; +export declare const UPLOAD_RANDOM_FACTOR = 0.5; +export declare const UPLOAD_INITIAL_DELAY = 5000; +export declare const UPLOAD_MAX_DELAY = 90000; +export declare const DEPLOY_POLL = 1000; +//# sourceMappingURL=constants.d.ts.map \ No newline at end of file diff --git a/dist/utils/deploy/constants.d.ts.map b/dist/utils/deploy/constants.d.ts.map new file mode 100644 index 00000000000..5210e761150 --- /dev/null +++ b/dist/utils/deploy/constants.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/utils/deploy/constants.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,sBAAsB,UAAY,CAAA;AAE/C,eAAO,MAAM,uBAAuB,MAAM,CAAA;AAE1C,eAAO,MAAM,yBAAyB,IAAI,CAAA;AAE1C,eAAO,MAAM,kBAAkB,MAAM,CAAA;AAErC,eAAO,MAAM,iBAAiB,IAAI,CAAA;AAElC,eAAO,MAAM,oBAAoB,MAAM,CAAA;AAEvC,eAAO,MAAM,oBAAoB,OAAO,CAAA;AAExC,eAAO,MAAM,gBAAgB,QAAS,CAAA;AAGtC,eAAO,MAAM,WAAW,OAAO,CAAA"} \ No newline at end of file diff --git a/dist/utils/deploy/constants.js b/dist/utils/deploy/constants.js new file mode 100644 index 00000000000..2e90d4689ee --- /dev/null +++ b/dist/utils/deploy/constants.js @@ -0,0 +1,18 @@ +// Local deploy timeout in ms: 20 mins +export const DEFAULT_DEPLOY_TIMEOUT = 1_200_000; +// Concurrent file hash calls +export const DEFAULT_CONCURRENT_HASH = 100; +// Number of concurrent uploads +export const DEFAULT_CONCURRENT_UPLOAD = 5; +// Number of files +export const DEFAULT_SYNC_LIMIT = 100; +// Number of times to retry an upload +export const DEFAULT_MAX_RETRY = 5; +export const UPLOAD_RANDOM_FACTOR = 0.5; +// 5 seconds +export const UPLOAD_INITIAL_DELAY = 5000; +// 1.5 minute (90s) +export const UPLOAD_MAX_DELAY = 90_000; +// 1 second +export const DEPLOY_POLL = 1000; +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/dist/utils/deploy/constants.js.map b/dist/utils/deploy/constants.js.map new file mode 100644 index 00000000000..c9f5ae93dd8 --- /dev/null +++ b/dist/utils/deploy/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/utils/deploy/constants.ts"],"names":[],"mappings":"AAAA,sCAAsC;AACtC,MAAM,CAAC,MAAM,sBAAsB,GAAG,SAAS,CAAA;AAC/C,6BAA6B;AAC7B,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAG,CAAA;AAC1C,+BAA+B;AAC/B,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,CAAA;AAC1C,kBAAkB;AAClB,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAA;AACrC,qCAAqC;AACrC,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAA;AAElC,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAA;AACvC,YAAY;AACZ,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAA;AACxC,mBAAmB;AACnB,MAAM,CAAC,MAAM,gBAAgB,GAAG,MAAM,CAAA;AAEtC,WAAW;AACX,MAAM,CAAC,MAAM,WAAW,GAAG,IAAI,CAAA"} \ No newline at end of file diff --git a/dist/utils/deploy/deploy-site.d.ts b/dist/utils/deploy/deploy-site.d.ts new file mode 100644 index 00000000000..18921a439d1 --- /dev/null +++ b/dist/utils/deploy/deploy-site.d.ts @@ -0,0 +1,21 @@ +import BaseCommand from '../../commands/base-command.js'; +import { type $TSFixMe } from '../../commands/types.js'; +import type { DeployEvent } from './status-cb.js'; +export type { DeployEvent }; +export declare const deploySite: (command: BaseCommand, api: $TSFixMe, siteId: any, dir: any, { assetType, branch, concurrentHash, concurrentUpload, config, deployId, deployTimeout, draft, filter, fnDir, functionsConfig, hashAlgorithm, manifestPath, maxRetry, siteRoot, skipFunctionsCache, statusCb, syncFileLimit, tmpDir, workingDir, }: { + concurrentHash?: number; + concurrentUpload?: number; + deployTimeout?: number; + draft?: boolean; + maxRetry?: number; + statusCb?: (status: DeployEvent) => void; + syncFileLimit?: number; + tmpDir?: string; + fnDir?: string[]; + workingDir: string; +}) => Promise<{ + deployId: any; + deploy: any; + uploadList: any[]; +}>; +//# sourceMappingURL=deploy-site.d.ts.map \ No newline at end of file diff --git a/dist/utils/deploy/deploy-site.d.ts.map b/dist/utils/deploy/deploy-site.d.ts.map new file mode 100644 index 00000000000..03890a13ef3 --- /dev/null +++ b/dist/utils/deploy/deploy-site.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"deploy-site.d.ts","sourceRoot":"","sources":["../../../src/utils/deploy/deploy-site.ts"],"names":[],"mappings":"AAIA,OAAO,WAAW,MAAM,gCAAgC,CAAA;AACxD,OAAO,EAAE,KAAK,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAgBvD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAA;AAGjD,YAAY,EAAE,WAAW,EAAE,CAAA;AAS3B,eAAO,MAAM,UAAU,GACrB,SAAS,WAAW,EACpB,KAAK,QAAQ,EAEb,WAAM,EAEN,QAAG,EACH,oPAiCG;IACD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,QAAQ,CAAC,EAAE,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAA;IACxC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,KAAK,CAAC,EAAE,MAAM,EAAE,CAAA;IAChB,UAAU,EAAE,MAAM,CAAA;CACnB;;;;EAuIF,CAAA"} \ No newline at end of file diff --git a/dist/utils/deploy/deploy-site.js b/dist/utils/deploy/deploy-site.js new file mode 100644 index 00000000000..335598cb4d9 --- /dev/null +++ b/dist/utils/deploy/deploy-site.js @@ -0,0 +1,156 @@ +import { rm } from 'fs/promises'; +import cleanDeep from 'clean-deep'; +import { deployFileNormalizer, getDistPathIfExists, isEdgeFunctionFile } from '../../lib/edge-functions/deploy.js'; +import { warn } from '../command-helpers.js'; +import { DEFAULT_CONCURRENT_HASH, DEFAULT_CONCURRENT_UPLOAD, DEFAULT_DEPLOY_TIMEOUT, DEFAULT_MAX_RETRY, DEFAULT_SYNC_LIMIT, } from './constants.js'; +import { hashConfig } from './hash-config.js'; +import hashFiles from './hash-files.js'; +import hashFns from './hash-fns.js'; +import uploadFiles from './upload-files.js'; +import { getUploadList, waitForDeploy, waitForDiff } from './util.js'; +import { temporaryDirectory } from '../temporary-file.js'; +const buildStatsString = (possibleParts) => { + const parts = possibleParts.filter(Boolean); + const message = parts.slice(0, -1).join(', '); + return parts.length > 1 ? `${message} and ${parts[parts.length - 1]}` : message; +}; +export const deploySite = async (command, api, +// @ts-expect-error TS(7006) FIXME: Parameter 'siteId' implicitly has an 'any' type. +siteId, +// @ts-expect-error TS(7006) FIXME: Parameter 'dir' implicitly has an 'any' type. +dir, { +// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message +assetType, +// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message +branch, concurrentHash = DEFAULT_CONCURRENT_HASH, concurrentUpload = DEFAULT_CONCURRENT_UPLOAD, +// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message +config, +// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message +deployId, deployTimeout = DEFAULT_DEPLOY_TIMEOUT, draft = false, +// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message +filter, fnDir = [], +// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message +functionsConfig, +// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message +hashAlgorithm, +// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message +manifestPath, maxRetry = DEFAULT_MAX_RETRY, +// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message +siteRoot, +// @ts-expect-error TS(2525) FIXME: Initializer provides no value for this binding ele... Remove this comment to see the full error message +skipFunctionsCache, statusCb = () => { + /* default to noop */ +}, syncFileLimit = DEFAULT_SYNC_LIMIT, tmpDir = temporaryDirectory(), workingDir, }) => { + statusCb({ + type: 'hashing', + msg: `Hashing files...`, + phase: 'start', + }); + const edgeFunctionsDistPath = await getDistPathIfExists(workingDir); + const [{ files: staticFiles, filesShaMap: staticShaMap }, { fnConfig, fnShaMap, functionSchedules, functions, functionsWithNativeModules }, configFile,] = await Promise.all([ + hashFiles({ + assetType, + concurrentHash, + directories: [dir, edgeFunctionsDistPath].filter(Boolean), + filter, + hashAlgorithm, + normalizer: deployFileNormalizer.bind(null, workingDir), + statusCb, + }), + hashFns(command, fnDir, { + functionsConfig, + tmpDir, + concurrentHash, + hashAlgorithm, + statusCb, + manifestPath, + skipFunctionsCache, + rootDir: siteRoot, + }), + hashConfig({ config }), + ]); + const files = { ...staticFiles, [configFile.normalizedPath]: configFile.hash }; + const filesShaMap = { ...staticShaMap, [configFile.hash]: [configFile] }; + const edgeFunctionsCount = Object.keys(files).filter(isEdgeFunctionFile).length; + const filesCount = Object.keys(files).length - edgeFunctionsCount; + const functionsCount = Object.keys(functions).length; + const stats = buildStatsString([ + filesCount > 0 && `${filesCount} files`, + functionsCount > 0 && `${functionsCount} functions`, + edgeFunctionsCount > 0 && 'edge functions', + ]); + statusCb({ + type: 'hashing', + msg: `Finished hashing ${stats}`, + phase: 'stop', + }); + if (filesCount === 0 && functionsCount === 0) { + throw new Error('No files or functions to deploy'); + } + if (functionsWithNativeModules.length !== 0) { + const functionsWithNativeModulesMessage = functionsWithNativeModules + .map(({ name }) => `- ${name}`) + .join('\n'); + warn(`Modules with native dependencies\n + ${functionsWithNativeModulesMessage} + +The serverless functions above use Node.js modules with native dependencies, which +must be installed on a system with the same architecture as the function runtime. A +mismatch in the system and runtime may lead to errors when invoking your functions. +To ensure your functions work as expected, we recommend using continuous deployment +instead of manual deployment. + +For more information, visit https://ntl.fyi/cli-native-modules.`); + } + statusCb({ + type: 'create-deploy', + msg: 'CDN diffing files...', + phase: 'start', + }); + // @ts-expect-error TS(2349) This expression is not callable + const deployParams = cleanDeep({ + siteId, + deploy_id: deployId, + body: { + files, + functions, + function_schedules: functionSchedules, + functions_config: fnConfig, + async: Object.keys(files).length > syncFileLimit, + branch, + draft, + }, + }); + let deploy = await api.updateSiteDeploy(deployParams); + if (deployParams.body.async) + deploy = await waitForDiff(api, deploy.id, siteId, deployTimeout); + const { required: requiredFiles, required_functions: requiredFns } = deploy; + statusCb({ + type: 'create-deploy', + msg: `CDN requesting ${requiredFiles.length} files${Array.isArray(requiredFns) ? ` and ${requiredFns.length} functions` : ''}`, + phase: 'stop', + }); + const filesUploadList = getUploadList(requiredFiles, filesShaMap); + const functionsUploadList = getUploadList(requiredFns, fnShaMap); + const uploadList = [...filesUploadList, ...functionsUploadList]; + await uploadFiles(api, deployId, uploadList, { concurrentUpload, statusCb, maxRetry }); + statusCb({ + type: 'wait-for-deploy', + msg: 'Waiting for deploy to go live...', + phase: 'start', + }); + deploy = await waitForDeploy(api, deployId, siteId, deployTimeout); + statusCb({ + type: 'wait-for-deploy', + msg: draft ? 'Draft deploy is live!' : 'Deploy is live!', + phase: 'stop', + }); + await rm(tmpDir, { force: true, recursive: true }); + const deployManifest = { + deployId, + deploy, + uploadList, + }; + return deployManifest; +}; +//# sourceMappingURL=deploy-site.js.map \ No newline at end of file diff --git a/dist/utils/deploy/deploy-site.js.map b/dist/utils/deploy/deploy-site.js.map new file mode 100644 index 00000000000..2b8e6ac658b --- /dev/null +++ b/dist/utils/deploy/deploy-site.js.map @@ -0,0 +1 @@ +{"version":3,"file":"deploy-site.js","sourceRoot":"","sources":["../../../src/utils/deploy/deploy-site.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/deploy/hash-config.d.ts b/dist/utils/deploy/hash-config.d.ts new file mode 100644 index 00000000000..00b3ce90fc2 --- /dev/null +++ b/dist/utils/deploy/hash-config.d.ts @@ -0,0 +1,10 @@ +export declare const hashConfig: ({ config }: { + config: any; +}) => { + assetType: string; + body: string; + hash: string; + normalizedPath: string; +}; +export declare const serializeToml: (object: any) => string; +//# sourceMappingURL=hash-config.d.ts.map \ No newline at end of file diff --git a/dist/utils/deploy/hash-config.d.ts.map b/dist/utils/deploy/hash-config.d.ts.map new file mode 100644 index 00000000000..4954971d19f --- /dev/null +++ b/dist/utils/deploy/hash-config.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"hash-config.d.ts","sourceRoot":"","sources":["../../../src/utils/deploy/hash-config.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,UAAU,GAAI;;CAAU;;;;;CAYpC,CAAA;AAGD,eAAO,MAAM,aAAa,GAAa,WAAM,WAE5C,CAAA"} \ No newline at end of file diff --git a/dist/utils/deploy/hash-config.js b/dist/utils/deploy/hash-config.js new file mode 100644 index 00000000000..15ab1592c21 --- /dev/null +++ b/dist/utils/deploy/hash-config.js @@ -0,0 +1,26 @@ +import { createHash } from 'node:crypto'; +import tomlify from 'tomlify-j0.4'; +// @ts-expect-error TS(7031) FIXME: Binding element 'config' implicitly has an 'any' t... Remove this comment to see the full error message +export const hashConfig = ({ config }) => { + if (!config) + throw new Error('Missing config option'); + const configString = serializeToml(config); + const hash = createHash('sha1').update(configString).digest('hex'); + return { + assetType: 'file', + body: configString, + hash, + normalizedPath: 'netlify.toml', + }; +}; +// @ts-expect-error TS(7006) FIXME: Parameter 'object' implicitly has an 'any' type. +export const serializeToml = function (object) { + return tomlify.toToml(object, { space: 2, replace: replaceTomlValue }); +}; +// `tomlify-j0.4` serializes integers as floats, e.g. `200.0`. +// This is a problem with `redirects[*].status`. +// @ts-expect-error TS(7006) FIXME: Parameter 'key' implicitly has an 'any' type. +const replaceTomlValue = function (key, value) { + return Number.isInteger(value) ? String(value) : false; +}; +//# sourceMappingURL=hash-config.js.map \ No newline at end of file diff --git a/dist/utils/deploy/hash-config.js.map b/dist/utils/deploy/hash-config.js.map new file mode 100644 index 00000000000..1eccb737c1f --- /dev/null +++ b/dist/utils/deploy/hash-config.js.map @@ -0,0 +1 @@ +{"version":3,"file":"hash-config.js","sourceRoot":"","sources":["../../../src/utils/deploy/hash-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,OAAO,OAAO,MAAM,cAAc,CAAA;AAElC,2IAA2I;AAC3I,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE;IACvC,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAA;IACrD,MAAM,YAAY,GAAG,aAAa,CAAC,MAAM,CAAC,CAAA;IAE1C,MAAM,IAAI,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAA;IAElE,OAAO;QACL,SAAS,EAAE,MAAM;QACjB,IAAI,EAAE,YAAY;QAClB,IAAI;QACJ,cAAc,EAAE,cAAc;KAC/B,CAAA;AACH,CAAC,CAAA;AAED,oFAAoF;AACpF,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,MAAM;IAC3C,OAAO,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC,CAAA;AACxE,CAAC,CAAA;AAED,8DAA8D;AAC9D,gDAAgD;AAChD,iFAAiF;AACjF,MAAM,gBAAgB,GAAG,UAAU,GAAG,EAAE,KAAK;IAC3C,OAAO,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;AACxD,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/deploy/hash-files.d.ts b/dist/utils/deploy/hash-files.d.ts new file mode 100644 index 00000000000..5778dd0e08b --- /dev/null +++ b/dist/utils/deploy/hash-files.d.ts @@ -0,0 +1,15 @@ +import { $TSFixMe } from '../../commands/types.js'; +declare const hashFiles: ({ assetType, concurrentHash, directories, filter, hashAlgorithm, normalizer, statusCb, }: { + assetType?: string | undefined; + concurrentHash: $TSFixMe; + directories: $TSFixMe; + filter: $TSFixMe; + hashAlgorithm?: string | undefined; + normalizer?: $TSFixMe; + statusCb: $TSFixMe; +}) => Promise<{ + files: Record; + filesShaMap: Record; +}>; +export default hashFiles; +//# sourceMappingURL=hash-files.d.ts.map \ No newline at end of file diff --git a/dist/utils/deploy/hash-files.d.ts.map b/dist/utils/deploy/hash-files.d.ts.map new file mode 100644 index 00000000000..985eb753f5c --- /dev/null +++ b/dist/utils/deploy/hash-files.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"hash-files.d.ts","sourceRoot":"","sources":["../../../src/utils/deploy/hash-files.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAElD,QAAA,MAAM,SAAS,GAAU,0FAQtB;IACD,SAAS,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,cAAc,EAAE,QAAQ,CAAA;IACxB,WAAW,EAAE,QAAQ,CAAA;IACrB,MAAM,EAAE,QAAQ,CAAA;IAChB,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,UAAU,CAAC,EAAE,QAAQ,CAAA;IACrB,QAAQ,EAAE,QAAQ,CAAA;CACnB,KAAG,OAAO,CAAC;IAAE,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAA;CAAE,CAkBrF,CAAA;AAED,eAAe,SAAS,CAAA"} \ No newline at end of file diff --git a/dist/utils/deploy/hash-files.js b/dist/utils/deploy/hash-files.js new file mode 100644 index 00000000000..ff6e4bb8f21 --- /dev/null +++ b/dist/utils/deploy/hash-files.js @@ -0,0 +1,21 @@ +import { pipeline } from 'stream/promises'; +import walker from 'folder-walker'; +import { fileFilterCtor, fileNormalizerCtor, hasherCtor, manifestCollectorCtor } from './hasher-segments.js'; +const hashFiles = async ({ assetType = 'file', concurrentHash, directories, filter, hashAlgorithm = 'sha1', normalizer, statusCb, }) => { + if (!filter) + throw new Error('Missing filter function option'); + const fileStream = walker(directories, { filter }); + const fileFilter = fileFilterCtor(); + const hasher = hasherCtor({ concurrentHash, hashAlgorithm }); + const fileNormalizer = fileNormalizerCtor({ assetType, normalizer }); + // Written to by manifestCollector + // normalizedPath: hash (wanted by deploy API) + const files = {}; + // hash: [fileObj, fileObj, fileObj] + const filesShaMap = {}; + const manifestCollector = manifestCollectorCtor(files, filesShaMap, { statusCb }); + await pipeline([fileStream, fileFilter, hasher, fileNormalizer, manifestCollector]); + return { files, filesShaMap }; +}; +export default hashFiles; +//# sourceMappingURL=hash-files.js.map \ No newline at end of file diff --git a/dist/utils/deploy/hash-files.js.map b/dist/utils/deploy/hash-files.js.map new file mode 100644 index 00000000000..a5be1b34967 --- /dev/null +++ b/dist/utils/deploy/hash-files.js.map @@ -0,0 +1 @@ +{"version":3,"file":"hash-files.js","sourceRoot":"","sources":["../../../src/utils/deploy/hash-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAA;AAE1C,OAAO,MAAM,MAAM,eAAe,CAAA;AAElC,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,UAAU,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAG5G,MAAM,SAAS,GAAG,KAAK,EAAE,EACvB,SAAS,GAAG,MAAM,EAClB,cAAc,EACd,WAAW,EACX,MAAM,EACN,aAAa,GAAG,MAAM,EACtB,UAAU,EACV,QAAQ,GAST,EAAuF,EAAE;IACxF,IAAI,CAAC,MAAM;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;IAE9D,MAAM,UAAU,GAAG,MAAM,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,CAAC,CAAA;IAClD,MAAM,UAAU,GAAG,cAAc,EAAE,CAAA;IACnC,MAAM,MAAM,GAAG,UAAU,CAAC,EAAE,cAAc,EAAE,aAAa,EAAE,CAAC,CAAA;IAC5D,MAAM,cAAc,GAAG,kBAAkB,CAAC,EAAE,SAAS,EAAE,UAAU,EAAE,CAAC,CAAA;IAEpE,kCAAkC;IAClC,8CAA8C;IAC9C,MAAM,KAAK,GAAG,EAAE,CAAA;IAChB,oCAAoC;IACpC,MAAM,WAAW,GAAG,EAAE,CAAA;IACtB,MAAM,iBAAiB,GAAG,qBAAqB,CAAC,KAAK,EAAE,WAAW,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAA;IAEjF,MAAM,QAAQ,CAAC,CAAC,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,iBAAiB,CAAC,CAAC,CAAA;IAEnF,OAAO,EAAE,KAAK,EAAE,WAAW,EAAE,CAAA;AAC/B,CAAC,CAAA;AAED,eAAe,SAAS,CAAA"} \ No newline at end of file diff --git a/dist/utils/deploy/hash-fns.d.ts b/dist/utils/deploy/hash-fns.d.ts new file mode 100644 index 00000000000..c14de106680 --- /dev/null +++ b/dist/utils/deploy/hash-fns.d.ts @@ -0,0 +1,24 @@ +import BaseCommand from '../../commands/base-command.js'; +import { $TSFixMe } from '../../commands/types.js'; +declare const hashFns: (command: BaseCommand, directories: string[], { concurrentHash, functionsConfig, hashAlgorithm, manifestPath, rootDir, skipFunctionsCache, statusCb, tmpDir, }: { + concurrentHash?: number; + functionsConfig?: $TSFixMe; + hashAlgorithm?: string | undefined; + manifestPath?: string | undefined; + rootDir?: string | undefined; + skipFunctionsCache?: boolean | undefined; + statusCb: $TSFixMe; + tmpDir: $TSFixMe; +}) => Promise<{ + functionSchedules?: { + name: string; + cron: string; + }[] | undefined; + functions: Record; + functionsWithNativeModules: $TSFixMe[]; + shaMap?: Record | undefined; + fnShaMap?: Record | undefined; + fnConfig?: Record | undefined; +}>; +export default hashFns; +//# sourceMappingURL=hash-fns.d.ts.map \ No newline at end of file diff --git a/dist/utils/deploy/hash-fns.d.ts.map b/dist/utils/deploy/hash-fns.d.ts.map new file mode 100644 index 00000000000..8cfd4c0f32b --- /dev/null +++ b/dist/utils/deploy/hash-fns.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"hash-fns.d.ts","sourceRoot":"","sources":["../../../src/utils/deploy/hash-fns.ts"],"names":[],"mappings":"AAOA,OAAO,WAAW,MAAM,gCAAgC,CAAA;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA;AAkGlD,QAAA,MAAM,OAAO,GACX,SAAS,WAAW,EACpB,aAAa,MAAM,EAAE,EACrB,kHASG;IACD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,eAAe,CAAC,EAAE,QAAQ,CAAA;IAC1B,aAAa,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAClC,YAAY,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IACjC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B,kBAAkB,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IACxC,QAAQ,EAAE,QAAQ,CAAA;IAClB,MAAM,EAAE,QAAQ,CAAA;CACjB,KACA,OAAO,CAAC;IACT,iBAAiB,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,GAAG,SAAS,CAAA;IAChE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IACjC,0BAA0B,EAAE,QAAQ,EAAE,CAAA;IACtC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,SAAS,CAAA;IAC7C,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG,SAAS,CAAA;IACjD,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,GAAG,SAAS,CAAA;CAChD,CA4FA,CAAA;AAED,eAAe,OAAO,CAAA"} \ No newline at end of file diff --git a/dist/utils/deploy/hash-fns.js b/dist/utils/deploy/hash-fns.js new file mode 100644 index 00000000000..b8b9bafb4ad --- /dev/null +++ b/dist/utils/deploy/hash-fns.js @@ -0,0 +1,141 @@ +import { readFile } from 'fs/promises'; +import path from 'path'; +import { pipeline } from 'stream/promises'; +import { Readable } from 'stream'; +import { zipFunctions } from '@netlify/zip-it-and-ship-it'; +import { INTERNAL_FUNCTIONS_FOLDER } from '../functions/functions.js'; +import { hasherCtor, manifestCollectorCtor } from './hasher-segments.js'; +// Maximum age of functions manifest (2 minutes). +const MANIFEST_FILE_TTL = 12e4; +const getFunctionZips = async ({ command, directories, functionsConfig, manifestPath, rootDir, skipFunctionsCache, statusCb, tmpDir, }) => { + statusCb({ + type: 'functions-manifest', + msg: 'Looking for a functions cache...', + phase: 'start', + }); + if (manifestPath) { + try { + // read manifest.json file + // @ts-expect-error TS(2345) FIXME: Argument of type 'Buffer' is not assignable to par... Remove this comment to see the full error message + const { functions, timestamp } = JSON.parse(await readFile(manifestPath)); + const manifestAge = Date.now() - timestamp; + if (manifestAge > MANIFEST_FILE_TTL) { + throw new Error('Manifest expired'); + } + statusCb({ + type: 'functions-manifest', + msg: 'Deploying functions from cache (use --skip-functions-cache to override)', + phase: 'stop', + }); + return functions; + } + catch { + statusCb({ + type: 'functions-manifest', + msg: 'Ignored invalid or expired functions cache', + phase: 'stop', + }); + } + } + else { + const msg = skipFunctionsCache + ? 'Ignoring functions cache (use without --skip-functions-cache to change)' + : 'No cached functions were found'; + statusCb({ + type: 'functions-manifest', + msg, + phase: 'stop', + }); + } + return await zipFunctions(directories, tmpDir, { + basePath: rootDir, + configFileDirectories: [command.getPathInProject(INTERNAL_FUNCTIONS_FOLDER)], + config: functionsConfig, + }); +}; +const trafficRulesConfig = (trafficRules) => { + if (!trafficRules) { + return; + } + return { + action: { + type: trafficRules?.action?.type, + config: { + rate_limit_config: { + algorithm: trafficRules?.action?.config?.rateLimitConfig?.algorithm, + window_size: trafficRules?.action?.config?.rateLimitConfig?.windowSize, + window_limit: trafficRules?.action?.config?.rateLimitConfig?.windowLimit, + }, + aggregate: trafficRules?.action?.config?.aggregate, + to: trafficRules?.action?.config?.to, + }, + }, + }; +}; +const hashFns = async (command, directories, { concurrentHash, functionsConfig, hashAlgorithm = 'sha256', manifestPath, rootDir, skipFunctionsCache, statusCb, tmpDir, }) => { + // Exit early if no functions directories are configured. + if (directories.length === 0) { + return { functions: {}, functionsWithNativeModules: [], shaMap: {} }; + } + if (!tmpDir) { + throw new Error('Missing tmpDir directory for zipping files'); + } + const functionZips = await getFunctionZips({ + command, + directories, + functionsConfig, + manifestPath, + rootDir, + skipFunctionsCache, + statusCb, + tmpDir, + }); + const fileObjs = functionZips.map(({ buildData, displayName, generator, invocationMode, path: functionPath, priority, runtime, runtimeVersion, timeout, trafficRules, }) => ({ + filepath: functionPath, + root: tmpDir, + relname: path.relative(tmpDir, functionPath), + basename: path.basename(functionPath), + extname: path.extname(functionPath), + type: 'file', + assetType: 'function', + normalizedPath: path.basename(functionPath, path.extname(functionPath)), + runtime: runtimeVersion ?? runtime, + displayName, + generator, + invocationMode, + timeout, + buildData, + priority, + trafficRules, + })); + const fnConfig = functionZips + .filter((func) => Boolean(func.displayName || func.generator || func.routes || func.buildData || func.priority || func.trafficRules)) + .reduce((funcs, curr) => ({ + ...funcs, + [curr.name]: { + display_name: curr.displayName, + excluded_routes: curr.excludedRoutes, + generator: curr.generator, + routes: curr.routes, + build_data: curr.buildData, + priority: curr.priority, + traffic_rules: trafficRulesConfig(curr.trafficRules), + }, + }), {}); + const functionSchedules = functionZips + .map(({ name, schedule }) => schedule && { name, cron: schedule }) + .filter((schedule) => schedule !== '' && schedule !== undefined); + const functionsWithNativeModules = functionZips.filter(({ nativeNodeModules }) => nativeNodeModules !== undefined && Object.keys(nativeNodeModules).length !== 0); + const functionStream = Readable.from(fileObjs); + const hasher = hasherCtor({ concurrentHash, hashAlgorithm }); + // Written to by manifestCollector + // normalizedPath: hash (wanted by deploy API) + const functions = {}; + // hash: [fileObj, fileObj, fileObj] + const fnShaMap = {}; + const manifestCollector = manifestCollectorCtor(functions, fnShaMap, { statusCb }); + await pipeline([functionStream, hasher, manifestCollector]); + return { functionSchedules, functions, functionsWithNativeModules, fnShaMap, fnConfig }; +}; +export default hashFns; +//# sourceMappingURL=hash-fns.js.map \ No newline at end of file diff --git a/dist/utils/deploy/hash-fns.js.map b/dist/utils/deploy/hash-fns.js.map new file mode 100644 index 00000000000..77c479d4d99 --- /dev/null +++ b/dist/utils/deploy/hash-fns.js.map @@ -0,0 +1 @@ +{"version":3,"file":"hash-fns.js","sourceRoot":"","sources":["../../../src/utils/deploy/hash-fns.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/deploy/hasher-segments.d.ts b/dist/utils/deploy/hasher-segments.d.ts new file mode 100644 index 00000000000..eec70d4d570 --- /dev/null +++ b/dist/utils/deploy/hasher-segments.d.ts @@ -0,0 +1,15 @@ +import { Transform, Writable } from 'node:stream'; +import type { StatusCallback } from './status-cb.js'; +export declare const hasherCtor: ({ concurrentHash, hashAlgorithm }: { + concurrentHash: any; + hashAlgorithm: any; +}) => Transform; +export declare const fileNormalizerCtor: ({ assetType, normalizer: normalizeFunction, }: { + assetType: string; + normalizer?: (file: unknown) => unknown; +}) => Transform; +export declare const manifestCollectorCtor: (filesObj: Record, shaMap: Record, { statusCb }: { + statusCb: StatusCallback; +}) => Writable; +export declare const fileFilterCtor: () => Transform; +//# sourceMappingURL=hasher-segments.d.ts.map \ No newline at end of file diff --git a/dist/utils/deploy/hasher-segments.d.ts.map b/dist/utils/deploy/hasher-segments.d.ts.map new file mode 100644 index 00000000000..5be7ce6d22a --- /dev/null +++ b/dist/utils/deploy/hasher-segments.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"hasher-segments.d.ts","sourceRoot":"","sources":["../../../src/utils/deploy/hasher-segments.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAMjD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAA;AAYpD,eAAO,MAAM,UAAU,GAAI;;;CAAiC,cAa3D,CAAA;AAGD,eAAO,MAAM,kBAAkB,GAAI,+CAGhC;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAA;CACxC,cAaA,CAAA;AAGD,eAAO,MAAM,qBAAqB,GAChC,UAAU,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EACjC,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,EACjC,cAAc;IAAE,QAAQ,EAAE,cAAc,CAAA;CAAE,aAuB3C,CAAA;AAED,eAAO,MAAM,cAAc,iBASvB,CAAA"} \ No newline at end of file diff --git a/dist/utils/deploy/hasher-segments.js b/dist/utils/deploy/hasher-segments.js new file mode 100644 index 00000000000..5a4bbabf6a7 --- /dev/null +++ b/dist/utils/deploy/hasher-segments.js @@ -0,0 +1,74 @@ +import { createHash } from 'node:crypto'; +import { createReadStream } from 'node:fs'; +import { Transform, Writable } from 'node:stream'; +import { pipeline } from 'node:stream/promises'; +import transform from 'parallel-transform'; +import { normalizePath } from './util.js'; +const hashFile = async (filePath, algorithm) => { + const hasher = createHash(algorithm); + await pipeline([createReadStream(filePath), hasher]); + return hasher.digest('hex'); +}; +// a parallel transform stream segment ctor that hashes fileObj's created by folder-walker +// TODO: use promises instead of callbacks +// @ts-expect-error TS(7031) FIXME: Binding element 'concurrentHash' implicitly has an... Remove this comment to see the full error message +export const hasherCtor = ({ concurrentHash, hashAlgorithm }) => { + if (!concurrentHash) + throw new Error('Missing required opts'); + return transform(concurrentHash, { objectMode: true }, async (fileObj, cb) => { + try { + const hash = await hashFile(fileObj.filepath, hashAlgorithm); + // insert hash and asset type to file obj + cb(null, { ...fileObj, hash }); + return; + } + catch (error) { + cb(error); + return; + } + }); +}; +// Inject normalized file names into normalizedPath and assetType +export const fileNormalizerCtor = ({ assetType, normalizer: normalizeFunction, }) => { + return new Transform({ + objectMode: true, + transform(fileObj, _, callback) { + const normalizedFile = { ...fileObj, assetType, normalizedPath: normalizePath(fileObj.relname) }; + const result = normalizeFunction !== undefined ? normalizeFunction(normalizedFile) : normalizedFile; + this.push(result); + callback(); + }, + }); +}; +// A writable stream segment ctor that normalizes file paths, and writes shaMap's +export const manifestCollectorCtor = (filesObj, shaMap, { statusCb }) => { + return new Writable({ + objectMode: true, + write(fileObj, _encoding, callback) { + filesObj[fileObj.normalizedPath] = fileObj.hash; + // Maintain hash to fileObj mapping + if (Array.isArray(shaMap[fileObj.hash])) { + shaMap[fileObj.hash].push(fileObj); + } + else { + shaMap[fileObj.hash] = [fileObj]; + } + statusCb({ + type: 'hashing', + msg: `Hashing ${fileObj.relname}`, + phase: 'progress', + }); + callback(); + }, + }); +}; +export const fileFilterCtor = () => new Transform({ + objectMode: true, + transform(fileObj, _, callback) { + if (fileObj.type === 'file') { + this.push(fileObj); + } + callback(); + }, +}); +//# sourceMappingURL=hasher-segments.js.map \ No newline at end of file diff --git a/dist/utils/deploy/hasher-segments.js.map b/dist/utils/deploy/hasher-segments.js.map new file mode 100644 index 00000000000..4270d4ff0ef --- /dev/null +++ b/dist/utils/deploy/hasher-segments.js.map @@ -0,0 +1 @@ +{"version":3,"file":"hasher-segments.js","sourceRoot":"","sources":["../../../src/utils/deploy/hasher-segments.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/deploy/status-cb.d.ts b/dist/utils/deploy/status-cb.d.ts new file mode 100644 index 00000000000..da9ef9e9233 --- /dev/null +++ b/dist/utils/deploy/status-cb.d.ts @@ -0,0 +1,7 @@ +export interface DeployEvent { + type: string; + msg: string; + phase: 'start' | 'progress' | 'error' | 'stop'; +} +export type StatusCallback = (status: DeployEvent) => void; +//# sourceMappingURL=status-cb.d.ts.map \ No newline at end of file diff --git a/dist/utils/deploy/status-cb.d.ts.map b/dist/utils/deploy/status-cb.d.ts.map new file mode 100644 index 00000000000..333e7b0decf --- /dev/null +++ b/dist/utils/deploy/status-cb.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"status-cb.d.ts","sourceRoot":"","sources":["../../../src/utils/deploy/status-cb.ts"],"names":[],"mappings":"AACA,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAA;IACZ,GAAG,EAAE,MAAM,CAAA;IACX,KAAK,EAAE,OAAO,GAAG,UAAU,GAAG,OAAO,GAAG,MAAM,CAAA;CAC/C;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,MAAM,EAAE,WAAW,KAAK,IAAI,CAAA"} \ No newline at end of file diff --git a/dist/utils/deploy/status-cb.js b/dist/utils/deploy/status-cb.js new file mode 100644 index 00000000000..c19b04a9e70 --- /dev/null +++ b/dist/utils/deploy/status-cb.js @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=status-cb.js.map \ No newline at end of file diff --git a/dist/utils/deploy/status-cb.js.map b/dist/utils/deploy/status-cb.js.map new file mode 100644 index 00000000000..e250f67c522 --- /dev/null +++ b/dist/utils/deploy/status-cb.js.map @@ -0,0 +1 @@ +{"version":3,"file":"status-cb.js","sourceRoot":"","sources":["../../../src/utils/deploy/status-cb.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/utils/deploy/upload-files.d.ts b/dist/utils/deploy/upload-files.d.ts new file mode 100644 index 00000000000..25d5d5dbc59 --- /dev/null +++ b/dist/utils/deploy/upload-files.d.ts @@ -0,0 +1,7 @@ +declare const uploadFiles: (api: any, deployId: any, uploadList: any, { concurrentUpload, maxRetry, statusCb }: { + concurrentUpload: any; + maxRetry: any; + statusCb: any; +}) => Promise; +export default uploadFiles; +//# sourceMappingURL=upload-files.d.ts.map \ No newline at end of file diff --git a/dist/utils/deploy/upload-files.d.ts.map b/dist/utils/deploy/upload-files.d.ts.map new file mode 100644 index 00000000000..78c8060fcb0 --- /dev/null +++ b/dist/utils/deploy/upload-files.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"upload-files.d.ts","sourceRoot":"","sources":["../../../src/utils/deploy/upload-files.ts"],"names":[],"mappings":"AAQA,QAAA,MAAM,WAAW,GAAU,QAAG,EAAE,aAAQ,EAAE,eAAU,EAAE;;;;CAAwC,uBAwE7F,CAAA;AA2DD,eAAe,WAAW,CAAA"} \ No newline at end of file diff --git a/dist/utils/deploy/upload-files.js b/dist/utils/deploy/upload-files.js new file mode 100644 index 00000000000..424d44dc316 --- /dev/null +++ b/dist/utils/deploy/upload-files.js @@ -0,0 +1,116 @@ +import fs from 'fs'; +import backoff from 'backoff'; +import pMap from 'p-map'; +import { UPLOAD_INITIAL_DELAY, UPLOAD_MAX_DELAY, UPLOAD_RANDOM_FACTOR } from './constants.js'; +// @ts-expect-error TS(7006) FIXME: Parameter 'api' implicitly has an 'any' type. +const uploadFiles = async (api, deployId, uploadList, { concurrentUpload, maxRetry, statusCb }) => { + if (!concurrentUpload || !statusCb || !maxRetry) + throw new Error('Missing required option concurrentUpload'); + statusCb({ + type: 'upload', + msg: `Uploading ${uploadList.length} files`, + phase: 'start', + }); + // @ts-expect-error TS(7006) FIXME: Parameter 'fileObj' implicitly has an 'any' type. + const uploadFile = async (fileObj, index) => { + const { assetType, body, filepath, invocationMode, normalizedPath, runtime, timeout } = fileObj; + const readStreamCtor = () => body ?? fs.createReadStream(filepath); + statusCb({ + type: 'upload', + msg: `(${index}/${uploadList.length}) Uploading ${normalizedPath}...`, + phase: 'progress', + }); + let response; + switch (assetType) { + case 'file': { + response = await retryUpload(() => api.uploadDeployFile({ + body: readStreamCtor, + deployId, + path: encodeURI(normalizedPath), + }), maxRetry); + break; + } + case 'function': { + // @ts-expect-error TS(7006) FIXME: Parameter 'retryCount' implicitly has an 'any' typ... Remove this comment to see the full error message + response = await retryUpload((retryCount) => { + const params = { + body: readStreamCtor, + deployId, + invocationMode, + timeout, + name: encodeURI(normalizedPath), + runtime, + }; + if (retryCount > 0) { + // @ts-expect-error TS(2339) FIXME: Property 'xNfRetryCount' does not exist on type '{... Remove this comment to see the full error message + params.xNfRetryCount = retryCount; + } + return api.uploadDeployFunction(params); + }, maxRetry); + break; + } + default: { + const error = new Error('File Object missing assetType property'); + // @ts-expect-error TS(2339) FIXME: Property 'fileObj' does not exist on type 'Error'. + error.fileObj = fileObj; + throw error; + } + } + return response; + }; + const results = await pMap(uploadList, uploadFile, { concurrency: concurrentUpload }); + statusCb({ + type: 'upload', + msg: `Finished uploading ${uploadList.length} assets`, + phase: 'stop', + }); + return results; +}; +// @ts-expect-error TS(7006) FIXME: Parameter 'uploadFn' implicitly has an 'any' type. +const retryUpload = (uploadFn, maxRetry) => new Promise((resolve, reject) => { + // @ts-expect-error TS(7034) FIXME: Variable 'lastError' implicitly has type 'any' in ... Remove this comment to see the full error message + let lastError; + const fibonacciBackoff = backoff.fibonacci({ + randomisationFactor: UPLOAD_RANDOM_FACTOR, + initialDelay: UPLOAD_INITIAL_DELAY, + maxDelay: UPLOAD_MAX_DELAY, + }); + const tryUpload = async (retryIndex = -1) => { + try { + const results = await uploadFn(retryIndex + 1); + resolve(results); + return; + } + catch (error) { + lastError = error; + // We don't need to retry for 400 or 422 errors + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + if (error.status === 400 || error.status === 422) { + reject(error); + return; + } + // observed errors: 408, 401 (4** swallowed), 502 + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + if (error.status > 400 || error.name === 'FetchError') { + fibonacciBackoff.backoff(); + return; + } + reject(error); + return; + } + }; + fibonacciBackoff.failAfter(maxRetry); + fibonacciBackoff.on('backoff', () => { + // Do something when backoff starts, e.g. show to the + // user the delay before next reconnection attempt. + }); + // eslint-disable-next-line @typescript-eslint/no-misused-promises + fibonacciBackoff.on('ready', tryUpload); + fibonacciBackoff.on('fail', () => { + // @ts-expect-error TS(7005) FIXME: Variable 'lastError' implicitly has an 'any' type. + reject(lastError); + }); + tryUpload(); +}); +export default uploadFiles; +//# sourceMappingURL=upload-files.js.map \ No newline at end of file diff --git a/dist/utils/deploy/upload-files.js.map b/dist/utils/deploy/upload-files.js.map new file mode 100644 index 00000000000..c471fdc190b --- /dev/null +++ b/dist/utils/deploy/upload-files.js.map @@ -0,0 +1 @@ +{"version":3,"file":"upload-files.js","sourceRoot":"","sources":["../../../src/utils/deploy/upload-files.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/deploy/util.d.ts b/dist/utils/deploy/util.d.ts new file mode 100644 index 00000000000..9486aa00977 --- /dev/null +++ b/dist/utils/deploy/util.d.ts @@ -0,0 +1,5 @@ +export declare const normalizePath: (relname: string) => string; +export declare const waitForDiff: (api: any, deployId: any, siteId: any, timeout: any) => Promise; +export declare const waitForDeploy: (api: any, deployId: any, siteId: any, timeout: any) => Promise; +export declare const getUploadList: (required: any, shaMap: any) => any; +//# sourceMappingURL=util.d.ts.map \ No newline at end of file diff --git a/dist/utils/deploy/util.d.ts.map b/dist/utils/deploy/util.d.ts.map new file mode 100644 index 00000000000..d15eae2db46 --- /dev/null +++ b/dist/utils/deploy/util.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../../../src/utils/deploy/util.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,aAAa,GAAI,SAAS,MAAM,KAAG,MAK/C,CAAA;AAID,eAAO,MAAM,WAAW,GAAU,QAAG,EAAE,aAAQ,EAAE,WAAM,EAAE,YAAO,uBAsC/D,CAAA;AAID,eAAO,MAAM,aAAa,GAAU,QAAG,EAAE,aAAQ,EAAE,WAAM,EAAE,YAAO,uBAqCjE,CAAA;AAID,eAAO,MAAM,aAAa,GAAI,aAAQ,EAAE,WAAM,QAI7C,CAAA"} \ No newline at end of file diff --git a/dist/utils/deploy/util.js b/dist/utils/deploy/util.js new file mode 100644 index 00000000000..4da9358cb02 --- /dev/null +++ b/dist/utils/deploy/util.js @@ -0,0 +1,93 @@ +import { sep } from 'path'; +import pWaitFor from 'p-wait-for'; +import { DEPLOY_POLL } from './constants.js'; +// normalize windows paths to unix paths +export const normalizePath = (relname) => { + if (relname.includes('#') || relname.includes('?')) { + throw new Error(`Invalid filename ${relname}. Deployed filenames cannot contain # or ? characters`); + } + return relname.split(sep).join('/'); +}; +// poll an async deployId until its done diffing +// @ts-expect-error TS(7006) FIXME: Parameter 'api' implicitly has an 'any' type. +export const waitForDiff = async (api, deployId, siteId, timeout) => { + // capture ready deploy during poll + let deploy; + const loadDeploy = async () => { + const siteDeploy = await api.getSiteDeploy({ siteId, deployId }); + switch (siteDeploy.state) { + // https://github.com/netlify/bitballoon/blob/master/app/models/deploy.rb#L21-L33 + case 'error': { + const deployError = new Error(siteDeploy.error_message || `Deploy ${deployId} had an error`); + // @ts-expect-error TS(2339) FIXME: Property 'deploy' does not exist on type 'Error'. + deployError.deploy = siteDeploy; + throw deployError; + } + case 'prepared': + case 'uploading': + case 'uploaded': + case 'ready': { + deploy = siteDeploy; + return true; + } + case 'preparing': + default: { + return false; + } + } + }; + await pWaitFor(loadDeploy, { + interval: DEPLOY_POLL, + timeout: { + milliseconds: timeout, + message: 'Timeout while waiting for deploy', + }, + }); + return deploy; +}; +// Poll a deployId until its ready +// @ts-expect-error TS(7006) FIXME: Parameter 'api' implicitly has an 'any' type. +export const waitForDeploy = async (api, deployId, siteId, timeout) => { + // capture ready deploy during poll + let deploy; + const loadDeploy = async () => { + const siteDeploy = await api.getSiteDeploy({ siteId, deployId }); + switch (siteDeploy.state) { + // https://github.com/netlify/bitballoon/blob/master/app/models/deploy.rb#L21-L33 + case 'error': { + const deployError = new Error(siteDeploy.error_message || `Deploy ${deployId} had an error`); + // @ts-expect-error TS(2339) FIXME: Property 'deploy' does not exist on type 'Error'. + deployError.deploy = siteDeploy; + throw deployError; + } + case 'ready': { + deploy = siteDeploy; + return true; + } + case 'preparing': + case 'prepared': + case 'uploaded': + case 'uploading': + default: { + return false; + } + } + }; + await pWaitFor(loadDeploy, { + interval: DEPLOY_POLL, + timeout: { + milliseconds: timeout, + message: 'Timeout while waiting for deploy', + }, + }); + return deploy; +}; +// Transform the fileShaMap and fnShaMap into a generic shaMap that file-uploader.js can use +// @ts-expect-error TS(7006) FIXME: Parameter 'required' implicitly has an 'any' type. +export const getUploadList = (required, shaMap) => { + if (!required || !shaMap) + return []; + // @ts-expect-error TS(7006) FIXME: Parameter 'sha' implicitly has an 'any' type. + return required.flatMap((sha) => shaMap[sha]); +}; +//# sourceMappingURL=util.js.map \ No newline at end of file diff --git a/dist/utils/deploy/util.js.map b/dist/utils/deploy/util.js.map new file mode 100644 index 00000000000..7731f5612bc --- /dev/null +++ b/dist/utils/deploy/util.js.map @@ -0,0 +1 @@ +{"version":3,"file":"util.js","sourceRoot":"","sources":["../../../src/utils/deploy/util.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/detect-server-settings.d.ts b/dist/utils/detect-server-settings.d.ts new file mode 100644 index 00000000000..aa31efc00c8 --- /dev/null +++ b/dist/utils/detect-server-settings.d.ts @@ -0,0 +1,108 @@ +import type { OptionValues } from 'commander'; +import BaseCommand from '../commands/base-command.js'; +import { type DevConfig } from '../commands/dev/types.js'; +import { ServerSettings } from './types.js'; +import { CachedConfig } from '../lib/build.js'; +/** + * Get the server settings based on the flags and the devConfig + */ +declare const detectServerSettings: (devConfig: DevConfig, flags: OptionValues, command: BaseCommand) => Promise; +/** + * Returns a copy of the provided config with any plugins provided by the + * server settings + */ +export declare const getConfigWithPlugins: (config: CachedConfig["config"], settings: ServerSettings) => { + build: { + base: string; + command?: string | undefined; + functions?: string | undefined; + functionsSource?: string | undefined; + edge_functions?: string | undefined; + environment: Record; + processing: { + css: Record; + html: Record; + images: Record; + js: Record; + }; + publish: string; + publishOrigin: string; + services: Record; + }; + dev?: undefined | { + command?: string | undefined; + functions?: string | undefined; + functionsPort?: number | undefined; + https?: { + certFile: string; + keyFile: string; + } | undefined; + processing: { + html?: { + injections?: { + location?: "before_closing_head_tag" | "before_closing_body_tag"; + html: string; + }[]; + }; + }; + }; + edge_functions?: import("../lib/edge-functions/proxy.js").EdgeFunctionDeclaration[]; + functions?: import("@netlify/build").NetlifyConfig["functions"]; + functionsDirectory?: undefined | string; + headers: import("@netlify/headers-parser").MinimalHeader[]; + images: { + remote_images: string[]; + }; + plugins?: import("./types.js").Plugin[]; + redirects: undefined | import("@netlify/build").NetlifyConfig["redirects"]; +} | { + plugins: (import("./types.js").Plugin | { + package: string; + origin: "config"; + inputs: Record; + })[]; + build: { + base: string; + command?: string | undefined; + functions?: string | undefined; + functionsSource?: string | undefined; + edge_functions?: string | undefined; + environment: Record; + processing: { + css: Record; + html: Record; + images: Record; + js: Record; + }; + publish: string; + publishOrigin: string; + services: Record; + }; + dev?: undefined | { + command?: string | undefined; + functions?: string | undefined; + functionsPort?: number | undefined; + https?: { + certFile: string; + keyFile: string; + } | undefined; + processing: { + html?: { + injections?: { + location?: "before_closing_head_tag" | "before_closing_body_tag"; + html: string; + }[]; + }; + }; + }; + edge_functions?: import("../lib/edge-functions/proxy.js").EdgeFunctionDeclaration[]; + functions?: import("@netlify/build").NetlifyConfig["functions"]; + functionsDirectory?: undefined | string; + headers: import("@netlify/headers-parser").MinimalHeader[]; + images: { + remote_images: string[]; + }; + redirects: undefined | import("@netlify/build").NetlifyConfig["redirects"]; +}; +export default detectServerSettings; +//# sourceMappingURL=detect-server-settings.d.ts.map \ No newline at end of file diff --git a/dist/utils/detect-server-settings.d.ts.map b/dist/utils/detect-server-settings.d.ts.map new file mode 100644 index 00000000000..4ffd69bac4f --- /dev/null +++ b/dist/utils/detect-server-settings.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"detect-server-settings.d.ts","sourceRoot":"","sources":["../../src/utils/detect-server-settings.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAG7C,OAAO,WAAW,MAAM,6BAA6B,CAAA;AACrD,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,0BAA0B,CAAA;AAMzD,OAAO,EAAsB,cAAc,EAAE,MAAM,YAAY,CAAA;AAC/D,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AA2O9C;;GAEG;AACH,QAAA,MAAM,oBAAoB,GACxB,WAAW,SAAS,EACpB,OAAO,YAAY,EACnB,SAAS,WAAW,KACnB,OAAO,CAAC,cAAc,CA4DxB,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,YAAY,CAAC,QAAQ,CAAC,EAAE,UAAU,cAAc;;;eA5S7C,CAAC;iBAAqC,CAAA;uBAGnC,CAAC;sBAAyC,CAAC;;;;;;;;;;;;;eAiBlD,CAAC;iBAEjC,CAAC;qBACQ,CAAC;aAAoC,CAAC;;;;;gBAUjC,CAAC;0BAA6B,CAAA;4BAQ7C,CAAC;;;;;;;;;;;;;;;;;iBAsR+B,MAAM;gBAAU,QAAQ;gBAAU,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC;;;;eA/TjD,CAAC;iBAAqC,CAAA;uBAGnC,CAAC;sBAAyC,CAAC;;;;;;;;;;;;;eAiBlD,CAAC;iBAEjC,CAAC;qBACQ,CAAC;aAAoC,CAAC;;;;;gBAUjC,CAAC;0BAA6B,CAAA;4BAQ7C,CAAC;;;;;;;;;;;;;;CA4RX,CAAA;AAED,eAAe,oBAAoB,CAAA"} \ No newline at end of file diff --git a/dist/utils/detect-server-settings.js b/dist/utils/detect-server-settings.js new file mode 100644 index 00000000000..3b5486cf259 --- /dev/null +++ b/dist/utils/detect-server-settings.js @@ -0,0 +1,252 @@ +import { readFile } from 'fs/promises'; +import { EOL } from 'os'; +import { dirname, relative, resolve } from 'path'; +import { getFramework, getSettings } from '@netlify/build-info'; +import getPort from 'get-port'; +import { detectFrameworkSettings } from './build-info.js'; +import { NETLIFYDEVWARN, chalk, log } from './command-helpers.js'; +import { acquirePort } from './dev.js'; +import { getPluginsToAutoInstall } from './init/utils.js'; +const formatProperty = (str) => chalk.magenta(`'${str}'`); +const formatValue = (str) => chalk.green(`'${str}'`); +const readHttpsSettings = async (options) => { + if (typeof options !== 'object' || !options.keyFile || !options.certFile) { + throw new TypeError(`https options should be an object with ${formatProperty('keyFile')} and ${formatProperty('certFile')} string properties`); + } + const { certFile, keyFile } = options; + if (typeof keyFile !== 'string') { + throw new TypeError(`Private key file configuration should be a string`); + } + if (typeof certFile !== 'string') { + throw new TypeError(`Certificate file configuration should be a string`); + } + const [key, cert] = await Promise.allSettled([readFile(keyFile, 'utf-8'), readFile(certFile, 'utf-8')]); + if (key.status === 'rejected') { + throw new Error(`Error reading private key file: ${key.reason}`); + } + if (cert.status === 'rejected') { + throw new Error(`Error reading certificate file: ${cert.reason}`); + } + return { key: key.value, cert: cert.value, keyFilePath: resolve(keyFile), certFilePath: resolve(certFile) }; +}; +/** + * Validates a property inside the devConfig to be of a given type + */ +function validateProperty(devConfig, property, type) { + if (devConfig[property] && typeof devConfig[property] !== type) { + const formattedProperty = formatProperty(property); + throw new TypeError(`Invalid ${formattedProperty} option provided in config. The value of ${formattedProperty} option must be of type ${type}`); + } +} +const validateFrameworkConfig = ({ devConfig }) => { + validateProperty(devConfig, 'command', 'string'); + validateProperty(devConfig, 'port', 'number'); + validateProperty(devConfig, 'targetPort', 'number'); + if (devConfig.targetPort && devConfig.targetPort === devConfig.port) { + throw new Error(`${formatProperty('port')} and ${formatProperty('targetPort')} options cannot have same values. Please consult the documentation for more details: https://ntl.fyi/ports-and-netlify-dev`); + } +}; +const validateConfiguredPort = ({ detectedPort, devConfig }) => { + if (devConfig.port && devConfig.port === detectedPort) { + const formattedPort = formatProperty('port'); + throw new Error(`The ${formattedPort} option you specified conflicts with the port of your application. Please use a different value for ${formattedPort}`); + } +}; +const DEFAULT_PORT = 8888; +const DEFAULT_STATIC_PORT = 3999; +/** + * Logs a message that it was unable to determine the dist directory and falls back to the workingDir + */ +const getDefaultDist = (workingDir) => { + log(`${NETLIFYDEVWARN} Unable to determine public folder to serve files from. Using current working directory`); + log(`${NETLIFYDEVWARN} Setup a netlify.toml file with a [dev] section to specify your dev server settings.`); + log(`${NETLIFYDEVWARN} See docs at: https://docs.netlify.com/cli/local-development/#project-detection`); + return workingDir; +}; +const getStaticServerPort = async ({ devConfig }) => { + const port = await acquirePort({ + configuredPort: devConfig.staticServerPort, + defaultPort: DEFAULT_STATIC_PORT, + errorMessage: 'Could not acquire configured static server port', + }); + return port; +}; +const handleStaticServer = async ({ devConfig, flags, workingDir, }) => { + validateProperty(devConfig, 'staticServerPort', 'number'); + if (flags.dir) { + log(`${NETLIFYDEVWARN} Using simple static server because ${formatProperty('--dir')} flag was specified`); + } + else if (devConfig.framework === '#static') { + log(`${NETLIFYDEVWARN} Using simple static server because ${formatProperty('[dev.framework]')} was set to ${formatValue('#static')}`); + } + if (devConfig.targetPort) { + log(`${NETLIFYDEVWARN} Ignoring ${formatProperty('targetPort')} setting since using a simple static server.${EOL}${NETLIFYDEVWARN} Use --staticServerPort or [dev.staticServerPort] to configure the static server port`); + } + const dist = flags.dir || devConfig.publish || getDefaultDist(workingDir); + log(`${NETLIFYDEVWARN} Running static server from "${relative(dirname(workingDir), dist)}"`); + const frameworkPort = await getStaticServerPort({ devConfig }); + return { + ...(devConfig.command && { command: devConfig.command }), + useStaticServer: true, + frameworkPort, + dist, + }; +}; +/** + * Retrieves the settings from a framework + */ +const getSettingsFromDetectedSettings = (command, settings) => { + if (!settings) { + return; + } + return { + baseDirectory: settings.baseDirectory, + command: settings.devCommand, + frameworkPort: settings.frameworkPort, + dist: settings.dist, + framework: settings.framework.name, + env: settings.env, + pollingStrategies: settings.pollingStrategies, + plugins: getPluginsToAutoInstall(command, settings.plugins_from_config_file, settings.plugins_recommended), + clearPublishDirectory: settings.clearPublishDirectory, + }; +}; +const hasCommandAndTargetPort = (devConfig) => devConfig.command && devConfig.targetPort; +/** + * Creates settings for the custom framework + */ +const handleCustomFramework = ({ devConfig, workingDir, }) => { + if (!hasCommandAndTargetPort(devConfig)) { + throw new Error(`${formatProperty('command')} and ${formatProperty('targetPort')} properties are required when ${formatProperty('framework')} is set to ${formatValue('#custom')}`); + } + return { + command: devConfig.command, + frameworkPort: devConfig.targetPort, + dist: devConfig.publish || getDefaultDist(workingDir), + framework: '#custom', + pollingStrategies: devConfig.pollingStrategies ?? [], + }; +}; +/** + * Merges the framework settings with the devConfig + */ +const mergeSettings = async ({ devConfig, frameworkSettings, workingDir, }) => { + const command = devConfig.command || frameworkSettings?.command; + const frameworkPort = devConfig.targetPort || frameworkSettings?.frameworkPort; + const useStaticServer = !(command && frameworkPort); + return { + baseDirectory: devConfig.base || frameworkSettings?.baseDirectory, + command, + frameworkPort: useStaticServer ? await getStaticServerPort({ devConfig }) : frameworkPort, + dist: devConfig.publish || frameworkSettings?.dist || getDefaultDist(workingDir), + framework: frameworkSettings?.framework, + env: frameworkSettings?.env, + pollingStrategies: frameworkSettings?.pollingStrategies ?? [], + useStaticServer, + clearPublishDirectory: frameworkSettings?.clearPublishDirectory, + }; +}; +/** + * Handles a forced framework and retrieves the settings for it + */ +const handleForcedFramework = async (options) => { + // this throws if `devConfig.framework` is not a supported framework + const framework = await getFramework(options.devConfig.framework, options.project); + const settings = await getSettings(framework, options.project, options.workspacePackage || ''); + const frameworkSettings = getSettingsFromDetectedSettings(options.command, settings); + // TODO(serhalp): Remove and update `getSettingsFromDetectedSettings` type to return non-nullable + // when given non-nullable second arg + if (frameworkSettings == null) { + throw new Error(`Could not get settings for framework ${options.devConfig.framework}`); + } + return mergeSettings({ devConfig: options.devConfig, workingDir: options.workingDir, frameworkSettings }); +}; +/** + * Get the server settings based on the flags and the devConfig + */ +const detectServerSettings = async (devConfig, flags, command) => { + validateProperty(devConfig, 'framework', 'string'); + // eslint-disable-next-line @typescript-eslint/no-explicit-any -- TODO(serhalp): Set to `BaseServerSettings`. Good luck! + let settings = {}; + if (flags.dir || devConfig.framework === '#static') { + // serving files statically without a framework server + settings = await handleStaticServer({ flags, devConfig, workingDir: command.workingDir }); + } + else if (devConfig.framework === '#auto') { + // this is the default CLI behavior + const runDetection = !hasCommandAndTargetPort(devConfig); + const frameworkSettings = runDetection + ? getSettingsFromDetectedSettings(command, await detectFrameworkSettings(command, 'dev')) + : undefined; + if (frameworkSettings === undefined && runDetection) { + log(`${NETLIFYDEVWARN} No app server detected. Using simple static server`); + settings = await handleStaticServer({ flags, devConfig, workingDir: command.workingDir }); + } + else { + validateFrameworkConfig({ devConfig }); + settings = await mergeSettings({ devConfig, frameworkSettings, workingDir: command.workingDir }); + } + settings.plugins = frameworkSettings?.plugins; + } + else if (devConfig.framework === '#custom') { + validateFrameworkConfig({ devConfig }); + // when the users wants to configure `command` and `targetPort` + settings = handleCustomFramework({ devConfig, workingDir: command.workingDir }); + } + else if (devConfig.framework) { + validateFrameworkConfig({ devConfig }); + // this is when the user explicitly configures a framework, e.g. `framework = "gatsby"` + settings = await handleForcedFramework({ + command, + devConfig, + project: command.project, + workingDir: command.workingDir, + workspacePackage: command.workspacePackage, + }); + } + validateConfiguredPort({ devConfig, detectedPort: settings.frameworkPort }); + const acquiredPort = await acquirePort({ + configuredPort: devConfig.port, + defaultPort: DEFAULT_PORT, + errorMessage: `Could not acquire required ${formatProperty('port')}`, + }); + const functionsDir = devConfig.functions || settings.functions; + return { + ...settings, + port: acquiredPort, + jwtSecret: devConfig.jwtSecret || 'secret', + jwtRolePath: devConfig.jwtRolePath || 'app_metadata.authorization.roles', + functions: functionsDir, + functionsPort: await getPort({ port: devConfig.functionsPort || 0 }), + ...(devConfig.https && { https: await readHttpsSettings(devConfig.https) }), + }; +}; +/** + * Returns a copy of the provided config with any plugins provided by the + * server settings + */ +export const getConfigWithPlugins = (config, settings) => { + if (!settings.plugins) { + return config; + } + // If there are plugins that we should be running for this project, add them + // to the config as if they were declared in netlify.toml. We must check + // whether the plugin has already been added by another source (like the + // TOML file or the UI), as we don't want to run the same plugin twice. + const { plugins: existingPlugins = [] } = config; + const existingPluginNames = new Set(existingPlugins.map((plugin) => plugin.package)); + const newPlugins = settings.plugins + .map((pluginName) => { + if (existingPluginNames.has(pluginName)) { + return; + } + return { package: pluginName, origin: 'config', inputs: {} }; + }) + .filter((plugin) => plugin != null); + return { + ...config, + plugins: [...newPlugins, ...(config.plugins ?? [])], + }; +}; +export default detectServerSettings; +//# sourceMappingURL=detect-server-settings.js.map \ No newline at end of file diff --git a/dist/utils/detect-server-settings.js.map b/dist/utils/detect-server-settings.js.map new file mode 100644 index 00000000000..c1e647b9752 --- /dev/null +++ b/dist/utils/detect-server-settings.js.map @@ -0,0 +1 @@ +{"version":3,"file":"detect-server-settings.js","sourceRoot":"","sources":["../../src/utils/detect-server-settings.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/dev-server-banner.d.ts b/dist/utils/dev-server-banner.d.ts new file mode 100644 index 00000000000..bcaae2a4e2f --- /dev/null +++ b/dist/utils/dev-server-banner.d.ts @@ -0,0 +1,4 @@ +export declare const printBanner: (options: { + url: string; +}) => void; +//# sourceMappingURL=dev-server-banner.d.ts.map \ No newline at end of file diff --git a/dist/utils/dev-server-banner.d.ts.map b/dist/utils/dev-server-banner.d.ts.map new file mode 100644 index 00000000000..22f997a9d9b --- /dev/null +++ b/dist/utils/dev-server-banner.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dev-server-banner.d.ts","sourceRoot":"","sources":["../../src/utils/dev-server-banner.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,WAAW,GAAI,SAAS;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,KAAG,IAatD,CAAA"} \ No newline at end of file diff --git a/dist/utils/dev-server-banner.js b/dist/utils/dev-server-banner.js new file mode 100644 index 00000000000..8f3140a6294 --- /dev/null +++ b/dist/utils/dev-server-banner.js @@ -0,0 +1,15 @@ +import boxen from 'boxen'; +import { chalk, log, NETLIFY_CYAN_HEX } from './command-helpers.js'; +export const printBanner = (options) => { + log(boxen(`Local dev server ready: ${chalk.inverse.cyan(options.url)}`, { + padding: 1, + margin: 1, + textAlignment: 'center', + borderStyle: 'round', + borderColor: NETLIFY_CYAN_HEX, + // This is an intentional half-width space to work around a unicode padding math bug in boxen + title: '⬄ ', + titleAlignment: 'center', + })); +}; +//# sourceMappingURL=dev-server-banner.js.map \ No newline at end of file diff --git a/dist/utils/dev-server-banner.js.map b/dist/utils/dev-server-banner.js.map new file mode 100644 index 00000000000..4df28ff03aa --- /dev/null +++ b/dist/utils/dev-server-banner.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dev-server-banner.js","sourceRoot":"","sources":["../../src/utils/dev-server-banner.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAEnE,MAAM,CAAC,MAAM,WAAW,GAAG,CAAC,OAAwB,EAAQ,EAAE;IAC5D,GAAG,CACD,KAAK,CAAC,2BAA2B,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,EAAE;QAClE,OAAO,EAAE,CAAC;QACV,MAAM,EAAE,CAAC;QACT,aAAa,EAAE,QAAQ;QACvB,WAAW,EAAE,OAAO;QACpB,WAAW,EAAE,gBAAgB;QAC7B,6FAA6F;QAC7F,KAAK,EAAE,IAAI;QACX,cAAc,EAAE,QAAQ;KACzB,CAAC,CACH,CAAA;AACH,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/dev.d.ts b/dist/utils/dev.d.ts new file mode 100644 index 00000000000..301b8368d2b --- /dev/null +++ b/dist/utils/dev.d.ts @@ -0,0 +1,72 @@ +import type { NetlifyAPI } from '@netlify/api'; +import type { EnvironmentVariables } from './types.js'; +type ApiAccount = Awaited>[number]; +type Capabilities = NonNullable & { + background_functions?: { + included?: boolean | undefined; + } | undefined; +}; +export type Capability = keyof Capabilities; +export type Account = ApiAccount & { + capabilities?: Capabilities; +}; +/** + * + * @param {object} config + * @param {boolean} config.offline + * @param {*} config.api + * @param {*} config.site + * @param {*} config.siteInfo + * @returns + */ +export declare const getSiteInformation: ({ api, offline, site, siteInfo }: { + api: any; + offline: any; + site: any; + siteInfo: any; +}) => Promise<{ + addonsUrls: { + [k: string]: any; + }; + siteUrl: any; + accountId: string | undefined; + capabilities: { + backgroundFunctions: boolean; + }; + timeouts: { + syncFunctions: any; + backgroundFunctions: number; + }; +} | { + addonsUrls: {}; + siteUrl: string; + capabilities: { + backgroundFunctions?: undefined; + }; + timeouts: { + syncFunctions: number; + backgroundFunctions: number; + }; + accountId?: undefined; +}>; +/** + * @param {{devConfig: any, env: Record, site: any}} param0 + */ +export declare const getDotEnvVariables: ({ devConfig, env, site }: { + devConfig: any; + env: any; + site: any; +}) => Promise; +/** + * Takes a set of environment variables in the format provided by @netlify/config and injects them into `process.env` + */ +export declare const injectEnvVariables: (env: EnvironmentVariables) => void; +export declare const acquirePort: ({ configuredPort, defaultPort, errorMessage, }: { + configuredPort?: number; + defaultPort: number; + errorMessage: string; +}) => Promise; +export declare const processOnExit: (fn: any) => void; +export declare const UNLINKED_SITE_MOCK_ID = "unlinked"; +export {}; +//# sourceMappingURL=dev.d.ts.map \ No newline at end of file diff --git a/dist/utils/dev.d.ts.map b/dist/utils/dev.d.ts.map new file mode 100644 index 00000000000..376231cf9d0 --- /dev/null +++ b/dist/utils/dev.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dev.d.ts","sourceRoot":"","sources":["../../src/utils/dev.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAQ9C,OAAO,KAAK,EAAE,oBAAoB,EAAY,MAAM,YAAY,CAAA;AA0ChE,KAAK,UAAU,GAAG,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAA;AAChF,KAAK,YAAY,GAAG,WAAW,CAAC,UAAU,CAAC,cAAc,CAAC,CAAC,GAAG;IAE5D,oBAAoB,CAAC,EACjB;QACE,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;KAC/B,GACD,SAAS,CAAA;CACd,CAAA;AACD,MAAM,MAAM,UAAU,GAAG,MAAM,YAAY,CAAA;AAC3C,MAAM,MAAM,OAAO,GAAG,UAAU,GAAG;IACjC,YAAY,CAAC,EAAE,YAAY,CAAA;CAC5B,CAAA;AAmDD;;;;;;;;GAQG;AAEH,eAAO,MAAM,kBAAkB,GAAU;;;;;CAAgC;;;;;;;;;;;;;;;;;;;;;;;;EAgCxE,CAAA;AAUD;;GAEG;AAEH,eAAO,MAAM,kBAAkB,GAAU;;;;CAAwB,KAAG,OAAO,CAAC,oBAAoB,CAqB/F,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,GAAI,KAAK,oBAAoB,KAAG,IAmC9D,CAAA;AAED,eAAO,MAAM,WAAW,GAAU,gDAI/B;IACD,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,WAAW,EAAE,MAAM,CAAA;IACnB,YAAY,EAAE,MAAM,CAAA;CACrB,oBAMA,CAAA;AAGD,eAAO,MAAM,aAAa,GAAI,OAAE,SAK/B,CAAA;AAED,eAAO,MAAM,qBAAqB,aAAa,CAAA"} \ No newline at end of file diff --git a/dist/utils/dev.js b/dist/utils/dev.js new file mode 100644 index 00000000000..47fd1206c34 --- /dev/null +++ b/dist/utils/dev.js @@ -0,0 +1,192 @@ +import process from 'process'; +import getPort from 'get-port'; +import isEmpty from 'lodash/isEmpty.js'; +import { supportsBackgroundFunctions } from '../lib/account.js'; +import { NETLIFYDEVLOG, chalk, logAndThrowError, log, warn } from './command-helpers.js'; +import { loadDotEnvFiles } from './dot-env.js'; +// Possible sources of environment variables. For the purpose of printing log messages only. Order does not matter. +const ENV_VAR_SOURCES = { + account: { + name: 'shared', + printFn: chalk.magenta, + }, + addons: { + name: 'addon', + printFn: chalk.yellow, + }, + configFile: { + name: 'netlify.toml file', + printFn: chalk.green, + }, + general: { + name: 'general context', + printFn: chalk.italic, + }, + process: { + name: 'process', + printFn: chalk.red, + }, + ui: { + name: 'project settings', + printFn: chalk.blue, + }, +}; +const ERROR_CALL_TO_ACTION = "Double-check your login status with 'netlify status' or contact support with details of your error."; +// @ts-expect-error TS(7031) FIXME: Binding element 'site' implicitly has an 'any' typ... Remove this comment to see the full error message +const validateSiteInfo = ({ site, siteInfo }) => { + if (isEmpty(siteInfo)) { + return logAndThrowError(`Failed to retrieve project information for project ${chalk.yellow(site.id)}. ${ERROR_CALL_TO_ACTION}`); + } +}; +const getAccounts = async ({ api }) => { + try { + const accounts = await api.listAccountsForUser(); + return accounts; + } + catch (error_) { + return logAndThrowError(`Failed retrieving user account: ${error_.message}. ${ERROR_CALL_TO_ACTION}`); + } +}; +// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message +const getAddons = async ({ api, site }) => { + try { + const addons = await api.listServiceInstancesForSite({ siteId: site.id }); + return addons; + } + catch (error_) { + return logAndThrowError(`Failed retrieving addons for site ${chalk.yellow(site.id)}: ${error_.message}. ${ERROR_CALL_TO_ACTION}`); + } +}; +// @ts-expect-error TS(7031) FIXME: Binding element 'addons' implicitly has an 'any' t... Remove this comment to see the full error message +const getAddonsInformation = ({ addons, siteInfo }) => { + const urls = Object.fromEntries( + // @ts-expect-error TS(7006) FIXME: Parameter 'addon' implicitly has an 'any' type. + addons.map((addon) => [addon.service_slug, `${siteInfo.ssl_url}${addon.service_path}`])); + // @ts-expect-error TS(7006) FIXME: Parameter 'addon' implicitly has an 'any' type. + const env = Object.assign({}, ...addons.map((addon) => addon.env)); + return { urls, env }; +}; +const getSiteAccount = ({ accounts, siteInfo }) => { + const siteAccount = accounts.find((account) => account.slug === siteInfo.account_slug); + if (!siteAccount) { + warn(`Could not find account for project '${siteInfo.name}' with account slug '${siteInfo.account_slug}'`); + return undefined; + } + return siteAccount; +}; +// default 10 seconds for synchronous functions +const SYNCHRONOUS_FUNCTION_TIMEOUT = 30; +// default 15 minutes for background functions +const BACKGROUND_FUNCTION_TIMEOUT = 900; +/** + * + * @param {object} config + * @param {boolean} config.offline + * @param {*} config.api + * @param {*} config.site + * @param {*} config.siteInfo + * @returns + */ +// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message +export const getSiteInformation = async ({ api, offline, site, siteInfo }) => { + if (site.id && !offline) { + validateSiteInfo({ site, siteInfo }); + const [accounts, addons] = await Promise.all([getAccounts({ api }), getAddons({ api, site })]); + const { urls: addonsUrls } = getAddonsInformation({ siteInfo, addons }); + const account = getSiteAccount({ siteInfo, accounts }); + return { + addonsUrls, + siteUrl: siteInfo.ssl_url, + accountId: account?.id, + capabilities: { + backgroundFunctions: supportsBackgroundFunctions(account), + }, + timeouts: { + syncFunctions: siteInfo.functions_timeout ?? siteInfo.functions_config?.timeout ?? SYNCHRONOUS_FUNCTION_TIMEOUT, + backgroundFunctions: BACKGROUND_FUNCTION_TIMEOUT, + }, + }; + } + // best defaults we can have without retrieving site information + return { + addonsUrls: {}, + siteUrl: '', + capabilities: {}, + timeouts: { + syncFunctions: SYNCHRONOUS_FUNCTION_TIMEOUT, + backgroundFunctions: BACKGROUND_FUNCTION_TIMEOUT, + }, + }; +}; +// @ts-expect-error TS(7006) FIXME: Parameter 'source' implicitly has an 'any' type. +const getEnvSourceName = (source) => { + // @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message + const { name = source, printFn = chalk.green } = ENV_VAR_SOURCES[source] || {}; + return printFn(name); +}; +/** + * @param {{devConfig: any, env: Record, site: any}} param0 + */ +// @ts-expect-error TS(7031) FIXME: Binding element 'devConfig' implicitly has an 'any... Remove this comment to see the full error message +export const getDotEnvVariables = async ({ devConfig, env, site }) => { + const dotEnvFiles = await loadDotEnvFiles({ envFiles: devConfig.envFiles, projectDir: site.root }); + // @ts-expect-error TS(2339) FIXME: Property 'env' does not exist on type '{ warning: ... Remove this comment to see the full error message + dotEnvFiles.forEach(({ env: fileEnv, file }) => { + const newSourceName = `${file} file`; + Object.keys(fileEnv).forEach((key) => { + const sources = key in env ? [newSourceName, ...env[key].sources] : [newSourceName]; + if (sources.includes('internal')) { + return; + } + env[key] = { + sources, + value: fileEnv[key], + }; + }); + }); + return env; +}; +/** + * Takes a set of environment variables in the format provided by @netlify/config and injects them into `process.env` + */ +export const injectEnvVariables = (env) => { + const envVarsToLogByUsedSource = {}; + for (const [key, variable] of Object.entries(env)) { + const existsInProcess = process.env[key] !== undefined; + const [usedSource, ...overriddenSources] = existsInProcess ? ['process', ...variable.sources] : variable.sources; + const usedSourceName = getEnvSourceName(usedSource); + const isInternal = variable.sources.includes('internal'); + overriddenSources.forEach((source) => { + const sourceName = getEnvSourceName(source); + log(chalk.dim(`${NETLIFYDEVLOG} Ignored ${chalk.bold(sourceName)} env var: ${chalk.yellow(key)} (defined in ${usedSourceName})`)); + }); + if (!existsInProcess || isInternal) { + // Omitting `general` and `internal` env vars to reduce noise in the logs. + if (usedSource !== 'general' && !isInternal) { + envVarsToLogByUsedSource[usedSource] ??= []; + envVarsToLogByUsedSource[usedSource].push(key); + } + process.env[key] = variable.value; + } + } + for (const [source, keys] of Object.entries(envVarsToLogByUsedSource)) { + const sourceName = getEnvSourceName(source); + log(`${NETLIFYDEVLOG} Injected ${sourceName} env vars: ${keys.map((key) => chalk.yellow(key)).join(', ')}`); + } +}; +export const acquirePort = async ({ configuredPort, defaultPort, errorMessage, }) => { + const acquiredPort = await getPort({ port: configuredPort || defaultPort }); + if (configuredPort && acquiredPort !== configuredPort) { + throw new Error(`${errorMessage}: '${configuredPort}'`); + } + return acquiredPort; +}; +// @ts-expect-error TS(7006) FIXME: Parameter 'fn' implicitly has an 'any' type. +export const processOnExit = (fn) => { + const signals = ['SIGINT', 'SIGTERM', 'SIGQUIT', 'SIGHUP', 'exit']; + signals.forEach((signal) => { + process.on(signal, fn); + }); +}; +export const UNLINKED_SITE_MOCK_ID = 'unlinked'; +//# sourceMappingURL=dev.js.map \ No newline at end of file diff --git a/dist/utils/dev.js.map b/dist/utils/dev.js.map new file mode 100644 index 00000000000..941f00932fe --- /dev/null +++ b/dist/utils/dev.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dev.js","sourceRoot":"","sources":["../../src/utils/dev.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/dot-env.d.ts b/dist/utils/dot-env.d.ts new file mode 100644 index 00000000000..2bf2abb182d --- /dev/null +++ b/dist/utils/dot-env.d.ts @@ -0,0 +1,26 @@ +import dotenv from 'dotenv'; +export declare const loadDotEnvFiles: ({ envFiles, projectDir }: { + envFiles: any; + projectDir: any; +}) => Promise<({ + warning: string; + file?: undefined; + env?: undefined; +} | { + file: string; + env: dotenv.DotenvParseOutput; + warning?: undefined; +} | undefined)[]>; +export declare const tryLoadDotEnvFiles: ({ dotenvFiles, projectDir }: { + dotenvFiles?: string[] | undefined; + projectDir: any; +}) => Promise<({ + warning: string; + file?: undefined; + env?: undefined; +} | { + file: string; + env: dotenv.DotenvParseOutput; + warning?: undefined; +} | undefined)[]>; +//# sourceMappingURL=dot-env.d.ts.map \ No newline at end of file diff --git a/dist/utils/dot-env.d.ts.map b/dist/utils/dot-env.d.ts.map new file mode 100644 index 00000000000..ba0aab149f1 --- /dev/null +++ b/dist/utils/dot-env.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"dot-env.d.ts","sourceRoot":"","sources":["../../src/utils/dot-env.ts"],"names":[],"mappings":"AAGA,OAAO,MAAM,MAAM,QAAQ,CAAA;AAO3B,eAAO,MAAM,eAAe,GAAmB;;;CAAwB;;;;;;;;iBAYtE,CAAA;AAMD,eAAO,MAAM,kBAAkB,GAAU;;;CAA6C;;;;;;;;iBAuBrF,CAAA"} \ No newline at end of file diff --git a/dist/utils/dot-env.js b/dist/utils/dot-env.js new file mode 100644 index 00000000000..ef7557ff3b5 --- /dev/null +++ b/dist/utils/dot-env.js @@ -0,0 +1,43 @@ +import { readFile } from 'fs/promises'; +import path from 'path'; +import dotenv from 'dotenv'; +import { isFileAsync } from '../lib/fs.js'; +import { warn } from './command-helpers.js'; +// @ts-expect-error TS(7031) FIXME: Binding element 'envFiles' implicitly has an 'any'... Remove this comment to see the full error message +export const loadDotEnvFiles = async function ({ envFiles, projectDir }) { + const response = await tryLoadDotEnvFiles({ projectDir, dotenvFiles: envFiles }); + // @ts-expect-error TS(2532) FIXME: Object is possibly 'undefined'. + const filesWithWarning = response.filter((el) => el.warning); + filesWithWarning.forEach((el) => { + // @ts-expect-error TS(2532) FIXME: Object is possibly 'undefined'. + warn(el.warning); + }); + // @ts-expect-error TS(2532) FIXME: Object is possibly 'undefined'. + return response.filter((el) => el.file && el.env); +}; +// in the user configuration, the order is highest to lowest +const defaultEnvFiles = ['.env.development.local', '.env.local', '.env.development', '.env']; +// @ts-expect-error TS(7031) FIXME: Binding element 'projectDir' implicitly has an 'an... Remove this comment to see the full error message +export const tryLoadDotEnvFiles = async ({ dotenvFiles = defaultEnvFiles, projectDir }) => { + const results = await Promise.all(dotenvFiles.map(async (file) => { + const filepath = path.resolve(projectDir, file); + try { + const isFile = await isFileAsync(filepath); + if (!isFile) { + return; + } + } + catch (error) { + return { + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + warning: `Failed reading env variables from file: ${filepath}: ${error.message}`, + }; + } + const content = await readFile(filepath, 'utf-8'); + const env = dotenv.parse(content); + return { file, env }; + })); + // we return in order of lowest to highest priority + return results.filter(Boolean).reverse(); +}; +//# sourceMappingURL=dot-env.js.map \ No newline at end of file diff --git a/dist/utils/dot-env.js.map b/dist/utils/dot-env.js.map new file mode 100644 index 00000000000..442fa257d6b --- /dev/null +++ b/dist/utils/dot-env.js.map @@ -0,0 +1 @@ +{"version":3,"file":"dot-env.js","sourceRoot":"","sources":["../../src/utils/dot-env.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,OAAO,MAAM,MAAM,QAAQ,CAAA;AAE3B,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AAE1C,OAAO,EAAE,IAAI,EAAE,MAAM,sBAAsB,CAAA;AAE3C,2IAA2I;AAC3I,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,WAAW,EAAE,QAAQ,EAAE,UAAU,EAAE;IACrE,MAAM,QAAQ,GAAG,MAAM,kBAAkB,CAAC,EAAE,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAA;IAEhF,mEAAmE;IACnE,MAAM,gBAAgB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,CAAA;IAC5D,gBAAgB,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE;QAC9B,mEAAmE;QACnE,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,CAAA;IAClB,CAAC,CAAC,CAAA;IAEF,mEAAmE;IACnE,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,CAAC,CAAA;AACnD,CAAC,CAAA;AAED,4DAA4D;AAC5D,MAAM,eAAe,GAAG,CAAC,wBAAwB,EAAE,YAAY,EAAE,kBAAkB,EAAE,MAAM,CAAC,CAAA;AAE5F,2IAA2I;AAC3I,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EAAE,EAAE,WAAW,GAAG,eAAe,EAAE,UAAU,EAAE,EAAE,EAAE;IACxF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,GAAG,CAC/B,WAAW,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE;QAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,IAAI,CAAC,CAAA;QAC/C,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,WAAW,CAAC,QAAQ,CAAC,CAAA;YAC1C,IAAI,CAAC,MAAM,EAAE,CAAC;gBACZ,OAAM;YACR,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO;gBACL,gEAAgE;gBAChE,OAAO,EAAE,2CAA2C,QAAQ,KAAK,KAAK,CAAC,OAAO,EAAE;aACjF,CAAA;QACH,CAAC;QACD,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAA;QACjD,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;QACjC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,CAAA;IACtB,CAAC,CAAC,CACH,CAAA;IAED,mDAAmD;IACnD,OAAO,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAA;AAC1C,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/env/index.d.ts b/dist/utils/env/index.d.ts new file mode 100644 index 00000000000..599674cb774 --- /dev/null +++ b/dist/utils/env/index.d.ts @@ -0,0 +1,164 @@ +import type { NetlifyAPI } from '@netlify/api'; +import type { SiteInfo, EnvironmentVariableSource } from '../../utils/types.js'; +/** + * Supported values for the user-provided env `context` option. + * These all match possible `context` values returned by the Envelope API. + * Note that a user may also specify a branch name with the special `branch:my-branch-name` format. + */ +export declare const SUPPORTED_CONTEXTS: readonly ["all", "production", "deploy-preview", "branch-deploy", "dev"]; +/** + * Supported values for the user-provided env `scope` option. + * These exactly match possible `scope` values returned by the Envelope API. + * Note that `any` is also supported. + */ +export declare const ALL_ENVELOPE_SCOPES: readonly ["builds", "functions", "runtime", "post_processing"]; +type EnvelopeEnvVarScope = Exclude>[number]['scopes']>[number], 'post-processing'> | 'post_processing'; +type EnvelopeEnvVar = Awaited>[number] & { + scopes: EnvelopeEnvVarScope[]; +}; +type EnvelopeEnvVarContext = NonNullable[number]['context']>; +export type EnvelopeEnvVarValue = { + /** + * The deploy context of the this env var value + */ + context?: EnvelopeEnvVarContext; + /** + * For parameterized contexts (i.e. only `branch`), context parameter (i.e. the branch name) + */ + context_parameter?: string | undefined; + /** + * The value of the environment variable for this context. Note that this appears to be an empty string + * when the env var is not set for this context. + */ + value?: string | undefined; +}; +export type EnvelopeItem = { + key: string; + scopes: EnvelopeEnvVarScope[]; + values: EnvelopeEnvVarValue[]; +}; +type SupportedScope = EnvelopeEnvVarScope | 'post_processing' | 'any'; +type ContextOrBranch = string; +/** + * Normalizes a user-provided "context". Note that this may be the special `branch:my-branch-name` format. + * + * - If this is a supported alias of a context, it will be normalized to the canonical context. + * - Valid canonical contexts are returned as is. + * - If this starts with `branch:`, it will be normalized to the branch name. + * + * @param context A user-provided context, context alias, or a string in the `branch:my-branch-name` format. + * + * @returns The normalized context name or just the branch name + */ +export declare const normalizeContext: (context: string) => ContextOrBranch; +/** + * Finds a matching environment variable value for a given context + * @private + */ +export declare const getValueForContext: ( +/** + * An array of environment variable values from Envelope + */ +values: EnvelopeEnvVarValue[], +/** + * The deploy context or branch of the environment variable value + */ +contextOrBranch: ContextOrBranch) => EnvelopeEnvVarValue | undefined; +/** + * Finds environment variables that match a given source + * @param env - The dictionary of environment variables + * @param source - The source of the environment variable + * @returns The dictionary of env vars that match the given source + */ +export declare const filterEnvBySource: (env: object, source: EnvironmentVariableSource) => typeof env; +/** + * Filters and sorts data from Envelope by a given context and/or scope + * @param context - The deploy context or branch of the environment variable value + * @param envelopeItems - An array of environment variables from the Envelope service + * @param scope - The scope of the environment variables + * @param source - The source of the environment variable + * @returns A dicionary in the following format: + * { + * FOO: { + * context: 'dev', + * scopes: ['builds', 'functions'], + * sources: ['ui'], + * value: 'bar', + * }, + * BAZ: { + * context: 'branch', + * branch: 'staging', + * scopes: ['runtime'], + * sources: ['account'], + * value: 'bang', + * }, + * } + */ +export declare const formatEnvelopeData: ({ context, envelopeItems, scope, source, }: { + context?: ContextOrBranch; + envelopeItems: EnvelopeItem[]; + scope?: SupportedScope; + source: string; +}) => Record; +/** + * Collects env vars from multiple sources and arranges them in the correct order of precedence + * @param opts.api The api singleton object + * @param opts.context The deploy context or branch of the environment variable + * @param opts.env The dictionary of environment variables + * @param opts.key If present, fetch a single key (case-sensitive) + * @param opts.raw Return a dictionary of raw key/value pairs for only the account and site sources + * @param opts.scope The scope of the environment variables + * @param opts.siteInfo The site object + * @returns An object of environment variables keys and their metadata + */ +export declare const getEnvelopeEnv: ({ api, context, env, key, raw, scope, siteInfo, }: { + api: NetlifyAPI; + context?: ContextOrBranch | undefined; + env: object; + key?: string | undefined; + raw?: boolean | undefined; + scope?: SupportedScope | undefined; + siteInfo: SiteInfo; +}) => Promise<{}>; +/** + * Returns a human-readable, comma-separated list of scopes + * @param scopes An array of scopes + * @returns A human-readable, comma-separated list of scopes + */ +export declare const getHumanReadableScopes: (scopes?: EnvelopeEnvVarScope[]) => string; +/** + * Translates a Mongo env into an Envelope env + * @param env The site's env as it exists in Mongo + * @returns The array of Envelope env vars + */ +export declare const translateFromMongoToEnvelope: (env?: Record) => { + key: string; + scopes: readonly ["builds", "functions", "runtime", "post_processing"]; + values: { + context: "all"; + value: string; + }[]; +}[]; +/** + * Translates an Envelope env into a Mongo env + * @param envVars The array of Envelope env vars + * @param context The deploy context or branch of the environment variable + * @returns The env object as compatible with Mongo + */ +export declare const translateFromEnvelopeToMongo: (envVars?: { + key: string; + scopes: string[]; + values: { + context: string; + value: string; + context_parameter?: string | undefined; + }[]; +}[], context?: string) => {}; +export {}; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/utils/env/index.d.ts.map b/dist/utils/env/index.d.ts.map new file mode 100644 index 00000000000..08669034123 --- /dev/null +++ b/dist/utils/env/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/env/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/env/index.js b/dist/utils/env/index.js new file mode 100644 index 00000000000..2f3225ee01d --- /dev/null +++ b/dist/utils/env/index.js @@ -0,0 +1,254 @@ +import { logAndThrowError } from '../command-helpers.js'; +/** + * Supported values for the user-provided env `context` option. + * These all match possible `context` values returned by the Envelope API. + * Note that a user may also specify a branch name with the special `branch:my-branch-name` format. + */ +export const SUPPORTED_CONTEXTS = ['all', 'production', 'deploy-preview', 'branch-deploy', 'dev']; +/** + * Additional aliases for the user-provided env `context` option. + */ +const SUPPORTED_CONTEXT_ALIASES = { + dp: 'deploy-preview', + prod: 'production', +}; +/** + * Supported values for the user-provided env `scope` option. + * These exactly match possible `scope` values returned by the Envelope API. + * Note that `any` is also supported. + */ +export const ALL_ENVELOPE_SCOPES = ['builds', 'functions', 'runtime', 'post_processing']; +/** + * Normalizes a user-provided "context". Note that this may be the special `branch:my-branch-name` format. + * + * - If this is a supported alias of a context, it will be normalized to the canonical context. + * - Valid canonical contexts are returned as is. + * - If this starts with `branch:`, it will be normalized to the branch name. + * + * @param context A user-provided context, context alias, or a string in the `branch:my-branch-name` format. + * + * @returns The normalized context name or just the branch name + */ +export const normalizeContext = (context) => { + if (!context) { + return context; + } + context = context.toLowerCase(); + if (context in SUPPORTED_CONTEXT_ALIASES) { + context = SUPPORTED_CONTEXT_ALIASES[context]; + } + const forbiddenContexts = SUPPORTED_CONTEXTS.map((ctx) => `branch:${ctx}`); + if (forbiddenContexts.includes(context)) { + return logAndThrowError(`The context ${context} includes a reserved keyword and is not allowed`); + } + return context.replace(/^branch:/, ''); +}; +/** + * Finds a matching environment variable value for a given context + * @private + */ +export const getValueForContext = ( +/** + * An array of environment variable values from Envelope + */ +values, +/** + * The deploy context or branch of the environment variable value + */ +contextOrBranch) => { + const isSupportedContext = SUPPORTED_CONTEXTS.includes(contextOrBranch); + if (!isSupportedContext) { + const valueMatchingAsBranch = values.find((val) => val.context_parameter === contextOrBranch); + // This is a `branch` context, which is an override, so it takes precedence + if (valueMatchingAsBranch != null) { + return valueMatchingAsBranch; + } + const valueMatchingContext = values.find((val) => val.context === 'all' || val.context === 'branch-deploy'); + return valueMatchingContext ?? undefined; + } + const valueMatchingAsContext = values.find((val) => val.context === 'all' || val.context === contextOrBranch); + return valueMatchingAsContext ?? undefined; +}; +/** + * Finds environment variables that match a given source + * @param env - The dictionary of environment variables + * @param source - The source of the environment variable + * @returns The dictionary of env vars that match the given source + */ +export const filterEnvBySource = (env, source) => Object.fromEntries(Object.entries(env).filter(([, variable]) => variable.sources[0] === source)); +const fetchEnvelopeItems = async function ({ accountId, api, key, siteId, }) { + if (accountId === undefined) { + return []; + } + try { + // if a single key is passed, fetch that single env var + if (key) { + const envelopeItem = await api.getEnvVar({ accountId, key, siteId }); + // See FIXME(serhalp) above + return [envelopeItem]; + } + // otherwise, fetch the entire list of env vars + const envelopeItems = await api.getEnvVars({ accountId, siteId }); + // See FIXME(serhalp) above + return envelopeItems; + } + catch { + // Collaborators aren't allowed to read shared env vars, + // so return an empty array silently in that case + return []; + } +}; +/** + * Filters and sorts data from Envelope by a given context and/or scope + * @param context - The deploy context or branch of the environment variable value + * @param envelopeItems - An array of environment variables from the Envelope service + * @param scope - The scope of the environment variables + * @param source - The source of the environment variable + * @returns A dicionary in the following format: + * { + * FOO: { + * context: 'dev', + * scopes: ['builds', 'functions'], + * sources: ['ui'], + * value: 'bar', + * }, + * BAZ: { + * context: 'branch', + * branch: 'staging', + * scopes: ['runtime'], + * sources: ['account'], + * value: 'bang', + * }, + * } + */ +export const formatEnvelopeData = ({ context = 'dev', envelopeItems = [], scope = 'any', source, }) => envelopeItems + // filter by context + .filter(({ values }) => Boolean(getValueForContext(values, context))) + // filter by scope + .filter(({ scopes }) => (scope === 'any' ? true : scopes.includes(scope))) + // sort alphabetically, case insensitive + .sort((left, right) => (left.key.toLowerCase() < right.key.toLowerCase() ? -1 : 1)) + // format the data + .reduce((acc, cur) => { + const val = getValueForContext(cur.values, context); + if (val === undefined) { + throw new TypeError(`failed to locate environment variable value for ${context} context`); + } + const { context: itemContext, context_parameter: branch, value } = val; + return { + ...acc, + [cur.key]: { + context: itemContext, + branch, + scopes: cur.scopes, + sources: [source], + value, + }, + }; +}, {}); +/** + * Collects env vars from multiple sources and arranges them in the correct order of precedence + * @param opts.api The api singleton object + * @param opts.context The deploy context or branch of the environment variable + * @param opts.env The dictionary of environment variables + * @param opts.key If present, fetch a single key (case-sensitive) + * @param opts.raw Return a dictionary of raw key/value pairs for only the account and site sources + * @param opts.scope The scope of the environment variables + * @param opts.siteInfo The site object + * @returns An object of environment variables keys and their metadata + */ +export const getEnvelopeEnv = async ({ api, context = 'dev', env, key = '', raw = false, scope = 'any', siteInfo, }) => { + const { account_slug: accountId, id: siteId } = siteInfo; + const [accountEnvelopeItems, siteEnvelopeItems] = await Promise.all([ + fetchEnvelopeItems({ api, accountId, key }), + fetchEnvelopeItems({ api, accountId, key, siteId }), + ]); + const accountEnv = formatEnvelopeData({ context, envelopeItems: accountEnvelopeItems, scope, source: 'account' }); + const siteEnv = formatEnvelopeData({ context, envelopeItems: siteEnvelopeItems, scope, source: 'ui' }); + if (raw) { + const entries = Object.entries({ ...accountEnv, ...siteEnv }); + return entries.reduce((obj, [envVarKey, metadata]) => ({ + ...obj, + [envVarKey]: metadata.value, + }), {}); + } + const generalEnv = filterEnvBySource(env, 'general'); + const internalEnv = filterEnvBySource(env, 'internal'); + const addonsEnv = filterEnvBySource(env, 'addons'); + const configFileEnv = filterEnvBySource(env, 'configFile'); + // filter out configFile env vars if a non-configFile scope is passed + const includeConfigEnvVars = /any|builds|post[-_]processing/.test(scope); + // Sources of environment variables, in ascending order of precedence. + return { + ...generalEnv, + ...accountEnv, + ...(includeConfigEnvVars ? addonsEnv : {}), + ...siteEnv, + ...(includeConfigEnvVars ? configFileEnv : {}), + ...internalEnv, + }; +}; +/** + * Returns a human-readable, comma-separated list of scopes + * @param scopes An array of scopes + * @returns A human-readable, comma-separated list of scopes + */ +export const getHumanReadableScopes = (scopes) => { + const HUMAN_SCOPES = ['Builds', 'Functions', 'Runtime', 'Post processing']; + const SCOPES_MAP = { + builds: HUMAN_SCOPES[0], + functions: HUMAN_SCOPES[1], + runtime: HUMAN_SCOPES[2], + post_processing: HUMAN_SCOPES[3], + // TODO(serhalp) I believe this isn't needed, as `post-processing` is a user-provided + // CLI option, not a scope returned by the Envelope API. + 'post-processing': HUMAN_SCOPES[3], + }; + if (!scopes) { + // if `scopes` is not available, the env var comes from netlify.toml + // env vars specified in netlify.toml are present in the `builds` and `post_processing` scope + return 'Builds, Post processing'; + } + if (scopes.length === Object.keys(HUMAN_SCOPES).length) { + // shorthand instead of listing every available scope + return 'All'; + } + return scopes.map((scope) => SCOPES_MAP[scope]).join(', '); +}; +/** + * Translates a Mongo env into an Envelope env + * @param env The site's env as it exists in Mongo + * @returns The array of Envelope env vars + */ +export const translateFromMongoToEnvelope = (env = {}) => { + const envVars = Object.entries(env).map(([key, value]) => ({ + key, + scopes: ALL_ENVELOPE_SCOPES, + values: [ + { + context: 'all', + value, + }, + ], + })); + return envVars; +}; +/** + * Translates an Envelope env into a Mongo env + * @param envVars The array of Envelope env vars + * @param context The deploy context or branch of the environment variable + * @returns The env object as compatible with Mongo + */ +export const translateFromEnvelopeToMongo = (envVars = [], context = 'dev') => envVars + .sort((a, b) => (a.key.toLowerCase() < b.key.toLowerCase() ? -1 : 1)) + .reduce((acc, cur) => { + const envVar = cur.values.find((val) => [context, 'all'].includes((val.context_parameter ?? '') || val.context)); + if (envVar && envVar.value) { + return { + ...acc, + [cur.key]: envVar.value, + }; + } + return acc; +}, {}); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/utils/env/index.js.map b/dist/utils/env/index.js.map new file mode 100644 index 00000000000..3e067d681e7 --- /dev/null +++ b/dist/utils/env/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/env/index.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/execa.d.ts b/dist/utils/execa.d.ts new file mode 100644 index 00000000000..d7cd14641ab --- /dev/null +++ b/dist/utils/execa.d.ts @@ -0,0 +1,4 @@ +import execaLib from 'execa'; +declare let execa: typeof execaLib; +export default execa; +//# sourceMappingURL=execa.d.ts.map \ No newline at end of file diff --git a/dist/utils/execa.d.ts.map b/dist/utils/execa.d.ts.map new file mode 100644 index 00000000000..d32c99d9c5f --- /dev/null +++ b/dist/utils/execa.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"execa.d.ts","sourceRoot":"","sources":["../../src/utils/execa.ts"],"names":[],"mappings":"AAEA,OAAO,QAAQ,MAAM,OAAO,CAAA;AAM5B,QAAA,IAAI,KAAK,EAAE,OAAO,QAAQ,CAAA;AAS1B,eAAe,KAAK,CAAA"} \ No newline at end of file diff --git a/dist/utils/execa.js b/dist/utils/execa.js new file mode 100644 index 00000000000..47e69ca9690 --- /dev/null +++ b/dist/utils/execa.js @@ -0,0 +1,15 @@ +import { env } from 'process'; +import execaLib from 'execa'; +// This is a thin layer on top of `execa` that allows consumers to provide an +// alternative path to the module location, making it easier to mock its logic +// in tests (see `tests/integration/utils/mock-execa.ts`). +let execa; +if (env.NETLIFY_CLI_EXECA_PATH) { + const execaMock = await import(env.NETLIFY_CLI_EXECA_PATH); + execa = execaMock.default; +} +else { + execa = execaLib; +} +export default execa; +//# sourceMappingURL=execa.js.map \ No newline at end of file diff --git a/dist/utils/execa.js.map b/dist/utils/execa.js.map new file mode 100644 index 00000000000..1770785a73f --- /dev/null +++ b/dist/utils/execa.js.map @@ -0,0 +1 @@ +{"version":3,"file":"execa.js","sourceRoot":"","sources":["../../src/utils/execa.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,SAAS,CAAA;AAE7B,OAAO,QAAQ,MAAM,OAAO,CAAA;AAE5B,6EAA6E;AAC7E,8EAA8E;AAC9E,0DAA0D;AAE1D,IAAI,KAAsB,CAAA;AAE1B,IAAI,GAAG,CAAC,sBAAsB,EAAE,CAAC;IAC/B,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,GAAG,CAAC,sBAAsB,CAAC,CAAA;IAC1D,KAAK,GAAG,SAAS,CAAC,OAAO,CAAA;AAC3B,CAAC;KAAM,CAAC;IACN,KAAK,GAAG,QAAQ,CAAA;AAClB,CAAC;AAED,eAAe,KAAK,CAAA"} \ No newline at end of file diff --git a/dist/utils/feature-flags.d.ts b/dist/utils/feature-flags.d.ts new file mode 100644 index 00000000000..f5ba8300a17 --- /dev/null +++ b/dist/utils/feature-flags.d.ts @@ -0,0 +1,20 @@ +/** + * Allows us to check if a feature flag is enabled for a site. + * Due to versioning of the cli, and the desire to remove flags from + * our feature flag service when they should always evaluate to true, + * we can't just look for the presense of {featureFlagName: true}, as + * the absense of a flag should also evaluate to the flag being enabled. + * Instead, we return that the feature flag is enabled if it isn't + * specifically set to false in the response + */ +export declare const isFeatureFlagEnabled: (flagName: string, siteInfo: { + feature_flags?: Record | undefined; +}) => boolean; +/** + * Retrieves all Feature flags from the siteInfo + */ +export declare const getFeatureFlagsFromSiteInfo: (siteInfo: { + feature_flags?: Record | undefined; +}) => FeatureFlags; +export type FeatureFlags = Record; +//# sourceMappingURL=feature-flags.d.ts.map \ No newline at end of file diff --git a/dist/utils/feature-flags.d.ts.map b/dist/utils/feature-flags.d.ts.map new file mode 100644 index 00000000000..c8ae7cc47a0 --- /dev/null +++ b/dist/utils/feature-flags.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"feature-flags.d.ts","sourceRoot":"","sources":["../../src/utils/feature-flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB,GAC/B,UAAU,MAAM,EAChB,UAAU;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,SAAS,CAAA;CAAE,KACzE,OAAwF,CAAA;AAE3F;;GAEG;AACH,eAAO,MAAM,2BAA2B,GAAI,UAAU;IACpD,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,GAAG,SAAS,CAAA;CAC7D,KAAG,YAMF,CAAA;AAEF,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/feature-flags.js b/dist/utils/feature-flags.js new file mode 100644 index 00000000000..4abd8b1bb48 --- /dev/null +++ b/dist/utils/feature-flags.js @@ -0,0 +1,21 @@ +/** + * Allows us to check if a feature flag is enabled for a site. + * Due to versioning of the cli, and the desire to remove flags from + * our feature flag service when they should always evaluate to true, + * we can't just look for the presense of {featureFlagName: true}, as + * the absense of a flag should also evaluate to the flag being enabled. + * Instead, we return that the feature flag is enabled if it isn't + * specifically set to false in the response + */ +export const isFeatureFlagEnabled = (flagName, siteInfo) => Boolean(siteInfo.feature_flags && siteInfo.feature_flags[flagName] !== false); +/** + * Retrieves all Feature flags from the siteInfo + */ +export const getFeatureFlagsFromSiteInfo = (siteInfo) => ({ + ...siteInfo.feature_flags, + // see https://github.com/netlify/pod-dev-foundations/issues/581#issuecomment-1731022753 + zisi_golang_use_al2: isFeatureFlagEnabled('cli_golang_use_al2', siteInfo), + netlify_build_frameworks_api: true, + project_ceruledge_ui: true, +}); +//# sourceMappingURL=feature-flags.js.map \ No newline at end of file diff --git a/dist/utils/feature-flags.js.map b/dist/utils/feature-flags.js.map new file mode 100644 index 00000000000..422a2681b9f --- /dev/null +++ b/dist/utils/feature-flags.js.map @@ -0,0 +1 @@ +{"version":3,"file":"feature-flags.js","sourceRoot":"","sources":["../../src/utils/feature-flags.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,QAAgB,EAChB,QAA0E,EACjE,EAAE,CAAC,OAAO,CAAC,QAAQ,CAAC,aAAa,IAAI,QAAQ,CAAC,aAAa,CAAC,QAAQ,CAAC,KAAK,KAAK,CAAC,CAAA;AAE3F;;GAEG;AACH,MAAM,CAAC,MAAM,2BAA2B,GAAG,CAAC,QAE3C,EAAgB,EAAE,CAAC,CAAC;IACnB,GAAG,QAAQ,CAAC,aAAa;IACzB,wFAAwF;IACxF,mBAAmB,EAAE,oBAAoB,CAAC,oBAAoB,EAAE,QAAQ,CAAC;IACzE,4BAA4B,EAAE,IAAI;IAClC,oBAAoB,EAAE,IAAI;CAC3B,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/framework-server.d.ts b/dist/utils/framework-server.d.ts new file mode 100644 index 00000000000..2715dde1797 --- /dev/null +++ b/dist/utils/framework-server.d.ts @@ -0,0 +1,13 @@ +import type { ServerSettings } from './types.js'; +interface StartReturnObject { + ipVersion?: 4 | 6; +} +/** + * Start a static server if the `useStaticServer` is provided or a framework specific server + */ +export declare const startFrameworkServer: ({ cwd, settings, }: { + cwd: string; + settings: ServerSettings; +}) => Promise; +export {}; +//# sourceMappingURL=framework-server.d.ts.map \ No newline at end of file diff --git a/dist/utils/framework-server.d.ts.map b/dist/utils/framework-server.d.ts.map new file mode 100644 index 00000000000..99e402194b1 --- /dev/null +++ b/dist/utils/framework-server.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"framework-server.d.ts","sourceRoot":"","sources":["../../src/utils/framework-server.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAKhD,UAAU,iBAAiB;IACzB,SAAS,CAAC,EAAE,CAAC,GAAG,CAAC,CAAA;CAClB;AAED;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAmB,oBAGjD;IACD,GAAG,EAAE,MAAM,CAAA;IACX,QAAQ,EAAE,cAAc,CAAA;CACzB,KAAG,OAAO,CAAC,iBAAiB,CA0E5B,CAAA"} \ No newline at end of file diff --git a/dist/utils/framework-server.js b/dist/utils/framework-server.js new file mode 100644 index 00000000000..2442b1a6bdd --- /dev/null +++ b/dist/utils/framework-server.js @@ -0,0 +1,71 @@ +import { rm } from 'node:fs/promises'; +import waitPort from 'wait-port'; +import { startSpinner, stopSpinner } from '../lib/spinner.js'; +import { logAndThrowError, log, NETLIFYDEVERR, NETLIFYDEVLOG, chalk } from './command-helpers.js'; +import { runCommand } from './shell.js'; +import { startStaticServer } from './static-server.js'; +const FRAMEWORK_PORT_TIMEOUT_MS = 10 * 60 * 1000; +const FRAMEWORK_PORT_WARN_TIMEOUT_MS = 5 * 1000; +/** + * Start a static server if the `useStaticServer` is provided or a framework specific server + */ +export const startFrameworkServer = async function ({ cwd, settings, }) { + if (settings.useStaticServer) { + if (settings.command) { + runCommand(settings.command, { env: settings.env, cwd }); + } + const { family } = await startStaticServer({ settings }); + return { ipVersion: family === 'IPv6' ? 6 : 4 }; + } + log(''); + log(`${NETLIFYDEVLOG} Starting ${settings.framework || 'framework'} dev server`); + const spinner = startSpinner({ + text: `Waiting for ${settings.framework || 'framework'} dev server to be ready on port ${settings.frameworkPort}`, + }); + if (settings.clearPublishDirectory && settings.dist) { + await rm(settings.dist, { recursive: true, force: true }); + } + if (settings.command) { + runCommand(settings.command, { env: settings.env, spinner, cwd }); + } + let port; + try { + if (settings.skipWaitPort) { + // default ip version based on node version + const ipVersion = parseInt(process.versions.node.split('.')[0]) >= 18 ? 6 : 4; + port = { open: true, ipVersion }; + } + else { + const waitPortPromise = waitPort({ + // eslint-disable-next-line @typescript-eslint/no-non-null-assertion + port: settings.frameworkPort, + host: 'localhost', + output: 'silent', + timeout: FRAMEWORK_PORT_TIMEOUT_MS, + ...(settings.pollingStrategies?.includes('HTTP') && { protocol: 'http' }), + }); + const timerId = setTimeout(() => { + if (!port?.open) { + spinner.update({ + text: `Still waiting for server on port ${settings.frameworkPort} to be ready. Are you sure this is the correct port${settings.framework ? ` for ${settings.framework}` : ''}? Change this with the ${chalk.yellow('targetPort')} option in your ${chalk.yellow('netlify.toml')}.`, + }); + } + }, FRAMEWORK_PORT_WARN_TIMEOUT_MS); + port = await waitPortPromise; + clearTimeout(timerId); + if (!port.open) { + throw new Error(`Timed out waiting for port '${settings.frameworkPort}' to be open`); + } + } + spinner.success(`${settings.framework || 'framework'} dev server ready on port ${settings.frameworkPort}`); + } + catch (error_) { + stopSpinner({ error: true, spinner }); + log(NETLIFYDEVERR, `Netlify Dev could not start or connect to localhost:${settings.frameworkPort}.`); + log(NETLIFYDEVERR, `Please make sure your framework server is running on port ${settings.frameworkPort}`); + log(NETLIFYDEVERR, `If not, you can configure it using the ${chalk.yellow('targetPort')} option in your ${chalk.yellow('netlify.toml')}.`); + return logAndThrowError(error_); + } + return { ipVersion: port.ipVersion }; +}; +//# sourceMappingURL=framework-server.js.map \ No newline at end of file diff --git a/dist/utils/framework-server.js.map b/dist/utils/framework-server.js.map new file mode 100644 index 00000000000..75267eeda1a --- /dev/null +++ b/dist/utils/framework-server.js.map @@ -0,0 +1 @@ +{"version":3,"file":"framework-server.js","sourceRoot":"","sources":["../../src/utils/framework-server.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/frameworks-api.d.ts b/dist/utils/frameworks-api.d.ts new file mode 100644 index 00000000000..498afcb37fd --- /dev/null +++ b/dist/utils/frameworks-api.d.ts @@ -0,0 +1,20 @@ +import type { NetlifyOptions } from '../commands/types.js'; +interface FrameworksAPIPath { + path: string; + ensureExists: () => Promise; + exists: () => Promise; +} +export type FrameworksAPIPaths = ReturnType; +/** + * Returns an object containing the paths for all the operations of the + * Frameworks API. Each key maps to an object containing a `path` property with + * the path of the operation, an `exists` method that returns whether the path + * exists, and an `ensureExists` method that creates it in case it doesn't. + */ +export declare const getFrameworksAPIPaths: (basePath: string, packagePath?: string) => Record<"config" | "functions" | "blobs" | "root" | "edgeFunctions" | "edgeFunctionsImportMap", FrameworksAPIPath>; +/** + * Merges a config object with any config options from the Frameworks API. + */ +export declare const getFrameworksAPIConfig: (config: NetlifyOptions["config"], frameworksAPIConfigPath: string) => Promise; +export {}; +//# sourceMappingURL=frameworks-api.d.ts.map \ No newline at end of file diff --git a/dist/utils/frameworks-api.d.ts.map b/dist/utils/frameworks-api.d.ts.map new file mode 100644 index 00000000000..5cee8a3dfc6 --- /dev/null +++ b/dist/utils/frameworks-api.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"frameworks-api.d.ts","sourceRoot":"","sources":["../../src/utils/frameworks-api.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAE1D,UAAU,iBAAiB;IACzB,IAAI,EAAE,MAAM,CAAA;IACZ,YAAY,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;IACjC,MAAM,EAAE,MAAM,OAAO,CAAC,OAAO,CAAC,CAAA;CAC/B;AAED,MAAM,MAAM,kBAAkB,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAA;AAEzE;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAAI,UAAU,MAAM,EAAE,cAAc,MAAM,sHAiC3E,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,sBAAsB,GAAU,QAAQ,cAAc,CAAC,QAAQ,CAAC,EAAE,yBAAyB,MAAM,yEAY7G,CAAA"} \ No newline at end of file diff --git a/dist/utils/frameworks-api.js b/dist/utils/frameworks-api.js new file mode 100644 index 00000000000..129859ac631 --- /dev/null +++ b/dist/utils/frameworks-api.js @@ -0,0 +1,54 @@ +import { access, mkdir, readFile } from 'node:fs/promises'; +import { resolve } from 'node:path'; +import { mergeConfigs } from '@netlify/config'; +/** + * Returns an object containing the paths for all the operations of the + * Frameworks API. Each key maps to an object containing a `path` property with + * the path of the operation, an `exists` method that returns whether the path + * exists, and an `ensureExists` method that creates it in case it doesn't. + */ +export const getFrameworksAPIPaths = (basePath, packagePath) => { + const root = resolve(basePath, packagePath || '', '.netlify/v1'); + const edgeFunctions = resolve(root, 'edge-functions'); + const paths = { + root, + config: resolve(root, 'config.json'), + functions: resolve(root, 'functions'), + edgeFunctions, + edgeFunctionsImportMap: resolve(edgeFunctions, 'import_map.json'), + blobs: resolve(root, 'blobs'), + }; + return Object.entries(paths).reduce((acc, [name, path]) => ({ + ...acc, + [name]: { + path, + ensureExists: async () => { + await mkdir(path, { recursive: true }); + }, + exists: async () => { + try { + await access(path); + return true; + } + catch { + return false; + } + }, + }, + }), {}); +}; +/** + * Merges a config object with any config options from the Frameworks API. + */ +export const getFrameworksAPIConfig = async (config, frameworksAPIConfigPath) => { + let frameworksAPIConfigFile; + try { + frameworksAPIConfigFile = await readFile(frameworksAPIConfigPath, 'utf8'); + } + catch { + return config; + } + const frameworksAPIConfig = JSON.parse(frameworksAPIConfigFile); + return mergeConfigs([frameworksAPIConfig, config], { concatenateArrays: true }); +}; +//# sourceMappingURL=frameworks-api.js.map \ No newline at end of file diff --git a/dist/utils/frameworks-api.js.map b/dist/utils/frameworks-api.js.map new file mode 100644 index 00000000000..e0644f61747 --- /dev/null +++ b/dist/utils/frameworks-api.js.map @@ -0,0 +1 @@ +{"version":3,"file":"frameworks-api.js","sourceRoot":"","sources":["../../src/utils/frameworks-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAEnC,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAY9C;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,QAAgB,EAAE,WAAoB,EAAE,EAAE;IAC9E,MAAM,IAAI,GAAG,OAAO,CAAC,QAAQ,EAAE,WAAW,IAAI,EAAE,EAAE,aAAa,CAAC,CAAA;IAChE,MAAM,aAAa,GAAG,OAAO,CAAC,IAAI,EAAE,gBAAgB,CAAC,CAAA;IACrD,MAAM,KAAK,GAAG;QACZ,IAAI;QACJ,MAAM,EAAE,OAAO,CAAC,IAAI,EAAE,aAAa,CAAC;QACpC,SAAS,EAAE,OAAO,CAAC,IAAI,EAAE,WAAW,CAAC;QACrC,aAAa;QACb,sBAAsB,EAAE,OAAO,CAAC,aAAa,EAAE,iBAAiB,CAAC;QACjE,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC;KAC9B,CAAA;IAED,OAAO,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,MAAM,CACjC,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC;QACtB,GAAG,GAAG;QACN,CAAC,IAAI,CAAC,EAAE;YACN,IAAI;YACJ,YAAY,EAAE,KAAK,IAAI,EAAE;gBACvB,MAAM,KAAK,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;YACxC,CAAC;YACD,MAAM,EAAE,KAAK,IAAI,EAAE;gBACjB,IAAI,CAAC;oBACH,MAAM,MAAM,CAAC,IAAI,CAAC,CAAA;oBAElB,OAAO,IAAI,CAAA;gBACb,CAAC;gBAAC,MAAM,CAAC;oBACP,OAAO,KAAK,CAAA;gBACd,CAAC;YACH,CAAC;SACF;KACF,CAAC,EACF,EAAmD,CACpD,CAAA;AACH,CAAC,CAAA;AAED;;GAEG;AACH,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,EAAE,MAAgC,EAAE,uBAA+B,EAAE,EAAE;IAChH,IAAI,uBAA2C,CAAA;IAE/C,IAAI,CAAC;QACH,uBAAuB,GAAG,MAAM,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC,CAAA;IAC3E,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,MAAM,CAAA;IACf,CAAC;IAED,MAAM,mBAAmB,GAAG,IAAI,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAA;IAE/D,OAAO,YAAY,CAAC,CAAC,mBAAmB,EAAE,MAAM,CAAC,EAAE,EAAE,iBAAiB,EAAE,IAAI,EAAE,CAA6B,CAAA;AAC7G,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/functions/constants.d.ts b/dist/utils/functions/constants.d.ts new file mode 100644 index 00000000000..08f8ef33fd6 --- /dev/null +++ b/dist/utils/functions/constants.d.ts @@ -0,0 +1,2 @@ +export declare const CLOCKWORK_USERAGENT = "Netlify Clockwork"; +//# sourceMappingURL=constants.d.ts.map \ No newline at end of file diff --git a/dist/utils/functions/constants.d.ts.map b/dist/utils/functions/constants.d.ts.map new file mode 100644 index 00000000000..8c59bc7af53 --- /dev/null +++ b/dist/utils/functions/constants.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../../src/utils/functions/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,mBAAmB,sBAAsB,CAAA"} \ No newline at end of file diff --git a/dist/utils/functions/constants.js b/dist/utils/functions/constants.js new file mode 100644 index 00000000000..882c00fbfb2 --- /dev/null +++ b/dist/utils/functions/constants.js @@ -0,0 +1,2 @@ +export const CLOCKWORK_USERAGENT = 'Netlify Clockwork'; +//# sourceMappingURL=constants.js.map \ No newline at end of file diff --git a/dist/utils/functions/constants.js.map b/dist/utils/functions/constants.js.map new file mode 100644 index 00000000000..958a29be608 --- /dev/null +++ b/dist/utils/functions/constants.js.map @@ -0,0 +1 @@ +{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../../src/utils/functions/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,mBAAmB,GAAG,mBAAmB,CAAA"} \ No newline at end of file diff --git a/dist/utils/functions/functions.d.ts b/dist/utils/functions/functions.d.ts new file mode 100644 index 00000000000..17f3b4b5d42 --- /dev/null +++ b/dist/utils/functions/functions.d.ts @@ -0,0 +1,32 @@ +import type { OptionValues } from 'commander'; +import type { NormalizedCachedConfigConfig } from '../command-helpers.js'; +export declare const INTERNAL_FUNCTIONS_FOLDER = "functions-internal"; +export declare const SERVE_FUNCTIONS_FOLDER = "functions-serve"; +/** + * retrieves the function directory out of the flags or config + */ +export declare const getFunctionsDir: ({ config, options, }: { + config: NormalizedCachedConfigConfig; + options: OptionValues; +}, defaultValue?: string) => string | undefined; +export declare const getFunctionsManifestPath: ({ base, packagePath }: { + base: string; + packagePath?: string; +}) => Promise; +export declare const getFunctionsDistPath: ({ base, packagePath, }: { + base?: undefined | string; + packagePath?: string; +}) => Promise; +export declare const getFunctionsServePath: ({ base, packagePath, }: { + base?: undefined | string; + packagePath?: string; +}) => string; +/** + * Retrieves the internal functions directory and creates it if ensureExists is provided + */ +export declare const getInternalFunctionsDir: ({ base, ensureExists, packagePath, }: { + base?: undefined | string; + ensureExists?: boolean; + packagePath?: string; +}) => Promise; +//# sourceMappingURL=functions.d.ts.map \ No newline at end of file diff --git a/dist/utils/functions/functions.d.ts.map b/dist/utils/functions/functions.d.ts.map new file mode 100644 index 00000000000..e813ea5f910 --- /dev/null +++ b/dist/utils/functions/functions.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"functions.d.ts","sourceRoot":"","sources":["../../../src/utils/functions/functions.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAI7C,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAA;AAEzE,eAAO,MAAM,yBAAyB,uBAAuB,CAAA;AAC7D,eAAO,MAAM,sBAAsB,oBAAoB,CAAA;AAIvD;;GAEG;AACH,eAAO,MAAM,eAAe,GAC1B,sBAGG;IACD,MAAM,EAAE,4BAA4B,CAAA;IACpC,OAAO,EAAE,YAAY,CAAA;CACtB,EACD,eAAe,MAAM,KACpB,MAAM,GAAG,SAIE,CAAA;AAEd,eAAO,MAAM,wBAAwB,GAAU,uBAA4B;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,2BAKhH,CAAA;AAED,eAAO,MAAM,oBAAoB,GAAU,wBAGxC;IACD,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IACzB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,2BAKA,CAAA;AAED,eAAO,MAAM,qBAAqB,GAAI,wBAGnC;IACD,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IACzB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,WAIA,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAU,sCAI3C;IACD,IAAI,CAAC,EAAE,SAAS,GAAG,MAAM,CAAA;IACzB,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,oBAQA,CAAA"} \ No newline at end of file diff --git a/dist/utils/functions/functions.js b/dist/utils/functions/functions.js new file mode 100644 index 00000000000..d6d771ecfa9 --- /dev/null +++ b/dist/utils/functions/functions.js @@ -0,0 +1,39 @@ +import { promises as fs } from 'fs'; +import { resolve } from 'path'; +import { isDirectoryAsync, isFileAsync } from '../../lib/fs.js'; +import { getPathInProject } from '../../lib/settings.js'; +export const INTERNAL_FUNCTIONS_FOLDER = 'functions-internal'; +export const SERVE_FUNCTIONS_FOLDER = 'functions-serve'; +const isNonEmptyString = (s) => typeof s === 'string' && s.length > 0; +/** + * retrieves the function directory out of the flags or config + */ +export const getFunctionsDir = ({ config, options, }, defaultValue) => ('functions' in options && isNonEmptyString(options.functions) ? options.functions : null) ?? + (isNonEmptyString(config.dev?.functions) ? config.dev.functions : null) ?? + (isNonEmptyString(config.functionsDirectory) ? config.functionsDirectory : null) ?? + defaultValue; +export const getFunctionsManifestPath = async ({ base, packagePath = '' }) => { + const path = resolve(base, packagePath, getPathInProject(['functions', 'manifest.json'])); + const isFile = await isFileAsync(path); + return isFile ? path : null; +}; +export const getFunctionsDistPath = async ({ base, packagePath = '', }) => { + const path = resolve(base ?? '', packagePath, getPathInProject(['functions'])); + const isDirectory = await isDirectoryAsync(path); + return isDirectory ? path : null; +}; +export const getFunctionsServePath = ({ base, packagePath = '', }) => { + const path = resolve(base ?? '', packagePath, getPathInProject([SERVE_FUNCTIONS_FOLDER])); + return path; +}; +/** + * Retrieves the internal functions directory and creates it if ensureExists is provided + */ +export const getInternalFunctionsDir = async ({ base, ensureExists, packagePath = '', }) => { + const path = resolve(base ?? '', packagePath, getPathInProject([INTERNAL_FUNCTIONS_FOLDER])); + if (ensureExists) { + await fs.mkdir(path, { recursive: true }); + } + return path; +}; +//# sourceMappingURL=functions.js.map \ No newline at end of file diff --git a/dist/utils/functions/functions.js.map b/dist/utils/functions/functions.js.map new file mode 100644 index 00000000000..d56374e8805 --- /dev/null +++ b/dist/utils/functions/functions.js.map @@ -0,0 +1 @@ +{"version":3,"file":"functions.js","sourceRoot":"","sources":["../../../src/utils/functions/functions.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/functions/get-functions.d.ts b/dist/utils/functions/get-functions.d.ts new file mode 100644 index 00000000000..e825ff6ff03 --- /dev/null +++ b/dist/utils/functions/get-functions.d.ts @@ -0,0 +1,10 @@ +export declare const BACKGROUND = "-background"; +export declare const getFunctions: (functionsSrcDir: any, config?: {}) => Promise<{ + mainFile: any; + name: any; + runtime: any; + urlPath: string; + isBackground: any; + schedule: any; +}[]>; +//# sourceMappingURL=get-functions.d.ts.map \ No newline at end of file diff --git a/dist/utils/functions/get-functions.d.ts.map b/dist/utils/functions/get-functions.d.ts.map new file mode 100644 index 00000000000..a31563fa2a2 --- /dev/null +++ b/dist/utils/functions/get-functions.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"get-functions.d.ts","sourceRoot":"","sources":["../../../src/utils/functions/get-functions.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,UAAU,gBAAgB,CAAA;AAoBvC,eAAO,MAAM,YAAY,GAAU,oBAAe,EAAE,WAAW;;;;;;;IAa9D,CAAA"} \ No newline at end of file diff --git a/dist/utils/functions/get-functions.js b/dist/utils/functions/get-functions.js new file mode 100644 index 00000000000..ece87f5e2f3 --- /dev/null +++ b/dist/utils/functions/get-functions.js @@ -0,0 +1,35 @@ +import { listFunctions } from '@netlify/zip-it-and-ship-it'; +import { fileExistsAsync } from '../../lib/fs.js'; +// @ts-expect-error TS(7006) FIXME: Parameter 'functionName' implicitly has an 'any' t... Remove this comment to see the full error message +const getUrlPath = (functionName) => `/.netlify/functions/${functionName}`; +export const BACKGROUND = '-background'; +const JS = 'js'; +// @ts-expect-error TS(7031) FIXME: Binding element 'mainFile' implicitly has an 'any'... Remove this comment to see the full error message +const addFunctionProps = ({ mainFile, name, runtime, schedule }) => { + const urlPath = getUrlPath(name); + const isBackground = name.endsWith(BACKGROUND); + return { mainFile, name, runtime, urlPath, isBackground, schedule }; +}; +/** + * @param {Record} functionConfigRecord + * @returns {Record} + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'functionConfigRecord' implicitly has an... Remove this comment to see the full error message +const extractSchedule = (functionConfigRecord) => +// @ts-expect-error TS(2339) FIXME: Property 'schedule' does not exist on type 'unknow... Remove this comment to see the full error message +Object.fromEntries(Object.entries(functionConfigRecord).map(([name, { schedule }]) => [name, { schedule }])); +// @ts-expect-error TS(7006) FIXME: Parameter 'functionsSrcDir' implicitly has an 'any... Remove this comment to see the full error message +export const getFunctions = async (functionsSrcDir, config = {}) => { + if (!(await fileExistsAsync(functionsSrcDir))) { + return []; + } + const functions = await listFunctions(functionsSrcDir, { + // @ts-expect-error TS(2339) FIXME: Property 'functions' does not exist on type '{}'. + config: config.functions ? extractSchedule(config.functions) : undefined, + parseISC: true, + }); + // @ts-expect-error TS(2345) FIXME: Argument of type 'ListedFunction' is not assignabl... Remove this comment to see the full error message + const functionsWithProps = functions.filter(({ runtime }) => runtime === JS).map((func) => addFunctionProps(func)); + return functionsWithProps; +}; +//# sourceMappingURL=get-functions.js.map \ No newline at end of file diff --git a/dist/utils/functions/get-functions.js.map b/dist/utils/functions/get-functions.js.map new file mode 100644 index 00000000000..5307ee1d494 --- /dev/null +++ b/dist/utils/functions/get-functions.js.map @@ -0,0 +1 @@ +{"version":3,"file":"get-functions.js","sourceRoot":"","sources":["../../../src/utils/functions/get-functions.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAE3D,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AAEjD,2IAA2I;AAC3I,MAAM,UAAU,GAAG,CAAC,YAAY,EAAE,EAAE,CAAC,uBAAuB,YAAY,EAAE,CAAA;AAE1E,MAAM,CAAC,MAAM,UAAU,GAAG,aAAa,CAAA;AACvC,MAAM,EAAE,GAAG,IAAI,CAAA;AAEf,2IAA2I;AAC3I,MAAM,gBAAgB,GAAG,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE;IACjE,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAA;IAChC,MAAM,YAAY,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAA;IAC9C,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,QAAQ,EAAE,CAAA;AACrE,CAAC,CAAA;AAED;;;GAGG;AACH,2IAA2I;AAC3I,MAAM,eAAe,GAAG,CAAC,oBAAoB,EAAE,EAAE;AAC/C,2IAA2I;AAC3I,MAAM,CAAC,WAAW,CAAC,MAAM,CAAC,OAAO,CAAC,oBAAoB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAA;AAE9G,2IAA2I;AAC3I,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,EAAE,eAAe,EAAE,MAAM,GAAG,EAAE,EAAE,EAAE;IACjE,IAAI,CAAC,CAAC,MAAM,eAAe,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC;QAC9C,OAAO,EAAE,CAAA;IACX,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,eAAe,EAAE;QACrD,qFAAqF;QACrF,MAAM,EAAE,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS;QACxE,QAAQ,EAAE,IAAI;KACf,CAAC,CAAA;IACF,2IAA2I;IAC3I,MAAM,kBAAkB,GAAG,SAAS,CAAC,MAAM,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,CAAC,OAAO,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAA;IAClH,OAAO,kBAAkB,CAAA;AAC3B,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/functions/index.d.ts b/dist/utils/functions/index.d.ts new file mode 100644 index 00000000000..d5a62e3e3c6 --- /dev/null +++ b/dist/utils/functions/index.d.ts @@ -0,0 +1,4 @@ +export * from './constants.js'; +export * from './functions.js'; +export * from './get-functions.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/utils/functions/index.d.ts.map b/dist/utils/functions/index.d.ts.map new file mode 100644 index 00000000000..36d2955f644 --- /dev/null +++ b/dist/utils/functions/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/functions/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,oBAAoB,CAAA"} \ No newline at end of file diff --git a/dist/utils/functions/index.js b/dist/utils/functions/index.js new file mode 100644 index 00000000000..5c92923dc43 --- /dev/null +++ b/dist/utils/functions/index.js @@ -0,0 +1,4 @@ +export * from './constants.js'; +export * from './functions.js'; +export * from './get-functions.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/utils/functions/index.js.map b/dist/utils/functions/index.js.map new file mode 100644 index 00000000000..062c2db9805 --- /dev/null +++ b/dist/utils/functions/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/functions/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,oBAAoB,CAAA"} \ No newline at end of file diff --git a/dist/utils/get-cli-package-json.d.ts b/dist/utils/get-cli-package-json.d.ts new file mode 100644 index 00000000000..317367d67ad --- /dev/null +++ b/dist/utils/get-cli-package-json.d.ts @@ -0,0 +1,4 @@ +import { type Package } from 'normalize-package-data'; +declare const getPackageJson: () => Promise; +export default getPackageJson; +//# sourceMappingURL=get-cli-package-json.d.ts.map \ No newline at end of file diff --git a/dist/utils/get-cli-package-json.d.ts.map b/dist/utils/get-cli-package-json.d.ts.map new file mode 100644 index 00000000000..d4cbab46090 --- /dev/null +++ b/dist/utils/get-cli-package-json.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"get-cli-package-json.d.ts","sourceRoot":"","sources":["../../src/utils/get-cli-package-json.ts"],"names":[],"mappings":"AAIA,OAA6B,EAAE,KAAK,OAAO,EAAE,MAAM,wBAAwB,CAAA;AAI3E,QAAA,MAAM,cAAc,QAAa,OAAO,CAAC,OAAO,CAa/C,CAAA;AAED,eAAe,cAAc,CAAA"} \ No newline at end of file diff --git a/dist/utils/get-cli-package-json.js b/dist/utils/get-cli-package-json.js new file mode 100644 index 00000000000..77907463b3c --- /dev/null +++ b/dist/utils/get-cli-package-json.js @@ -0,0 +1,22 @@ +import { readFile } from 'fs/promises'; +import { dirname, join } from 'path'; +import { fileURLToPath } from 'url'; +import normalizePackageData from 'normalize-package-data'; +let packageJson; +const getPackageJson = async () => { + if (!packageJson) { + const packageJsonPath = join(dirname(fileURLToPath(import.meta.url)), '../../package.json'); + const packageData = JSON.parse(await readFile(packageJsonPath, 'utf-8')); + try { + normalizePackageData(packageData); + packageJson = packageData; + return packageJson; + } + catch (error) { + throw new Error('Could not find package.json', { cause: error }); + } + } + return packageJson; +}; +export default getPackageJson; +//# sourceMappingURL=get-cli-package-json.js.map \ No newline at end of file diff --git a/dist/utils/get-cli-package-json.js.map b/dist/utils/get-cli-package-json.js.map new file mode 100644 index 00000000000..2e5f430835a --- /dev/null +++ b/dist/utils/get-cli-package-json.js.map @@ -0,0 +1 @@ +{"version":3,"file":"get-cli-package-json.js","sourceRoot":"","sources":["../../src/utils/get-cli-package-json.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AACtC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AAEnC,OAAO,oBAAsC,MAAM,wBAAwB,CAAA;AAE3E,IAAI,WAAgC,CAAA;AAEpC,MAAM,cAAc,GAAG,KAAK,IAAsB,EAAE;IAClD,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,oBAAoB,CAAC,CAAA;QAC3F,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,CAA4B,CAAA;QACnG,IAAI,CAAC;YACH,oBAAoB,CAAC,WAAW,CAAC,CAAA;YACjC,WAAW,GAAG,WAAsB,CAAA;YACpC,OAAO,WAAW,CAAA;QACpB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CAAC,6BAA6B,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAA;QAClE,CAAC;IACH,CAAC;IACD,OAAO,WAAW,CAAA;AACpB,CAAC,CAAA;AAED,eAAe,cAAc,CAAA"} \ No newline at end of file diff --git a/dist/utils/get-global-config-store.d.ts b/dist/utils/get-global-config-store.d.ts new file mode 100644 index 00000000000..a023ff78cf2 --- /dev/null +++ b/dist/utils/get-global-config-store.d.ts @@ -0,0 +1,16 @@ +type ConfigStoreOptions> = { + defaults?: T | undefined; +}; +export declare class GlobalConfigStore = Record> { + #private; + constructor(options?: ConfigStoreOptions); + get all(): T; + set(key: string, value: unknown): void; + get(key: string): T[typeof key]; + private getConfig; + private writeConfig; +} +declare const getGlobalConfigStore: () => Promise; +export default getGlobalConfigStore; +export declare const resetConfigCache: () => void; +//# sourceMappingURL=get-global-config-store.d.ts.map \ No newline at end of file diff --git a/dist/utils/get-global-config-store.d.ts.map b/dist/utils/get-global-config-store.d.ts.map new file mode 100644 index 00000000000..af6568e9267 --- /dev/null +++ b/dist/utils/get-global-config-store.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"get-global-config-store.d.ts","sourceRoot":"","sources":["../../src/utils/get-global-config-store.ts"],"names":[],"mappings":"AAUA,KAAK,kBAAkB,CAErB,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAC3B;IACF,QAAQ,CAAC,EAAE,CAAC,GAAG,SAAS,CAAA;CACzB,CAAA;AAED,qBAAa,iBAAiB,CAE5B,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC;;gBAIhC,OAAO,GAAE,kBAAkB,CAAC,CAAC,CAAM;IAStD,IAAW,GAAG,IAAI,CAAC,CAElB;IAEM,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI;IAMtC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,CAAC,CAAC,OAAO,GAAG,CAAC;IAKtC,OAAO,CAAC,SAAS;IAsBjB,OAAO,CAAC,WAAW;CAIpB;AAYD,QAAA,MAAM,oBAAoB,QAAa,OAAO,CAAC,iBAAiB,CAkB/D,CAAA;AAED,eAAe,oBAAoB,CAAA;AAEnC,eAAO,MAAM,gBAAgB,YAE5B,CAAA"} \ No newline at end of file diff --git a/dist/utils/get-global-config-store.js b/dist/utils/get-global-config-store.js new file mode 100644 index 00000000000..c8a81483f45 --- /dev/null +++ b/dist/utils/get-global-config-store.js @@ -0,0 +1,87 @@ +import fs from 'node:fs/promises'; +import fss from 'node:fs'; +import path from 'node:path'; +import * as dot from 'dot-prop'; +import { v4 as uuidv4 } from 'uuid'; +import { sync as writeFileAtomicSync } from 'write-file-atomic'; +import { getLegacyPathInHome, getPathInHome } from '../lib/settings.js'; +export class GlobalConfigStore { + #storagePath; + constructor(options = {}) { + this.#storagePath = getPathInHome(['config.json']); + if (options.defaults) { + const config = this.getConfig(); + this.writeConfig({ ...options.defaults, ...config }); + } + } + get all() { + return this.getConfig(); + } + set(key, value) { + const config = this.getConfig(); + const updatedConfig = dot.setProperty(config, key, value); + this.writeConfig(updatedConfig); + } + get(key) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-return + return dot.getProperty(this.getConfig(), key); + } + getConfig() { + let raw; + try { + raw = fss.readFileSync(this.#storagePath, 'utf8'); + } + catch (err) { + if (err instanceof Error && 'code' in err) { + if (err.code === 'ENOENT') { + // File or parent directory does not exist + return {}; + } + } + throw err; + } + try { + return JSON.parse(raw); + } + catch { + writeFileAtomicSync(this.#storagePath, '', { mode: 0o0600 }); + return {}; + } + } + writeConfig(value) { + fss.mkdirSync(path.dirname(this.#storagePath), { mode: 0o0700, recursive: true }); + writeFileAtomicSync(this.#storagePath, JSON.stringify(value, undefined, '\t'), { mode: 0o0600 }); + } +} +const globalConfigDefaults = { + /* disable stats from being sent to Netlify */ + telemetryDisabled: false, + /* cliId */ + cliId: uuidv4(), +}; +// Memoise config result so that we only load it once +let configStore; +const getGlobalConfigStore = async () => { + if (!configStore) { + // Legacy config file in home ~/.netlify/config.json + const legacyPath = getLegacyPathInHome(['config.json']); + // Read legacy config if exists + let legacyConfig; + try { + legacyConfig = JSON.parse(await fs.readFile(legacyPath, 'utf8')); + } + catch { + // ignore error + } + // Use legacy config as default values + const defaults = { ...globalConfigDefaults, ...legacyConfig }; + // The id param is only used when not passing `configPath` but the type def requires it + configStore = new GlobalConfigStore({ defaults }); + } + return configStore; +}; +export default getGlobalConfigStore; +export const resetConfigCache = () => { + configStore = undefined; +}; +//# sourceMappingURL=get-global-config-store.js.map \ No newline at end of file diff --git a/dist/utils/get-global-config-store.js.map b/dist/utils/get-global-config-store.js.map new file mode 100644 index 00000000000..7f4154665a1 --- /dev/null +++ b/dist/utils/get-global-config-store.js.map @@ -0,0 +1 @@ +{"version":3,"file":"get-global-config-store.js","sourceRoot":"","sources":["../../src/utils/get-global-config-store.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/get-repo-data.d.ts b/dist/utils/get-repo-data.d.ts new file mode 100644 index 00000000000..81dffd3763b --- /dev/null +++ b/dist/utils/get-repo-data.d.ts @@ -0,0 +1,17 @@ +export interface RepoData { + name: string | null; + owner: string | null; + repo: string | null; + url: string; + branch: string; + provider: string | null; + httpsUrl: string; +} +declare const getRepoData: ({ remoteName, workingDir, }: { + remoteName?: string; + workingDir: string; +}) => Promise; +export default getRepoData; +//# sourceMappingURL=get-repo-data.d.ts.map \ No newline at end of file diff --git a/dist/utils/get-repo-data.d.ts.map b/dist/utils/get-repo-data.d.ts.map new file mode 100644 index 00000000000..2d8a2a7856a --- /dev/null +++ b/dist/utils/get-repo-data.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"get-repo-data.d.ts","sourceRoot":"","sources":["../../src/utils/get-repo-data.ts"],"names":[],"mappings":"AAUA,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAED,QAAA,MAAM,WAAW,GAAU,6BAGxB;IACD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;CACnB,KAAG,OAAO,CAAC,QAAQ,GAAG;IAAE,KAAK,EAAE,MAAM,CAAA;CAAE,CAsDvC,CAAA;AAOD,eAAe,WAAW,CAAA"} \ No newline at end of file diff --git a/dist/utils/get-repo-data.js b/dist/utils/get-repo-data.js new file mode 100644 index 00000000000..5ae871fbf47 --- /dev/null +++ b/dist/utils/get-repo-data.js @@ -0,0 +1,59 @@ +import { dirname } from 'path'; +import util from 'util'; +import { findUp } from 'find-up'; +import gitRepoInfo from 'git-repo-info'; +import gitconfiglocal from 'gitconfiglocal'; +import parseGithubUrl from 'parse-github-url'; +import { log } from './command-helpers.js'; +const getRepoData = async ({ remoteName, workingDir, }) => { + try { + const [gitConfig, gitDirectory] = await Promise.all([ + util.promisify(gitconfiglocal)(workingDir), + findUp('.git', { cwd: workingDir, type: 'directory' }), + ]); + if (!gitDirectory || !gitConfig || !gitConfig.remote || Object.keys(gitConfig.remote).length === 0) { + throw new Error('No Git remote found'); + } + const baseGitPath = dirname(gitDirectory); + if (workingDir !== baseGitPath) { + log(`Git directory located in ${baseGitPath}`); + } + if (!remoteName) { + const remotes = Object.keys(gitConfig.remote); + remoteName = remotes.find((remote) => remote === 'origin') || remotes[0]; + } + if (!Object.prototype.hasOwnProperty.call(gitConfig.remote, remoteName) || + !gitConfig.remote[remoteName] || + Object.keys(gitConfig.remote[remoteName]).length === 0) { + throw new Error(`The specified remote "${remoteName}" is not defined in Git repo. Please use --git-remote-name flag to specify a remote.`); + } + const { url } = gitConfig.remote[remoteName]; + const parsedUrl = parseGithubUrl(url); + // TODO(serhalp): Validate more aggressively? We should probably require `owner`, `repo`, `host`? + if (parsedUrl == null) { + throw new Error(`The specified Git remote ${remoteName} is not a valid URL: ${url}`); + } + const { host, name, owner, repo } = parsedUrl; + const { branch } = gitRepoInfo(); + return { + name, + owner, + repo, + url, + branch, + provider: host != null ? PROVIDERS[host] ?? host : host, + httpsUrl: `https://${host}/${repo}`, + }; + } + catch (error) { + return { + error: error instanceof Error ? error.message : error?.toString() ?? 'Failed to get repo data', + }; + } +}; +const PROVIDERS = { + 'github.com': 'github', + 'gitlab.com': 'gitlab', +}; +export default getRepoData; +//# sourceMappingURL=get-repo-data.js.map \ No newline at end of file diff --git a/dist/utils/get-repo-data.js.map b/dist/utils/get-repo-data.js.map new file mode 100644 index 00000000000..c7db9de95f1 --- /dev/null +++ b/dist/utils/get-repo-data.js.map @@ -0,0 +1 @@ +{"version":3,"file":"get-repo-data.js","sourceRoot":"","sources":["../../src/utils/get-repo-data.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/get-site.d.ts b/dist/utils/get-site.d.ts new file mode 100644 index 00000000000..cc371726c6e --- /dev/null +++ b/dist/utils/get-site.d.ts @@ -0,0 +1,4 @@ +import type { NetlifyAPI } from '@netlify/api'; +import type { SiteInfo } from './types.js'; +export declare const getSiteByName: (api: NetlifyAPI, siteName: string) => Promise; +//# sourceMappingURL=get-site.d.ts.map \ No newline at end of file diff --git a/dist/utils/get-site.d.ts.map b/dist/utils/get-site.d.ts.map new file mode 100644 index 00000000000..00eaaf4d91c --- /dev/null +++ b/dist/utils/get-site.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"get-site.d.ts","sourceRoot":"","sources":["../../src/utils/get-site.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAG9C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAA;AAE1C,eAAO,MAAM,aAAa,GAAU,KAAK,UAAU,EAAE,UAAU,MAAM,KAAG,OAAO,CAAC,QAAQ,CAkBvF,CAAA"} \ No newline at end of file diff --git a/dist/utils/get-site.js b/dist/utils/get-site.js new file mode 100644 index 00000000000..1ac77bd90b9 --- /dev/null +++ b/dist/utils/get-site.js @@ -0,0 +1,21 @@ +import { logAndThrowError } from './command-helpers.js'; +export const getSiteByName = async (api, siteName) => { + try { + const sites = await api.listSites({ name: siteName, filter: 'all' }); + const siteFoundByName = sites.find((filteredSite) => filteredSite.name === siteName); + if (!siteFoundByName) { + throw new Error(`Project "${siteName}" cannot be found`); + } + // FIXME(serhalp): `id` and `name` should be required in `netlify` package type + return siteFoundByName; + } + catch (error_) { + if (error_.status === 401) { + return logAndThrowError(`${error_.message}: could not retrieve project`); + } + else { + return logAndThrowError('Project not found. Please rerun "netlify link"'); + } + } +}; +//# sourceMappingURL=get-site.js.map \ No newline at end of file diff --git a/dist/utils/get-site.js.map b/dist/utils/get-site.js.map new file mode 100644 index 00000000000..1200481af6b --- /dev/null +++ b/dist/utils/get-site.js.map @@ -0,0 +1 @@ +{"version":3,"file":"get-site.js","sourceRoot":"","sources":["../../src/utils/get-site.ts"],"names":[],"mappings":"AAEA,OAAO,EAAiB,gBAAgB,EAAE,MAAM,sBAAsB,CAAA;AAGtE,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,GAAe,EAAE,QAAgB,EAAqB,EAAE;IAC1F,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,GAAG,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAA;QACpE,MAAM,eAAe,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAA;QAEpF,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,IAAI,KAAK,CAAC,YAAY,QAAQ,mBAAmB,CAAC,CAAA;QAC1D,CAAC;QAED,+EAA+E;QAC/E,OAAO,eAA2B,CAAA;IACpC,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,IAAK,MAAmB,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACxC,OAAO,gBAAgB,CAAC,GAAI,MAAmB,CAAC,OAAO,8BAA8B,CAAC,CAAA;QACxF,CAAC;aAAM,CAAC;YACN,OAAO,gBAAgB,CAAC,gDAAgD,CAAC,CAAA;QAC3E,CAAC;IACH,CAAC;AACH,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/gh-auth.d.ts b/dist/utils/gh-auth.d.ts new file mode 100644 index 00000000000..9ab12d38703 --- /dev/null +++ b/dist/utils/gh-auth.d.ts @@ -0,0 +1,14 @@ +export interface Token { + user: string; + token: string; + provider: string; +} +/** + * Authenticate with the netlify app + */ +export declare const authWithNetlify: () => Promise; +/** + * Get a GitHub token + */ +export declare const getGitHubToken: () => Promise; +//# sourceMappingURL=gh-auth.d.ts.map \ No newline at end of file diff --git a/dist/utils/gh-auth.d.ts.map b/dist/utils/gh-auth.d.ts.map new file mode 100644 index 00000000000..a5a2d630b81 --- /dev/null +++ b/dist/utils/gh-auth.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"gh-auth.d.ts","sourceRoot":"","sources":["../../src/utils/gh-auth.ts"],"names":[],"mappings":"AAcA,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;CACjB;AAqBD;;GAEG;AACH,eAAO,MAAM,eAAe,QAAa,OAAO,CAAC,KAAK,CAwCrD,CAAA;AAgCD;;GAEG;AACH,eAAO,MAAM,cAAc,QAAa,OAAO,CAAC,KAAK,CAMpD,CAAA"} \ No newline at end of file diff --git a/dist/utils/gh-auth.js b/dist/utils/gh-auth.js new file mode 100644 index 00000000000..8cafa7c376c --- /dev/null +++ b/dist/utils/gh-auth.js @@ -0,0 +1,92 @@ +// A simple ghauth inspired library for getting a personal access token +import http from 'http'; +import process from 'process'; +import { Octokit } from '@octokit/rest'; +import getPort from 'get-port'; +import inquirer from 'inquirer'; +import { log } from './command-helpers.js'; +import createDeferred from './create-deferred.js'; +import openBrowser from './open-browser.js'; +const SERVER_PORT = 3000; +const promptForAuthMethod = async () => { + const authChoiceNetlify = 'Authorize with GitHub through app.netlify.com'; + const authChoiceToken = 'Authorize with a GitHub personal access token'; + const authChoices = [authChoiceNetlify, authChoiceToken]; + const { authMethod } = await inquirer.prompt([ + { + type: 'list', + name: 'authMethod', + message: 'Netlify CLI needs access to your GitHub account to configure Webhooks and Deploy Keys. ' + + 'What would you like to do?', + choices: authChoices, + }, + ]); + return authMethod === authChoiceNetlify; +}; +/** + * Authenticate with the netlify app + */ +export const authWithNetlify = async () => { + const port = await getPort({ port: SERVER_PORT }); + const { promise: deferredPromise, reject: deferredReject, resolve: deferredResolve } = createDeferred(); + const server = http.createServer(function onRequest(req, res) { + const parameters = new URLSearchParams((req.url ?? '').slice((req.url ?? '').indexOf('?') + 1)); + if (parameters.get('token')) { + // TODO(serhalp): Parse payload to validate type actually conforms + deferredResolve(Object.fromEntries(parameters)); + res.end(`${"Logged in" + + "

Logged in

You're now logged into Netlify CLI with your "}${parameters.get('provider') ?? ''} credentials. Please close this window.

`); + server.close(); + return; + } + res.end('BAD PARAMETERS'); + server.close(); + deferredReject(new Error('Got invalid parameters for CLI login')); + }); + await new Promise(function waitForListening(resolve, reject) { + server.on('error', reject); + server.listen(port, () => { + resolve(undefined); + }); + }); + const webUI = process.env.NETLIFY_WEB_UI ?? 'https://app.netlify.com'; + const urlParams = new URLSearchParams({ + host: `http://localhost:${port.toString()}`, + provider: 'github', + }); + const url = `${webUI}/cli?${urlParams.toString()}`; + await openBrowser({ url }); + return deferredPromise; +}; +const getPersonalAccessToken = async () => { + const { token } = await inquirer.prompt([ + { + type: 'password', + name: 'token', + message: 'Your GitHub personal access token:', + filter: (input) => input.trim(), + }, + ]); + return { token }; +}; +/** + * Authenticate with the netlify app + */ +const authWithToken = async () => { + const { token } = await getPersonalAccessToken(); + if (!token) { + throw new Error('GitHub authentication failed'); + } + const octokit = new Octokit({ auth: `token ${token}` }); + const { data: { login: user }, } = await octokit.users.getAuthenticated(); + return { token, user, provider: 'github' }; +}; +/** + * Get a GitHub token + */ +export const getGitHubToken = async () => { + log(''); + const withNetlify = await promptForAuthMethod(); + return withNetlify ? await authWithNetlify() : await authWithToken(); +}; +//# sourceMappingURL=gh-auth.js.map \ No newline at end of file diff --git a/dist/utils/gh-auth.js.map b/dist/utils/gh-auth.js.map new file mode 100644 index 00000000000..27b9c031d25 --- /dev/null +++ b/dist/utils/gh-auth.js.map @@ -0,0 +1 @@ +{"version":3,"file":"gh-auth.js","sourceRoot":"","sources":["../../src/utils/gh-auth.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/gitignore.d.ts b/dist/utils/gitignore.d.ts new file mode 100644 index 00000000000..8e0848d3295 --- /dev/null +++ b/dist/utils/gitignore.d.ts @@ -0,0 +1,2 @@ +export declare const ensureNetlifyIgnore: (dir: string) => Promise; +//# sourceMappingURL=gitignore.d.ts.map \ No newline at end of file diff --git a/dist/utils/gitignore.d.ts.map b/dist/utils/gitignore.d.ts.map new file mode 100644 index 00000000000..99ae97b3e8c --- /dev/null +++ b/dist/utils/gitignore.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"gitignore.d.ts","sourceRoot":"","sources":["../../src/utils/gitignore.ts"],"names":[],"mappings":"AAeA,eAAO,MAAM,mBAAmB,GAAmB,KAAK,MAAM,+BAyB7D,CAAA"} \ No newline at end of file diff --git a/dist/utils/gitignore.js b/dist/utils/gitignore.js new file mode 100644 index 00000000000..542bd8edda8 --- /dev/null +++ b/dist/utils/gitignore.js @@ -0,0 +1,36 @@ +import { readFile, writeFile } from 'fs/promises'; +import path from 'path'; +import parseIgnore from 'parse-gitignore'; +import { fileExistsAsync } from '../lib/fs.js'; +import { log } from './command-helpers.js'; +const hasGitIgnore = async function (dir) { + const gitIgnorePath = path.join(dir, '.gitignore'); + const hasIgnore = await fileExistsAsync(gitIgnorePath); + return hasIgnore; +}; +export const ensureNetlifyIgnore = async function (dir) { + const gitIgnorePath = path.join(dir, '.gitignore'); + const ignoreContent = '# Local Netlify folder\n.netlify\n'; + /* No .gitignore file. Create one and ignore .netlify folder */ + if (!(await hasGitIgnore(dir))) { + await writeFile(gitIgnorePath, ignoreContent, 'utf8'); + return false; + } + let gitIgnoreContents; + let ignorePatterns; + try { + gitIgnoreContents = await readFile(gitIgnorePath, 'utf8'); + ignorePatterns = parseIgnore.parse(gitIgnoreContents); + } + catch { + // ignore + } + /* Not ignoring .netlify folder. Add to .gitignore */ + if (!ignorePatterns || !ignorePatterns.patterns.some((pattern) => /(^|\/|\\)\.netlify($|\/|\\)/.test(pattern))) { + log(); + log('Adding local .netlify folder to .gitignore file...'); + const newContents = `${gitIgnoreContents}\n${ignoreContent}`; + await writeFile(gitIgnorePath, newContents, 'utf8'); + } +}; +//# sourceMappingURL=gitignore.js.map \ No newline at end of file diff --git a/dist/utils/gitignore.js.map b/dist/utils/gitignore.js.map new file mode 100644 index 00000000000..787ecec061d --- /dev/null +++ b/dist/utils/gitignore.js.map @@ -0,0 +1 @@ +{"version":3,"file":"gitignore.js","sourceRoot":"","sources":["../../src/utils/gitignore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACjD,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,OAAO,WAAW,MAAM,iBAAiB,CAAA;AAEzC,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AAE9C,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAE1C,MAAM,YAAY,GAAG,KAAK,WAAW,GAAW;IAC9C,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAA;IAClD,MAAM,SAAS,GAAG,MAAM,eAAe,CAAC,aAAa,CAAC,CAAA;IACtD,OAAO,SAAS,CAAA;AAClB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,mBAAmB,GAAG,KAAK,WAAW,GAAW;IAC5D,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,YAAY,CAAC,CAAA;IAClD,MAAM,aAAa,GAAG,oCAAoC,CAAA;IAE1D,+DAA+D;IAC/D,IAAI,CAAC,CAAC,MAAM,YAAY,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAC/B,MAAM,SAAS,CAAC,aAAa,EAAE,aAAa,EAAE,MAAM,CAAC,CAAA;QACrD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,IAAI,iBAAiB,CAAA;IACrB,IAAI,cAAc,CAAA;IAClB,IAAI,CAAC;QACH,iBAAiB,GAAG,MAAM,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC,CAAA;QACzD,cAAc,GAAG,WAAW,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAA;IACvD,CAAC;IAAC,MAAM,CAAC;QACP,SAAS;IACX,CAAC;IACD,qDAAqD;IACrD,IAAI,CAAC,cAAc,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,6BAA6B,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QAC/G,GAAG,EAAE,CAAA;QACL,GAAG,CAAC,oDAAoD,CAAC,CAAA;QACzD,MAAM,WAAW,GAAG,GAAG,iBAAiB,KAAK,aAAa,EAAE,CAAA;QAC5D,MAAM,SAAS,CAAC,aAAa,EAAE,WAAW,EAAE,MAAM,CAAC,CAAA;IACrD,CAAC;AACH,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/headers.d.ts b/dist/utils/headers.d.ts new file mode 100644 index 00000000000..c1fd11f8d6b --- /dev/null +++ b/dist/utils/headers.d.ts @@ -0,0 +1,15 @@ +import { type Header } from '@netlify/headers-parser'; +import { type NormalizedCachedConfigConfig } from './command-helpers.js'; +/** + * Get the matching headers for `path` given a set of `rules`. + */ +export declare const headersForPath: (headers: Header[], path: string) => any; +export declare const parseHeaders: ({ config, configPath, headersFiles, }: { + config: NormalizedCachedConfigConfig; + configPath?: string | undefined; + headersFiles?: string[] | undefined; +}) => Promise; +export declare const NFFunctionName = "x-nf-function-name"; +export declare const NFFunctionRoute = "x-nf-function-route"; +export declare const NFRequestID = "x-nf-request-id"; +//# sourceMappingURL=headers.d.ts.map \ No newline at end of file diff --git a/dist/utils/headers.d.ts.map b/dist/utils/headers.d.ts.map new file mode 100644 index 00000000000..f313796c4a9 --- /dev/null +++ b/dist/utils/headers.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../src/utils/headers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAmB,MAAM,yBAAyB,CAAA;AAEtE,OAAO,EAAiB,KAAK,4BAA4B,EAAO,MAAM,sBAAsB,CAAA;AAE5F;;GAEG;AACH,eAAO,MAAM,cAAc,GAAa,SAAS,MAAM,EAAE,EAAE,MAAM,MAAM,QAItE,CAAA;AAMD,eAAO,MAAM,YAAY,GAAmB,uCAIzC;IACD,MAAM,EAAE,4BAA4B,CAAA;IACpC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,YAAY,CAAC,EAAE,MAAM,EAAE,GAAG,SAAS,CAAA;CACpC,KAAG,OAAO,CAAC,MAAM,EAAE,CAWnB,CAAA;AAeD,eAAO,MAAM,cAAc,uBAAuB,CAAA;AAClD,eAAO,MAAM,eAAe,wBAAwB,CAAA;AACpD,eAAO,MAAM,WAAW,oBAAoB,CAAA"} \ No newline at end of file diff --git a/dist/utils/headers.js b/dist/utils/headers.js new file mode 100644 index 00000000000..2ecbbb8fc7f --- /dev/null +++ b/dist/utils/headers.js @@ -0,0 +1,39 @@ +import { parseAllHeaders } from '@netlify/headers-parser'; +import { NETLIFYDEVERR, log } from './command-helpers.js'; +/** + * Get the matching headers for `path` given a set of `rules`. + */ +export const headersForPath = function (headers, path) { + const matchingHeaders = headers.filter(({ forRegExp }) => forRegExp.test(path)).map(getHeaderValues); + const headersRules = Object.assign({}, ...matchingHeaders); + return headersRules; +}; +const getHeaderValues = function ({ values }) { + return values; +}; +export const parseHeaders = async function ({ config, configPath, headersFiles, }) { + const { errors, headers } = await parseAllHeaders({ + headersFiles, + netlifyConfigPath: configPath, + minimal: false, + // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition -- XXX(serhalp): fixed in stacked PR. + configHeaders: config.headers ?? [], + }); + handleHeadersErrors(errors); + // TODO(serhalp): Make `parseAllHeaders()` smart enough to conditionally return a refined type based on `minimal` + return headers; +}; +const handleHeadersErrors = function (errors) { + if (errors.length === 0) { + return; + } + const errorMessage = errors.map(getErrorMessage).join('\n\n'); + log(NETLIFYDEVERR, `Headers syntax errors:\n${errorMessage}`); +}; +const getErrorMessage = function ({ message }) { + return message; +}; +export const NFFunctionName = 'x-nf-function-name'; +export const NFFunctionRoute = 'x-nf-function-route'; +export const NFRequestID = 'x-nf-request-id'; +//# sourceMappingURL=headers.js.map \ No newline at end of file diff --git a/dist/utils/headers.js.map b/dist/utils/headers.js.map new file mode 100644 index 00000000000..eca69f46300 --- /dev/null +++ b/dist/utils/headers.js.map @@ -0,0 +1 @@ +{"version":3,"file":"headers.js","sourceRoot":"","sources":["../../src/utils/headers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAEtE,OAAO,EAAE,aAAa,EAAqC,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAE5F;;GAEG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,OAAiB,EAAE,IAAY;IACrE,MAAM,eAAe,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,eAAe,CAAC,CAAA;IACpG,MAAM,YAAY,GAAG,MAAM,CAAC,MAAM,CAAC,EAAE,EAAE,GAAG,eAAe,CAAC,CAAA;IAC1D,OAAO,YAAY,CAAA;AACrB,CAAC,CAAA;AAED,MAAM,eAAe,GAAG,UAAU,EAAE,MAAM,EAAU;IAClD,OAAO,MAAM,CAAA;AACf,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,KAAK,WAAW,EAC1C,MAAM,EACN,UAAU,EACV,YAAY,GAKb;IACC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,eAAe,CAAC;QAChD,YAAY;QACZ,iBAAiB,EAAE,UAAU;QAC7B,OAAO,EAAE,KAAK;QACd,6GAA6G;QAC7G,aAAa,EAAE,MAAM,CAAC,OAAO,IAAI,EAAE;KACpC,CAAC,CAAA;IACF,mBAAmB,CAAC,MAAM,CAAC,CAAA;IAC3B,iHAAiH;IACjH,OAAO,OAAmB,CAAA;AAC5B,CAAC,CAAA;AAED,MAAM,mBAAmB,GAAG,UAAU,MAAe;IACnD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAM;IACR,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC7D,GAAG,CAAC,aAAa,EAAE,2BAA2B,YAAY,EAAE,CAAC,CAAA;AAC/D,CAAC,CAAA;AAED,MAAM,eAAe,GAAG,UAAU,EAAE,OAAO,EAAS;IAClD,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,cAAc,GAAG,oBAAoB,CAAA;AAClD,MAAM,CAAC,MAAM,eAAe,GAAG,qBAAqB,CAAA;AACpD,MAAM,CAAC,MAAM,WAAW,GAAG,iBAAiB,CAAA"} \ No newline at end of file diff --git a/dist/utils/hooks/requires-site-info.d.ts b/dist/utils/hooks/requires-site-info.d.ts new file mode 100644 index 00000000000..8b4c30aa2c9 --- /dev/null +++ b/dist/utils/hooks/requires-site-info.d.ts @@ -0,0 +1,7 @@ +import type { Command } from 'commander'; +/** + * A preAction hook that errors out if siteInfo is an empty object + */ +declare const requiresSiteInfo: (command: Command) => Promise; +export default requiresSiteInfo; +//# sourceMappingURL=requires-site-info.d.ts.map \ No newline at end of file diff --git a/dist/utils/hooks/requires-site-info.d.ts.map b/dist/utils/hooks/requires-site-info.d.ts.map new file mode 100644 index 00000000000..711099ea531 --- /dev/null +++ b/dist/utils/hooks/requires-site-info.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"requires-site-info.d.ts","sourceRoot":"","sources":["../../../src/utils/hooks/requires-site-info.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAKxC;;GAEG;AACH,QAAA,MAAM,gBAAgB,GAAU,SAAS,OAAO,uBAwB/C,CAAA;AAED,eAAe,gBAAgB,CAAA"} \ No newline at end of file diff --git a/dist/utils/hooks/requires-site-info.js b/dist/utils/hooks/requires-site-info.js new file mode 100644 index 00000000000..d77a707b477 --- /dev/null +++ b/dist/utils/hooks/requires-site-info.js @@ -0,0 +1,31 @@ +import { logAndThrowError, warn } from '../command-helpers.js'; +/** + * A preAction hook that errors out if siteInfo is an empty object + */ +const requiresSiteInfo = async (command) => { + // commander (at least the version we're on) is typed such that `.preAction()` can't accept + // a subclass of `Command`. This type assertion avoids a lot of type noise in every call site. + const { api, site } = command.netlify; + const siteId = site.id; + if (!siteId) { + warn('Did you run `netlify link` yet?'); + return logAndThrowError(`You don't appear to be in a folder that is linked to a project`); + } + try { + await api.getSite({ siteId }); + } + catch (error_) { + // unauthorized + if (error_.status === 401) { + warn(`Log in with a different account or re-link to a project you have permission for`); + return logAndThrowError(`Not authorized to view the currently linked project (${siteId})`); + } + // missing + if (error_.status === 404) { + return logAndThrowError(`The project this folder is linked to can't be found`); + } + return logAndThrowError(error_); + } +}; +export default requiresSiteInfo; +//# sourceMappingURL=requires-site-info.js.map \ No newline at end of file diff --git a/dist/utils/hooks/requires-site-info.js.map b/dist/utils/hooks/requires-site-info.js.map new file mode 100644 index 00000000000..1492349cc92 --- /dev/null +++ b/dist/utils/hooks/requires-site-info.js.map @@ -0,0 +1 @@ +{"version":3,"file":"requires-site-info.js","sourceRoot":"","sources":["../../../src/utils/hooks/requires-site-info.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAiB,MAAM,uBAAuB,CAAA;AAG7E;;GAEG;AACH,MAAM,gBAAgB,GAAG,KAAK,EAAE,OAAgB,EAAE,EAAE;IAClD,2FAA2F;IAC3F,8FAA8F;IAC9F,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAI,OAAuB,CAAC,OAAO,CAAA;IACtD,MAAM,MAAM,GAAG,IAAI,CAAC,EAAE,CAAA;IACtB,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,IAAI,CAAC,iCAAiC,CAAC,CAAA;QACvC,OAAO,gBAAgB,CAAC,gEAAgE,CAAC,CAAA;IAC3F,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC,CAAA;IAC/B,CAAC;IAAC,OAAO,MAAM,EAAE,CAAC;QAChB,eAAe;QACf,IAAK,MAAmB,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACxC,IAAI,CAAC,iFAAiF,CAAC,CAAA;YACvF,OAAO,gBAAgB,CAAC,wDAAwD,MAAM,GAAG,CAAC,CAAA;QAC5F,CAAC;QACD,UAAU;QACV,IAAK,MAAmB,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACxC,OAAO,gBAAgB,CAAC,qDAAqD,CAAC,CAAA;QAChF,CAAC;QAED,OAAO,gBAAgB,CAAC,MAAM,CAAC,CAAA;IACjC,CAAC;AACH,CAAC,CAAA;AAED,eAAe,gBAAgB,CAAA"} \ No newline at end of file diff --git a/dist/utils/init/config-github.d.ts b/dist/utils/init/config-github.d.ts new file mode 100644 index 00000000000..0ecaeb61e30 --- /dev/null +++ b/dist/utils/init/config-github.d.ts @@ -0,0 +1,15 @@ +import type { GlobalConfigStore } from '../types.js'; +import type { BaseCommand } from '../../commands/index.js'; +/** + * Get a valid GitHub token + */ +export declare const getGitHubToken: ({ globalConfig }: { + globalConfig: GlobalConfigStore; +}) => Promise; +export declare const configGithub: ({ command, repoName, repoOwner, siteId, }: { + command: BaseCommand; + repoName: string; + repoOwner: string; + siteId: string; +}) => Promise; +//# sourceMappingURL=config-github.d.ts.map \ No newline at end of file diff --git a/dist/utils/init/config-github.d.ts.map b/dist/utils/init/config-github.d.ts.map new file mode 100644 index 00000000000..1181cd9d1f8 --- /dev/null +++ b/dist/utils/init/config-github.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"config-github.d.ts","sourceRoot":"","sources":["../../../src/utils/init/config-github.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAA;AAW1D;;GAEG;AACH,eAAO,MAAM,cAAc,GAAU,kBAAkB;IAAE,YAAY,EAAE,iBAAiB,CAAA;CAAE,KAAG,OAAO,CAAC,MAAM,CAqB1G,CAAA;AA4KD,eAAO,MAAM,YAAY,GAAU,2CAKhC;IACD,OAAO,EAAE,WAAW,CAAA;IACpB,QAAQ,EAAE,MAAM,CAAA;IAChB,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;CACf,kBAiDA,CAAA"} \ No newline at end of file diff --git a/dist/utils/init/config-github.js b/dist/utils/init/config-github.js new file mode 100644 index 00000000000..c1669ba18ae --- /dev/null +++ b/dist/utils/init/config-github.js @@ -0,0 +1,214 @@ +import { Octokit } from '@octokit/rest'; +import { chalk, logAndThrowError, log } from '../command-helpers.js'; +import { getGitHubToken as ghauth } from '../gh-auth.js'; +import { createDeployKey, formatErrorMessage, getBuildSettings, saveNetlifyToml, setupSite } from './utils.js'; +const formatRepoAndOwner = ({ repoName, repoOwner }) => ({ + name: chalk.magenta(repoName), + owner: chalk.magenta(repoOwner), +}); +const PAGE_SIZE = 100; +/** + * Get a valid GitHub token + */ +export const getGitHubToken = async ({ globalConfig }) => { + const userId = globalConfig.get('userId'); + const githubToken = globalConfig.get(`users.${userId}.auth.github`); + if (githubToken?.user && githubToken.token) { + try { + const octokit = getGitHubClient(githubToken.token); + const { status } = await octokit.rest.users.getAuthenticated(); + if (status < 400) { + return githubToken.token; + } + } + catch { + log(chalk.yellow('Token is expired or invalid!')); + log('Generating a new Github token...'); + } + } + const newToken = await ghauth(); + globalConfig.set(`users.${userId}.auth.github`, newToken); + return newToken.token; +}; +const getGitHubClient = (token) => new Octokit({ + auth: `token ${token}`, +}); +const addDeployKey = async ({ api, octokit, repoName, repoOwner, }) => { + log('Adding deploy key to repository...'); + const key = await createDeployKey({ api }); + try { + await octokit.repos.createDeployKey({ + title: 'Netlify Deploy Key', + key: key.public_key ?? '', + owner: repoOwner, + repo: repoName, + read_only: true, + }); + log('Deploy key added!'); + return key; + } + catch (error) { + let message = formatErrorMessage({ message: 'Failed adding GitHub deploy key', error }); + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + if (error.status === 404) { + const { name, owner } = formatRepoAndOwner({ repoName, repoOwner }); + message = `${message}. Does the repository ${name} exist and do ${owner} has the correct permissions to set up deploy keys?`; + } + return logAndThrowError(message); + } +}; +const getGitHubRepo = async ({ octokit, repoName, repoOwner, }) => { + try { + const { data } = await octokit.repos.get({ + owner: repoOwner, + repo: repoName, + }); + return data; + } + catch (error) { + let message = formatErrorMessage({ message: 'Failed retrieving GitHub repository information', error }); + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + if (error.status === 404) { + const { name, owner } = formatRepoAndOwner({ repoName, repoOwner }); + message = `${message}. Does the repository ${name} exist and accessible by ${owner}`; + } + return logAndThrowError(message); + } +}; +// @ts-expect-error TS(7031) FIXME: Binding element 'deployHook' implicitly has an 'an... Remove this comment to see the full error message +const hookExists = async ({ deployHook, octokit, repoName, repoOwner }) => { + try { + const { data: hooks } = await octokit.repos.listWebhooks({ + owner: repoOwner, + repo: repoName, + per_page: PAGE_SIZE, + }); + // @ts-expect-error TS(7006) FIXME: Parameter 'hook' implicitly has an 'any' type. + const exists = hooks.some((hook) => hook.config.url === deployHook); + return exists; + } + catch { + // we don't need to fail if listHooks errors out + return false; + } +}; +// @ts-expect-error TS(7031) FIXME: Binding element 'deployHook' implicitly has an 'an... Remove this comment to see the full error message +const addDeployHook = async ({ deployHook, octokit, repoName, repoOwner }) => { + const exists = await hookExists({ deployHook, octokit, repoOwner, repoName }); + if (!exists) { + try { + await octokit.repos.createWebhook({ + owner: repoOwner, + repo: repoName, + name: 'web', + config: { + url: deployHook, + content_type: 'json', + }, + events: ['push', 'pull_request', 'delete'], + active: true, + }); + } + catch (error) { + // Ignore exists error if the list doesn't return all installed hooks + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + if (!error.message.includes('Hook already exists on this repository')) { + let message = formatErrorMessage({ message: 'Failed creating repo hook', error }); + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + if (error.status === 404) { + const { name, owner } = formatRepoAndOwner({ repoName, repoOwner }); + message = `${message}. Does the repository ${name} and do ${owner} has the correct permissions to set up hooks`; + } + return logAndThrowError(message); + } + } + } +}; +const GITHUB_HOOK_EVENTS = ['deploy_created', 'deploy_failed', 'deploy_building']; +const GITHUB_HOOK_TYPE = 'github_commit_status'; +// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message +const upsertHook = async ({ api, event, ntlHooks, siteId, token }) => { + // @ts-expect-error TS(7006) FIXME: Parameter 'hook' implicitly has an 'any' type. + const ntlHook = ntlHooks.find((hook) => hook.type === GITHUB_HOOK_TYPE && hook.event === event); + if (!ntlHook || ntlHook.disabled) { + return await api.createHookBySiteId({ + site_id: siteId, + body: { + type: GITHUB_HOOK_TYPE, + event, + data: { + access_token: token, + }, + }, + }); + } + return await api.updateHook({ + hook_id: ntlHook.id, + body: { + data: { + access_token: token, + }, + }, + }); +}; +// @ts-expect-error TS(7031) FIXME: Binding element 'api' implicitly has an 'any' type... Remove this comment to see the full error message +const addNotificationHooks = async ({ api, siteId, token }) => { + log(`Creating Netlify GitHub Notification Hooks...`); + let ntlHooks; + try { + ntlHooks = await api.listHooksBySiteId({ siteId }); + } + catch (error) { + const message = formatErrorMessage({ message: 'Failed retrieving Netlify hooks', error }); + return logAndThrowError(message); + } + await Promise.all(GITHUB_HOOK_EVENTS.map(async (event) => { + try { + await upsertHook({ ntlHooks, event, api, siteId, token }); + } + catch (error) { + const message = formatErrorMessage({ message: `Failed settings Netlify hook ${chalk.magenta(event)}`, error }); + return logAndThrowError(message); + } + })); + log(`Netlify Notification Hooks configured!`); +}; +export const configGithub = async ({ command, repoName, repoOwner, siteId, }) => { + const { netlify } = command; + const { api, cachedConfig: { configPath }, config, globalConfig, repositoryRoot, } = netlify; + const token = await getGitHubToken({ globalConfig }); + const { baseDir, buildCmd, buildDir, functionsDir, pluginsToInstall } = await getBuildSettings({ + config, + command, + }); + await saveNetlifyToml({ repositoryRoot, config, configPath, baseDir, buildCmd, buildDir, functionsDir }); + log(); + const octokit = getGitHubClient(token); + const [deployKey, githubRepo] = await Promise.all([ + addDeployKey({ api, octokit, repoOwner, repoName }), + getGitHubRepo({ octokit, repoOwner, repoName }), + ]); + const repo = { + id: githubRepo.id, + provider: 'github', + repo_path: githubRepo.full_name, + repo_branch: githubRepo.default_branch, + allowed_branches: [githubRepo.default_branch], + deploy_key_id: deployKey.id, + base: baseDir, + dir: buildDir, + functions_dir: functionsDir, + ...(buildCmd && { cmd: buildCmd }), + }; + const updatedSite = await setupSite({ + api, + siteId, + repo, + configPlugins: config.plugins ?? [], + pluginsToInstall, + }); + await addDeployHook({ deployHook: updatedSite.deploy_hook, octokit, repoOwner, repoName }); + log(); + await addNotificationHooks({ siteId, api, token }); +}; +//# sourceMappingURL=config-github.js.map \ No newline at end of file diff --git a/dist/utils/init/config-github.js.map b/dist/utils/init/config-github.js.map new file mode 100644 index 00000000000..79467625b4f --- /dev/null +++ b/dist/utils/init/config-github.js.map @@ -0,0 +1 @@ +{"version":3,"file":"config-github.js","sourceRoot":"","sources":["../../../src/utils/init/config-github.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/init/config-manual.d.ts b/dist/utils/init/config-manual.d.ts new file mode 100644 index 00000000000..2f31d7a7324 --- /dev/null +++ b/dist/utils/init/config-manual.d.ts @@ -0,0 +1,8 @@ +import type BaseCommand from '../../commands/base-command.js'; +import type { RepoData } from '../get-repo-data.js'; +export default function configManual({ command, repoData, siteId, }: { + command: BaseCommand; + repoData: RepoData; + siteId: string; +}): Promise; +//# sourceMappingURL=config-manual.d.ts.map \ No newline at end of file diff --git a/dist/utils/init/config-manual.d.ts.map b/dist/utils/init/config-manual.d.ts.map new file mode 100644 index 00000000000..87bfef28b8a --- /dev/null +++ b/dist/utils/init/config-manual.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"config-manual.d.ts","sourceRoot":"","sources":["../../../src/utils/init/config-manual.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,WAAW,MAAM,gCAAgC,CAAA;AAC7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AA0DnD,wBAA8B,YAAY,CAAC,EACzC,OAAO,EACP,QAAQ,EACR,MAAM,GACP,EAAE;IACD,OAAO,EAAE,WAAW,CAAA;IACpB,QAAQ,EAAE,QAAQ,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;CACf,iBA0CA"} \ No newline at end of file diff --git a/dist/utils/init/config-manual.js b/dist/utils/init/config-manual.js new file mode 100644 index 00000000000..d9eabd64d2b --- /dev/null +++ b/dist/utils/init/config-manual.js @@ -0,0 +1,86 @@ +import inquirer from 'inquirer'; +import { exit, log } from '../command-helpers.js'; +import { createDeployKey, getBuildSettings, saveNetlifyToml, setupSite } from './utils.js'; +/** + * Prompts for granting the netlify ssh public key access to your repo + */ +const addDeployKey = async (deployKey) => { + log('\nGive this Netlify SSH public key access to your repository:\n'); + // FIXME(serhalp): Handle nullish `deployKey.public_key` by throwing user-facing error or fixing upstream type. + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + log(`\n${deployKey.public_key}\n\n`); + const { sshKeyAdded } = (await inquirer.prompt([ + { + type: 'confirm', + name: 'sshKeyAdded', + message: 'Continue?', + default: true, + }, + ])); + if (!sshKeyAdded) { + return exit(); + } +}; +const getRepoPath = async ({ repoData }) => { + const { repoPath } = await inquirer.prompt([ + { + type: 'input', + name: 'repoPath', + message: 'The SSH URL of the remote git repo:', + default: repoData.url, + validate: (url) => (SSH_URL_REGEXP.test(url) ? true : 'The URL provided does not use the SSH protocol'), + }, + ]); + return repoPath; +}; +const addDeployHook = async (deployHook) => { + log('\nConfigure the following webhook for your repository:\n'); + // FIXME(serhalp): Handle nullish `deployHook` by throwing user-facing error or fixing upstream type. + // eslint-disable-next-line @typescript-eslint/restrict-template-expressions + log(`\n${deployHook}\n\n`); + const { deployHookAdded } = await inquirer.prompt([ + { + type: 'confirm', + name: 'deployHookAdded', + message: 'Continue?', + default: true, + }, + ]); + return deployHookAdded; +}; +export default async function configManual({ command, repoData, siteId, }) { + const { netlify } = command; + const { api, cachedConfig: { configPath }, config, repositoryRoot, } = netlify; + const { baseDir, buildCmd, buildDir, functionsDir, pluginsToInstall } = await getBuildSettings({ + config, + command, + }); + await saveNetlifyToml({ repositoryRoot, config, configPath, baseDir, buildCmd, buildDir, functionsDir }); + const deployKey = await createDeployKey({ api }); + await addDeployKey(deployKey); + const repoPath = await getRepoPath({ repoData }); + const repo = { + provider: 'manual', + repo_path: repoPath, + repo_branch: repoData.branch, + allowed_branches: [repoData.branch], + deploy_key_id: deployKey.id, + base: baseDir, + dir: buildDir, + functions_dir: functionsDir, + ...(buildCmd && { cmd: buildCmd }), + }; + const updatedSite = await setupSite({ + api, + siteId, + repo, + configPlugins: config.plugins ?? [], + pluginsToInstall, + }); + const deployHookAdded = await addDeployHook(updatedSite.deploy_hook); + if (!deployHookAdded) { + exit(); + } +} +const SSH_URL_REGEXP = /(ssh:\/\/|[a-zA-Z]*@|[a-zA-Z.].*:(?!\/\/))/; +//# sourceMappingURL=config-manual.js.map \ No newline at end of file diff --git a/dist/utils/init/config-manual.js.map b/dist/utils/init/config-manual.js.map new file mode 100644 index 00000000000..795e15f484d --- /dev/null +++ b/dist/utils/init/config-manual.js.map @@ -0,0 +1 @@ +{"version":3,"file":"config-manual.js","sourceRoot":"","sources":["../../../src/utils/init/config-manual.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/init/config.d.ts b/dist/utils/init/config.d.ts new file mode 100644 index 00000000000..23eb8e1e303 --- /dev/null +++ b/dist/utils/init/config.d.ts @@ -0,0 +1,9 @@ +import BaseCommand from '../../commands/base-command.js'; +import type { RepoData } from '../get-repo-data.js'; +export declare const configureRepo: ({ command, manual, repoData, siteId, }: { + command: BaseCommand; + manual: boolean; + repoData: RepoData; + siteId: string; +}) => Promise; +//# sourceMappingURL=config.d.ts.map \ No newline at end of file diff --git a/dist/utils/init/config.d.ts.map b/dist/utils/init/config.d.ts.map new file mode 100644 index 00000000000..1ddb2be4a59 --- /dev/null +++ b/dist/utils/init/config.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/utils/init/config.ts"],"names":[],"mappings":"AAAA,OAAO,WAAW,MAAM,gCAAgC,CAAA;AAExD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAkBnD,eAAO,MAAM,aAAa,GAAU,wCAKjC;IACD,OAAO,EAAE,WAAW,CAAA;IACpB,MAAM,EAAE,OAAO,CAAA;IACf,QAAQ,EAAE,QAAQ,CAAA;IAClB,MAAM,EAAE,MAAM,CAAA;CACf,kBAWA,CAAA"} \ No newline at end of file diff --git a/dist/utils/init/config.js b/dist/utils/init/config.js new file mode 100644 index 00000000000..11a6ed8e744 --- /dev/null +++ b/dist/utils/init/config.js @@ -0,0 +1,29 @@ +import { chalk, log } from '../command-helpers.js'; +import { configGithub } from './config-github.js'; +import configManual from './config-manual.js'; +const logSuccess = ({ provider }) => { + log(); + log(chalk.greenBright.bold.underline(`Success! Netlify CI/CD Configured!`)); + log(); + log(`This project is now configured to automatically deploy from ${provider} branches & pull requests`); + log(); + log(`Next steps: + + ${chalk.cyanBright.bold('git push')} Push to your git repository to trigger new project builds + ${chalk.cyanBright.bold('netlify open')} Open the Netlify admin URL of your project + `); +}; +export const configureRepo = async ({ command, manual, repoData, siteId, }) => { + if (manual) { + await configManual({ command, siteId, repoData }); + } + else if (repoData.provider === 'github') { + await configGithub({ command, siteId, repoName: repoData.name ?? '', repoOwner: repoData.owner ?? '' }); + } + else { + log(`No configurator found for the provided git remote. Configuring manually...`); + await configManual({ command, siteId, repoData }); + } + logSuccess(repoData); +}; +//# sourceMappingURL=config.js.map \ No newline at end of file diff --git a/dist/utils/init/config.js.map b/dist/utils/init/config.js.map new file mode 100644 index 00000000000..00967b616b1 --- /dev/null +++ b/dist/utils/init/config.js.map @@ -0,0 +1 @@ +{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../src/utils/init/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAGlD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,YAAY,MAAM,oBAAoB,CAAA;AAE7C,MAAM,UAAU,GAAG,CAAC,EAAE,QAAQ,EAAY,EAAQ,EAAE;IAClD,GAAG,EAAE,CAAA;IACL,GAAG,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,SAAS,CAAC,oCAAoC,CAAC,CAAC,CAAA;IAC3E,GAAG,EAAE,CAAA;IACL,GAAG,CAAC,+DAA+D,QAAQ,2BAA2B,CAAC,CAAA;IACvG,GAAG,EAAE,CAAA;IACL,GAAG,CAAC;;IAEF,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,UAAU,CAAC;IACjC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,cAAc,CAAC;GACtC,CAAC,CAAA;AACJ,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,EAClC,OAAO,EACP,MAAM,EACN,QAAQ,EACR,MAAM,GAMP,EAAE,EAAE;IACH,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,YAAY,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAA;IACnD,CAAC;SAAM,IAAI,QAAQ,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAC1C,MAAM,YAAY,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,IAAI,IAAI,EAAE,EAAE,SAAS,EAAE,QAAQ,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC,CAAA;IACzG,CAAC;SAAM,CAAC;QACN,GAAG,CAAC,4EAA4E,CAAC,CAAA;QACjF,MAAM,YAAY,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAA;IACnD,CAAC;IAED,UAAU,CAAC,QAAQ,CAAC,CAAA;AACtB,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/init/plugins.d.ts b/dist/utils/init/plugins.d.ts new file mode 100644 index 00000000000..2445ef29d8e --- /dev/null +++ b/dist/utils/init/plugins.d.ts @@ -0,0 +1,7 @@ +import type { NormalizedCachedConfigConfig } from '../command-helpers.js'; +import type { Plugin } from '../types.js'; +export declare const getRecommendPlugins: (frameworkPlugins: string[], config: NormalizedCachedConfigConfig) => string[]; +export declare const getUIPlugins: (configPlugins: Plugin[]) => { + package: string; +}[]; +//# sourceMappingURL=plugins.d.ts.map \ No newline at end of file diff --git a/dist/utils/init/plugins.d.ts.map b/dist/utils/init/plugins.d.ts.map new file mode 100644 index 00000000000..9249b6ceaee --- /dev/null +++ b/dist/utils/init/plugins.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../../../src/utils/init/plugins.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,uBAAuB,CAAA;AACzE,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAKzC,eAAO,MAAM,mBAAmB,GAAI,kBAAkB,MAAM,EAAE,EAAE,QAAQ,4BAA4B,KAAG,MAAM,EACtB,CAAA;AAEvF,eAAO,MAAM,YAAY,GAAI,eAAe,MAAM,EAAE,KAAG;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,EAC2B,CAAA"} \ No newline at end of file diff --git a/dist/utils/init/plugins.js b/dist/utils/init/plugins.js new file mode 100644 index 00000000000..998945f2b87 --- /dev/null +++ b/dist/utils/init/plugins.js @@ -0,0 +1,4 @@ +const isPluginInstalled = (configPlugins, pluginName) => configPlugins.some(({ package: configPlugin }) => configPlugin === pluginName); +export const getRecommendPlugins = (frameworkPlugins, config) => frameworkPlugins.filter((plugin) => !isPluginInstalled(config.plugins ?? [], plugin)); +export const getUIPlugins = (configPlugins) => configPlugins.filter(({ origin }) => origin === 'ui').map(({ package: pkg }) => ({ package: pkg })); +//# sourceMappingURL=plugins.js.map \ No newline at end of file diff --git a/dist/utils/init/plugins.js.map b/dist/utils/init/plugins.js.map new file mode 100644 index 00000000000..80ef7a98af7 --- /dev/null +++ b/dist/utils/init/plugins.js.map @@ -0,0 +1 @@ +{"version":3,"file":"plugins.js","sourceRoot":"","sources":["../../../src/utils/init/plugins.ts"],"names":[],"mappings":"AAGA,MAAM,iBAAiB,GAAG,CAAC,aAAuB,EAAE,UAAkB,EAAW,EAAE,CACjF,aAAa,CAAC,IAAI,CAAC,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,EAAE,EAAE,CAAC,YAAY,KAAK,UAAU,CAAC,CAAA;AAEhF,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,gBAA0B,EAAE,MAAoC,EAAY,EAAE,CAChH,gBAAgB,CAAC,MAAM,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,OAAO,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC,CAAA;AAEvF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,aAAuB,EAAyB,EAAE,CAC7E,aAAa,CAAC,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,KAAK,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/init/utils.d.ts b/dist/utils/init/utils.d.ts new file mode 100644 index 00000000000..83402a33bd7 --- /dev/null +++ b/dist/utils/init/utils.d.ts @@ -0,0 +1,154 @@ +import type { NetlifyAPI } from '@netlify/api'; +import type BaseCommand from '../../commands/base-command.js'; +import { type NormalizedCachedConfigConfig } from '../command-helpers.js'; +import type { Plugin } from '../types.js'; +/** + * Retrieve a list of plugins to auto install + * @param pluginsToAlwaysInstall these plugins represent runtimes that are + * expected to be "automatically" installed. Even though + * they can be installed on package/toml, we always + * want them installed in the site settings. When installed + * there our build will automatically install the latest without + * user management of the versioning. + */ +export declare const getPluginsToAutoInstall: (_command: BaseCommand, pluginsInstalled?: string[], pluginsRecommended?: string[]) => string[]; +export declare const getBuildSettings: ({ command, config, }: { + command: BaseCommand; + config: NormalizedCachedConfigConfig; +}) => Promise<{ + baseDir: string | undefined; + buildCmd: string; + buildDir: string; + functionsDir: string; + pluginsToInstall: { + package: string; + }[]; +}>; +export declare const saveNetlifyToml: ({ baseDir, buildCmd, buildDir, config, configPath, functionsDir, repositoryRoot, }: { + baseDir: string | undefined; + buildCmd: string; + buildDir: string; + config: NormalizedCachedConfigConfig; + configPath: string | undefined; + functionsDir: string | undefined; + repositoryRoot: string; +}) => Promise; +export declare const formatErrorMessage: ({ error, message }: { + error: any; + message: any; +}) => string; +export type DeployKey = Awaited>; +export declare const createDeployKey: ({ api }: { + api: NetlifyAPI; +}) => Promise; +type UpdateSiteRequestBody = Exclude[0]['body'], () => unknown>; +export declare const updateSite: ({ api, options, siteId, }: { + api: NetlifyAPI; + options: UpdateSiteRequestBody; + siteId: string; +}) => Promise<{ + id?: string; + state?: string; + plan?: string; + name?: string; + custom_domain?: string; + domain_aliases?: string[]; + branch_deploy_custom_domain?: string; + deploy_preview_custom_domain?: string; + password?: string; + notification_email?: string; + url?: string; + ssl_url?: string; + admin_url?: string; + screenshot_url?: string; + created_at?: string; + updated_at?: string; + user_id?: string; + session_id?: string; + ssl?: boolean; + force_ssl?: boolean; + managed_dns?: boolean; + deploy_url?: string; + published_deploy?: import("@netlify/open-api").components["schemas"]["deploy"]; + account_id?: string; + account_name?: string; + account_slug?: string; + git_provider?: string; + deploy_hook?: string; + capabilities?: { + [key: string]: { + [key: string]: unknown; + }; + }; + processing_settings?: { + html?: { + pretty_urls?: boolean; + }; + }; + build_settings?: import("@netlify/open-api").components["schemas"]["repoInfo"]; + id_domain?: string; + default_hooks_data?: { + access_token?: string; + }; + build_image?: string; + prerender?: string; + functions_region?: string; +}>; +export declare const setupSite: ({ api, configPlugins, pluginsToInstall, repo, siteId, }: { + api: NetlifyAPI; + configPlugins: Plugin[]; + pluginsToInstall: { + package: string; + }[]; + repo: NonNullable["repo"]; + siteId: string; +}) => Promise<{ + id?: string; + state?: string; + plan?: string; + name?: string; + custom_domain?: string; + domain_aliases?: string[]; + branch_deploy_custom_domain?: string; + deploy_preview_custom_domain?: string; + password?: string; + notification_email?: string; + url?: string; + ssl_url?: string; + admin_url?: string; + screenshot_url?: string; + created_at?: string; + updated_at?: string; + user_id?: string; + session_id?: string; + ssl?: boolean; + force_ssl?: boolean; + managed_dns?: boolean; + deploy_url?: string; + published_deploy?: import("@netlify/open-api").components["schemas"]["deploy"]; + account_id?: string; + account_name?: string; + account_slug?: string; + git_provider?: string; + deploy_hook?: string; + capabilities?: { + [key: string]: { + [key: string]: unknown; + }; + }; + processing_settings?: { + html?: { + pretty_urls?: boolean; + }; + }; + build_settings?: import("@netlify/open-api").components["schemas"]["repoInfo"]; + id_domain?: string; + default_hooks_data?: { + access_token?: string; + }; + build_image?: string; + prerender?: string; + functions_region?: string; +}>; +export {}; +//# sourceMappingURL=utils.d.ts.map \ No newline at end of file diff --git a/dist/utils/init/utils.d.ts.map b/dist/utils/init/utils.d.ts.map new file mode 100644 index 00000000000..de9a90285bb --- /dev/null +++ b/dist/utils/init/utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/utils/init/utils.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,cAAc,CAAA;AAK9C,OAAO,KAAK,WAAW,MAAM,gCAAgC,CAAA;AAI7D,OAAO,EAAgC,KAAK,4BAA4B,EAAQ,MAAM,uBAAuB,CAAA;AAC7G,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAMzC;;;;;;;;GAQG;AACH,eAAO,MAAM,uBAAuB,GAClC,UAAU,WAAW,EACrB,mBAAkB,MAAM,EAAO,EAC/B,qBAAoB,MAAM,EAAO,aASlC,CAAA;AAiDD,eAAO,MAAM,gBAAgB,GAAU,sBAGpC;IACD,OAAO,EAAE,WAAW,CAAA;IACpB,MAAM,EAAE,4BAA4B,CAAA;CACrC;;;;;;;;EA2BA,CAAA;AA6BD,eAAO,MAAM,eAAe,GAAU,oFAQnC;IACD,OAAO,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,4BAA4B,CAAA;IACpC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAA;IAC9B,YAAY,EAAE,MAAM,GAAG,SAAS,CAAA;IAChC,cAAc,EAAE,MAAM,CAAA;CACvB,kBAoCA,CAAA;AAGD,eAAO,MAAM,kBAAkB,GAAI;;;CAAkB,WAGpD,CAAA;AAED,MAAM,MAAM,SAAS,GAAG,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAA;AAE1E,eAAO,MAAM,eAAe,GAAU,SAAS;IAAE,GAAG,EAAE,UAAU,CAAA;CAAE,KAAG,OAAO,CAAC,SAAS,CAQrF,CAAA;AAGD,KAAK,qBAAqB,GAAG,OAAO,CAAC,UAAU,CAAC,UAAU,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,OAAO,CAAC,CAAA;AAEpG,eAAO,MAAM,UAAU,GAAU,2BAI9B;IACD,GAAG,EAAE,UAAU,CAAA;IACf,OAAO,EAAE,qBAAqB,CAAA;IAC9B,MAAM,EAAE,MAAM,CAAA;CACf;;;;;;;;;;;;;;;;;;;;;;;uBAiCmq0B,iDAAsB;;;;;;;;;;;;YAAwQ,CAAC;uBAAyB,CAAC;;;qBAAqD,iDAAsB;;;oBAAyF,CAAC;;;;;EAzBjo1B,CAAA;AAED,eAAO,MAAM,SAAS,GAAU,yDAM7B;IACD,GAAG,EAAE,UAAU,CAAA;IACf,aAAa,EAAE,MAAM,EAAE,CAAA;IACvB,gBAAgB,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACvC,IAAI,EAAE,WAAW,CAAC,qBAAqB,CAAC,CAAC,MAAM,CAAC,CAAA;IAChD,MAAM,EAAE,MAAM,CAAA;CACf;;;;;;;;;;;;;;;;;;;;;;;uBAWmq0B,iDAAsB;;;;;;;;;;;;YAAwQ,CAAC;uBAAyB,CAAC;;;qBAAqD,iDAAsB;;;oBAAyF,CAAC;;;;;EADjo1B,CAAA"} \ No newline at end of file diff --git a/dist/utils/init/utils.js b/dist/utils/init/utils.js new file mode 100644 index 00000000000..50dca1ab266 --- /dev/null +++ b/dist/utils/init/utils.js @@ -0,0 +1,164 @@ +import { writeFile } from 'fs/promises'; +import path from 'path'; +import cleanDeep from 'clean-deep'; +import inquirer from 'inquirer'; +import { fileExistsAsync } from '../../lib/fs.js'; +import { normalizeBackslash } from '../../lib/path.js'; +import { detectBuildSettings } from '../build-info.js'; +import { chalk, logAndThrowError, log, warn } from '../command-helpers.js'; +import { getRecommendPlugins, getUIPlugins } from './plugins.js'; +const formatTitle = (title) => chalk.cyan(title); +/** + * Retrieve a list of plugins to auto install + * @param pluginsToAlwaysInstall these plugins represent runtimes that are + * expected to be "automatically" installed. Even though + * they can be installed on package/toml, we always + * want them installed in the site settings. When installed + * there our build will automatically install the latest without + * user management of the versioning. + */ +export const getPluginsToAutoInstall = (_command, pluginsInstalled = [], pluginsRecommended = []) => { + const nextRuntime = '@netlify/plugin-nextjs'; + const pluginsToAlwaysInstall = new Set([nextRuntime]); + return pluginsRecommended.reduce((acc, plugin) => pluginsInstalled.includes(plugin) && !pluginsToAlwaysInstall.has(plugin) ? acc : [...acc, plugin], []); +}; +const normalizeSettings = (settings, config, command) => { + const plugins = getPluginsToAutoInstall(command, settings.plugins_from_config_file, settings.plugins_recommended); + const recommendedPlugins = getRecommendPlugins(plugins, config); + return { + defaultBaseDir: settings.baseDirectory ?? command.project.relativeBaseDirectory ?? '', + defaultBuildCmd: config.build.command || settings.buildCommand, + defaultBuildDir: settings.dist, + defaultFunctionsDir: config.build.functions || 'netlify/functions', + recommendedPlugins, + }; +}; +const getPromptInputs = ({ defaultBaseDir, defaultBuildCmd, defaultBuildDir, }) => { + const inputs = [ + defaultBaseDir !== '' && { + type: 'input', + name: 'baseDir', + message: 'Base directory `(blank for current dir):', + default: defaultBaseDir, + }, + { + type: 'input', + name: 'buildCmd', + message: 'Your build command (hugo build/yarn run build/etc):', + filter: (val) => (val === '' ? '# no build command' : val), + default: defaultBuildCmd, + }, + { + type: 'input', + name: 'buildDir', + message: 'Directory to deploy (blank for current dir):', + default: defaultBuildDir, + }, + ].filter(Boolean); + return inputs.filter(Boolean); +}; +export const getBuildSettings = async ({ command, config, }) => { + const settings = await detectBuildSettings(command); + const setting = settings.length > 0 ? settings[0] : {}; + const { defaultBaseDir, defaultBuildCmd, defaultBuildDir, defaultFunctionsDir, recommendedPlugins } = normalizeSettings(setting, config, command); + if (recommendedPlugins.length !== 0 && setting.framework?.name) { + log(`Configuring ${formatTitle(setting.framework.name)} runtime...`); + log(); + } + const { baseDir, buildCmd, buildDir } = await inquirer.prompt(getPromptInputs({ + defaultBaseDir, + defaultBuildCmd, + defaultBuildDir, + })); + const pluginsToInstall = recommendedPlugins.map((plugin) => ({ package: plugin })); + const normalizedBaseDir = baseDir ? normalizeBackslash(baseDir) : undefined; + return { baseDir: normalizedBaseDir, buildCmd, buildDir, functionsDir: defaultFunctionsDir, pluginsToInstall }; +}; +const getNetlifyToml = ({ command = '# no build command', functions = 'functions', publish = '.', }) => `# example netlify.toml +[build] + command = "${command}" + functions = "${functions}" + publish = "${publish}" + + ## Uncomment to use this redirect for Single Page Applications like create-react-app. + ## Not needed for static site generators. + #[[redirects]] + # from = "/*" + # to = "/index.html" + # status = 200 + + ## (optional) Settings for Netlify Dev + ## https://github.com/netlify/cli/blob/main/docs/netlify-dev.md#project-detection + #[dev] + # command = "yarn start" # Command to start your dev server + # port = 3000 # Port that the dev server will be listening on + # publish = "dist" # Folder with the static content for _redirect file + + ## more info on configuring this file: https://ntl.fyi/file-based-build-config +`; +export const saveNetlifyToml = async ({ baseDir, buildCmd, buildDir, config, configPath, functionsDir, repositoryRoot, }) => { + const tomlPathParts = [repositoryRoot, baseDir, 'netlify.toml'].filter((part) => part != null && part.length > 0); + const tomlPath = path.join(...tomlPathParts); + if (await fileExistsAsync(tomlPath)) { + return; + } + // We don't want to create a `netlify.toml` file that overrides existing configuration + // In a monorepo the configuration can come from a repo level netlify.toml + // so we make sure it doesn't by checking `configPath === undefined` + // @ts-expect-error TS(2349) + if (configPath === undefined && Object.keys(cleanDeep(config)).length !== 0) { + return; + } + const { makeNetlifyTOML } = await inquirer.prompt([ + { + type: 'confirm', + name: 'makeNetlifyTOML', + message: 'No netlify.toml detected. Would you like to create one with these build settings?', + default: true, + }, + ]); + if (makeNetlifyTOML) { + try { + await writeFile(tomlPath, getNetlifyToml({ command: buildCmd, publish: buildDir, functions: functionsDir }), 'utf-8'); + } + catch (error) { + warn(`Failed saving Netlify toml file: ${error instanceof Error ? error.message : error?.toString()}`); + } + } +}; +// @ts-expect-error TS(7031) FIXME: Binding element 'error' implicitly has an 'any' ty... Remove this comment to see the full error message +export const formatErrorMessage = ({ error, message }) => { + const errorMessage = error.json ? `${error.message} - ${JSON.stringify(error.json)}` : error.message; + return `${message} with error: ${chalk.red(errorMessage)}`; +}; +export const createDeployKey = async ({ api }) => { + try { + const deployKey = await api.createDeployKey(); + return deployKey; + } + catch (error) { + const message = formatErrorMessage({ message: 'Failed creating deploy key', error }); + return logAndThrowError(message); + } +}; +export const updateSite = async ({ api, options, siteId, }) => { + try { + const updatedSite = await api.updateSite({ siteId, body: options }); + return updatedSite; + } + catch (error) { + const message = formatErrorMessage({ message: 'Failed updating project with repo information', error }); + return logAndThrowError(message); + } +}; +export const setupSite = async ({ api, configPlugins, pluginsToInstall, repo, siteId, }) => { + const updatedSite = await updateSite({ + siteId, + api, + // merge existing plugins with new ones + // @ts-expect-error(serhalp) -- `plugins` is missing from `api.updateSite()` req body type + options: { repo, plugins: [...getUIPlugins(configPlugins), ...pluginsToInstall] }, + }); + return updatedSite; +}; +//# sourceMappingURL=utils.js.map \ No newline at end of file diff --git a/dist/utils/init/utils.js.map b/dist/utils/init/utils.js.map new file mode 100644 index 00000000000..5c258e3ce2d --- /dev/null +++ b/dist/utils/init/utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/utils/init/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AACvC,OAAO,IAAI,MAAM,MAAM,CAAA;AAIvB,OAAO,SAAS,MAAM,YAAY,CAAA;AAClC,OAAO,QAAQ,MAAM,UAAU,CAAA;AAG/B,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AACtD,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAA;AACtD,OAAO,EAAE,KAAK,EAAE,gBAAgB,EAAE,GAAG,EAAqC,IAAI,EAAE,MAAM,uBAAuB,CAAA;AAG7G,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AAEhE,MAAM,WAAW,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;AAExD;;;;;;;;GAQG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,QAAqB,EACrB,mBAA6B,EAAE,EAC/B,qBAA+B,EAAE,EACjC,EAAE;IACF,MAAM,WAAW,GAAG,wBAAwB,CAAA;IAC5C,MAAM,sBAAsB,GAAG,IAAI,GAAG,CAAC,CAAC,WAAW,CAAC,CAAC,CAAA;IACrD,OAAO,kBAAkB,CAAC,MAAM,CAC9B,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE,CACd,gBAAgB,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,EAAE,MAAM,CAAC,EACnG,EAAE,CACH,CAAA;AACH,CAAC,CAAA;AAED,MAAM,iBAAiB,GAAG,CAAC,QAA2B,EAAE,MAAoC,EAAE,OAAoB,EAAE,EAAE;IACpH,MAAM,OAAO,GAAG,uBAAuB,CAAC,OAAO,EAAE,QAAQ,CAAC,wBAAwB,EAAE,QAAQ,CAAC,mBAAmB,CAAC,CAAA;IACjH,MAAM,kBAAkB,GAAG,mBAAmB,CAAC,OAAO,EAAE,MAAM,CAAC,CAAA;IAE/D,OAAO;QACL,cAAc,EAAE,QAAQ,CAAC,aAAa,IAAI,OAAO,CAAC,OAAO,CAAC,qBAAqB,IAAI,EAAE;QACrF,eAAe,EAAE,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,QAAQ,CAAC,YAAY;QAC9D,eAAe,EAAE,QAAQ,CAAC,IAAI;QAC9B,mBAAmB,EAAE,MAAM,CAAC,KAAK,CAAC,SAAS,IAAI,mBAAmB;QAClE,kBAAkB;KACnB,CAAA;AACH,CAAC,CAAA;AAED,MAAM,eAAe,GAAG,CAAC,EACvB,cAAc,EACd,eAAe,EACf,eAAe,GAKhB,EAAE,EAAE;IACH,MAAM,MAAM,GAAG;QACb,cAAc,KAAK,EAAE,IAAI;YACvB,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,SAAS;YACf,OAAO,EAAE,0CAA0C;YACnD,OAAO,EAAE,cAAc;SACxB;QACD;YACE,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,qDAAqD;YAC9D,MAAM,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,GAAG,CAAC;YAClE,OAAO,EAAE,eAAe;SACzB;QACD;YACE,IAAI,EAAE,OAAO;YACb,IAAI,EAAE,UAAU;YAChB,OAAO,EAAE,8CAA8C;YACvD,OAAO,EAAE,eAAe;SACzB;KACF,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;IAEjB,OAAO,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;AAC/B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EAAE,EACrC,OAAO,EACP,MAAM,GAIP,EAAE,EAAE;IACH,MAAM,QAAQ,GAAG,MAAM,mBAAmB,CAAC,OAAO,CAAC,CAAA;IACnD,MAAM,OAAO,GAAsB,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IACzE,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,GACjG,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;IAE7C,IAAI,kBAAkB,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,SAAS,EAAE,IAAI,EAAE,CAAC;QAC/D,GAAG,CAAC,eAAe,WAAW,CAAC,OAAO,CAAC,SAAS,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QACpE,GAAG,EAAE,CAAA;IACP,CAAC;IAED,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAK3D,eAAe,CAAC;QACd,cAAc;QACd,eAAe;QACf,eAAe;KAChB,CAAC,CACH,CAAA;IAED,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,CAAC,CAAA;IAClF,MAAM,iBAAiB,GAAG,OAAO,CAAC,CAAC,CAAC,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAA;IAE3E,OAAO,EAAE,OAAO,EAAE,iBAAiB,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,CAAA;AAChH,CAAC,CAAA;AAED,MAAM,cAAc,GAAG,CAAC,EACtB,OAAO,GAAG,oBAAoB,EAC9B,SAAS,GAAG,WAAW,EACvB,OAAO,GAAG,GAAG,GACd,EAAE,EAAE,CAAC;;eAES,OAAO;iBACL,SAAS;eACX,OAAO;;;;;;;;;;;;;;;;;CAiBrB,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,EACpC,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,MAAM,EACN,UAAU,EACV,YAAY,EACZ,cAAc,GASf,EAAE,EAAE;IACH,MAAM,aAAa,GAAG,CAAC,cAAc,EAAE,OAAO,EAAE,cAAc,CAAC,CAAC,MAAM,CACpE,CAAC,IAAI,EAAkB,EAAE,CAAC,IAAI,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAC1D,CAAA;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAA;IAC5C,IAAI,MAAM,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;QACpC,OAAM;IACR,CAAC;IAED,sFAAsF;IACtF,0EAA0E;IAC1E,oEAAoE;IACpE,4BAA4B;IAC5B,IAAI,UAAU,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5E,OAAM;IACR,CAAC;IAED,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;QAChD;YACE,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,iBAAiB;YACvB,OAAO,EAAE,mFAAmF;YAC5F,OAAO,EAAE,IAAI;SACd;KACF,CAAC,CAAA;IACF,IAAI,eAAe,EAAE,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,SAAS,CACb,QAAQ,EACR,cAAc,CAAC,EAAE,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC,EACjF,OAAO,CACR,CAAA;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,CAAC,oCAAoC,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAA;QACxG,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED,2IAA2I;AAC3I,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,EAAE;IACvD,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,OAAO,MAAM,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAA;IACpG,OAAO,GAAG,OAAO,gBAAgB,KAAK,CAAC,GAAG,CAAC,YAAY,CAAC,EAAE,CAAA;AAC5D,CAAC,CAAA;AAID,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,EAAE,GAAG,EAAuB,EAAsB,EAAE;IACxF,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,GAAG,CAAC,eAAe,EAAE,CAAA;QAC7C,OAAO,SAAS,CAAA;IAClB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,kBAAkB,CAAC,EAAE,OAAO,EAAE,4BAA4B,EAAE,KAAK,EAAE,CAAC,CAAA;QACpF,OAAO,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAClC,CAAC;AACH,CAAC,CAAA;AAKD,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,EAC/B,GAAG,EACH,OAAO,EACP,MAAM,GAKP,EAAE,EAAE;IACH,IAAI,CAAC;QACH,MAAM,WAAW,GAAG,MAAM,GAAG,CAAC,UAAU,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAA;QACnE,OAAO,WAAW,CAAA;IACpB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,OAAO,GAAG,kBAAkB,CAAC,EAAE,OAAO,EAAE,+CAA+C,EAAE,KAAK,EAAE,CAAC,CAAA;QACvG,OAAO,gBAAgB,CAAC,OAAO,CAAC,CAAA;IAClC,CAAC;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,SAAS,GAAG,KAAK,EAAE,EAC9B,GAAG,EACH,aAAa,EACb,gBAAgB,EAChB,IAAI,EACJ,MAAM,GAOP,EAAE,EAAE;IACH,MAAM,WAAW,GAAG,MAAM,UAAU,CAAC;QACnC,MAAM;QACN,GAAG;QACH,uCAAuC;QACvC,0FAA0F;QAC1F,OAAO,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,GAAG,YAAY,CAAC,aAAa,CAAC,EAAE,GAAG,gBAAgB,CAAC,EAAE;KAClF,CAAC,CAAA;IAEF,OAAO,WAAW,CAAA;AACpB,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/live-tunnel.d.ts b/dist/utils/live-tunnel.d.ts new file mode 100644 index 00000000000..16a436c064c --- /dev/null +++ b/dist/utils/live-tunnel.d.ts @@ -0,0 +1,9 @@ +import type CLIState from './cli-state.js'; +export declare const startLiveTunnel: ({ localPort, netlifyApiToken, siteId, slug, }: { + localPort: number; + netlifyApiToken?: string | null | undefined; + siteId?: string | undefined; + slug: string; +}) => Promise; +export declare const getLiveTunnelSlug: (state: CLIState, override?: string) => string; +//# sourceMappingURL=live-tunnel.d.ts.map \ No newline at end of file diff --git a/dist/utils/live-tunnel.d.ts.map b/dist/utils/live-tunnel.d.ts.map new file mode 100644 index 00000000000..5f434090046 --- /dev/null +++ b/dist/utils/live-tunnel.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"live-tunnel.d.ts","sourceRoot":"","sources":["../../src/utils/live-tunnel.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAiG1C,eAAO,MAAM,eAAe,GAAU,+CAKnC;IACD,SAAS,EAAE,MAAM,CAAA;IACjB,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAA;IAC3C,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC3B,IAAI,EAAE,MAAM,CAAA;CACb,oBAwDA,CAAA;AAED,eAAO,MAAM,iBAAiB,GAAI,OAAO,QAAQ,EAAE,WAAW,MAAM,WAwBnE,CAAA"} \ No newline at end of file diff --git a/dist/utils/live-tunnel.js b/dist/utils/live-tunnel.js new file mode 100644 index 00000000000..41ca8e7d6c1 --- /dev/null +++ b/dist/utils/live-tunnel.js @@ -0,0 +1,126 @@ +import { platform } from 'process'; +import fetch from 'node-fetch'; +import pWaitFor from 'p-wait-for'; +import { v4 as uuidv4 } from 'uuid'; +import { fetchLatestVersion, shouldFetchLatestVersion } from '../lib/exec-fetcher.js'; +import { getPathInHome } from '../lib/settings.js'; +import { NETLIFYDEVERR, NETLIFYDEVLOG, chalk, exit, log } from './command-helpers.js'; +import execa from './execa.js'; +const PACKAGE_NAME = 'live-tunnel-client'; +const EXEC_NAME = PACKAGE_NAME; +const SLUG_LOCAL_STATE_KEY = 'liveTunnelSlug'; +// 1 second +const TUNNEL_POLL_INTERVAL = 1e3; +// 5 minutes +const TUNNEL_POLL_TIMEOUT = 3e5; +const createTunnel = async function ({ netlifyApiToken, siteId, slug, }) { + await installTunnelClient(); + const url = `https://api.netlify.com/api/v1/live_sessions?site_id=${siteId}&slug=${slug}`; + const response = await fetch(url, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${netlifyApiToken}`, + }, + body: JSON.stringify({}), + }); + const data = await response.json(); + if (response.status !== 201) { + // TODO(serhalp): Use typed `netlify` API client? + throw new Error(data != null && typeof data === 'object' && 'message' in data && typeof data.message === 'string' + ? data.message + : ''); + } + return data; +}; +const connectTunnel = function ({ localPort, netlifyApiToken, session, }) { + const execPath = getPathInHome(['tunnel', 'bin', EXEC_NAME]); + const args = ['connect', '-s', session.id, '-t', netlifyApiToken, '-l', localPort.toString()]; + if (process.env.DEBUG) { + args.push('-v'); + log(execPath, args.toString()); + } + const ps = execa(execPath, args, { stdio: 'inherit' }); + void ps.on('close', (code) => exit(code ?? undefined)); + void ps.on('SIGINT', () => exit()); + void ps.on('SIGTERM', () => exit()); +}; +const installTunnelClient = async function () { + const binPath = getPathInHome(['tunnel', 'bin']); + const shouldFetch = await shouldFetchLatestVersion({ + binPath, + packageName: PACKAGE_NAME, + execArgs: ['version'], + pattern: `${PACKAGE_NAME}\\/v?([^\\s]+)`, + execName: EXEC_NAME, + }); + if (!shouldFetch) { + return; + } + log(`${NETLIFYDEVLOG} Installing Live Tunnel Client`); + await fetchLatestVersion({ + packageName: PACKAGE_NAME, + execName: EXEC_NAME, + destination: binPath, + extension: platform === 'win32' ? 'zip' : 'tar.gz', + }); +}; +export const startLiveTunnel = async ({ localPort, netlifyApiToken, siteId, slug, }) => { + if (!siteId) { + console.error(`${NETLIFYDEVERR} Error: no project ID defined, did you forget to run ${chalk.yellow('netlify init')} or ${chalk.yellow('netlify link')}?`); + return exit(1); + } + if (!netlifyApiToken) { + console.error(`${NETLIFYDEVERR} Error: no Netlify auth token defined, did you forget to run ${chalk.yellow('netlify login')} or define 'NETLIFY_AUTH_TOKEN'?`); + return exit(1); + } + const session = await createTunnel({ + siteId, + netlifyApiToken, + slug, + }); + const isLiveTunnelReady = async () => { + const url = `https://api.netlify.com/api/v1/live_sessions/${session.id}`; + const response = await fetch(url, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${netlifyApiToken}`, + }, + }); + const data = await response.json(); + if (response.status !== 200) { + // TODO(serhalp): Use typed `netlify` API client? + throw new Error(data != null && typeof data === 'object' && 'message' in data && typeof data.message === 'string' + ? data.message + : ''); + } + return data.state === 'online'; + }; + connectTunnel({ session, netlifyApiToken, localPort }); + // Waiting for the live session to have a state of `online`. + await pWaitFor(isLiveTunnelReady, { + interval: TUNNEL_POLL_INTERVAL, + timeout: TUNNEL_POLL_TIMEOUT, + }); + return session.session_url; +}; +export const getLiveTunnelSlug = (state, override) => { + if (override !== undefined) { + return override; + } + const newSlug = generateRandomSlug(); + try { + const existingSlug = state.get(SLUG_LOCAL_STATE_KEY); + if (existingSlug !== undefined) { + return existingSlug; + } + state.set(SLUG_LOCAL_STATE_KEY, newSlug); + } + catch (error) { + log(`${NETLIFYDEVERR} Could not read or write local state file: ${error instanceof Error ? error.message : error?.toString() ?? ''}`); + } + return newSlug; +}; +const generateRandomSlug = () => uuidv4().slice(0, 8); +//# sourceMappingURL=live-tunnel.js.map \ No newline at end of file diff --git a/dist/utils/live-tunnel.js.map b/dist/utils/live-tunnel.js.map new file mode 100644 index 00000000000..0dda36d4c8c --- /dev/null +++ b/dist/utils/live-tunnel.js.map @@ -0,0 +1 @@ +{"version":3,"file":"live-tunnel.js","sourceRoot":"","sources":["../../src/utils/live-tunnel.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/mcp-utils.d.ts b/dist/utils/mcp-utils.d.ts new file mode 100644 index 00000000000..171ca9abd5a --- /dev/null +++ b/dist/utils/mcp-utils.d.ts @@ -0,0 +1,22 @@ +import type { ConsumerConfig } from '../recipes/ai-context/context.js'; +/** + * Generate MCP configuration for the detected IDE or development environment + */ +export declare const generateMcpConfig: (ide: ConsumerConfig) => Record; +/** + * VS Code specific MCP configuration + */ +export declare const configureMcpForVSCode: (config: Record, projectPath: string) => Promise; +/** + * Cursor specific MCP configuration + */ +export declare const configureMcpForCursor: (config: Record, projectPath: string) => Promise; +/** + * Windsurf specific MCP configuration + */ +export declare const configureMcpForWindsurf: (config: Record, _projectPath: string) => Promise; +/** + * Generic MCP configuration display + */ +export declare const showGenericMcpConfig: (config: Record, ideName: string) => void; +//# sourceMappingURL=mcp-utils.d.ts.map \ No newline at end of file diff --git a/dist/utils/mcp-utils.d.ts.map b/dist/utils/mcp-utils.d.ts.map new file mode 100644 index 00000000000..a9efe9dfc1d --- /dev/null +++ b/dist/utils/mcp-utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"mcp-utils.d.ts","sourceRoot":"","sources":["../../src/utils/mcp-utils.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kCAAkC,CAAA;AAEtE;;GAEG;AACH,eAAO,MAAM,iBAAiB,GAAI,KAAK,cAAc,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAuC7E,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAAU,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,MAAM,KAAG,OAAO,CAAC,IAAI,CAwB9G,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,qBAAqB,GAAU,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,aAAa,MAAM,KAAG,OAAO,CAAC,IAAI,CAU9G,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,uBAAuB,GAAU,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,cAAc,MAAM,KAAG,OAAO,CAAC,IAAI,CAmCjH,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,oBAAoB,GAAI,QAAQ,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,SAAS,MAAM,KAAG,IAMvF,CAAA"} \ No newline at end of file diff --git a/dist/utils/mcp-utils.js b/dist/utils/mcp-utils.js new file mode 100644 index 00000000000..26c617dac10 --- /dev/null +++ b/dist/utils/mcp-utils.js @@ -0,0 +1,131 @@ +import { resolve } from 'node:path'; +import { promises as fs } from 'node:fs'; +import { homedir } from 'node:os'; +import { chalk, log } from './command-helpers.js'; +/** + * Generate MCP configuration for the detected IDE or development environment + */ +export const generateMcpConfig = (ide) => { + const configs = { + vscode: { + servers: { + netlify: { + type: 'stdio', + command: 'npx', + args: ['-y', '@netlify/mcp'], + }, + }, + }, + cursor: { + mcpServers: { + netlify: { + command: 'npx', + args: ['-y', '@netlify/mcp'], + }, + }, + }, + windsurf: { + mcpServers: { + netlify: { + command: 'npx', + args: ['-y', '@netlify/mcp'], + }, + }, + }, + }; + return (configs[ide.key] ?? { + mcpServers: { + netlify: { + command: 'npx', + args: ['-y', '@netlify/mcp'], + }, + }, + }); +}; +/** + * VS Code specific MCP configuration + */ +export const configureMcpForVSCode = async (config, projectPath) => { + const vscodeDirPath = resolve(projectPath, '.vscode'); + const configPath = resolve(vscodeDirPath, 'mcp.json'); + try { + // Create .vscode directory if it doesn't exist + await fs.mkdir(vscodeDirPath, { recursive: true }); + // Write or update mcp.json + let existingConfig = {}; + try { + const existingContent = await fs.readFile(configPath, 'utf-8'); + existingConfig = JSON.parse(existingContent); + } + catch { + // File doesn't exist or is invalid JSON + } + const updatedConfig = { ...existingConfig, ...config }; + await fs.writeFile(configPath, JSON.stringify(updatedConfig, null, 2), 'utf-8'); + log(`${chalk.green('āœ…')} VS Code MCP configuration saved to ${chalk.cyan('.vscode/mcp.json')}`); + } + catch (error) { + throw new Error(`Failed to configure VS Code MCP: ${error instanceof Error ? error.message : 'Unknown error'}`); + } +}; +/** + * Cursor specific MCP configuration + */ +export const configureMcpForCursor = async (config, projectPath) => { + const configPath = resolve(projectPath, '.cursor', 'mcp.json'); + try { + await fs.mkdir(resolve(projectPath, '.cursor'), { recursive: true }); + await fs.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8'); + log(`${chalk.green('āœ…')} Cursor MCP configuration saved to ${chalk.cyan('.cursor/mcp.json')}`); + } + catch (error) { + throw new Error(`Failed to configure Cursor MCP: ${error instanceof Error ? error.message : 'Unknown error'}`); + } +}; +/** + * Windsurf specific MCP configuration + */ +export const configureMcpForWindsurf = async (config, _projectPath) => { + const windsurfDirPath = resolve(homedir(), '.codeium', 'windsurf'); + const configPath = resolve(windsurfDirPath, 'mcp_config.json'); + try { + // Create .codeium/windsurf directory if it doesn't exist + await fs.mkdir(windsurfDirPath, { recursive: true }); + // Read existing config or create new one + let existingConfig = {}; + try { + const existingContent = await fs.readFile(configPath, 'utf-8'); + existingConfig = JSON.parse(existingContent); + } + catch { + // File doesn't exist or is invalid JSON + } + // Merge mcpServers from both configs + const existingServers = existingConfig.mcpServers ?? {}; + const newServers = config.mcpServers ?? {}; + const updatedConfig = { + ...existingConfig, + mcpServers: { + ...existingServers, + ...newServers, + }, + }; + await fs.writeFile(configPath, JSON.stringify(updatedConfig, null, 2), 'utf-8'); + log(`${chalk.green('āœ…')} Windsurf MCP configuration saved`); + log(`${chalk.gray('šŸ’”')} Restart Windsurf to activate the MCP server`); + } + catch (error) { + throw new Error(`Failed to configure Windsurf MCP: ${error instanceof Error ? error.message : 'Unknown error'}`); + } +}; +/** + * Generic MCP configuration display + */ +export const showGenericMcpConfig = (config, ideName) => { + log(`\n${chalk.yellow('šŸ“‹ Manual configuration required')}`); + log(`Please add the following configuration to your ${ideName} settings:`); + log(`\n${chalk.gray('--- Configuration ---')}`); + log(JSON.stringify(config, null, 2)); + log(`${chalk.gray('--- End Configuration ---')}\n`); +}; +//# sourceMappingURL=mcp-utils.js.map \ No newline at end of file diff --git a/dist/utils/mcp-utils.js.map b/dist/utils/mcp-utils.js.map new file mode 100644 index 00000000000..79d4fda9ad4 --- /dev/null +++ b/dist/utils/mcp-utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"mcp-utils.js","sourceRoot":"","sources":["../../src/utils/mcp-utils.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/multimap.d.ts b/dist/utils/multimap.d.ts new file mode 100644 index 00000000000..96f5c8dbe0a --- /dev/null +++ b/dist/utils/multimap.d.ts @@ -0,0 +1,6 @@ +export declare class MultiMap { + private map; + add(key: K, value: V): void; + get(key: K): readonly V[]; +} +//# sourceMappingURL=multimap.d.ts.map \ No newline at end of file diff --git a/dist/utils/multimap.d.ts.map b/dist/utils/multimap.d.ts.map new file mode 100644 index 00000000000..6ce91154929 --- /dev/null +++ b/dist/utils/multimap.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"multimap.d.ts","sourceRoot":"","sources":["../../src/utils/multimap.ts"],"names":[],"mappings":"AAAA,qBAAa,QAAQ,CAAC,CAAC,EAAE,CAAC;IACxB,OAAO,CAAC,GAAG,CAAoB;IAE/B,GAAG,CAAC,GAAG,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC;IAIpB,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,SAAS,CAAC,EAAE;CAG1B"} \ No newline at end of file diff --git a/dist/utils/multimap.js b/dist/utils/multimap.js new file mode 100644 index 00000000000..69a2d245e60 --- /dev/null +++ b/dist/utils/multimap.js @@ -0,0 +1,10 @@ +export class MultiMap { + map = new Map(); + add(key, value) { + this.map.set(key, [...(this.map.get(key) ?? []), value]); + } + get(key) { + return this.map.get(key) ?? []; + } +} +//# sourceMappingURL=multimap.js.map \ No newline at end of file diff --git a/dist/utils/multimap.js.map b/dist/utils/multimap.js.map new file mode 100644 index 00000000000..978a6471ebc --- /dev/null +++ b/dist/utils/multimap.js.map @@ -0,0 +1 @@ +{"version":3,"file":"multimap.js","sourceRoot":"","sources":["../../src/utils/multimap.ts"],"names":[],"mappings":"AAAA,MAAM,OAAO,QAAQ;IACX,GAAG,GAAG,IAAI,GAAG,EAAU,CAAA;IAE/B,GAAG,CAAC,GAAM,EAAE,KAAQ;QAClB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,CAAA;IAC1D,CAAC;IAED,GAAG,CAAC,GAAM;QACR,OAAO,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAA;IAChC,CAAC;CACF"} \ No newline at end of file diff --git a/dist/utils/nodejs-compile-cache.d.ts b/dist/utils/nodejs-compile-cache.d.ts new file mode 100644 index 00000000000..237da83e355 --- /dev/null +++ b/dist/utils/nodejs-compile-cache.d.ts @@ -0,0 +1,24 @@ +export declare let didEnableCompileCache: boolean; +/** + * This enables the Node.js compile cache (aka the V8 code cache or bytecode cache), if it is available and if we + * detect that we are not running in a CI environment. + * + * This feature is a performance optimization that allows the V8 JS engine to cache some (parse/compile) work from one + * execution on disk and reuse it on subsequent executions. There's a performance hit on the first (cold) run, but all + * subsequent (warm) runs get performance savings. As the CLI is generally run hundreds of times, it is worth a small + * overhead on the occasional cold run to shave tens to hundreds of milliseconds on several subsequent warm runs. + * + * Keep in mind that the cache is specific to a version of netlify-cli and a version of node.js and it is stored on the + * user's disk in a temp dir. If any of these changes or the temp dir is cleared, the next run is a cold run. + * + * The programmatic API to enable this (`enableCompileCache()`) was added in node 22.8.0, but we currently support + * >=20.12.2, hence the conditional below. (For completeness, note that support via the env var was added in 22.1.0.) + * + * The Netlify CLI is often used in CI workflows. In this context, we wouldn't want the overhead of the first run + * because we almost certainly would not get any benefits on "subsequent runs". Even if the user has configured caching + * of the CLI itself, there's no chance they've configured the V8 compile cache directory to be cached. + * + * @see https://nodejs.org/api/module.html#moduleenablecompilecachecachedir + */ +export declare const maybeEnableCompileCache: () => void; +//# sourceMappingURL=nodejs-compile-cache.d.ts.map \ No newline at end of file diff --git a/dist/utils/nodejs-compile-cache.d.ts.map b/dist/utils/nodejs-compile-cache.d.ts.map new file mode 100644 index 00000000000..e4150b83e8d --- /dev/null +++ b/dist/utils/nodejs-compile-cache.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"nodejs-compile-cache.d.ts","sourceRoot":"","sources":["../../src/utils/nodejs-compile-cache.ts"],"names":[],"mappings":"AAIA,eAAO,IAAI,qBAAqB,SAAQ,CAAA;AAExC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,uBAAuB,QAAO,IAmB1C,CAAA"} \ No newline at end of file diff --git a/dist/utils/nodejs-compile-cache.js b/dist/utils/nodejs-compile-cache.js new file mode 100644 index 00000000000..a44bf26b478 --- /dev/null +++ b/dist/utils/nodejs-compile-cache.js @@ -0,0 +1,44 @@ +import * as module from 'module'; +import { isCI } from 'ci-info'; +export let didEnableCompileCache = false; +/** + * This enables the Node.js compile cache (aka the V8 code cache or bytecode cache), if it is available and if we + * detect that we are not running in a CI environment. + * + * This feature is a performance optimization that allows the V8 JS engine to cache some (parse/compile) work from one + * execution on disk and reuse it on subsequent executions. There's a performance hit on the first (cold) run, but all + * subsequent (warm) runs get performance savings. As the CLI is generally run hundreds of times, it is worth a small + * overhead on the occasional cold run to shave tens to hundreds of milliseconds on several subsequent warm runs. + * + * Keep in mind that the cache is specific to a version of netlify-cli and a version of node.js and it is stored on the + * user's disk in a temp dir. If any of these changes or the temp dir is cleared, the next run is a cold run. + * + * The programmatic API to enable this (`enableCompileCache()`) was added in node 22.8.0, but we currently support + * >=20.12.2, hence the conditional below. (For completeness, note that support via the env var was added in 22.1.0.) + * + * The Netlify CLI is often used in CI workflows. In this context, we wouldn't want the overhead of the first run + * because we almost certainly would not get any benefits on "subsequent runs". Even if the user has configured caching + * of the CLI itself, there's no chance they've configured the V8 compile cache directory to be cached. + * + * @see https://nodejs.org/api/module.html#moduleenablecompilecachecachedir + */ +export const maybeEnableCompileCache = () => { + if (isCI) + return; + // The docs recommend turning this off when running tests to generate precise coverage + if (process.env.NODE_ENV === 'test') + return; + // eslint-disable-next-line n/no-unsupported-features/node-builtins + if ('enableCompileCache' in module && typeof module.enableCompileCache === 'function') { + // eslint-disable-next-line n/no-unsupported-features/node-builtins + const { directory } = module.enableCompileCache(); + if (directory == null) + return; + didEnableCompileCache = true; + // TODO(serhalp): Investigate enabling the compile cache for spawned subprocesses by passing + // NODE_COMPILE_CACHE=directory. + return; + } + return; +}; +//# sourceMappingURL=nodejs-compile-cache.js.map \ No newline at end of file diff --git a/dist/utils/nodejs-compile-cache.js.map b/dist/utils/nodejs-compile-cache.js.map new file mode 100644 index 00000000000..adb3aecef57 --- /dev/null +++ b/dist/utils/nodejs-compile-cache.js.map @@ -0,0 +1 @@ +{"version":3,"file":"nodejs-compile-cache.js","sourceRoot":"","sources":["../../src/utils/nodejs-compile-cache.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAA;AAEhC,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAE9B,MAAM,CAAC,IAAI,qBAAqB,GAAG,KAAK,CAAA;AAExC;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,GAAS,EAAE;IAChD,IAAI,IAAI;QAAE,OAAM;IAChB,sFAAsF;IACtF,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,MAAM;QAAE,OAAM;IAE3C,mEAAmE;IACnE,IAAI,oBAAoB,IAAI,MAAM,IAAI,OAAO,MAAM,CAAC,kBAAkB,KAAK,UAAU,EAAE,CAAC;QACtF,mEAAmE;QACnE,MAAM,EAAE,SAAS,EAAE,GAAI,MAAM,CAAC,kBAA8D,EAAE,CAAA;QAE9F,IAAI,SAAS,IAAI,IAAI;YAAE,OAAM;QAC7B,qBAAqB,GAAG,IAAI,CAAA;QAE5B,4FAA4F;QAC5F,gCAAgC;QAEhC,OAAM;IACR,CAAC;IACD,OAAM;AACR,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/normalize-repo-url.d.ts b/dist/utils/normalize-repo-url.d.ts new file mode 100644 index 00000000000..ab46c4d9107 --- /dev/null +++ b/dist/utils/normalize-repo-url.d.ts @@ -0,0 +1,11 @@ +/** + * Normalize a user-provided repository specifier into a git URL and an HTTPS URL. + * + * @param repo Either a GitHub URL or a string in the format `owner/repo` (assumed to be GitHub) + */ +export declare const normalizeRepoUrl: (repo: string) => { + repoUrl: string; + httpsUrl: string; + repoName: string; +}; +//# sourceMappingURL=normalize-repo-url.d.ts.map \ No newline at end of file diff --git a/dist/utils/normalize-repo-url.d.ts.map b/dist/utils/normalize-repo-url.d.ts.map new file mode 100644 index 00000000000..2579c9e33ff --- /dev/null +++ b/dist/utils/normalize-repo-url.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"normalize-repo-url.d.ts","sourceRoot":"","sources":["../../src/utils/normalize-repo-url.ts"],"names":[],"mappings":"AAEA;;;;GAIG;AACH,eAAO,MAAM,gBAAgB,GAAI,MAAM,MAAM,KAAG;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAgBpG,CAAA"} \ No newline at end of file diff --git a/dist/utils/normalize-repo-url.js b/dist/utils/normalize-repo-url.js new file mode 100644 index 00000000000..aca91180ef7 --- /dev/null +++ b/dist/utils/normalize-repo-url.js @@ -0,0 +1,24 @@ +import parseGitHubUrl from 'parse-github-url'; +/** + * Normalize a user-provided repository specifier into a git URL and an HTTPS URL. + * + * @param repo Either a GitHub URL or a string in the format `owner/repo` (assumed to be GitHub) + */ +export const normalizeRepoUrl = (repo) => { + const parsedRepoUrl = parseGitHubUrl(repo); + if (!parsedRepoUrl?.owner || !parsedRepoUrl.name) { + throw new Error(`Invalid repository URL: ${repo}`); + } + const repoUrl = parsedRepoUrl.hostname + ? parsedRepoUrl.href + : `git@github.com:${parsedRepoUrl.owner}/${parsedRepoUrl.name}.git`; + const httpsUrl = parsedRepoUrl.hostname + ? `https://${parsedRepoUrl.hostname}/${parsedRepoUrl.owner}/${parsedRepoUrl.name}` + : `https://github.com/${parsedRepoUrl.owner}/${parsedRepoUrl.name}`; + return { + repoUrl, + httpsUrl, + repoName: parsedRepoUrl.name, + }; +}; +//# sourceMappingURL=normalize-repo-url.js.map \ No newline at end of file diff --git a/dist/utils/normalize-repo-url.js.map b/dist/utils/normalize-repo-url.js.map new file mode 100644 index 00000000000..d13b30999cf --- /dev/null +++ b/dist/utils/normalize-repo-url.js.map @@ -0,0 +1 @@ +{"version":3,"file":"normalize-repo-url.js","sourceRoot":"","sources":["../../src/utils/normalize-repo-url.ts"],"names":[],"mappings":"AAAA,OAAO,cAAc,MAAM,kBAAkB,CAAA;AAE7C;;;;GAIG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,IAAY,EAA2D,EAAE;IACxG,MAAM,aAAa,GAAG,cAAc,CAAC,IAAI,CAAC,CAAA;IAC1C,IAAI,CAAC,aAAa,EAAE,KAAK,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC;QACjD,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,EAAE,CAAC,CAAA;IACpD,CAAC;IACD,MAAM,OAAO,GAAG,aAAa,CAAC,QAAQ;QACpC,CAAC,CAAC,aAAa,CAAC,IAAI;QACpB,CAAC,CAAC,kBAAkB,aAAa,CAAC,KAAK,IAAI,aAAa,CAAC,IAAI,MAAM,CAAA;IACrE,MAAM,QAAQ,GAAG,aAAa,CAAC,QAAQ;QACrC,CAAC,CAAC,WAAW,aAAa,CAAC,QAAQ,IAAI,aAAa,CAAC,KAAK,IAAI,aAAa,CAAC,IAAI,EAAE;QAClF,CAAC,CAAC,sBAAsB,aAAa,CAAC,KAAK,IAAI,aAAa,CAAC,IAAI,EAAE,CAAA;IACrE,OAAO;QACL,OAAO;QACP,QAAQ;QACR,QAAQ,EAAE,aAAa,CAAC,IAAI;KAC7B,CAAA;AACH,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/open-browser.d.ts b/dist/utils/open-browser.d.ts new file mode 100644 index 00000000000..541cdc2e61d --- /dev/null +++ b/dist/utils/open-browser.d.ts @@ -0,0 +1,7 @@ +type OpenBrowsrProps = { + silentBrowserNoneError?: boolean; + url: string; +}; +declare const openBrowser: ({ silentBrowserNoneError, url }: OpenBrowsrProps) => Promise; +export default openBrowser; +//# sourceMappingURL=open-browser.d.ts.map \ No newline at end of file diff --git a/dist/utils/open-browser.d.ts.map b/dist/utils/open-browser.d.ts.map new file mode 100644 index 00000000000..9375229cf48 --- /dev/null +++ b/dist/utils/open-browser.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"open-browser.d.ts","sourceRoot":"","sources":["../../src/utils/open-browser.ts"],"names":[],"mappings":"AAoBA,KAAK,eAAe,GAAG;IACrB,sBAAsB,CAAC,EAAE,OAAO,CAAA;IAChC,GAAG,EAAE,MAAM,CAAA;CACZ,CAAA;AAED,QAAA,MAAM,WAAW,GAAmB,iCAAiC,eAAe,kBAmBnF,CAAA;AAED,eAAe,WAAW,CAAA"} \ No newline at end of file diff --git a/dist/utils/open-browser.js b/dist/utils/open-browser.js new file mode 100644 index 00000000000..22fcf75c7ea --- /dev/null +++ b/dist/utils/open-browser.js @@ -0,0 +1,33 @@ +import process from 'process'; +import open from 'open'; +import isDockerContainer from 'is-docker'; +import { chalk, log } from './command-helpers.js'; +const unableToOpenBrowserMessage = function ({ message, url }) { + log('---------------------------'); + log(chalk.redBright(`Error: Unable to open browser automatically: ${message}`)); + log(chalk.cyan('Please open your browser and open the URL below:')); + log(chalk.bold(url)); + log('---------------------------'); +}; +const openBrowser = async function ({ silentBrowserNoneError, url }) { + if (isDockerContainer()) { + unableToOpenBrowserMessage({ url, message: 'Running inside a docker container' }); + return; + } + if (process.env.BROWSER === 'none') { + if (!silentBrowserNoneError) { + unableToOpenBrowserMessage({ url, message: "BROWSER environment variable is set to 'none'" }); + } + return; + } + try { + await open(url); + } + catch (error) { + if (error instanceof Error) { + unableToOpenBrowserMessage({ url, message: error.message }); + } + } +}; +export default openBrowser; +//# sourceMappingURL=open-browser.js.map \ No newline at end of file diff --git a/dist/utils/open-browser.js.map b/dist/utils/open-browser.js.map new file mode 100644 index 00000000000..bbf758ac317 --- /dev/null +++ b/dist/utils/open-browser.js.map @@ -0,0 +1 @@ +{"version":3,"file":"open-browser.js","sourceRoot":"","sources":["../../src/utils/open-browser.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAA;AAE7B,OAAO,IAAI,MAAM,MAAM,CAAA;AACvB,OAAO,iBAAiB,MAAM,WAAW,CAAA;AAEzC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAOjD,MAAM,0BAA0B,GAAG,UAAU,EAAE,OAAO,EAAE,GAAG,EAAwB;IACjF,GAAG,CAAC,6BAA6B,CAAC,CAAA;IAClC,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,gDAAgD,OAAO,EAAE,CAAC,CAAC,CAAA;IAC/E,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,kDAAkD,CAAC,CAAC,CAAA;IACnE,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;IACpB,GAAG,CAAC,6BAA6B,CAAC,CAAA;AACpC,CAAC,CAAA;AAOD,MAAM,WAAW,GAAG,KAAK,WAAW,EAAE,sBAAsB,EAAE,GAAG,EAAmB;IAClF,IAAI,iBAAiB,EAAE,EAAE,CAAC;QACxB,0BAA0B,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,mCAAmC,EAAE,CAAC,CAAA;QACjF,OAAM;IACR,CAAC;IACD,IAAI,OAAO,CAAC,GAAG,CAAC,OAAO,KAAK,MAAM,EAAE,CAAC;QACnC,IAAI,CAAC,sBAAsB,EAAE,CAAC;YAC5B,0BAA0B,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,+CAA+C,EAAE,CAAC,CAAA;QAC/F,CAAC;QACD,OAAM;IACR,CAAC;IAED,IAAI,CAAC;QACH,MAAM,IAAI,CAAC,GAAG,CAAC,CAAA;IACjB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,IAAI,KAAK,YAAY,KAAK,EAAE,CAAC;YAC3B,0BAA0B,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;QAC7D,CAAC;IACH,CAAC;AACH,CAAC,CAAA;AAED,eAAe,WAAW,CAAA"} \ No newline at end of file diff --git a/dist/utils/parse-raw-flags.d.ts b/dist/utils/parse-raw-flags.d.ts new file mode 100644 index 00000000000..7b71e53d813 --- /dev/null +++ b/dist/utils/parse-raw-flags.d.ts @@ -0,0 +1,3 @@ +export declare const parseRawFlags: (raw: any) => any; +export declare const aggressiveJSONParse: (value: any) => any; +//# sourceMappingURL=parse-raw-flags.d.ts.map \ No newline at end of file diff --git a/dist/utils/parse-raw-flags.d.ts.map b/dist/utils/parse-raw-flags.d.ts.map new file mode 100644 index 00000000000..598b3a588b3 --- /dev/null +++ b/dist/utils/parse-raw-flags.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"parse-raw-flags.d.ts","sourceRoot":"","sources":["../../src/utils/parse-raw-flags.ts"],"names":[],"mappings":"AAaA,eAAO,MAAM,aAAa,GAAa,QAAG,QAiBzC,CAAA;AAGD,eAAO,MAAM,mBAAmB,GAAa,UAAK,QAkBjD,CAAA"} \ No newline at end of file diff --git a/dist/utils/parse-raw-flags.js b/dist/utils/parse-raw-flags.js new file mode 100644 index 00000000000..97635955467 --- /dev/null +++ b/dist/utils/parse-raw-flags.js @@ -0,0 +1,54 @@ +// Get flags from `raw` data +// +// Needed for commands using Command.strict = false +// +// Usage: +// const { flags, raw } = this.parse(addonsCreateCommand) +// // flags = {} +// const rawFlags = parseRawFlags(raw) +// // rawFlags = {stuff: yay!} +// +// @ts-expect-error TS(7006) FIXME: Parameter 'raw' implicitly has an 'any' type. +export const parseRawFlags = function (raw) { + // @ts-expect-error TS(7006) FIXME: Parameter 'acc' implicitly has an 'any' type. + const rawFlags = raw.reduce((acc, curr, index, array) => { + if (/^-{1,2}/.test(curr)) { + const key = curr.replace(/^-{1,2}/, ''); + const next = array[index + 1]; + if (!next) { + acc[key] = true; + } + else if (/^-{1,2}/.test(next)) { + acc[key] = true; + } + else { + acc[key] = next ? aggressiveJSONParse(next) : true; + } + } + return acc; + }, {}); + return rawFlags; +}; +// @ts-expect-error TS(7006) FIXME: Parameter 'value' implicitly has an 'any' type. +export const aggressiveJSONParse = function (value) { + if (value === 'true') { + return true; + } + if (value === 'false') { + return false; + } + let parsed; + try { + parsed = JSON.parse(value); + } + catch { + try { + parsed = JSON.parse(`"${value}"`); + } + catch { + parsed = value; + } + } + return parsed; +}; +//# sourceMappingURL=parse-raw-flags.js.map \ No newline at end of file diff --git a/dist/utils/parse-raw-flags.js.map b/dist/utils/parse-raw-flags.js.map new file mode 100644 index 00000000000..985fb3f3b31 --- /dev/null +++ b/dist/utils/parse-raw-flags.js.map @@ -0,0 +1 @@ +{"version":3,"file":"parse-raw-flags.js","sourceRoot":"","sources":["../../src/utils/parse-raw-flags.ts"],"names":[],"mappings":"AAAA,4BAA4B;AAC5B,EAAE;AACF,mDAAmD;AACnD,EAAE;AAEF,SAAS;AACT,yDAAyD;AACzD,gBAAgB;AAChB,sCAAsC;AACtC,8BAA8B;AAC9B,EAAE;AAEF,iFAAiF;AACjF,MAAM,CAAC,MAAM,aAAa,GAAG,UAAU,GAAG;IACxC,iFAAiF;IACjF,MAAM,QAAQ,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE;QACtD,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAA;YACvC,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,GAAG,CAAC,CAAC,CAAA;YAC7B,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAA;YACjB,CAAC;iBAAM,IAAI,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;gBAChC,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAA;YACjB,CAAC;iBAAM,CAAC;gBACN,GAAG,CAAC,GAAG,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,mBAAmB,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;YACpD,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAA;IACZ,CAAC,EAAE,EAAE,CAAC,CAAA;IACN,OAAO,QAAQ,CAAA;AACjB,CAAC,CAAA;AAED,mFAAmF;AACnF,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,KAAK;IAChD,IAAI,KAAK,KAAK,MAAM,EAAE,CAAC;QACrB,OAAO,IAAI,CAAA;IACb,CAAC;IACD,IAAI,KAAK,KAAK,OAAO,EAAE,CAAC;QACtB,OAAO,KAAK,CAAA;IACd,CAAC;IACD,IAAI,MAAM,CAAA;IACV,IAAI,CAAC;QACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAA;QACnC,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,GAAG,KAAK,CAAA;QAChB,CAAC;IACH,CAAC;IACD,OAAO,MAAM,CAAA;AACf,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/prompts/blob-delete-prompts.d.ts b/dist/utils/prompts/blob-delete-prompts.d.ts new file mode 100644 index 00000000000..ee5f0542b11 --- /dev/null +++ b/dist/utils/prompts/blob-delete-prompts.d.ts @@ -0,0 +1,2 @@ +export declare const promptBlobDelete: (key: string, storeName: string) => Promise; +//# sourceMappingURL=blob-delete-prompts.d.ts.map \ No newline at end of file diff --git a/dist/utils/prompts/blob-delete-prompts.d.ts.map b/dist/utils/prompts/blob-delete-prompts.d.ts.map new file mode 100644 index 00000000000..26dbe609484 --- /dev/null +++ b/dist/utils/prompts/blob-delete-prompts.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"blob-delete-prompts.d.ts","sourceRoot":"","sources":["../../../src/utils/prompts/blob-delete-prompts.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,gBAAgB,GAAU,KAAK,MAAM,EAAE,WAAW,MAAM,KAAG,OAAO,CAAC,IAAI,CAQnF,CAAA"} \ No newline at end of file diff --git a/dist/utils/prompts/blob-delete-prompts.js b/dist/utils/prompts/blob-delete-prompts.js new file mode 100644 index 00000000000..c0f3691b52f --- /dev/null +++ b/dist/utils/prompts/blob-delete-prompts.js @@ -0,0 +1,12 @@ +import { log } from '../command-helpers.js'; +import { confirmPrompt } from './confirm-prompt.js'; +import { destructiveCommandMessages } from './prompt-messages.js'; +export const promptBlobDelete = async (key, storeName) => { + const warningMessage = destructiveCommandMessages.blobDelete.generateWarning(key, storeName); + log(); + log(warningMessage); + log(); + log(destructiveCommandMessages.overwriteNotice); + await confirmPrompt(destructiveCommandMessages.blobDelete.overwriteConfirmation); +}; +//# sourceMappingURL=blob-delete-prompts.js.map \ No newline at end of file diff --git a/dist/utils/prompts/blob-delete-prompts.js.map b/dist/utils/prompts/blob-delete-prompts.js.map new file mode 100644 index 00000000000..d32b3632a0f --- /dev/null +++ b/dist/utils/prompts/blob-delete-prompts.js.map @@ -0,0 +1 @@ +{"version":3,"file":"blob-delete-prompts.js","sourceRoot":"","sources":["../../../src/utils/prompts/blob-delete-prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAE3C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAA;AAEjE,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EAAE,GAAW,EAAE,SAAiB,EAAiB,EAAE;IACtF,MAAM,cAAc,GAAG,0BAA0B,CAAC,UAAU,CAAC,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;IAE5F,GAAG,EAAE,CAAA;IACL,GAAG,CAAC,cAAc,CAAC,CAAA;IACnB,GAAG,EAAE,CAAA;IACL,GAAG,CAAC,0BAA0B,CAAC,eAAe,CAAC,CAAA;IAC/C,MAAM,aAAa,CAAC,0BAA0B,CAAC,UAAU,CAAC,qBAAqB,CAAC,CAAA;AAClF,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/prompts/blob-set-prompt.d.ts b/dist/utils/prompts/blob-set-prompt.d.ts new file mode 100644 index 00000000000..268b69c53ba --- /dev/null +++ b/dist/utils/prompts/blob-set-prompt.d.ts @@ -0,0 +1,2 @@ +export declare const promptBlobSetOverwrite: (key: string, storeName: string) => Promise; +//# sourceMappingURL=blob-set-prompt.d.ts.map \ No newline at end of file diff --git a/dist/utils/prompts/blob-set-prompt.d.ts.map b/dist/utils/prompts/blob-set-prompt.d.ts.map new file mode 100644 index 00000000000..22ec3ed4879 --- /dev/null +++ b/dist/utils/prompts/blob-set-prompt.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"blob-set-prompt.d.ts","sourceRoot":"","sources":["../../../src/utils/prompts/blob-set-prompt.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,sBAAsB,GAAU,KAAK,MAAM,EAAE,WAAW,MAAM,KAAG,OAAO,CAAC,IAAI,CAQzF,CAAA"} \ No newline at end of file diff --git a/dist/utils/prompts/blob-set-prompt.js b/dist/utils/prompts/blob-set-prompt.js new file mode 100644 index 00000000000..715189f2cb6 --- /dev/null +++ b/dist/utils/prompts/blob-set-prompt.js @@ -0,0 +1,12 @@ +import { log } from '../command-helpers.js'; +import { confirmPrompt } from './confirm-prompt.js'; +import { destructiveCommandMessages } from './prompt-messages.js'; +export const promptBlobSetOverwrite = async (key, storeName) => { + const warningMessage = destructiveCommandMessages.blobSet.generateWarning(key, storeName); + log(); + log(warningMessage); + log(); + log(destructiveCommandMessages.overwriteNotice); + await confirmPrompt(destructiveCommandMessages.blobSet.overwriteConfirmation); +}; +//# sourceMappingURL=blob-set-prompt.js.map \ No newline at end of file diff --git a/dist/utils/prompts/blob-set-prompt.js.map b/dist/utils/prompts/blob-set-prompt.js.map new file mode 100644 index 00000000000..206037f1e04 --- /dev/null +++ b/dist/utils/prompts/blob-set-prompt.js.map @@ -0,0 +1 @@ +{"version":3,"file":"blob-set-prompt.js","sourceRoot":"","sources":["../../../src/utils/prompts/blob-set-prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAE3C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAA;AAEjE,MAAM,CAAC,MAAM,sBAAsB,GAAG,KAAK,EAAE,GAAW,EAAE,SAAiB,EAAiB,EAAE;IAC5F,MAAM,cAAc,GAAG,0BAA0B,CAAC,OAAO,CAAC,eAAe,CAAC,GAAG,EAAE,SAAS,CAAC,CAAA;IAEzF,GAAG,EAAE,CAAA;IACL,GAAG,CAAC,cAAc,CAAC,CAAA;IACnB,GAAG,EAAE,CAAA;IACL,GAAG,CAAC,0BAA0B,CAAC,eAAe,CAAC,CAAA;IAC/C,MAAM,aAAa,CAAC,0BAA0B,CAAC,OAAO,CAAC,qBAAqB,CAAC,CAAA;AAC/E,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/prompts/confirm-prompt.d.ts b/dist/utils/prompts/confirm-prompt.d.ts new file mode 100644 index 00000000000..9db41e0db8c --- /dev/null +++ b/dist/utils/prompts/confirm-prompt.d.ts @@ -0,0 +1,2 @@ +export declare const confirmPrompt: (message: string) => Promise; +//# sourceMappingURL=confirm-prompt.d.ts.map \ No newline at end of file diff --git a/dist/utils/prompts/confirm-prompt.d.ts.map b/dist/utils/prompts/confirm-prompt.d.ts.map new file mode 100644 index 00000000000..2a4c7b0127f --- /dev/null +++ b/dist/utils/prompts/confirm-prompt.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"confirm-prompt.d.ts","sourceRoot":"","sources":["../../../src/utils/prompts/confirm-prompt.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,aAAa,GAAU,SAAS,MAAM,KAAG,OAAO,CAAC,IAAI,CAgBjE,CAAA"} \ No newline at end of file diff --git a/dist/utils/prompts/confirm-prompt.js b/dist/utils/prompts/confirm-prompt.js new file mode 100644 index 00000000000..b1923ca272b --- /dev/null +++ b/dist/utils/prompts/confirm-prompt.js @@ -0,0 +1,21 @@ +import inquirer from 'inquirer'; +import { log, exit } from '../command-helpers.js'; +export const confirmPrompt = async (message) => { + try { + const { confirm } = await inquirer.prompt({ + type: 'confirm', + name: 'confirm', + message, + default: false, + }); + log(); + if (!confirm) { + exit(); + } + } + catch (error) { + console.error(error); + exit(); + } +}; +//# sourceMappingURL=confirm-prompt.js.map \ No newline at end of file diff --git a/dist/utils/prompts/confirm-prompt.js.map b/dist/utils/prompts/confirm-prompt.js.map new file mode 100644 index 00000000000..9e5917d48fb --- /dev/null +++ b/dist/utils/prompts/confirm-prompt.js.map @@ -0,0 +1 @@ +{"version":3,"file":"confirm-prompt.js","sourceRoot":"","sources":["../../../src/utils/prompts/confirm-prompt.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAA;AAE/B,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAA;AAEjD,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,EAAE,OAAe,EAAiB,EAAE;IACpE,IAAI,CAAC;QACH,MAAM,EAAE,OAAO,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;YACxC,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,SAAS;YACf,OAAO;YACP,OAAO,EAAE,KAAK;SACf,CAAC,CAAA;QACF,GAAG,EAAE,CAAA;QACL,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,IAAI,EAAE,CAAA;QACR,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;QACpB,IAAI,EAAE,CAAA;IACR,CAAC;AACH,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/prompts/env-clone-prompt.d.ts b/dist/utils/prompts/env-clone-prompt.d.ts new file mode 100644 index 00000000000..67d5c1c7215 --- /dev/null +++ b/dist/utils/prompts/env-clone-prompt.d.ts @@ -0,0 +1,11 @@ +import { EnvVar } from '../types.js'; +export declare const generateEnvVarsList: (envVarsToDelete: EnvVar[]) => string[]; +/** + * Prompts the user to confirm overwriting environment variables on a project. + * + * @param {string} siteId - The ID of the project. + * @param {EnvVar[]} existingEnvVars - The environment variables that already exist on the project. + * @returns {Promise} A promise that resolves when the user has confirmed the overwriting of the variables. + */ +export declare function promptEnvCloneOverwrite(siteId: string, existingEnvVars: EnvVar[]): Promise; +//# sourceMappingURL=env-clone-prompt.d.ts.map \ No newline at end of file diff --git a/dist/utils/prompts/env-clone-prompt.d.ts.map b/dist/utils/prompts/env-clone-prompt.d.ts.map new file mode 100644 index 00000000000..687bdafcb52 --- /dev/null +++ b/dist/utils/prompts/env-clone-prompt.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"env-clone-prompt.d.ts","sourceRoot":"","sources":["../../../src/utils/prompts/env-clone-prompt.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AAKpC,eAAO,MAAM,mBAAmB,GAAI,iBAAiB,MAAM,EAAE,aAAgD,CAAA;AAE7G;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAkBtG"} \ No newline at end of file diff --git a/dist/utils/prompts/env-clone-prompt.js b/dist/utils/prompts/env-clone-prompt.js new file mode 100644 index 00000000000..0b4ef3753ee --- /dev/null +++ b/dist/utils/prompts/env-clone-prompt.js @@ -0,0 +1,28 @@ +import { log } from '../command-helpers.js'; +import { confirmPrompt } from './confirm-prompt.js'; +import { destructiveCommandMessages } from './prompt-messages.js'; +export const generateEnvVarsList = (envVarsToDelete) => envVarsToDelete.map((envVar) => envVar.key); +/** + * Prompts the user to confirm overwriting environment variables on a project. + * + * @param {string} siteId - The ID of the project. + * @param {EnvVar[]} existingEnvVars - The environment variables that already exist on the project. + * @returns {Promise} A promise that resolves when the user has confirmed the overwriting of the variables. + */ +export async function promptEnvCloneOverwrite(siteId, existingEnvVars) { + const { generateWarning } = destructiveCommandMessages.envClone; + const existingEnvVarKeys = generateEnvVarsList(existingEnvVars); + const warningMessage = generateWarning(siteId); + log(); + log(warningMessage); + log(); + log(destructiveCommandMessages.envClone.noticeEnvVars); + log(); + existingEnvVarKeys.forEach((envVar) => { + log(envVar); + }); + log(); + log(destructiveCommandMessages.overwriteNotice); + await confirmPrompt(destructiveCommandMessages.envClone.overwriteConfirmation); +} +//# sourceMappingURL=env-clone-prompt.js.map \ No newline at end of file diff --git a/dist/utils/prompts/env-clone-prompt.js.map b/dist/utils/prompts/env-clone-prompt.js.map new file mode 100644 index 00000000000..51708538585 --- /dev/null +++ b/dist/utils/prompts/env-clone-prompt.js.map @@ -0,0 +1 @@ +{"version":3,"file":"env-clone-prompt.js","sourceRoot":"","sources":["../../../src/utils/prompts/env-clone-prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAG3C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAA;AAEjE,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,eAAyB,EAAE,EAAE,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;AAE7G;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,MAAc,EAAE,eAAyB;IACrF,MAAM,EAAE,eAAe,EAAE,GAAG,0BAA0B,CAAC,QAAQ,CAAA;IAE/D,MAAM,kBAAkB,GAAG,mBAAmB,CAAC,eAAe,CAAC,CAAA;IAC/D,MAAM,cAAc,GAAG,eAAe,CAAC,MAAM,CAAC,CAAA;IAE9C,GAAG,EAAE,CAAA;IACL,GAAG,CAAC,cAAc,CAAC,CAAA;IACnB,GAAG,EAAE,CAAA;IACL,GAAG,CAAC,0BAA0B,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAA;IACtD,GAAG,EAAE,CAAA;IACL,kBAAkB,CAAC,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE;QACpC,GAAG,CAAC,MAAM,CAAC,CAAA;IACb,CAAC,CAAC,CAAA;IACF,GAAG,EAAE,CAAA;IACL,GAAG,CAAC,0BAA0B,CAAC,eAAe,CAAC,CAAA;IAE/C,MAAM,aAAa,CAAC,0BAA0B,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAA;AAChF,CAAC"} \ No newline at end of file diff --git a/dist/utils/prompts/env-set-prompts.d.ts b/dist/utils/prompts/env-set-prompts.d.ts new file mode 100644 index 00000000000..3dbf19d8af2 --- /dev/null +++ b/dist/utils/prompts/env-set-prompts.d.ts @@ -0,0 +1,2 @@ +export declare const promptOverwriteEnvVariable: (key: string) => Promise; +//# sourceMappingURL=env-set-prompts.d.ts.map \ No newline at end of file diff --git a/dist/utils/prompts/env-set-prompts.d.ts.map b/dist/utils/prompts/env-set-prompts.d.ts.map new file mode 100644 index 00000000000..b4d9802a185 --- /dev/null +++ b/dist/utils/prompts/env-set-prompts.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"env-set-prompts.d.ts","sourceRoot":"","sources":["../../../src/utils/prompts/env-set-prompts.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,0BAA0B,GAAU,KAAK,MAAM,KAAG,OAAO,CAAC,IAAI,CAQ1E,CAAA"} \ No newline at end of file diff --git a/dist/utils/prompts/env-set-prompts.js b/dist/utils/prompts/env-set-prompts.js new file mode 100644 index 00000000000..738c4fd6524 --- /dev/null +++ b/dist/utils/prompts/env-set-prompts.js @@ -0,0 +1,12 @@ +import { log } from '../command-helpers.js'; +import { confirmPrompt } from './confirm-prompt.js'; +import { destructiveCommandMessages } from './prompt-messages.js'; +export const promptOverwriteEnvVariable = async (key) => { + const warningMessage = destructiveCommandMessages.envSet.generateWarning(key); + log(); + log(warningMessage); + log(); + log(destructiveCommandMessages.overwriteNotice); + await confirmPrompt(destructiveCommandMessages.envSet.overwriteConfirmation); +}; +//# sourceMappingURL=env-set-prompts.js.map \ No newline at end of file diff --git a/dist/utils/prompts/env-set-prompts.js.map b/dist/utils/prompts/env-set-prompts.js.map new file mode 100644 index 00000000000..02c9f07ea4c --- /dev/null +++ b/dist/utils/prompts/env-set-prompts.js.map @@ -0,0 +1 @@ +{"version":3,"file":"env-set-prompts.js","sourceRoot":"","sources":["../../../src/utils/prompts/env-set-prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAE3C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAA;AAEjE,MAAM,CAAC,MAAM,0BAA0B,GAAG,KAAK,EAAE,GAAW,EAAiB,EAAE;IAC7E,MAAM,cAAc,GAAG,0BAA0B,CAAC,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAA;IAE7E,GAAG,EAAE,CAAA;IACL,GAAG,CAAC,cAAc,CAAC,CAAA;IACnB,GAAG,EAAE,CAAA;IACL,GAAG,CAAC,0BAA0B,CAAC,eAAe,CAAC,CAAA;IAC/C,MAAM,aAAa,CAAC,0BAA0B,CAAC,MAAM,CAAC,qBAAqB,CAAC,CAAA;AAC9E,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/prompts/env-unset-prompts.d.ts b/dist/utils/prompts/env-unset-prompts.d.ts new file mode 100644 index 00000000000..0a1a934ef87 --- /dev/null +++ b/dist/utils/prompts/env-unset-prompts.d.ts @@ -0,0 +1,8 @@ +/** + * Logs a warning and prompts user to confirm overwriting an existing environment variable + * + * @param {string} key - The key of the environment variable that already exists + * @returns {Promise} A promise that resolves when the user has confirmed overwriting the variable + */ +export declare const promptOverwriteEnvVariable: (existingKey: string) => Promise; +//# sourceMappingURL=env-unset-prompts.d.ts.map \ No newline at end of file diff --git a/dist/utils/prompts/env-unset-prompts.d.ts.map b/dist/utils/prompts/env-unset-prompts.d.ts.map new file mode 100644 index 00000000000..20159159b5b --- /dev/null +++ b/dist/utils/prompts/env-unset-prompts.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"env-unset-prompts.d.ts","sourceRoot":"","sources":["../../../src/utils/prompts/env-unset-prompts.ts"],"names":[],"mappings":"AAKA;;;;;GAKG;AACH,eAAO,MAAM,0BAA0B,GAAU,aAAa,MAAM,KAAG,OAAO,CAAC,IAAI,CASlF,CAAA"} \ No newline at end of file diff --git a/dist/utils/prompts/env-unset-prompts.js b/dist/utils/prompts/env-unset-prompts.js new file mode 100644 index 00000000000..425eb5f0abd --- /dev/null +++ b/dist/utils/prompts/env-unset-prompts.js @@ -0,0 +1,18 @@ +import { log } from '../command-helpers.js'; +import { confirmPrompt } from './confirm-prompt.js'; +import { destructiveCommandMessages } from './prompt-messages.js'; +/** + * Logs a warning and prompts user to confirm overwriting an existing environment variable + * + * @param {string} key - The key of the environment variable that already exists + * @returns {Promise} A promise that resolves when the user has confirmed overwriting the variable + */ +export const promptOverwriteEnvVariable = async (existingKey) => { + const { generateWarning } = destructiveCommandMessages.envUnset; + const warningMessage = generateWarning(existingKey); + log(warningMessage); + log(); + log(destructiveCommandMessages.overwriteNotice); + await confirmPrompt(destructiveCommandMessages.envUnset.overwriteConfirmation); +}; +//# sourceMappingURL=env-unset-prompts.js.map \ No newline at end of file diff --git a/dist/utils/prompts/env-unset-prompts.js.map b/dist/utils/prompts/env-unset-prompts.js.map new file mode 100644 index 00000000000..f54fa202c02 --- /dev/null +++ b/dist/utils/prompts/env-unset-prompts.js.map @@ -0,0 +1 @@ +{"version":3,"file":"env-unset-prompts.js","sourceRoot":"","sources":["../../../src/utils/prompts/env-unset-prompts.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAE3C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAA;AACnD,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAA;AAEjE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,KAAK,EAAE,WAAmB,EAAiB,EAAE;IACrF,MAAM,EAAE,eAAe,EAAE,GAAG,0BAA0B,CAAC,QAAQ,CAAA;IAE/D,MAAM,cAAc,GAAG,eAAe,CAAC,WAAW,CAAC,CAAA;IAEnD,GAAG,CAAC,cAAc,CAAC,CAAA;IACnB,GAAG,EAAE,CAAA;IACL,GAAG,CAAC,0BAA0B,CAAC,eAAe,CAAC,CAAA;IAC/C,MAAM,aAAa,CAAC,0BAA0B,CAAC,QAAQ,CAAC,qBAAqB,CAAC,CAAA;AAChF,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/prompts/prompt-messages.d.ts b/dist/utils/prompts/prompt-messages.d.ts new file mode 100644 index 00000000000..a4ba993bcd3 --- /dev/null +++ b/dist/utils/prompts/prompt-messages.d.ts @@ -0,0 +1,25 @@ +export declare const destructiveCommandMessages: { + overwriteNotice: string; + blobSet: { + generateWarning: (key: string, storeName: string) => string; + overwriteConfirmation: string; + }; + blobDelete: { + generateWarning: (key: string, storeName: string) => string; + overwriteConfirmation: string; + }; + envSet: { + generateWarning: (variableName: string) => string; + overwriteConfirmation: string; + }; + envUnset: { + generateWarning: (variableName: string) => string; + overwriteConfirmation: string; + }; + envClone: { + generateWarning: (siteId: string) => string; + noticeEnvVars: string; + overwriteConfirmation: string; + }; +}; +//# sourceMappingURL=prompt-messages.d.ts.map \ No newline at end of file diff --git a/dist/utils/prompts/prompt-messages.d.ts.map b/dist/utils/prompts/prompt-messages.d.ts.map new file mode 100644 index 00000000000..742c43146ed --- /dev/null +++ b/dist/utils/prompts/prompt-messages.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"prompt-messages.d.ts","sourceRoot":"","sources":["../../../src/utils/prompts/prompt-messages.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,0BAA0B;;;+BAIZ,MAAM,aAAa,MAAM;;;;+BAQzB,MAAM,aAAa,MAAM;;;;wCAQhB,MAAM;;;;wCAMN,MAAM;;;;kCAQZ,MAAM;;;;CASnC,CAAA"} \ No newline at end of file diff --git a/dist/utils/prompts/prompt-messages.js b/dist/utils/prompts/prompt-messages.js new file mode 100644 index 00000000000..cc135629a23 --- /dev/null +++ b/dist/utils/prompts/prompt-messages.js @@ -0,0 +1,26 @@ +import { chalk } from '../command-helpers.js'; +export const destructiveCommandMessages = { + overwriteNotice: `${chalk.yellowBright('Notice')}: To overwrite without this warning, you can use the --force flag.`, + blobSet: { + generateWarning: (key, storeName) => `${chalk.redBright('Warning')}: The blob key ${chalk.cyan(key)} already exists in store ${chalk.cyan(storeName)}!`, + overwriteConfirmation: 'Do you want to proceed with overwriting this blob key existing value?', + }, + blobDelete: { + generateWarning: (key, storeName) => `${chalk.redBright('Warning')}: The following blob key ${chalk.cyan(key)} will be deleted from store ${chalk.cyan(storeName)}!`, + overwriteConfirmation: 'Do you want to proceed with deleting the value at this key?', + }, + envSet: { + generateWarning: (variableName) => `${chalk.redBright('Warning')}: The environment variable ${chalk.bgBlueBright(variableName)} already exists!`, + overwriteConfirmation: 'Do you want to overwrite it?', + }, + envUnset: { + generateWarning: (variableName) => `${chalk.redBright('Warning')}: The environment variable ${chalk.bgBlueBright(variableName)} will be removed from all contexts!`, + overwriteConfirmation: 'Do you want to remove it?', + }, + envClone: { + generateWarning: (siteId) => `${chalk.redBright('Warning')}: The following environment variables are already set on the project with ID ${chalk.bgBlueBright(siteId)}. They will be overwritten!`, + noticeEnvVars: `${chalk.yellowBright('Notice')}: The following variables will be overwritten:`, + overwriteConfirmation: 'The environment variables already exist. Do you want to overwrite them?', + }, +}; +//# sourceMappingURL=prompt-messages.js.map \ No newline at end of file diff --git a/dist/utils/prompts/prompt-messages.js.map b/dist/utils/prompts/prompt-messages.js.map new file mode 100644 index 00000000000..77f76557cfa --- /dev/null +++ b/dist/utils/prompts/prompt-messages.js.map @@ -0,0 +1 @@ +{"version":3,"file":"prompt-messages.js","sourceRoot":"","sources":["../../../src/utils/prompts/prompt-messages.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAA;AAE7C,MAAM,CAAC,MAAM,0BAA0B,GAAG;IACxC,eAAe,EAAE,GAAG,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,oEAAoE;IAEpH,OAAO,EAAE;QACP,eAAe,EAAE,CAAC,GAAW,EAAE,SAAiB,EAAE,EAAE,CAClD,GAAG,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,kBAAkB,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,4BAA4B,KAAK,CAAC,IAAI,CAClG,SAAS,CACV,GAAG;QACN,qBAAqB,EAAE,uEAAuE;KAC/F;IAED,UAAU,EAAE;QACV,eAAe,EAAE,CAAC,GAAW,EAAE,SAAiB,EAAE,EAAE,CAClD,GAAG,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,4BAA4B,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,+BAA+B,KAAK,CAAC,IAAI,CAC/G,SAAS,CACV,GAAG;QACN,qBAAqB,EAAE,6DAA6D;KACrF;IAED,MAAM,EAAE;QACN,eAAe,EAAE,CAAC,YAAoB,EAAE,EAAE,CACxC,GAAG,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,8BAA8B,KAAK,CAAC,YAAY,CAAC,YAAY,CAAC,kBAAkB;QAC/G,qBAAqB,EAAE,8BAA8B;KACtD;IAED,QAAQ,EAAE;QACR,eAAe,EAAE,CAAC,YAAoB,EAAE,EAAE,CACxC,GAAG,KAAK,CAAC,SAAS,CAAC,SAAS,CAAC,8BAA8B,KAAK,CAAC,YAAY,CAC3E,YAAY,CACb,qCAAqC;QACxC,qBAAqB,EAAE,2BAA2B;KACnD;IAED,QAAQ,EAAE;QACR,eAAe,EAAE,CAAC,MAAc,EAAE,EAAE,CAClC,GAAG,KAAK,CAAC,SAAS,CAChB,SAAS,CACV,gFAAgF,KAAK,CAAC,YAAY,CACjG,MAAM,CACP,6BAA6B;QAChC,aAAa,EAAE,GAAG,KAAK,CAAC,YAAY,CAAC,QAAQ,CAAC,gDAAgD;QAC9F,qBAAqB,EAAE,yEAAyE;KACjG;CACF,CAAA"} \ No newline at end of file diff --git a/dist/utils/proxy-server.d.ts b/dist/utils/proxy-server.d.ts new file mode 100644 index 00000000000..ee8b93ae2ef --- /dev/null +++ b/dist/utils/proxy-server.d.ts @@ -0,0 +1,39 @@ +import type BaseCommand from '../commands/base-command.js'; +import type { $TSFixMe, NetlifyOptions } from '../commands/types.js'; +import type { BlobsContextWithEdgeAccess } from '../lib/blobs/blobs.js'; +import type { FunctionsRegistry } from '../lib/functions/registry.js'; +import { type NormalizedCachedConfigConfig } from './command-helpers.js'; +import type CLIState from './cli-state.js'; +import type { ServerSettings } from './types.js'; +interface InspectSettings { + enabled: boolean; + pause: boolean; + address?: string; +} +export declare const generateInspectSettings: (edgeInspect: boolean | string, edgeInspectBrk: boolean | string) => InspectSettings; +export declare const startProxyServer: ({ accountId, addonsUrls, api, blobsContext, command, config, configPath, debug, disableEdgeFunctions, env, functionsRegistry, geoCountry, geolocationMode, getUpdatedConfig, inspectSettings, offline, projectDir, repositoryRoot, settings, site, siteInfo, state, }: { + accountId: string | undefined; + addonsUrls: $TSFixMe; + api?: NetlifyOptions["api"]; + blobsContext?: BlobsContextWithEdgeAccess; + command: BaseCommand; + config: NormalizedCachedConfigConfig; + configPath?: string; + debug: boolean; + disableEdgeFunctions: boolean; + env: NetlifyOptions["cachedConfig"]["env"]; + inspectSettings: InspectSettings; + getUpdatedConfig: () => Promise; + geolocationMode: string; + geoCountry: string; + settings: ServerSettings; + offline: boolean; + site: $TSFixMe; + siteInfo: $TSFixMe; + projectDir: string; + repositoryRoot?: string; + state: CLIState; + functionsRegistry?: FunctionsRegistry; +}) => Promise; +export {}; +//# sourceMappingURL=proxy-server.d.ts.map \ No newline at end of file diff --git a/dist/utils/proxy-server.d.ts.map b/dist/utils/proxy-server.d.ts.map new file mode 100644 index 00000000000..7c507475642 --- /dev/null +++ b/dist/utils/proxy-server.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"proxy-server.d.ts","sourceRoot":"","sources":["../../src/utils/proxy-server.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,WAAW,MAAM,6BAA6B,CAAA;AAC1D,OAAO,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AACpE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,uBAAuB,CAAA;AACvE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAErE,OAAO,EAA4B,KAAK,4BAA4B,EAAE,MAAM,sBAAsB,CAAA;AAElG,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAA;AAC1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAEhD,UAAU,eAAe;IAEvB,OAAO,EAAE,OAAO,CAAA;IAEhB,KAAK,EAAE,OAAO,CAAA;IAEd,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED,eAAO,MAAM,uBAAuB,GAClC,aAAa,OAAO,GAAG,MAAM,EAC7B,gBAAgB,OAAO,GAAG,MAAM,KAC/B,eAiBF,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAU,uQAuBpC;IACD,SAAS,EAAE,MAAM,GAAG,SAAS,CAAA;IAC7B,UAAU,EAAE,QAAQ,CAAA;IACpB,GAAG,CAAC,EAAE,cAAc,CAAC,KAAK,CAAC,CAAA;IAC3B,YAAY,CAAC,EAAE,0BAA0B,CAAA;IACzC,OAAO,EAAE,WAAW,CAAA;IACpB,MAAM,EAAE,4BAA4B,CAAA;IAEpC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,KAAK,EAAE,OAAO,CAAA;IACd,oBAAoB,EAAE,OAAO,CAAA;IAC7B,GAAG,EAAE,cAAc,CAAC,cAAc,CAAC,CAAC,KAAK,CAAC,CAAA;IAC1C,eAAe,EAAE,eAAe,CAAA;IAChC,gBAAgB,EAAE,MAAM,OAAO,CAAC,4BAA4B,CAAC,CAAA;IAC7D,eAAe,EAAE,MAAM,CAAA;IACvB,UAAU,EAAE,MAAM,CAAA;IAClB,QAAQ,EAAE,cAAc,CAAA;IACxB,OAAO,EAAE,OAAO,CAAA;IAChB,IAAI,EAAE,QAAQ,CAAA;IACd,QAAQ,EAAE,QAAQ,CAAA;IAClB,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,KAAK,EAAE,QAAQ,CAAA;IACf,iBAAiB,CAAC,EAAE,iBAAiB,CAAA;CACtC,oBA8BA,CAAA"} \ No newline at end of file diff --git a/dist/utils/proxy-server.js b/dist/utils/proxy-server.js new file mode 100644 index 00000000000..54c6a8e7097 --- /dev/null +++ b/dist/utils/proxy-server.js @@ -0,0 +1,50 @@ +import { exit, log, NETLIFYDEVERR } from './command-helpers.js'; +import { startProxy } from './proxy.js'; +export const generateInspectSettings = (edgeInspect, edgeInspectBrk) => { + const enabled = Boolean(edgeInspect) || Boolean(edgeInspectBrk); + const pause = Boolean(edgeInspectBrk); + const getAddress = () => { + if (edgeInspect) { + return typeof edgeInspect === 'string' ? edgeInspect : undefined; + } + if (edgeInspectBrk) { + return typeof edgeInspectBrk === 'string' ? edgeInspectBrk : undefined; + } + }; + return { + enabled, + pause, + address: getAddress(), + }; +}; +export const startProxyServer = async ({ accountId, addonsUrls, api, blobsContext, command, config, configPath, debug, disableEdgeFunctions, env, functionsRegistry, geoCountry, geolocationMode, getUpdatedConfig, inspectSettings, offline, projectDir, repositoryRoot, settings, site, siteInfo, state, }) => { + const url = await startProxy({ + addonsUrls, + blobsContext, + command, + config, + configPath: configPath || site.configPath, + debug, + disableEdgeFunctions, + env, + functionsRegistry, + geolocationMode, + geoCountry, + getUpdatedConfig, + inspectSettings, + offline, + projectDir, + settings, + state, + siteInfo, + accountId, + repositoryRoot, + api, + }); + if (!url) { + log(NETLIFYDEVERR, `Unable to start proxy server on port '${settings.port}'`); + exit(1); + } + return url; +}; +//# sourceMappingURL=proxy-server.js.map \ No newline at end of file diff --git a/dist/utils/proxy-server.js.map b/dist/utils/proxy-server.js.map new file mode 100644 index 00000000000..105f2f54a09 --- /dev/null +++ b/dist/utils/proxy-server.js.map @@ -0,0 +1 @@ +{"version":3,"file":"proxy-server.js","sourceRoot":"","sources":["../../src/utils/proxy-server.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,aAAa,EAAqC,MAAM,sBAAsB,CAAA;AAClG,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAavC,MAAM,CAAC,MAAM,uBAAuB,GAAG,CACrC,WAA6B,EAC7B,cAAgC,EACf,EAAE;IACnB,MAAM,OAAO,GAAG,OAAO,CAAC,WAAW,CAAC,IAAI,OAAO,CAAC,cAAc,CAAC,CAAA;IAC/D,MAAM,KAAK,GAAG,OAAO,CAAC,cAAc,CAAC,CAAA;IACrC,MAAM,UAAU,GAAG,GAAG,EAAE;QACtB,IAAI,WAAW,EAAE,CAAC;YAChB,OAAO,OAAO,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS,CAAA;QAClE,CAAC;QACD,IAAI,cAAc,EAAE,CAAC;YACnB,OAAO,OAAO,cAAc,KAAK,QAAQ,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,SAAS,CAAA;QACxE,CAAC;IACH,CAAC,CAAA;IAED,OAAO;QACL,OAAO;QACP,KAAK;QACL,OAAO,EAAE,UAAU,EAAE;KACtB,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,gBAAgB,GAAG,KAAK,EAAE,EACrC,SAAS,EACT,UAAU,EACV,GAAG,EACH,YAAY,EACZ,OAAO,EACP,MAAM,EACN,UAAU,EACV,KAAK,EACL,oBAAoB,EACpB,GAAG,EACH,iBAAiB,EACjB,UAAU,EACV,eAAe,EACf,gBAAgB,EAChB,eAAe,EACf,OAAO,EACP,UAAU,EACV,cAAc,EACd,QAAQ,EACR,IAAI,EACJ,QAAQ,EACR,KAAK,GAyBN,EAAE,EAAE;IACH,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC;QAC3B,UAAU;QACV,YAAY;QACZ,OAAO;QACP,MAAM;QACN,UAAU,EAAE,UAAU,IAAI,IAAI,CAAC,UAAU;QACzC,KAAK;QACL,oBAAoB;QACpB,GAAG;QACH,iBAAiB;QACjB,eAAe;QACf,UAAU;QACV,gBAAgB;QAChB,eAAe;QACf,OAAO;QACP,UAAU;QACV,QAAQ;QACR,KAAK;QACL,QAAQ;QACR,SAAS;QACT,cAAc;QACd,GAAG;KACJ,CAAC,CAAA;IACF,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,GAAG,CAAC,aAAa,EAAE,yCAAyC,QAAQ,CAAC,IAAI,GAAG,CAAC,CAAA;QAC7E,IAAI,CAAC,CAAC,CAAC,CAAA;IACT,CAAC;IAED,OAAO,GAAG,CAAA;AACZ,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/proxy.d.ts b/dist/utils/proxy.d.ts new file mode 100644 index 00000000000..0eaa859a806 --- /dev/null +++ b/dist/utils/proxy.d.ts @@ -0,0 +1,13 @@ +import type { BaseCommand } from '../commands/index.js'; +import type { $TSFixMe } from '../commands/types.js'; +import { type NormalizedCachedConfigConfig } from './command-helpers.js'; +import type { ServerSettings } from './types.js'; +export declare const getProxyUrl: (settings: Pick) => string; +export declare const startProxy: ({ accountId, addonsUrls, api, blobsContext, command, config, configPath, debug, disableEdgeFunctions, env, functionsRegistry, geoCountry, geolocationMode, getUpdatedConfig, inspectSettings, offline, projectDir, repositoryRoot, settings, siteInfo, state, }: { + command: BaseCommand; + config: NormalizedCachedConfigConfig; + settings: ServerSettings; + disableEdgeFunctions: boolean; + getUpdatedConfig: () => Promise; +} & Record) => Promise; +//# sourceMappingURL=proxy.d.ts.map \ No newline at end of file diff --git a/dist/utils/proxy.d.ts.map b/dist/utils/proxy.d.ts.map new file mode 100644 index 00000000000..d4bd0d41654 --- /dev/null +++ b/dist/utils/proxy.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../../src/utils/proxy.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,QAAQ,EAAkB,MAAM,sBAAsB,CAAA;AAYpE,OAAO,EAAiC,KAAK,4BAA4B,EAAc,MAAM,sBAAsB,CAAA;AAMnH,OAAO,KAAK,EAAqB,cAAc,EAAE,MAAM,YAAY,CAAA;AAw1BnE,eAAO,MAAM,WAAW,GAAa,UAAU,IAAI,CAAC,cAAc,EAAE,OAAO,GAAG,MAAM,CAAC,WAGpF,CAAA;AAID,eAAO,MAAM,UAAU,GAAmB,iQAsBvC;IACD,OAAO,EAAE,WAAW,CAAA;IACpB,MAAM,EAAE,4BAA4B,CAAA;IACpC,QAAQ,EAAE,cAAc,CAAA;IACxB,oBAAoB,EAAE,OAAO,CAAA;IAC7B,gBAAgB,EAAE,MAAM,OAAO,CAAC,4BAA4B,CAAC,CAAA;CAC9D,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,oBA6G3B,CAAA"} \ No newline at end of file diff --git a/dist/utils/proxy.js b/dist/utils/proxy.js new file mode 100644 index 00000000000..72c90c403c2 --- /dev/null +++ b/dist/utils/proxy.js @@ -0,0 +1,782 @@ +import { Buffer } from 'buffer'; +import { once } from 'events'; +import { readFile } from 'fs/promises'; +import http from 'http'; +import https from 'https'; +import { isIPv6 } from 'net'; +import { Socket } from 'node:net'; +import { Readable } from 'node:stream'; +import path from 'path'; +import process from 'process'; +import url from 'url'; +import util from 'util'; +import zlib from 'zlib'; +import contentType from 'content-type'; +import cookie from 'cookie'; +import { getProperty } from 'dot-prop'; +import generateETag from 'etag'; +import getAvailablePort from 'get-port'; +import httpProxy from 'http-proxy'; +import { createProxyMiddleware } from 'http-proxy-middleware'; +import { jwtDecode } from 'jwt-decode'; +import { locatePath } from 'locate-path'; +import throttle from 'lodash/throttle.js'; +import pFilter from 'p-filter'; +import { handleProxyRequest, initializeProxy as initializeEdgeFunctionsProxy, isEdgeFunctionsRequest, } from '../lib/edge-functions/proxy.js'; +import { fileExistsAsync, isFileAsync } from '../lib/fs.js'; +import { getFormHandler } from '../lib/functions/form-submissions-handler.js'; +import { DEFAULT_FUNCTION_URL_EXPRESSION } from '../lib/functions/registry.js'; +import { initializeProxy as initializeImageProxy, isImageRequest } from '../lib/images/proxy.js'; +import renderErrorTemplate from '../lib/render-error-template.js'; +import { NETLIFYDEVLOG, NETLIFYDEVWARN, chalk, log } from './command-helpers.js'; +import createStreamPromise from './create-stream-promise.js'; +import { NFFunctionName, NFFunctionRoute, NFRequestID, headersForPath, parseHeaders } from './headers.js'; +import { generateRequestID } from './request-id.js'; +import { createRewriter, onChanges } from './rules-proxy.js'; +import { signRedirect } from './sign-redirect.js'; +const gunzip = util.promisify(zlib.gunzip); +const gzip = util.promisify(zlib.gzip); +const brotliDecompress = util.promisify(zlib.brotliDecompress); +const brotliCompress = util.promisify(zlib.brotliCompress); +const deflate = util.promisify(zlib.deflate); +const inflate = util.promisify(zlib.inflate); +const shouldGenerateETag = Symbol('Internal: response should generate ETag'); +const decompressResponseBody = async function (body, contentEncoding = '') { + switch (contentEncoding) { + case 'gzip': + return await gunzip(body); + case 'br': + return await brotliDecompress(body); + case 'deflate': + return await inflate(body); + default: + return body; + } +}; +const compressResponseBody = async function (body, contentEncoding = '') { + switch (contentEncoding) { + case 'gzip': + return await gzip(body); + case 'br': + return await brotliCompress(body); + case 'deflate': + return await deflate(body); + default: + return Buffer.from(body, 'utf8'); + } +}; +const injectHtml = async function (responseBody, proxyRes, htmlInjections) { + const decompressedBody = await decompressResponseBody(responseBody, proxyRes.headers['content-encoding']); + const bodyWithInjections = (htmlInjections ?? []).reduce((accum, htmlInjection) => { + if (!htmlInjection.html || typeof htmlInjection.html !== 'string') { + return accum; + } + const location = htmlInjection.location ?? 'before_closing_head_tag'; + if (location === 'before_closing_head_tag') { + accum = accum.replace('', `${htmlInjection.html}`); + } + else if (location === 'before_closing_body_tag') { + accum = accum.replace('', `${htmlInjection.html}`); + } + return accum; + }, decompressedBody.toString()); + return await compressResponseBody(bodyWithInjections, proxyRes.headers['content-encoding']); +}; +const formatEdgeFunctionError = (errorBuffer, acceptsHtml) => { + const { error: { message, name, stack }, } = JSON.parse(errorBuffer.toString()); + if (!acceptsHtml) { + return `${name}: ${message}\n ${stack}`; + } + return JSON.stringify({ + errorType: name, + errorMessage: message, + trace: stack.split('\\n'), + }); +}; +function isInternal(url) { + return url?.startsWith('/.netlify/') ?? false; +} +function isFunction(functionsPort, url) { + return functionsPort && url.match(DEFAULT_FUNCTION_URL_EXPRESSION); +} +function getAddonUrl(addonsUrls, req) { + const matches = req.url?.match(/^\/.netlify\/([^/]+)(\/.*)/); + const addonUrl = matches && addonsUrls[matches[1]]; + return addonUrl ? `${addonUrl}${matches[2]}` : null; +} +const getStatic = async function (pathname, publicFolder) { + const alternatives = [pathname, ...alternativePathsFor(pathname)].map((filePath) => path.resolve(publicFolder, filePath.slice(1))); + const file = await locatePath(alternatives); + if (file === undefined) { + return false; + } + return `/${path.relative(publicFolder, file)}`; +}; +const isEndpointExists = async function (endpoint, origin) { + const url = new URL(endpoint, origin); + try { + const res = await fetch(url, { method: 'HEAD' }); + return res.status !== 404; + } + catch (e) { + return false; + } +}; +const isExternal = function (match) { + return 'to' in match && /^https?:\/\//.exec(match.to) != null; +}; +const stripOrigin = function ({ hash, pathname, search }) { + return `${pathname}${search}${hash}`; +}; +const proxyToExternalUrl = function ({ dest, destURL, req, res, }) { + const handler = createProxyMiddleware({ + target: dest.origin, + changeOrigin: true, + pathRewrite: () => destURL, + // hide logging + logLevel: 'warn', + ...(Buffer.isBuffer(req.originalBody) && { buffer: Readable.from(req.originalBody) }), + }); + // @ts-expect-error TS(2345) FIXME: Argument of type 'Request' is not assignable to parameter of type 'Request>'. + handler(req, res, () => { }); +}; +// @ts-expect-error TS(7031) FIXME: Binding element 'addonUrl' implicitly has an 'any'... Remove this comment to see the full error message +const handleAddonUrl = function ({ addonUrl, req, res }) { + const dest = new URL(addonUrl); + const destURL = stripOrigin(dest); + proxyToExternalUrl({ req, res, dest, destURL }); +}; +const isRedirect = function (match) { + return 'status' in match && match.status != null && match.status >= 300 && match.status <= 400; +}; +const render404 = async function (publicFolder) { + const maybe404Page = path.resolve(publicFolder, '404.html'); + try { + const isFile = await isFileAsync(maybe404Page); + if (isFile) + return await readFile(maybe404Page, 'utf-8'); + } + catch (error) { + console.warn(NETLIFYDEVWARN, 'Error while serving 404.html file', error instanceof Error ? error.message : error?.toString()); + } + return 'Not Found'; +}; +// Used as an optimization to avoid dual lookups for missing assets +const assetExtensionRegExp = /\.(html?|png|jpg|js|css|svg|gif|ico|woff|woff2)$/; +// @ts-expect-error TS(7006) FIXME: Parameter 'url' implicitly has an 'any' type. +const alternativePathsFor = function (url) { + if (isFunction(true, url)) { + return []; + } + const paths = []; + if (url[url.length - 1] === '/') { + const end = url.length - 1; + if (url !== '/') { + paths.push(`${url.slice(0, end)}.html`, `${url.slice(0, end)}.htm`); + } + paths.push(`${url}index.html`, `${url}index.htm`); + } + else if (!assetExtensionRegExp.test(url)) { + paths.push(`${url}.html`, `${url}.htm`, `${url}/index.html`, `${url}/index.htm`); + } + return paths; +}; +const notifyActivity = throttle((api, siteId, devServerId) => { + // @ts-expect-error(serhalp) -- It looks like the generated API types don't include "internal" methods + // (https://github.com/netlify/open-api/blob/66813d46e47f207443b7aebce2c22c4a4c8ca867/swagger.yml#L2642). Fix? + api.markDevServerActivity({ siteId, devServerId }).catch((error) => { + console.error(`${NETLIFYDEVWARN} Failed to notify activity`, error); + }); +}, 30 * 1000); +const serveRedirect = async function ({ env, functionsRegistry, imageProxy, match, options, proxy, req, res, siteInfo, }) { + if (!match) + return proxy.web(req, res, options); + options = options || req.proxyOptions || {}; + options.match = null; + if (match.force404) { + res.writeHead(404); + res.end(await render404(options.publicFolder)); + return; + } + if (match.proxyHeaders && Object.keys(match.proxyHeaders).length >= 0) { + Object.entries(match.proxyHeaders).forEach(([key, value]) => { + req.headers[key] = value; + }); + } + if (match.signingSecret) { + const signingSecretVar = env[match.signingSecret]; + if (signingSecretVar) { + req.headers['x-nf-sign'] = signRedirect({ + deployContext: 'dev', + secret: signingSecretVar.value, + siteID: siteInfo.id, + siteURL: siteInfo.url, + }); + } + else { + log(NETLIFYDEVWARN, `Could not sign redirect because environment variable ${chalk.yellow(match.signingSecret)} is not set`); + } + } + if (isFunction(options.functionsPort, req.url)) { + return proxy.web(req, res, { target: options.functionsServer }); + } + const urlForAddons = getAddonUrl(options.addonsUrls, req); + if (urlForAddons) { + handleAddonUrl({ req, res, addonUrl: urlForAddons }); + return; + } + const originalURL = req.url; + if (match.exceptions && match.exceptions.JWT) { + // Some values of JWT can start with :, so, make sure to normalize them + const expectedRoles = new Set(match.exceptions.JWT.split(',').map((value) => (value.startsWith(':') ? value.slice(1) : value))); + const cookieValues = cookie.parse(req.headers.cookie || ''); + const token = cookieValues.nf_jwt; + // Serve not found by default + req.url = '/.netlify/non-existent-path'; + if (token) { + let jwtValue = {}; + try { + jwtValue = jwtDecode(token) || {}; + } + catch (error) { + // @ts-expect-error TS(2571) FIXME: Object is of type 'unknown'. + console.warn(NETLIFYDEVWARN, 'Error while decoding JWT provided in request', error.message); + res.writeHead(400); + res.end('Invalid JWT provided. Please see logs for more info.'); + return; + } + // @ts-expect-error TS(2339) FIXME: Property 'exp' does not exist on type '{}'. + if ((jwtValue.exp || 0) < Math.round(Date.now() / MILLISEC_TO_SEC)) { + console.warn(NETLIFYDEVWARN, 'Expired JWT provided in request', req.url); + } + else { + const presentedRoles = getProperty(jwtValue, options.jwtRolePath) || []; + if (!Array.isArray(presentedRoles)) { + console.warn(NETLIFYDEVWARN, `Invalid roles value provided in JWT ${options.jwtRolePath}`, presentedRoles); + res.writeHead(400); + res.end('Invalid JWT provided. Please see logs for more info.'); + return; + } + // Restore the URL if everything is correct + if (presentedRoles.some((pr) => expectedRoles.has(pr))) { + req.url = originalURL; + } + } + } + } + const reqUrl = reqToURL(req, req.url); + const isHiddenProxy = match.proxyHeaders && + Object.entries(match.proxyHeaders).some(([key, val]) => key.toLowerCase() === 'x-nf-hidden-proxy' && val === 'true'); + const staticFile = await getStatic(decodeURIComponent(reqUrl.pathname), options.publicFolder); + const endpointExists = !staticFile && + !isHiddenProxy && + process.env.NETLIFY_DEV_SERVER_CHECK_SSG_ENDPOINTS && + (await isEndpointExists(decodeURIComponent(reqUrl.pathname), options.target)); + if (staticFile || endpointExists) { + const pathname = staticFile || reqUrl.pathname; + req.url = encodeURI(decodeURI(pathname)) + reqUrl.search; + // if there is an existing static file and it is not a forced redirect, return the file + if (!match.force) { + return proxy.web(req, res, { ...options, staticFile }); + } + } + if (match.force || !staticFile || !options.framework || req.method === 'POST') { + // construct destination URL from redirect rule match + const dest = new URL(match.to, `${reqUrl.protocol}//${reqUrl.host}`); + // We pass through request params if the redirect rule + // doesn't have any query params + if ([...dest.searchParams].length === 0) { + dest.searchParams.forEach((_, key) => { + dest.searchParams.delete(key); + }); + const requestParams = new URLSearchParams(reqUrl.searchParams); + requestParams.forEach((val, key) => { + dest.searchParams.append(key, val); + }); + } + let destURL = stripOrigin(dest); + if (isExternal(match)) { + if (isRedirect(match)) { + // This is a redirect, so we set the complete external URL as destination + destURL = `${dest}`; + } + else { + if (!isHiddenProxy) { + console.log(`${NETLIFYDEVLOG} Proxying to ${dest}`); + } + proxyToExternalUrl({ req, res, dest, destURL }); + return; + } + } + if (isRedirect(match)) { + console.log(`${NETLIFYDEVLOG} Redirecting ${req.url} to ${destURL}`); + res.writeHead(match.status, { + Location: destURL, + 'Cache-Control': 'no-cache', + }); + res.end(`Redirecting to ${destURL}`); + return; + } + const ct = req.headers['content-type'] ? contentType.parse(req).type : ''; + if (req.method === 'POST' && + !isInternal(req.url) && + !isInternal(destURL) && + (ct.endsWith('/x-www-form-urlencoded') || ct === 'multipart/form-data')) { + return proxy.web(req, res, { target: options.functionsServer }); + } + const destStaticFile = await getStatic(dest.pathname, options.publicFolder); + const matchingFunction = functionsRegistry && + (await functionsRegistry.getFunctionForURLPath(destURL, req.method, () => Boolean(destStaticFile))); + let statusValue; + if (match.force || + (!staticFile && ((!options.framework && destStaticFile) || isInternal(destURL) || matchingFunction))) { + req.url = destStaticFile ? destStaticFile + dest.search : destURL; + const { status } = match; + statusValue = status; + console.log(`${NETLIFYDEVLOG} Rewrote URL to`, req.url); + } + if (matchingFunction) { + const functionHeaders = matchingFunction.func + ? { + [NFFunctionName]: matchingFunction.func?.name, + [NFFunctionRoute]: matchingFunction.route, + } + : {}; + const url = reqToURL(req, originalURL); + req.headers['x-netlify-original-pathname'] = url.pathname; + req.headers['x-netlify-original-search'] = url.search; + return proxy.web(req, res, { headers: functionHeaders, target: options.functionsServer }); + } + if (isImageRequest(req)) { + return imageProxy(req, res); + } + const addonUrl = getAddonUrl(options.addonsUrls, req); + if (addonUrl) { + handleAddonUrl({ req, res, addonUrl }); + return; + } + return proxy.web(req, res, { ...options, status: statusValue }); + } + return proxy.web(req, res, options); +}; +// @ts-expect-error TS(7006) FIXME: Parameter 'req' implicitly has an 'any' type. +const reqToURL = function (req, pathname) { + return new URL(pathname, `${req.protocol || (req.headers.scheme && `${req.headers.scheme}:`) || 'http:'}//${req.headers.host || req.hostname}`); +}; +const MILLISEC_TO_SEC = 1e3; +const initializeProxy = async function ({ config, configPath, distDir, env, host, imageProxy, port, projectDir, siteInfo, }) { + const proxy = httpProxy.createProxyServer({ + selfHandleResponse: true, + target: { + host, + port, + }, + }); + const headersFiles = [...new Set([path.resolve(projectDir, '_headers'), path.resolve(distDir, '_headers')])]; + let headers = await parseHeaders({ headersFiles, configPath, config }); + const watchedHeadersFiles = configPath === undefined ? headersFiles : [...headersFiles, configPath]; + onChanges(watchedHeadersFiles, async () => { + const existingHeadersFiles = await pFilter(watchedHeadersFiles, fileExistsAsync); + console.log(`${NETLIFYDEVLOG} Reloading headers files from`, existingHeadersFiles.map((headerFile) => path.relative(projectDir, headerFile))); + headers = await parseHeaders({ headersFiles, configPath, config }); + }); + // @ts-expect-error TS(2339) FIXME: Property 'before' does not exist on type 'Server'. + proxy.before('web', 'stream', (req) => { + // See https://github.com/http-party/node-http-proxy/issues/1219#issuecomment-511110375 + if (req.headers.expect) { + req.__expectHeader = req.headers.expect; + delete req.headers.expect; + } + }); + proxy.on('error', (err, req, res, proxyUrl) => { + // @ts-expect-error TS(2339) FIXME: Property 'proxyOptions' does not exist on type 'In... Remove this comment to see the full error message + const options = req.proxyOptions; + const isConRefused = 'code' in err && err.code === 'ECONNREFUSED'; + if (options?.detectTarget && !(res instanceof Socket) && isConRefused && proxyUrl) { + // got econnrefused while detectTarget set to true -> try to switch between current ipVer and other (4 to 6 and vice versa) + // proxyUrl is parsed in http-proxy using url, parsing the same here. Difference between it and + // URL that hostname not includes [] symbols when using url.parse + // eslint-disable-next-line n/no-deprecated-api + const targetUrl = typeof proxyUrl === 'string' ? url.parse(proxyUrl) : proxyUrl; + const isCurrentHost = targetUrl.hostname === options.targetHostname; + if (targetUrl.hostname && isCurrentHost) { + const newHost = isIPv6(targetUrl.hostname) ? '127.0.0.1' : '::1'; + options.target = `http://${isIPv6(newHost) ? `[${newHost}]` : newHost}:${targetUrl.port}`; + options.targetHostname = newHost; + options.isChangingTarget = true; + proxy.web(req, res, options); + return; + } + } + if (res instanceof http.ServerResponse) { + res.writeHead(500, { + 'Content-Type': 'text/plain', + }); + } + const message = isEdgeFunctionsRequest(req) + ? 'There was an error with an Edge Function. Please check the terminal for more details.' + : 'Could not proxy request.'; + res.end(message); + }); + proxy.on('proxyReq', (proxyReq, req) => { + const requestID = generateRequestID(); + proxyReq.setHeader(NFRequestID, requestID); + req.headers[NFRequestID] = requestID; + if (isEdgeFunctionsRequest(req)) { + handleProxyRequest(req, proxyReq); + } + // @ts-expect-error TS(2339) FIXME: Property '__expectHeader' does not exist on type '... Remove this comment to see the full error message + if (req.__expectHeader) { + // @ts-expect-error TS(2339) FIXME: Property '__expectHeader' does not exist on type '... Remove this comment to see the full error message + proxyReq.setHeader('Expect', req.__expectHeader); + } + // @ts-expect-error TS(2339) FIXME: Property 'originalBody' does not exist on type 'In... Remove this comment to see the full error message + if (req.originalBody) { + // @ts-expect-error TS(2339) FIXME: Property 'originalBody' does not exist on type 'In... Remove this comment to see the full error message + proxyReq.write(req.originalBody); + } + }); + proxy.on('proxyRes', (proxyRes, req, res) => { + res.setHeader('server', 'Netlify'); + const requestID = req.headers[NFRequestID]; + if (requestID) { + res.setHeader(NFRequestID, requestID); + } + // @ts-expect-error TS(2339) FIXME: Property 'proxyOptions' does not exist on type 'In... Remove this comment to see the full error message + const options = req.proxyOptions; + if (options.isChangingTarget) { + // got a response after switching the ipVer for host (and its not an error since we will be in on('error') handler) - let's remember this host now + // options are not exported in ts for the proxy: + // @ts-expect-error TS(2339) FIXME: Property 'options' does not exist on type 'In... + proxy.options.target.host = options.targetHostname; + options.changeSettings?.({ + frameworkHost: options.targetHostname, + detectFrameworkHost: false, + }); + console.log(`${NETLIFYDEVLOG} Switched host to ${options.targetHostname}`); + } + if (proxyRes.statusCode === 404 || proxyRes.statusCode === 403) { + // If a request for `/path` has failed, we'll a few variations like + // `/path/index.html` to mimic the CDN behavior. + // @ts-expect-error TS(2339) FIXME: Property 'alternativePaths' does not exist on type... Remove this comment to see the full error message + if (req.alternativePaths && req.alternativePaths.length !== 0) { + // @ts-expect-error TS(2339) FIXME: Property 'alternativePaths' does not exist on type... Remove this comment to see the full error message + req.url = req.alternativePaths.shift(); + // @ts-expect-error TS(2339) FIXME: Property 'proxyOptions' does not exist on type 'In... Remove this comment to see the full error message + proxy.web(req, res, req.proxyOptions); + return; + } + // The request has failed but we might still have a matching redirect + // rule (without `force`) that should kick in. This is how we mimic the + // file shadowing behavior from the CDN. + if (options && options.match) { + return serveRedirect({ + // We don't want to match functions at this point because any redirects + // to functions will have already been processed, so we don't supply a + // functions registry to `serveRedirect`. + functionsRegistry: null, + req, + res, + proxy: handlers, + imageProxy, + match: options.match, + options, + siteInfo, + env, + }); + } + } + if (options.staticFile && isRedirect({ status: proxyRes.statusCode }) && proxyRes.headers.location) { + req.url = proxyRes.headers.location; + return serveRedirect({ + // We don't want to match functions at this point because any redirects + // to functions will have already been processed, so we don't supply a + // functions registry to `serveRedirect`. + functionsRegistry: null, + req, + res, + proxy: handlers, + imageProxy, + match: null, + options, + siteInfo, + env, + }); + } + // @ts-expect-error TS(7034) FIXME: Variable 'responseData' implicitly has type 'any[]... Remove this comment to see the full error message + const responseData = []; + // @ts-expect-error TS(2345) FIXME: Argument of type 'string | undefined' is not assig... Remove this comment to see the full error message + const requestURL = new URL(req.url, `http://${req.headers.host || '127.0.0.1'}`); + const headersRules = headersForPath(headers, requestURL.pathname); + const configInjections = config.dev?.processing?.html?.injections ?? []; + const htmlInjections = configInjections.length > 0 && proxyRes.headers?.['content-type']?.startsWith('text/html') + ? configInjections + : undefined; + // for streamed responses, we can't do etag generation nor error templates. + // we'll just stream them through! + // when html_injections are present in dev config, we can't use streamed response + const isStreamedResponse = proxyRes.headers['content-length'] === undefined; + if (isStreamedResponse && !htmlInjections) { + Object.entries(headersRules).forEach(([key, val]) => { + // @ts-expect-error TS(2345) FIXME: Argument of type 'unknown' is not assignable to pa... Remove this comment to see the full error message + res.setHeader(key, val); + }); + res.writeHead(options.status || proxyRes.statusCode, proxyRes.headers); + proxyRes.on('data', function onData(data) { + res.write(data); + }); + proxyRes.on('end', function onEnd() { + res.end(); + }); + return; + } + proxyRes.on('data', function onData(data) { + responseData.push(data); + }); + proxyRes.on('end', async function onEnd() { + // @ts-expect-error TS(7005) FIXME: Variable 'responseData' implicitly has an 'any[]' ... Remove this comment to see the full error message + let responseBody = Buffer.concat(responseData); + let responseStatus = options.status || proxyRes.statusCode; + // `req[shouldGenerateETag]` may contain a function that determines + // whether the response should have an ETag header. + if ( + // @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message + typeof req[shouldGenerateETag] === 'function' && + // @ts-expect-error TS(7053) FIXME: Element implicitly has an 'any' type because expre... Remove this comment to see the full error message + req[shouldGenerateETag]({ statusCode: responseStatus }) === true) { + const etag = generateETag(responseBody, { weak: true }); + if (req.headers['if-none-match'] === etag) { + responseStatus = 304; + } + res.setHeader('etag', etag); + } + Object.entries(headersRules).forEach(([key, val]) => { + // @ts-expect-error TS(2345) FIXME: Argument of type 'unknown' is not assignable to pa... Remove this comment to see the full error message + res.setHeader(key, val); + }); + const isUncaughtError = proxyRes.headers['x-nf-uncaught-error'] === '1'; + if (isEdgeFunctionsRequest(req) && isUncaughtError) { + const acceptsHtml = req.headers.accept?.includes('text/html') ?? false; + const decompressedBody = await decompressResponseBody(responseBody, proxyRes.headers['content-encoding']); + const formattedBody = formatEdgeFunctionError(decompressedBody, acceptsHtml); + const errorResponse = acceptsHtml + ? await renderErrorTemplate(formattedBody, '../../src/lib/templates/function-error.html', 'edge function') + : formattedBody; + const contentLength = Buffer.from(errorResponse, 'utf8').byteLength; + res.setHeader('content-length', contentLength); + res.statusCode = 500; + res.write(errorResponse); + return res.end(); + } + let proxyResHeaders = proxyRes.headers; + if (htmlInjections) { + responseBody = await injectHtml(responseBody, proxyRes, htmlInjections); + proxyResHeaders = { + ...proxyResHeaders, + 'content-length': String(responseBody.byteLength), + }; + delete proxyResHeaders['transfer-encoding']; + } + res.writeHead(responseStatus, proxyResHeaders); + if (responseStatus !== 304) { + res.write(responseBody); + } + res.end(); + }); + }); + const handlers = { + // @ts-expect-error TS(7006) FIXME: Parameter 'req' implicitly has an 'any' type. + web: (req, res, options) => { + const requestURL = new URL(req.url, 'http://127.0.0.1'); + req.proxyOptions = options; + req.alternativePaths = alternativePathsFor(requestURL.pathname).map((filePath) => filePath + requestURL.search); + // Ref: https://nodejs.org/api/net.html#net_socket_remoteaddress + req.headers['x-forwarded-for'] = req.connection.remoteAddress || ''; + proxy.web(req, res, options); + }, + // @ts-expect-error TS(7006) FIXME: Parameter 'req' implicitly has an 'any' type. + ws: (req, socket, head, options) => { + proxy.ws(req, socket, head, options); + }, + }; + return handlers; +}; +const onRequest = async ({ addonsUrls, api, edgeFunctionsProxy, env, functionsRegistry, functionsServer, imageProxy, proxy, rewriter, settings, siteInfo, }, req, res) => { + req.originalBody = + req.method && ['GET', 'OPTIONS', 'HEAD'].includes(req.method) ? null : await createStreamPromise(req, BYTES_LIMIT); + if (isImageRequest(req)) { + return imageProxy(req, res); + } + const edgeFunctionsProxyURL = await edgeFunctionsProxy?.(req); + if (edgeFunctionsProxyURL !== undefined) { + return proxy.web(req, res, { target: edgeFunctionsProxyURL }); + } + const functionMatch = functionsRegistry && + (await functionsRegistry.getFunctionForURLPath(req.url, req.method, () => getStatic(decodeURIComponent(reqToURL(req, req.url).pathname), settings.dist ?? ''))); + if (functionMatch) { + // Setting an internal header with the function name so that we don't + // have to match the URL again in the functions server. + const headers = {}; + if (functionMatch.func) { + headers[NFFunctionName] = functionMatch.func.name; + } + if (functionMatch.route) { + headers[NFFunctionRoute] = functionMatch.route.pattern; + } + return proxy.web(req, res, { headers, target: functionsServer }); + } + const addonUrl = getAddonUrl(addonsUrls, req); + if (addonUrl) { + handleAddonUrl({ req, res, addonUrl }); + return; + } + const match = await rewriter(req); + const options = { + match, + addonsUrls, + target: `http://${settings.frameworkHost && isIPv6(settings.frameworkHost) ? `[${settings.frameworkHost}]` : settings.frameworkHost}:${settings.frameworkPort}`, + detectTarget: settings.detectFrameworkHost, + targetHostname: settings.frameworkHost, + publicFolder: settings.dist, + functionsServer, + functionsPort: settings.functionsPort, + jwtRolePath: settings.jwtRolePath, + framework: settings.framework, + changeSettings(newSettings) { + Object.assign(settings, newSettings); + }, + }; + const maybeNotifyActivity = () => { + if (req.method === 'GET' && api && process.env.NETLIFY_DEV_SERVER_ID) { + notifyActivity(api, siteInfo.id, process.env.NETLIFY_DEV_SERVER_ID); + } + }; + if (match) { + if (!isExternal(match)) { + maybeNotifyActivity(); + } + // We don't want to generate an ETag for 3xx redirects. + // @ts-expect-error TS(7031) FIXME: Binding element 'statusCode' implicitly has an 'an... Remove this comment to see the full error message + req[shouldGenerateETag] = ({ statusCode }) => statusCode < 300 || statusCode >= 400; + return serveRedirect({ req, res, proxy, imageProxy, match, options, siteInfo, env, functionsRegistry }); + } + // The request will be served by the framework server, which means we want to + // generate an ETag unless we're rendering an error page. The only way for + // us to know that is by looking at the status code + // @ts-expect-error TS(7031) FIXME: Binding element 'statusCode' implicitly has an 'an... Remove this comment to see the full error message + req[shouldGenerateETag] = ({ statusCode }) => statusCode >= 200 && statusCode < 300; + const hasFormSubmissionHandler = functionsRegistry && getFormHandler({ functionsRegistry, logWarning: false }); + const ct = req.headers['content-type'] ? contentType.parse(req).type : ''; + if (hasFormSubmissionHandler && + functionsServer && + req.method === 'POST' && + !isInternal(req.url) && + (ct.endsWith('/x-www-form-urlencoded') || ct === 'multipart/form-data')) { + return proxy.web(req, res, { target: functionsServer }); + } + maybeNotifyActivity(); + proxy.web(req, res, options); +}; +export const getProxyUrl = function (settings) { + const scheme = settings.https ? 'https' : 'http'; + return `${scheme}://localhost:${settings.port}`; +}; +export const startProxy = async function ({ accountId, addonsUrls, api, blobsContext, command, config, configPath, debug, disableEdgeFunctions, env, functionsRegistry, geoCountry, geolocationMode, getUpdatedConfig, inspectSettings, offline, projectDir, repositoryRoot, settings, siteInfo, state, }) { + const secondaryServerPort = settings.https ? await getAvailablePort() : null; + const functionsServer = settings.functionsPort ? `http://127.0.0.1:${settings.functionsPort}` : null; + let edgeFunctionsProxy; + if (disableEdgeFunctions) { + log(NETLIFYDEVWARN, 'Edge functions are disabled. Run without the --internal-disable-edge-functions flag to enable them.'); + } + else { + edgeFunctionsProxy = await initializeEdgeFunctionsProxy({ + command, + blobsContext, + config, + configPath, + debug, + env, + geolocationMode, + geoCountry, + getUpdatedConfig, + inspectSettings, + mainPort: settings.port, + offline, + passthroughPort: secondaryServerPort || settings.port, + settings, + projectDir, + repositoryRoot, + siteInfo, + accountId, + state, + }); + } + const imageProxy = initializeImageProxy({ + config, + settings, + }); + const proxy = await initializeProxy({ + env, + host: settings.frameworkHost, + port: settings.frameworkPort, + distDir: settings.dist, + projectDir, + configPath, + siteInfo, + imageProxy, + config, + }); + const rewriter = await createRewriter({ + config, + configPath, + distDir: settings.dist, + geoCountry, + jwtSecret: settings.jwtSecret, + jwtRoleClaim: settings.jwtRolePath, + projectDir, + }); + const onRequestWithOptions = onRequest.bind(undefined, { + proxy, + rewriter, + settings, + addonsUrls, + functionsRegistry, + functionsServer, + edgeFunctionsProxy, + imageProxy, + siteInfo, + env, + api, + }); + const primaryServer = settings.https + ? https.createServer({ cert: settings.https.cert, key: settings.https.key }, onRequestWithOptions) + : http.createServer(onRequestWithOptions); + const onUpgrade = async function onUpgrade(req, socket, head) { + const match = await rewriter(req); + if (match && !match.force404 && isExternal(match)) { + const reqUrl = reqToURL(req, req.url); + const dest = new URL(match.to, `${reqUrl.protocol}//${reqUrl.host}`); + const destURL = stripOrigin(dest); + proxy.ws(req, socket, head, { target: dest.origin, changeOrigin: true, pathRewrite: () => destURL }); + return; + } + proxy.ws(req, socket, head, {}); + }; + primaryServer.on('upgrade', onUpgrade); + primaryServer.listen({ port: settings.port }); + const eventQueue = [once(primaryServer, 'listening')]; + // If we're running the main server on HTTPS, we need to start a secondary + // server on HTTP for receiving passthrough requests from edge functions. + // This lets us run the Deno server on HTTP and avoid the complications of + // Deno talking to Node on HTTPS with potentially untrusted certificates. + if (secondaryServerPort) { + const secondaryServer = http.createServer(onRequestWithOptions); + secondaryServer.on('upgrade', onUpgrade); + secondaryServer.listen({ port: secondaryServerPort }); + eventQueue.push(once(secondaryServer, 'listening')); + } + await Promise.all(eventQueue); + return getProxyUrl(settings); +}; +const BYTES_LIMIT = 30; +//# sourceMappingURL=proxy.js.map \ No newline at end of file diff --git a/dist/utils/proxy.js.map b/dist/utils/proxy.js.map new file mode 100644 index 00000000000..9ecb6c684f9 --- /dev/null +++ b/dist/utils/proxy.js.map @@ -0,0 +1 @@ +{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../../src/utils/proxy.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/read-repo-url.d.ts b/dist/utils/read-repo-url.d.ts new file mode 100644 index 00000000000..2f0c499b35e --- /dev/null +++ b/dist/utils/read-repo-url.d.ts @@ -0,0 +1,12 @@ +declare const GITHUB = "GitHub"; +/** + * Takes a url like https://github.com/netlify-labs/all-the-functions/tree/master/functions/9-using-middleware + * and returns https://api.github.com/repos/netlify-labs/all-the-functions/contents/functions/9-using-middleware + */ +export declare const readRepoURL: (url: string) => Promise; +export declare const validateRepoURL: (url: string) => typeof GITHUB | null; +export declare const parseRepoURL: (repoHost: string, url: { + path: string | null; +}) => string[]; +export {}; +//# sourceMappingURL=read-repo-url.d.ts.map \ No newline at end of file diff --git a/dist/utils/read-repo-url.d.ts.map b/dist/utils/read-repo-url.d.ts.map new file mode 100644 index 00000000000..a44fe56cd50 --- /dev/null +++ b/dist/utils/read-repo-url.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"read-repo-url.d.ts","sourceRoot":"","sources":["../../src/utils/read-repo-url.ts"],"names":[],"mappings":"AAKA,QAAA,MAAM,MAAM,WAAW,CAAA;AAEvB;;;GAGG;AACH,eAAO,MAAM,WAAW,GAAmB,KAAK,MAAM,qBAWrD,CAAA;AAqBD,eAAO,MAAM,eAAe,GAAa,KAAK,MAAM,KAAG,OAAO,MAAM,GAAG,IAOtE,CAAA;AAED,eAAO,MAAM,YAAY,GAAa,UAAU,MAAM,EAAE,KAAK;IAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,aASnF,CAAA"} \ No newline at end of file diff --git a/dist/utils/read-repo-url.js b/dist/utils/read-repo-url.js new file mode 100644 index 00000000000..d85e7f54d36 --- /dev/null +++ b/dist/utils/read-repo-url.js @@ -0,0 +1,53 @@ +import URL from 'url'; +import fetch from 'node-fetch'; +// supported repo host types +const GITHUB = 'GitHub'; +/** + * Takes a url like https://github.com/netlify-labs/all-the-functions/tree/master/functions/9-using-middleware + * and returns https://api.github.com/repos/netlify-labs/all-the-functions/contents/functions/9-using-middleware + */ +export const readRepoURL = async function (url) { + // eslint-disable-next-line n/no-deprecated-api -- TODO: use `url.URL()` instead + const parsedURL = URL.parse(url); + const repoHost = validateRepoURL(url); + if (repoHost !== GITHUB) { + throw new Error('only GitHub repos are supported for now'); + } + const [ownerAndRepo, contentsPath] = parseRepoURL(repoHost, parsedURL); + const folderContents = await getRepoURLContents(repoHost, ownerAndRepo, contentsPath); + return folderContents; +}; +const getRepoURLContents = async function (repoHost, ownerAndRepo, contentsPath) { + // naive joining strategy for now + if (repoHost === GITHUB) { + // https://developer.github.com/v3/repos/contents/#get-contents + const APIURL = `https://api.github.com/repos/${ownerAndRepo}/contents/${contentsPath}`; + try { + const res = await fetch(APIURL); + return await res.json(); + } + catch (error) { + console.error(`Error occurred while fetching ${APIURL}`, error); + } + } + throw new Error(`unsupported host: ${repoHost}`); +}; +export const validateRepoURL = function (url) { + // eslint-disable-next-line n/no-deprecated-api -- TODO: use `url.URL()` instead + const parsedURL = URL.parse(url); + if (parsedURL.host === 'github.com') { + return GITHUB; + } + return null; +}; +export const parseRepoURL = function (repoHost, url) { + // naive splitting strategy for now + if (repoHost === GITHUB) { + // https://developer.github.com/v3/repos/contents/#get-contents + // what if it's not master? note that our contents retrieval may assume it is master + const [ownerAndRepo, contentsPath] = (url.path ?? '').slice(1).split('/tree/master/'); + return [ownerAndRepo, contentsPath]; + } + throw new Error(`Unsupported host ${repoHost}`); +}; +//# sourceMappingURL=read-repo-url.js.map \ No newline at end of file diff --git a/dist/utils/read-repo-url.js.map b/dist/utils/read-repo-url.js.map new file mode 100644 index 00000000000..525413985e7 --- /dev/null +++ b/dist/utils/read-repo-url.js.map @@ -0,0 +1 @@ +{"version":3,"file":"read-repo-url.js","sourceRoot":"","sources":["../../src/utils/read-repo-url.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,KAAK,CAAA;AAErB,OAAO,KAAK,MAAM,YAAY,CAAA;AAE9B,4BAA4B;AAC5B,MAAM,MAAM,GAAG,QAAQ,CAAA;AAEvB;;;GAGG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,WAAW,GAAW;IACpD,gFAAgF;IAChF,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAChC,MAAM,QAAQ,GAAG,eAAe,CAAC,GAAG,CAAC,CAAA;IACrC,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC,CAAA;IAC5D,CAAC;IAED,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC,GAAG,YAAY,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;IACtE,MAAM,cAAc,GAAG,MAAM,kBAAkB,CAAC,QAAQ,EAAE,YAAY,EAAE,YAAY,CAAC,CAAA;IACrF,OAAO,cAAc,CAAA;AACvB,CAAC,CAAA;AAED,MAAM,kBAAkB,GAAG,KAAK,WAC9B,QAAgB,EAChB,YAAoB,EACpB,YAAoB;IAEpB,iCAAiC;IACjC,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxB,+DAA+D;QAC/D,MAAM,MAAM,GAAG,gCAAgC,YAAY,aAAa,YAAY,EAAE,CAAA;QACtF,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,CAAA;YAC/B,OAAO,MAAM,GAAG,CAAC,IAAI,EAAE,CAAA;QACzB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,iCAAiC,MAAM,EAAE,EAAE,KAAK,CAAC,CAAA;QACjE,CAAC;IACH,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,EAAE,CAAC,CAAA;AAClD,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,UAAU,GAAW;IAClD,gFAAgF;IAChF,MAAM,SAAS,GAAG,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAChC,IAAI,SAAS,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;QACpC,OAAO,MAAM,CAAA;IACf,CAAC;IACD,OAAO,IAAI,CAAA;AACb,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,YAAY,GAAG,UAAU,QAAgB,EAAE,GAA4B;IAClF,mCAAmC;IACnC,IAAI,QAAQ,KAAK,MAAM,EAAE,CAAC;QACxB,+DAA+D;QAC/D,oFAAoF;QACpF,MAAM,CAAC,YAAY,EAAE,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,eAAe,CAAC,CAAA;QACrF,OAAO,CAAC,YAAY,EAAE,YAAY,CAAC,CAAA;IACrC,CAAC;IACD,MAAM,IAAI,KAAK,CAAC,oBAAoB,QAAQ,EAAE,CAAC,CAAA;AACjD,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/redirects.d.ts b/dist/utils/redirects.d.ts new file mode 100644 index 00000000000..75ce9542c62 --- /dev/null +++ b/dist/utils/redirects.d.ts @@ -0,0 +1,6 @@ +export declare const parseRedirects: ({ config, configPath, redirectsFiles }: { + config: any; + configPath: any; + redirectsFiles: any; +}) => Promise; +//# sourceMappingURL=redirects.d.ts.map \ No newline at end of file diff --git a/dist/utils/redirects.d.ts.map b/dist/utils/redirects.d.ts.map new file mode 100644 index 00000000000..1f2a902547d --- /dev/null +++ b/dist/utils/redirects.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"redirects.d.ts","sourceRoot":"","sources":["../../src/utils/redirects.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,cAAc,GAAmB;;;;CAAsC,mBAUnF,CAAA"} \ No newline at end of file diff --git a/dist/utils/redirects.js b/dist/utils/redirects.js new file mode 100644 index 00000000000..c47c7829a5d --- /dev/null +++ b/dist/utils/redirects.js @@ -0,0 +1,59 @@ +import { parseAllRedirects } from '@netlify/redirect-parser'; +import { NETLIFYDEVERR, log } from './command-helpers.js'; +// Parse, normalize and validate all redirects from `_redirects` files +// and `netlify.toml` +// @ts-expect-error TS(7031) FIXME: Binding element 'configPath' implicitly has an 'an... Remove this comment to see the full error message +export const parseRedirects = async function ({ config, configPath, redirectsFiles }) { + const { errors, redirects } = await parseAllRedirects({ + redirectsFiles, + netlifyConfigPath: configPath, + minimal: false, + configRedirects: config?.redirects || [], + }); + handleRedirectParsingErrors(errors); + // @ts-expect-error TS(2345) FIXME: Argument of type '({ conditions: { country, langua... Remove this comment to see the full error message + return redirects.map(normalizeRedirect); +}; +// @ts-expect-error TS(7006) FIXME: Parameter 'errors' implicitly has an 'any' type. +const handleRedirectParsingErrors = function (errors) { + if (errors.length === 0) { + return; + } + const errorMessage = errors.map(getErrorMessage).join('\n\n'); + log(NETLIFYDEVERR, `Redirects syntax errors:\n${errorMessage}`); +}; +// @ts-expect-error TS(7031) FIXME: Binding element 'message' implicitly has an 'any' ... Remove this comment to see the full error message +const getErrorMessage = function ({ message }) { + return message; +}; +// `netlify-redirector` does not handle the same shape as the backend: +// - `from` is called `origin` +// - `query` is called `params` +// - `conditions.role|country|language` are capitalized +const normalizeRedirect = function ({ +// @ts-expect-error TS(7031) FIXME: Binding element 'country' implicitly has an 'any' ... Remove this comment to see the full error message +conditions: { country, language, role, ...conditions }, +// @ts-expect-error TS(7031) FIXME: Binding element 'from' implicitly has an 'any' typ... Remove this comment to see the full error message +from, +// @ts-expect-error TS(7031) FIXME: Binding element 'query' implicitly has an 'any' ty... Remove this comment to see the full error message +query, +// @ts-expect-error TS(7031) FIXME: Binding element 'signed' implicitly has an 'any' t... Remove this comment to see the full error message +signed, ...redirect }) { + return { + ...redirect, + origin: from, + params: query, + conditions: { + ...conditions, + ...(role && { Role: role }), + ...(country && { Country: country }), + ...(language && { Language: language }), + }, + ...(signed && { + sign: { + jwt_secret: signed, + }, + }), + }; +}; +//# sourceMappingURL=redirects.js.map \ No newline at end of file diff --git a/dist/utils/redirects.js.map b/dist/utils/redirects.js.map new file mode 100644 index 00000000000..b9144303401 --- /dev/null +++ b/dist/utils/redirects.js.map @@ -0,0 +1 @@ +{"version":3,"file":"redirects.js","sourceRoot":"","sources":["../../src/utils/redirects.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAA;AAE5D,OAAO,EAAE,aAAa,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAEzD,sEAAsE;AACtE,qBAAqB;AACrB,2IAA2I;AAC3I,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,cAAc,EAAE;IAClF,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,iBAAiB,CAAC;QACpD,cAAc;QACd,iBAAiB,EAAE,UAAU;QAC7B,OAAO,EAAE,KAAK;QACd,eAAe,EAAE,MAAM,EAAE,SAAS,IAAI,EAAE;KACzC,CAAC,CAAA;IACF,2BAA2B,CAAC,MAAM,CAAC,CAAA;IACnC,2IAA2I;IAC3I,OAAO,SAAS,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAA;AACzC,CAAC,CAAA;AAED,oFAAoF;AACpF,MAAM,2BAA2B,GAAG,UAAU,MAAM;IAClD,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAM;IACR,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAC7D,GAAG,CAAC,aAAa,EAAE,6BAA6B,YAAY,EAAE,CAAC,CAAA;AACjE,CAAC,CAAA;AAED,2IAA2I;AAC3I,MAAM,eAAe,GAAG,UAAU,EAAE,OAAO,EAAE;IAC3C,OAAO,OAAO,CAAA;AAChB,CAAC,CAAA;AAED,sEAAsE;AACtE,+BAA+B;AAC/B,gCAAgC;AAChC,wDAAwD;AACxD,MAAM,iBAAiB,GAAG,UAAU;AAClC,2IAA2I;AAC3I,UAAU,EAAE,EAAE,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,UAAU,EAAE;AACtD,2IAA2I;AAC3I,IAAI;AACJ,2IAA2I;AAC3I,KAAK;AACL,2IAA2I;AAC3I,MAAM,EACN,GAAG,QAAQ,EACZ;IACC,OAAO;QACL,GAAG,QAAQ;QACX,MAAM,EAAE,IAAI;QACZ,MAAM,EAAE,KAAK;QACb,UAAU,EAAE;YACV,GAAG,UAAU;YACb,GAAG,CAAC,IAAI,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;YAC3B,GAAG,CAAC,OAAO,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;YACpC,GAAG,CAAC,QAAQ,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAC;SACxC;QACD,GAAG,CAAC,MAAM,IAAI;YACZ,IAAI,EAAE;gBACJ,UAAU,EAAE,MAAM;aACnB;SACF,CAAC;KACH,CAAA;AACH,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/request-id.d.ts b/dist/utils/request-id.d.ts new file mode 100644 index 00000000000..6378a947451 --- /dev/null +++ b/dist/utils/request-id.d.ts @@ -0,0 +1,2 @@ +export declare const generateRequestID: () => string; +//# sourceMappingURL=request-id.d.ts.map \ No newline at end of file diff --git a/dist/utils/request-id.d.ts.map b/dist/utils/request-id.d.ts.map new file mode 100644 index 00000000000..0d08f16ba45 --- /dev/null +++ b/dist/utils/request-id.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"request-id.d.ts","sourceRoot":"","sources":["../../src/utils/request-id.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,iBAAiB,cAAe,CAAA"} \ No newline at end of file diff --git a/dist/utils/request-id.js b/dist/utils/request-id.js new file mode 100644 index 00000000000..3a9ea843705 --- /dev/null +++ b/dist/utils/request-id.js @@ -0,0 +1,3 @@ +import { ulid } from 'ulid'; +export const generateRequestID = () => ulid(); +//# sourceMappingURL=request-id.js.map \ No newline at end of file diff --git a/dist/utils/request-id.js.map b/dist/utils/request-id.js.map new file mode 100644 index 00000000000..63174d1d08d --- /dev/null +++ b/dist/utils/request-id.js.map @@ -0,0 +1 @@ +{"version":3,"file":"request-id.js","sourceRoot":"","sources":["../../src/utils/request-id.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAE3B,MAAM,CAAC,MAAM,iBAAiB,GAAG,GAAG,EAAE,CAAC,IAAI,EAAE,CAAA"} \ No newline at end of file diff --git a/dist/utils/rules-proxy.d.ts b/dist/utils/rules-proxy.d.ts new file mode 100644 index 00000000000..e00d01755c8 --- /dev/null +++ b/dist/utils/rules-proxy.d.ts @@ -0,0 +1,16 @@ +import { type FSWatcher } from 'chokidar'; +import { type NormalizedCachedConfigConfig } from './command-helpers.js'; +import type { Rewriter } from './types.js'; +export declare const onChanges: (files: string[], listener: () => unknown) => void; +export declare const getWatchers: () => FSWatcher[]; +export declare const getLanguage: (headers: Record) => string; +export declare const createRewriter: ({ config, configPath, distDir, geoCountry, jwtRoleClaim, jwtSecret, projectDir, }: { + config: NormalizedCachedConfigConfig; + configPath?: string | undefined; + distDir?: string | undefined; + geoCountry?: string | undefined; + jwtRoleClaim: string; + jwtSecret: string; + projectDir: string; +}) => Promise; +//# sourceMappingURL=rules-proxy.d.ts.map \ No newline at end of file diff --git a/dist/utils/rules-proxy.d.ts.map b/dist/utils/rules-proxy.d.ts.map new file mode 100644 index 00000000000..d9bf39eea62 --- /dev/null +++ b/dist/utils/rules-proxy.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"rules-proxy.d.ts","sourceRoot":"","sources":["../../src/utils/rules-proxy.ts"],"names":[],"mappings":"AAEA,OAAiB,EAAE,KAAK,SAAS,EAAE,MAAM,UAAU,CAAA;AAQnD,OAAO,EAAiB,KAAK,4BAA4B,EAAE,MAAM,sBAAsB,CAAA;AAEvF,OAAO,KAAK,EAAW,QAAQ,EAAE,MAAM,YAAY,CAAA;AAInD,eAAO,MAAM,SAAS,GAAa,OAAO,MAAM,EAAE,EAAE,UAAU,MAAM,OAAO,KAAG,IAO7E,CAAA;AAED,eAAO,MAAM,WAAW,QAAgB,SAAS,EAEhD,CAAA;AAED,eAAO,MAAM,WAAW,GAAa,SAAS,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS,CAAC,WAS1F,CAAA;AAED,eAAO,MAAM,cAAc,GAAmB,mFAQ3C;IACD,MAAM,EAAE,4BAA4B,CAAA;IACpC,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC5B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAA;IAC/B,YAAY,EAAE,MAAM,CAAA;IACpB,SAAS,EAAE,MAAM,CAAA;IACjB,UAAU,EAAE,MAAM,CAAA;CACnB,KAAG,OAAO,CAAC,QAAQ,CAqEnB,CAAA"} \ No newline at end of file diff --git a/dist/utils/rules-proxy.js b/dist/utils/rules-proxy.js new file mode 100644 index 00000000000..31db7dba033 --- /dev/null +++ b/dist/utils/rules-proxy.js @@ -0,0 +1,87 @@ +import path from 'path'; +import chokidar from 'chokidar'; +import cookie from 'cookie'; +import redirector from 'netlify-redirector'; +import pFilter from 'p-filter'; +import { fileExistsAsync } from '../lib/fs.js'; +import { NETLIFYDEVLOG } from './command-helpers.js'; +import { parseRedirects } from './redirects.js'; +const watchers = []; +export const onChanges = function (files, listener) { + files.forEach((file) => { + const watcher = chokidar.watch(file); + watcher.on('change', listener); + watcher.on('unlink', listener); + watchers.push(watcher); + }); +}; +export const getWatchers = function () { + return watchers; +}; +export const getLanguage = function (headers) { + if (headers['accept-language']) { + return (Array.isArray(headers['accept-language']) ? headers['accept-language'].join(', ') : headers['accept-language']) + .split(',')[0] + .slice(0, 2); + } + return 'en'; +}; +export const createRewriter = async function ({ config, configPath, distDir, geoCountry, jwtRoleClaim, jwtSecret, projectDir, }) { + let matcher = null; + const redirectsFiles = [ + ...new Set([path.resolve(distDir ?? '', '_redirects'), path.resolve(projectDir, '_redirects')]), + ]; + let redirects = await parseRedirects({ config, redirectsFiles, configPath }); + const watchedRedirectFiles = configPath === undefined ? redirectsFiles : [...redirectsFiles, configPath]; + onChanges(watchedRedirectFiles, async () => { + const existingRedirectsFiles = await pFilter(watchedRedirectFiles, fileExistsAsync); + console.log(`${NETLIFYDEVLOG} Reloading redirect rules from`, existingRedirectsFiles.map((redirectFile) => path.relative(projectDir, redirectFile))); + redirects = await parseRedirects({ config, redirectsFiles, configPath }); + matcher = null; + }); + const getMatcher = async () => { + if (matcher) + return matcher; + if (redirects.length !== 0) { + return (matcher = await redirector.parseJSON(JSON.stringify(redirects), { + jwtSecret, + jwtRoleClaim, + })); + } + return { + match() { + return null; + }, + }; + }; + return async function rewriter(req) { + const matcherFunc = await getMatcher(); + const reqUrl = new URL(req.url ?? '', `${req.protocol || (req.headers.scheme && `${req.headers.scheme}:`) || 'http:'}//${req.hostname || req.headers.host}`); + const cookieValues = cookie.parse(req.headers.cookie || ''); + const headers = { + 'x-language': cookieValues.nf_lang || getLanguage(req.headers), + 'x-country': cookieValues.nf_country || geoCountry || 'us', + ...req.headers, + }; + // Definition: https://github.com/netlify/libredirect/blob/e81bbeeff9f7c260a5fb74cad296ccc67a92325b/node/src/redirects.cpp#L28-L60 + const matchReq = { + scheme: reqUrl.protocol.replace(/:.*$/, ''), + host: reqUrl.hostname, + path: decodeURIComponent(reqUrl.pathname), + query: reqUrl.search.slice(1), + headers, + cookieValues, + getHeader: (name) => { + const val = headers[name.toLowerCase()]; + if (Array.isArray(val)) { + return val[0]; + } + return val || ''; + }, + getCookie: (key) => cookieValues[key] || '', + }; + const match = matcherFunc.match(matchReq); + return match; + }; +}; +//# sourceMappingURL=rules-proxy.js.map \ No newline at end of file diff --git a/dist/utils/rules-proxy.js.map b/dist/utils/rules-proxy.js.map new file mode 100644 index 00000000000..6f36a9a1e34 --- /dev/null +++ b/dist/utils/rules-proxy.js.map @@ -0,0 +1 @@ +{"version":3,"file":"rules-proxy.js","sourceRoot":"","sources":["../../src/utils/rules-proxy.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/run-build.d.ts b/dist/utils/run-build.d.ts new file mode 100644 index 00000000000..bddbc083795 --- /dev/null +++ b/dist/utils/run-build.d.ts @@ -0,0 +1,33 @@ +import BaseCommand from '../commands/base-command.js'; +import { $TSFixMe } from '../commands/types.js'; +import { ServerSettings } from './types.js'; +export declare const runNetlifyBuild: ({ command, env, options, settings, timeline, }: { + command: BaseCommand; + options: $TSFixMe; + settings: ServerSettings; + env: NodeJS.ProcessEnv; + timeline: "build" | "dev"; +}) => Promise<{ + configPath: string; + configMutations?: undefined; +} | { + configMutations: any; + configPath?: undefined; +}>; +type RunTimelineOptions = Omit[0], 'timeline'>; +export declare const runDevTimeline: (options: RunTimelineOptions) => Promise<{ + configPath: string; + configMutations?: undefined; +} | { + configMutations: any; + configPath?: undefined; +}>; +export declare const runBuildTimeline: (options: RunTimelineOptions) => Promise<{ + configPath: string; + configMutations?: undefined; +} | { + configMutations: any; + configPath?: undefined; +}>; +export {}; +//# sourceMappingURL=run-build.d.ts.map \ No newline at end of file diff --git a/dist/utils/run-build.d.ts.map b/dist/utils/run-build.d.ts.map new file mode 100644 index 00000000000..1e78b16e679 --- /dev/null +++ b/dist/utils/run-build.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"run-build.d.ts","sourceRoot":"","sources":["../../src/utils/run-build.ts"],"names":[],"mappings":"AAKA,OAAO,WAAW,MAAM,6BAA6B,CAAA;AACrD,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAA;AAS/C,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAkC3C,eAAO,MAAM,eAAe,GAAU,gDAMnC;IACD,OAAO,EAAE,WAAW,CAAA;IAEpB,OAAO,EAAE,QAAQ,CAAA;IACjB,QAAQ,EAAE,cAAc,CAAA;IACxB,GAAG,EAAE,MAAM,CAAC,UAAU,CAAA;IACtB,QAAQ,EAAE,OAAO,GAAG,KAAK,CAAA;CAC1B;;;;;;EA8GA,CAAA;AAED,KAAK,kBAAkB,GAAG,IAAI,CAAC,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAA;AAEjF,eAAO,MAAM,cAAc,GAAI,SAAS,kBAAkB;;;;;;EAAqD,CAAA;AAE/G,eAAO,MAAM,gBAAgB,GAAI,SAAS,kBAAkB;;;;;;EAAuD,CAAA"} \ No newline at end of file diff --git a/dist/utils/run-build.js b/dist/utils/run-build.js new file mode 100644 index 00000000000..fb59066d78a --- /dev/null +++ b/dist/utils/run-build.js @@ -0,0 +1,126 @@ +import { promises as fs } from 'fs'; +import path, { join } from 'path'; +import { getBootstrapURL } from '../lib/edge-functions/bootstrap.js'; +import { INTERNAL_EDGE_FUNCTIONS_FOLDER } from '../lib/edge-functions/consts.js'; +import { getPathInProject } from '../lib/settings.js'; +import { logAndThrowError } from './command-helpers.js'; +import { getFeatureFlagsFromSiteInfo } from './feature-flags.js'; +import { startFrameworkServer } from './framework-server.js'; +import { INTERNAL_FUNCTIONS_FOLDER } from './functions/index.js'; +const netlifyBuildPromise = import('@netlify/build'); +/** + * Copies `netlify.toml`, if one is defined, into the `.netlify` internal + * directory and returns the path to its new location. + */ +const copyConfig = async (configPath, destinationFolder) => { + const newConfigPath = path.resolve(destinationFolder, getPathInProject(['netlify.toml'])); + try { + await fs.copyFile(configPath, newConfigPath); + } + catch { + // no-op + } + return newConfigPath; +}; +const cleanInternalDirectory = async (basePath) => { + if (!basePath) { + return; + } + const ops = [INTERNAL_FUNCTIONS_FOLDER, INTERNAL_EDGE_FUNCTIONS_FOLDER, 'netlify.toml'].map((name) => { + const fullPath = path.resolve(basePath, getPathInProject([name])); + return fs.rm(fullPath, { force: true, recursive: true }); + }); + await Promise.all(ops); +}; +export const runNetlifyBuild = async ({ command, env = {}, options, settings, timeline = 'build', }) => { + const { apiOpts, cachedConfig, site } = command.netlify; + const { default: buildSite, startDev } = await netlifyBuildPromise; + const sharedOptions = { + cachedConfig, + configPath: cachedConfig.configPath, + siteId: cachedConfig.siteInfo.id, + token: cachedConfig.token, + apiHost: apiOpts.host, + dry: options.dry, + debug: options.debug, + context: options.context, + mode: 'cli', + telemetry: false, + buffer: false, + featureFlags: getFeatureFlagsFromSiteInfo(cachedConfig.siteInfo), + offline: options.offline, + packagePath: command.workspacePackage, + cwd: cachedConfig.buildDir, + quiet: options.quiet, + saveConfig: options.saveConfig, + edgeFunctionsBootstrapURL: await getBootstrapURL(), + }; + const devCommand = async ({ netlifyConfig, settingsOverrides, } = {}) => { + let cwd = command.workingDir; + if (!options.cwd && command.project.workspace?.packages.length) { + cwd = join(command.project.jsWorkspaceRoot, settings.baseDirectory || ''); + } + const { ipVersion } = await startFrameworkServer({ + settings: { + ...settings, + ...settingsOverrides, + ...(options.skipWaitPort ? { skipWaitPort: true } : {}), + env: { + ...settings.env, + ...settingsOverrides?.env, + ...netlifyConfig?.build.environment, + }, + }, + cwd, + }); + settings.frameworkHost = ipVersion === 6 ? '::1' : '127.0.0.1'; + settings.detectFrameworkHost = options.skipWaitPort; + }; + if (timeline === 'build') { + // Start by cleaning the internal directory, as it may have artifacts left + // by previous builds. + await cleanInternalDirectory(site.root); + // Copy `netlify.toml` into the internal directory. This will be the new + // location of the config file for the duration of the command. + const tempConfigPath = await copyConfig(cachedConfig.configPath ?? '', command.workingDir); + const buildSiteOptions = { + ...sharedOptions, + outputConfigPath: tempConfigPath, + saveConfig: true, + }; + // Run Netlify Build using the main entry point. + // @ts-expect-error TS(2345) FIXME: Argument of type '{ outputConfigPath: string; save... Remove this comment to see the full error message + const { netlifyConfig, success } = await buildSite(buildSiteOptions); + if (!success) { + return logAndThrowError('Could not start local server due to a build error'); + } + // Start the dev server, forcing the usage of a static server as opposed to + // the framework server. + const settingsOverrides = { + command: undefined, + useStaticServer: true, + dist: undefined, + }; + if (!options.dir && netlifyConfig?.build?.publish) { + settingsOverrides.dist = netlifyConfig.build.publish; + } + await devCommand({ netlifyConfig, settingsOverrides }); + return { configPath: tempConfigPath }; + } + const startDevOptions = { + ...sharedOptions, + // Set `quiet` to suppress non-essential output from Netlify Build unless + // the `debug` flag is set. + quiet: !options.debug, + env, + }; + // Run Netlify Build using the `startDev` entry point. + const { configMutations, error: startDevError, success } = await startDev(devCommand, startDevOptions); + if (!success && startDevError) { + return logAndThrowError(`Could not start local development server\n\n${startDevError.message}\n\n${startDevError.stack}`); + } + return { configMutations }; +}; +export const runDevTimeline = (options) => runNetlifyBuild({ ...options, timeline: 'dev' }); +export const runBuildTimeline = (options) => runNetlifyBuild({ ...options, timeline: 'build' }); +//# sourceMappingURL=run-build.js.map \ No newline at end of file diff --git a/dist/utils/run-build.js.map b/dist/utils/run-build.js.map new file mode 100644 index 00000000000..7b30bdd29e9 --- /dev/null +++ b/dist/utils/run-build.js.map @@ -0,0 +1 @@ +{"version":3,"file":"run-build.js","sourceRoot":"","sources":["../../src/utils/run-build.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/run-git.d.ts b/dist/utils/run-git.d.ts new file mode 100644 index 00000000000..e73a559ab74 --- /dev/null +++ b/dist/utils/run-git.d.ts @@ -0,0 +1,2 @@ +export declare const runGit: (args: string[], quiet: boolean) => Promise; +//# sourceMappingURL=run-git.d.ts.map \ No newline at end of file diff --git a/dist/utils/run-git.d.ts.map b/dist/utils/run-git.d.ts.map new file mode 100644 index 00000000000..d736172b6b2 --- /dev/null +++ b/dist/utils/run-git.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"run-git.d.ts","sourceRoot":"","sources":["../../src/utils/run-git.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM,GAAU,MAAM,MAAM,EAAE,EAAE,OAAO,OAAO,kBAI1D,CAAA"} \ No newline at end of file diff --git a/dist/utils/run-git.js b/dist/utils/run-git.js new file mode 100644 index 00000000000..88d0d3133fd --- /dev/null +++ b/dist/utils/run-git.js @@ -0,0 +1,7 @@ +import execa from './execa.js'; +export const runGit = async (args, quiet) => { + await execa('git', args, { + ...(quiet ? {} : { stdio: 'inherit' }), + }); +}; +//# sourceMappingURL=run-git.js.map \ No newline at end of file diff --git a/dist/utils/run-git.js.map b/dist/utils/run-git.js.map new file mode 100644 index 00000000000..1db2f94f7d8 --- /dev/null +++ b/dist/utils/run-git.js.map @@ -0,0 +1 @@ +{"version":3,"file":"run-git.js","sourceRoot":"","sources":["../../src/utils/run-git.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAA;AAE9B,MAAM,CAAC,MAAM,MAAM,GAAG,KAAK,EAAE,IAAc,EAAE,KAAc,EAAE,EAAE;IAC7D,MAAM,KAAK,CAAC,KAAK,EAAE,IAAI,EAAE;QACvB,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;KACvC,CAAC,CAAA;AACJ,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/run-program.d.ts b/dist/utils/run-program.d.ts new file mode 100644 index 00000000000..7f0b7393d57 --- /dev/null +++ b/dist/utils/run-program.d.ts @@ -0,0 +1,3 @@ +import { BaseCommand } from '../commands/index.js'; +export declare const runProgram: (program: BaseCommand, argv: string[]) => Promise; +//# sourceMappingURL=run-program.d.ts.map \ No newline at end of file diff --git a/dist/utils/run-program.d.ts.map b/dist/utils/run-program.d.ts.map new file mode 100644 index 00000000000..fd143020903 --- /dev/null +++ b/dist/utils/run-program.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"run-program.d.ts","sourceRoot":"","sources":["../../src/utils/run-program.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AAIlD,eAAO,MAAM,UAAU,GAAU,SAAS,WAAW,EAAE,MAAM,MAAM,EAAE,kBAUpE,CAAA"} \ No newline at end of file diff --git a/dist/utils/run-program.js b/dist/utils/run-program.js new file mode 100644 index 00000000000..85e3c33f966 --- /dev/null +++ b/dist/utils/run-program.js @@ -0,0 +1,13 @@ +import { injectForceFlagIfScripted } from './scripted-commands.js'; +import { CI_FORCED_COMMANDS } from '../commands/main.js'; +// This function is used to run the program with the correct flags +export const runProgram = async (program, argv) => { + const cmdName = argv[2]; + // checks if the command has a force option + const isValidForceCommand = cmdName in CI_FORCED_COMMANDS; + if (isValidForceCommand) { + injectForceFlagIfScripted(argv); + } + await program.parseAsync(argv); +}; +//# sourceMappingURL=run-program.js.map \ No newline at end of file diff --git a/dist/utils/run-program.js.map b/dist/utils/run-program.js.map new file mode 100644 index 00000000000..312531f3fbf --- /dev/null +++ b/dist/utils/run-program.js.map @@ -0,0 +1 @@ +{"version":3,"file":"run-program.js","sourceRoot":"","sources":["../../src/utils/run-program.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAA;AAElE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AAExD,kEAAkE;AAClE,MAAM,CAAC,MAAM,UAAU,GAAG,KAAK,EAAE,OAAoB,EAAE,IAAc,EAAE,EAAE;IACvE,MAAM,OAAO,GAAG,IAAI,CAAC,CAAC,CAAC,CAAA;IACvB,2CAA2C;IAC3C,MAAM,mBAAmB,GAAG,OAAO,IAAI,kBAAkB,CAAA;IAEzD,IAAI,mBAAmB,EAAE,CAAC;QACxB,yBAAyB,CAAC,IAAI,CAAC,CAAA;IACjC,CAAC;IAED,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAA;AAChC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/scripted-commands.d.ts b/dist/utils/scripted-commands.d.ts new file mode 100644 index 00000000000..16699fcbb83 --- /dev/null +++ b/dist/utils/scripted-commands.d.ts @@ -0,0 +1,3 @@ +export declare const shouldForceFlagBeInjected: (argv: string[]) => boolean; +export declare const injectForceFlagIfScripted: (argv: string[]) => void; +//# sourceMappingURL=scripted-commands.d.ts.map \ No newline at end of file diff --git a/dist/utils/scripted-commands.d.ts.map b/dist/utils/scripted-commands.d.ts.map new file mode 100644 index 00000000000..86a0667473a --- /dev/null +++ b/dist/utils/scripted-commands.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"scripted-commands.d.ts","sourceRoot":"","sources":["../../src/utils/scripted-commands.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,yBAAyB,GAAI,MAAM,MAAM,EAAE,KAAG,OAY1D,CAAA;AAED,eAAO,MAAM,yBAAyB,GAAI,MAAM,MAAM,EAAE,SAIvD,CAAA"} \ No newline at end of file diff --git a/dist/utils/scripted-commands.js b/dist/utils/scripted-commands.js new file mode 100644 index 00000000000..e57f0e65a4f --- /dev/null +++ b/dist/utils/scripted-commands.js @@ -0,0 +1,18 @@ +import process from 'process'; +import { isCI } from 'ci-info'; +export const shouldForceFlagBeInjected = (argv) => { + // Is the command run in a non-interactive shell or CI/CD environment? + const scriptedCommand = Boolean(!process.stdin.isTTY || isCI || process.env.CI); + // Is the `--force` flag not already present? + const noForceFlag = !argv.includes('--force'); + // ENV Variable used to tests prompts in CI/CD enviroment + const testingPrompts = process.env.TESTING_PROMPTS !== 'true'; + // Prevents prompts from blocking scripted commands + return Boolean(scriptedCommand && testingPrompts && noForceFlag); +}; +export const injectForceFlagIfScripted = (argv) => { + if (shouldForceFlagBeInjected(argv)) { + argv.push('--force'); + } +}; +//# sourceMappingURL=scripted-commands.js.map \ No newline at end of file diff --git a/dist/utils/scripted-commands.js.map b/dist/utils/scripted-commands.js.map new file mode 100644 index 00000000000..3056e8486e3 --- /dev/null +++ b/dist/utils/scripted-commands.js.map @@ -0,0 +1 @@ +{"version":3,"file":"scripted-commands.js","sourceRoot":"","sources":["../../src/utils/scripted-commands.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAA;AAC7B,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAE9B,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,IAAc,EAAW,EAAE;IACnE,sEAAsE;IACtE,MAAM,eAAe,GAAG,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAE/E,6CAA6C;IAC7C,MAAM,WAAW,GAAG,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAA;IAE7C,yDAAyD;IACzD,MAAM,cAAc,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,MAAM,CAAA;IAE7D,mDAAmD;IACnD,OAAO,OAAO,CAAC,eAAe,IAAI,cAAc,IAAI,WAAW,CAAC,CAAA;AAClE,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,yBAAyB,GAAG,CAAC,IAAc,EAAE,EAAE;IAC1D,IAAI,yBAAyB,CAAC,IAAI,CAAC,EAAE,CAAC;QACpC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACtB,CAAC;AACH,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/shell.d.ts b/dist/utils/shell.d.ts new file mode 100644 index 00000000000..6f2caaddaaa --- /dev/null +++ b/dist/utils/shell.d.ts @@ -0,0 +1,8 @@ +import execa from 'execa'; +import { type Spinner } from '../lib/spinner.js'; +export declare const runCommand: (command: string, options: { + spinner?: Spinner; + env?: NodeJS.ProcessEnv; + cwd: string; +}) => execa.ExecaChildProcess; +//# sourceMappingURL=shell.d.ts.map \ No newline at end of file diff --git a/dist/utils/shell.d.ts.map b/dist/utils/shell.d.ts.map new file mode 100644 index 00000000000..b1bad9f4d4e --- /dev/null +++ b/dist/utils/shell.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"shell.d.ts","sourceRoot":"","sources":["../../src/utils/shell.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,MAAM,OAAO,CAAA;AAEzB,OAAO,EAAE,KAAK,OAAO,EAAE,MAAM,mBAAmB,CAAA;AAkChD,eAAO,MAAM,UAAU,GACrB,SAAS,MAAM,EACf,SAAS;IACP,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAA;IACvB,GAAG,EAAE,MAAM,CAAA;CACZ,oCAsEF,CAAA"} \ No newline at end of file diff --git a/dist/utils/shell.js b/dist/utils/shell.js new file mode 100644 index 00000000000..000550f13e2 --- /dev/null +++ b/dist/utils/shell.js @@ -0,0 +1,106 @@ +import process from 'process'; +import { Transform } from 'stream'; +import { stripVTControlCharacters } from 'util'; +import execa from 'execa'; +import { chalk, log, NETLIFYDEVERR, NETLIFYDEVWARN } from './command-helpers.js'; +import { processOnExit } from './dev.js'; +const isErrnoException = (value) => value instanceof Error && Object.hasOwn(value, 'code'); +const createStripAnsiControlCharsStream = () => new Transform({ + transform(chunk, _encoding, callback) { + callback(null, stripVTControlCharacters(typeof chunk === 'string' ? chunk : chunk?.toString() ?? '')); + }, +}); +const cleanupWork = []; +let cleanupStarted = false; +const cleanupBeforeExit = async ({ exitCode } = {}) => { + // If cleanup has started, then wherever started it will be responsible for exiting + if (!cleanupStarted) { + cleanupStarted = true; + try { + await Promise.all(cleanupWork.map((cleanup) => cleanup())); + } + finally { + // eslint-disable-next-line n/no-process-exit + process.exit(exitCode); + } + } +}; +// TODO(serhalp): Move (or at least rename). This sounds like a generic shell util but it's specific +// to `netlify dev`... +export const runCommand = (command, options) => { + const { cwd, env = {}, spinner } = options; + const commandProcess = execa.command(command, { + preferLocal: true, + // we use reject=false to avoid rejecting synchronously when the command doesn't exist + reject: false, + env: { + // we want always colorful terminal outputs + FORCE_COLOR: 'true', + ...env, + }, + // windowsHide needs to be false for child process to terminate properly on Windows + windowsHide: false, + cwd, + }); + // Ensure that an active spinner stays at the bottom of the commandline + // even though the actual framework command might be outputting stuff + const pipeDataWithSpinner = (writeStream, chunk) => { + // Clear the spinner, write the framework command line, then resume spinning + if (spinner?.isSpinning()) { + spinner.clear(); + } + writeStream.write(chunk, () => { + if (spinner?.isSpinning()) { + spinner.spin(); + } + }); + }; + commandProcess.stdout + ?.pipe(createStripAnsiControlCharsStream()) + .on('data', pipeDataWithSpinner.bind(null, process.stdout)); + commandProcess.stderr + ?.pipe(createStripAnsiControlCharsStream()) + .on('data', pipeDataWithSpinner.bind(null, process.stderr)); + if (commandProcess.stdin != null) { + process.stdin.pipe(commandProcess.stdin); + } + // we can't try->await->catch since we don't want to block on the framework server which + // is a long running process + // eslint-disable-next-line @typescript-eslint/no-floating-promises + commandProcess.then(async () => { + const result = await commandProcess; + const [commandWithoutArgs] = command.split(' '); + if (result.failed && isNonExistingCommandError({ command: commandWithoutArgs, error: result })) { + log(`${NETLIFYDEVERR} Failed running command: ${command}. Please verify ${chalk.magenta(`'${commandWithoutArgs}'`)} exists`); + } + else { + const errorMessage = result.failed + ? // @ts-expect-error FIXME(serhalp): We use `reject: false` which means the resolved value is either the resolved value + // or the rejected value, but the types aren't smart enough to know this. + `${NETLIFYDEVERR} ${result.shortMessage}` + : `${NETLIFYDEVWARN} "${command}" exited with code ${result.exitCode.toString()}`; + log(`${errorMessage}. Shutting down Netlify Dev server`); + } + await cleanupBeforeExit({ exitCode: 1 }); + }); + processOnExit(async () => { + await cleanupBeforeExit({}); + }); + return commandProcess; +}; +const isNonExistingCommandError = ({ command, error: commandError }) => { + // `ENOENT` is only returned for non Windows systems + // See https://github.com/sindresorhus/execa/pull/447 + if (isErrnoException(commandError) && commandError.code === 'ENOENT') { + return true; + } + // if the command is a package manager we let it report the error + if (['yarn', 'npm', 'pnpm'].includes(command)) { + return false; + } + // this only works on English versions of Windows + return (commandError instanceof Error && + typeof commandError.message === 'string' && + commandError.message.includes('is not recognized as an internal or external command')); +}; +//# sourceMappingURL=shell.js.map \ No newline at end of file diff --git a/dist/utils/shell.js.map b/dist/utils/shell.js.map new file mode 100644 index 00000000000..efb1ee02b68 --- /dev/null +++ b/dist/utils/shell.js.map @@ -0,0 +1 @@ +{"version":3,"file":"shell.js","sourceRoot":"","sources":["../../src/utils/shell.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/sign-redirect.d.ts b/dist/utils/sign-redirect.d.ts new file mode 100644 index 00000000000..d10b9fa0207 --- /dev/null +++ b/dist/utils/sign-redirect.d.ts @@ -0,0 +1,7 @@ +export declare const signRedirect: ({ deployContext, secret, siteID, siteURL }: { + deployContext: any; + secret: any; + siteID: any; + siteURL: any; +}) => string; +//# sourceMappingURL=sign-redirect.d.ts.map \ No newline at end of file diff --git a/dist/utils/sign-redirect.d.ts.map b/dist/utils/sign-redirect.d.ts.map new file mode 100644 index 00000000000..0928a6c302a --- /dev/null +++ b/dist/utils/sign-redirect.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"sign-redirect.d.ts","sourceRoot":"","sources":["../../src/utils/sign-redirect.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,YAAY,GAAI;;;;;CAA0C,WAYtE,CAAA"} \ No newline at end of file diff --git a/dist/utils/sign-redirect.js b/dist/utils/sign-redirect.js new file mode 100644 index 00000000000..efa581721dd --- /dev/null +++ b/dist/utils/sign-redirect.js @@ -0,0 +1,16 @@ +import jwt from 'jsonwebtoken'; +// https://docs.netlify.com/routing/redirects/rewrites-proxies/#signed-proxy-redirects +// @ts-expect-error TS(7031) FIXME: Binding element 'deployContext' implicitly has an ... Remove this comment to see the full error message +export const signRedirect = ({ deployContext, secret, siteID, siteURL }) => { + const claims = { + deploy_context: deployContext, + netlify_id: siteID, + site_url: siteURL, + }; + const options = { + expiresIn: '5 minutes', + issuer: 'netlify', + }; + return jwt.sign(claims, secret, options); +}; +//# sourceMappingURL=sign-redirect.js.map \ No newline at end of file diff --git a/dist/utils/sign-redirect.js.map b/dist/utils/sign-redirect.js.map new file mode 100644 index 00000000000..10e8eeecc2b --- /dev/null +++ b/dist/utils/sign-redirect.js.map @@ -0,0 +1 @@ +{"version":3,"file":"sign-redirect.js","sourceRoot":"","sources":["../../src/utils/sign-redirect.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,cAAc,CAAA;AAE9B,sFAAsF;AACtF,2IAA2I;AAC3I,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,EAAE,EAAE;IACzE,MAAM,MAAM,GAAG;QACb,cAAc,EAAE,aAAa;QAC7B,UAAU,EAAE,MAAM;QAClB,QAAQ,EAAE,OAAO;KAClB,CAAA;IACD,MAAM,OAAO,GAAG;QACd,SAAS,EAAE,WAAoB;QAC/B,MAAM,EAAE,SAAS;KAClB,CAAA;IAED,OAAO,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;AAC1C,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/sites/create-template.d.ts b/dist/utils/sites/create-template.d.ts new file mode 100644 index 00000000000..6d119055535 --- /dev/null +++ b/dist/utils/sites/create-template.d.ts @@ -0,0 +1,14 @@ +import { OptionValues } from 'commander'; +import { Template } from '../types.js'; +export declare const fetchTemplates: (token: string) => Promise; +export declare const getTemplateName: ({ ghToken, options, repository, }: { + ghToken: string; + options: OptionValues; + repository: string; +}) => Promise; +export declare const deployedSiteExists: (name: string) => Promise; +export declare const getGitHubLink: ({ options, templateName }: { + options: OptionValues; + templateName: string; +}) => string; +//# sourceMappingURL=create-template.d.ts.map \ No newline at end of file diff --git a/dist/utils/sites/create-template.d.ts.map b/dist/utils/sites/create-template.d.ts.map new file mode 100644 index 00000000000..13b3d51be83 --- /dev/null +++ b/dist/utils/sites/create-template.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"create-template.d.ts","sourceRoot":"","sources":["../../../src/utils/sites/create-template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAKxC,OAAO,EAAE,QAAQ,EAAc,MAAM,aAAa,CAAA;AAIlD,eAAO,MAAM,cAAc,GAAU,OAAO,MAAM,KAAG,OAAO,CAAC,QAAQ,EAAE,CAatE,CAAA;AAED,eAAO,MAAM,eAAe,GAAU,mCAInC;IACD,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE,YAAY,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;CACnB,iBA4BA,CAAA;AAED,eAAO,MAAM,kBAAkB,GAAU,MAAM,MAAM,KAAG,OAAO,CAAC,OAAO,CAMtE,CAAA;AAED,eAAO,MAAM,aAAa,GAAI,2BAA2B;IAAE,OAAO,EAAE,YAAY,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,KAAG,MAC9B,CAAA"} \ No newline at end of file diff --git a/dist/utils/sites/create-template.js b/dist/utils/sites/create-template.js new file mode 100644 index 00000000000..52186ac83f3 --- /dev/null +++ b/dist/utils/sites/create-template.js @@ -0,0 +1,47 @@ +import inquirer from 'inquirer'; +import parseGitHubUrl from 'parse-github-url'; +import { log } from '../command-helpers.js'; +import { getTemplatesFromGitHub } from './utils.js'; +export const fetchTemplates = async (token) => { + const templatesFromGitHubOrg = await getTemplatesFromGitHub(token); + return (templatesFromGitHubOrg + // adding this filter because the react-based-templates has multiple templates in one repo so doesn't work for this command + .filter((repo) => !repo.archived && !repo.disabled && repo.name !== 'react-based-templates') + .map((template) => ({ + name: template.name, + sourceCodeUrl: template.html_url, + slug: template.full_name, + }))); +}; +export const getTemplateName = async ({ ghToken, options, repository, }) => { + if (repository) { + const parsedUrl = parseGitHubUrl(repository); + return parsedUrl?.repo || `netlify-templates/${repository}`; + } + if (options.url) { + const urlFromOptions = new URL(options.url); + return urlFromOptions.pathname.slice(1); + } + const templates = await fetchTemplates(ghToken); + log(`Choose one of our starter templates. Netlify will create a new repo for this template in your GitHub account.`); + const { templateName } = await inquirer.prompt([ + { + type: 'list', + name: 'templateName', + message: 'Template:', + choices: templates.map((template) => ({ + value: template.slug, + name: template.name, + })), + }, + ]); + return templateName; +}; +export const deployedSiteExists = async (name) => { + const resp = await fetch(`https://${name}.netlify.app`, { + method: 'GET', + }); + return resp.status === 200; +}; +export const getGitHubLink = ({ options, templateName }) => options.url || `https://github.com/${templateName}`; +//# sourceMappingURL=create-template.js.map \ No newline at end of file diff --git a/dist/utils/sites/create-template.js.map b/dist/utils/sites/create-template.js.map new file mode 100644 index 00000000000..ec196b40389 --- /dev/null +++ b/dist/utils/sites/create-template.js.map @@ -0,0 +1 @@ +{"version":3,"file":"create-template.js","sourceRoot":"","sources":["../../../src/utils/sites/create-template.ts"],"names":[],"mappings":"AACA,OAAO,QAAQ,MAAM,UAAU,CAAA;AAC/B,OAAO,cAAc,MAAM,kBAAkB,CAAA;AAE7C,OAAO,EAAE,GAAG,EAAE,MAAM,uBAAuB,CAAA;AAG3C,OAAO,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAA;AAEnD,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EAAE,KAAa,EAAuB,EAAE;IACzE,MAAM,sBAAsB,GAAiB,MAAM,sBAAsB,CAAC,KAAK,CAAC,CAAA;IAEhF,OAAO,CACL,sBAAsB;QACpB,2HAA2H;SAC1H,MAAM,CAAC,CAAC,IAAgB,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,IAAI,KAAK,uBAAuB,CAAC;SACvG,GAAG,CAAC,CAAC,QAAoB,EAAE,EAAE,CAAC,CAAC;QAC9B,IAAI,EAAE,QAAQ,CAAC,IAAI;QACnB,aAAa,EAAE,QAAQ,CAAC,QAAQ;QAChC,IAAI,EAAE,QAAQ,CAAC,SAAS;KACzB,CAAC,CAAC,CACN,CAAA;AACH,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,eAAe,GAAG,KAAK,EAAE,EACpC,OAAO,EACP,OAAO,EACP,UAAU,GAKX,EAAE,EAAE;IACH,IAAI,UAAU,EAAE,CAAC;QACf,MAAM,SAAS,GAAG,cAAc,CAAC,UAAU,CAAC,CAAA;QAC5C,OAAO,SAAS,EAAE,IAAI,IAAI,qBAAqB,UAAU,EAAE,CAAA;IAC7D,CAAC;IAED,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,MAAM,cAAc,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAA;QAC3C,OAAO,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IACzC,CAAC;IAED,MAAM,SAAS,GAAG,MAAM,cAAc,CAAC,OAAO,CAAC,CAAA;IAE/C,GAAG,CAAC,+GAA+G,CAAC,CAAA;IAEpH,MAAM,EAAE,YAAY,EAAE,GAAG,MAAM,QAAQ,CAAC,MAAM,CAAC;QAC7C;YACE,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,cAAc;YACpB,OAAO,EAAE,WAAW;YACpB,OAAO,EAAE,SAAS,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;gBACpC,KAAK,EAAE,QAAQ,CAAC,IAAI;gBACpB,IAAI,EAAE,QAAQ,CAAC,IAAI;aACpB,CAAC,CAAC;SACJ;KACF,CAAC,CAAA;IAEF,OAAO,YAAY,CAAA;AACrB,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,kBAAkB,GAAG,KAAK,EAAE,IAAY,EAAoB,EAAE;IACzE,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC,WAAW,IAAI,cAAc,EAAE;QACtD,MAAM,EAAE,KAAK;KACd,CAAC,CAAA;IAEF,OAAO,IAAI,CAAC,MAAM,KAAK,GAAG,CAAA;AAC5B,CAAC,CAAA;AAED,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAE,OAAO,EAAE,YAAY,EAAmD,EAAU,EAAE,CACjH,OAAO,CAAC,GAA0B,IAAI,sBAAsB,YAAY,EAAE,CAAA"} \ No newline at end of file diff --git a/dist/utils/sites/utils.d.ts b/dist/utils/sites/utils.d.ts new file mode 100644 index 00000000000..6ce2580e965 --- /dev/null +++ b/dist/utils/sites/utils.d.ts @@ -0,0 +1,16 @@ +import { GitHubRepoResponse } from '../command-helpers.js'; +import { GitHubRepo } from '../types.js'; +export declare const getTemplatesFromGitHub: (token: string) => Promise; +export declare const validateTemplate: ({ ghToken, templateName }: { + ghToken: string; + templateName: string; +}) => Promise<{ + exists: boolean; + isTemplate?: undefined; +} | { + exists: boolean; + isTemplate: boolean | undefined; +}>; +export declare const createRepo: (templateName: string, ghToken: string, siteName: string) => Promise; +export declare const callLinkSite: (cliPath: string, repoName: string, input: string) => Promise; +//# sourceMappingURL=utils.d.ts.map \ No newline at end of file diff --git a/dist/utils/sites/utils.d.ts.map b/dist/utils/sites/utils.d.ts.map new file mode 100644 index 00000000000..e84149428fd --- /dev/null +++ b/dist/utils/sites/utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/utils/sites/utils.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,kBAAkB,EAAoB,MAAM,uBAAuB,CAAA;AAC5E,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,eAAO,MAAM,sBAAsB,GAAU,OAAO,MAAM,KAAG,OAAO,CAAC,UAAU,EAAE,CAwBhF,CAAA;AAED,eAAO,MAAM,gBAAgB,GAAU,2BAA2B;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE;;;;;;EAkB1G,CAAA;AAED,eAAO,MAAM,UAAU,GACrB,cAAc,MAAM,EACpB,SAAS,MAAM,EACf,UAAU,MAAM,KACf,OAAO,CAAC,kBAAkB,CAc5B,CAAA;AAED,eAAO,MAAM,YAAY,GAAU,SAAS,MAAM,EAAE,UAAU,MAAM,EAAE,OAAO,MAAM,oBAMlF,CAAA"} \ No newline at end of file diff --git a/dist/utils/sites/utils.js b/dist/utils/sites/utils.js new file mode 100644 index 00000000000..e5d6d713cc7 --- /dev/null +++ b/dist/utils/sites/utils.js @@ -0,0 +1,63 @@ +import fetch from 'node-fetch'; +import execa from 'execa'; +import { logAndThrowError } from '../command-helpers.js'; +export const getTemplatesFromGitHub = async (token) => { + const getPublicGitHubReposFromOrg = new URL(`https://api.github.com/orgs/netlify-templates/repos`); + // GitHub returns 30 by default and we want to avoid our limit + // due to our archived repositories at any given time + const REPOS_PER_PAGE = 70; + getPublicGitHubReposFromOrg.searchParams.set('type', 'public'); + getPublicGitHubReposFromOrg.searchParams.set('sort', 'full_name'); + // @ts-expect-error TS(2345) FIXME: Argument of type 'number' is not assignable to par... Remove this comment to see the full error message + getPublicGitHubReposFromOrg.searchParams.set('per_page', REPOS_PER_PAGE); + let allTemplates = []; + try { + const templates = await fetch(getPublicGitHubReposFromOrg, { + method: 'GET', + headers: { + Authorization: `token ${token}`, + }, + }); + allTemplates = (await templates.json()); + } + catch (error_) { + return logAndThrowError(error_); + } + return allTemplates; +}; +export const validateTemplate = async ({ ghToken, templateName }) => { + const response = await fetch(`https://api.github.com/repos/${templateName}`, { + headers: { + Authorization: `token ${ghToken}`, + }, + }); + if (response.status === 404) { + return { exists: false }; + } + if (!response.ok) { + throw new Error(`Error fetching template ${templateName}: ${await response.text()}`); + } + const data = (await response.json()); + return { exists: true, isTemplate: data.is_template }; +}; +export const createRepo = async (templateName, ghToken, siteName) => { + const resp = await fetch(`https://api.github.com/repos/${templateName}/generate`, { + method: 'POST', + headers: { + Authorization: `token ${ghToken}`, + }, + body: JSON.stringify({ + name: siteName, + }), + }); + const data = await resp.json(); + return data; +}; +export const callLinkSite = async (cliPath, repoName, input) => { + const { stdout } = await execa(cliPath, ['link'], { + input, + cwd: repoName, + }); + return stdout; +}; +//# sourceMappingURL=utils.js.map \ No newline at end of file diff --git a/dist/utils/sites/utils.js.map b/dist/utils/sites/utils.js.map new file mode 100644 index 00000000000..c9ae95afb4c --- /dev/null +++ b/dist/utils/sites/utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/utils/sites/utils.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/static-server.d.ts b/dist/utils/static-server.d.ts new file mode 100644 index 00000000000..c9837feba36 --- /dev/null +++ b/dist/utils/static-server.d.ts @@ -0,0 +1,10 @@ +/** + * @param {object} config + * @param {import('./types.js').ServerSettings} config.settings + */ +export declare const startStaticServer: ({ settings }: { + settings: any; +}) => Promise<{ + family: string; +}>; +//# sourceMappingURL=static-server.d.ts.map \ No newline at end of file diff --git a/dist/utils/static-server.d.ts.map b/dist/utils/static-server.d.ts.map new file mode 100644 index 00000000000..a9345ab5147 --- /dev/null +++ b/dist/utils/static-server.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"static-server.d.ts","sourceRoot":"","sources":["../../src/utils/static-server.ts"],"names":[],"mappings":"AAOA;;;GAGG;AAEH,eAAO,MAAM,iBAAiB,GAAU;;CAAY;;EA2BnD,CAAA"} \ No newline at end of file diff --git a/dist/utils/static-server.js b/dist/utils/static-server.js new file mode 100644 index 00000000000..fee01763b8a --- /dev/null +++ b/dist/utils/static-server.js @@ -0,0 +1,36 @@ +import path from 'path'; +import fastifyStatic from '@fastify/static'; +import Fastify from 'fastify'; +import { log, NETLIFYDEVLOG } from './command-helpers.js'; +/** + * @param {object} config + * @param {import('./types.js').ServerSettings} config.settings + */ +// @ts-expect-error TS(7031) FIXME: Binding element 'settings' implicitly has an 'any'... Remove this comment to see the full error message +export const startStaticServer = async ({ settings }) => { + const server = Fastify(); + const rootPath = path.resolve(settings.dist); + server.register(fastifyStatic, { + root: rootPath, + etag: false, + acceptRanges: false, + lastModified: false, + }); + server.setNotFoundHandler((_req, res) => { + res.code(404).sendFile('404.html', rootPath); + }); + server.addHook('onRequest', (req, reply, done) => { + reply.header('age', '0'); + reply.header('cache-control', 'public, max-age=0, must-revalidate'); + const validMethods = ['GET', 'HEAD']; + if (!validMethods.includes(req.method)) { + reply.code(405).send('Method Not Allowed'); + } + done(); + }); + await server.listen({ port: settings.frameworkPort }); + const [address] = server.addresses(); + log(`\n${NETLIFYDEVLOG} Static server listening to`, settings.frameworkPort); + return { family: address.family }; +}; +//# sourceMappingURL=static-server.js.map \ No newline at end of file diff --git a/dist/utils/static-server.js.map b/dist/utils/static-server.js.map new file mode 100644 index 00000000000..6751446bdc3 --- /dev/null +++ b/dist/utils/static-server.js.map @@ -0,0 +1 @@ +{"version":3,"file":"static-server.js","sourceRoot":"","sources":["../../src/utils/static-server.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,MAAM,CAAA;AAEvB,OAAO,aAAa,MAAM,iBAAiB,CAAA;AAC3C,OAAO,OAAO,MAAM,SAAS,CAAA;AAE7B,OAAO,EAAE,GAAG,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAA;AAEzD;;;GAGG;AACH,2IAA2I;AAC3I,MAAM,CAAC,MAAM,iBAAiB,GAAG,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE;IACtD,MAAM,MAAM,GAAG,OAAO,EAAE,CAAA;IACxB,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC5C,MAAM,CAAC,QAAQ,CAAC,aAAa,EAAE;QAC7B,IAAI,EAAE,QAAQ;QACd,IAAI,EAAE,KAAK;QACX,YAAY,EAAE,KAAK;QACnB,YAAY,EAAE,KAAK;KACpB,CAAC,CAAA;IAEF,MAAM,CAAC,kBAAkB,CAAC,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QACtC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAA;IAC9C,CAAC,CAAC,CAAA;IAEF,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,EAAE;QAC/C,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,GAAG,CAAC,CAAA;QACxB,KAAK,CAAC,MAAM,CAAC,eAAe,EAAE,oCAAoC,CAAC,CAAA;QACnE,MAAM,YAAY,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAA;QACpC,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;YACvC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAA;QAC5C,CAAC;QACD,IAAI,EAAE,CAAA;IACR,CAAC,CAAC,CAAA;IACF,MAAM,MAAM,CAAC,MAAM,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,aAAa,EAAE,CAAC,CAAA;IACrD,MAAM,CAAC,OAAO,CAAC,GAAG,MAAM,CAAC,SAAS,EAAE,CAAA;IACpC,GAAG,CAAC,KAAK,aAAa,6BAA6B,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAA;IAC5E,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAA;AACnC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/telemetry/index.d.ts b/dist/utils/telemetry/index.d.ts new file mode 100644 index 00000000000..0372303acd3 --- /dev/null +++ b/dist/utils/telemetry/index.d.ts @@ -0,0 +1,3 @@ +export { track, identify } from './telemetry.js'; +export { reportError } from './report-error.js'; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/utils/telemetry/index.d.ts.map b/dist/utils/telemetry/index.d.ts.map new file mode 100644 index 00000000000..e2e4ce425af --- /dev/null +++ b/dist/utils/telemetry/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/telemetry/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA"} \ No newline at end of file diff --git a/dist/utils/telemetry/index.js b/dist/utils/telemetry/index.js new file mode 100644 index 00000000000..4a3a640a782 --- /dev/null +++ b/dist/utils/telemetry/index.js @@ -0,0 +1,3 @@ +export { track, identify } from './telemetry.js'; +export { reportError } from './report-error.js'; +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/utils/telemetry/index.js.map b/dist/utils/telemetry/index.js.map new file mode 100644 index 00000000000..a125922401e --- /dev/null +++ b/dist/utils/telemetry/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/telemetry/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA"} \ No newline at end of file diff --git a/dist/utils/telemetry/report-error.d.ts b/dist/utils/telemetry/report-error.d.ts new file mode 100644 index 00000000000..df23832d126 --- /dev/null +++ b/dist/utils/telemetry/report-error.d.ts @@ -0,0 +1,10 @@ +/** + * + * @param {import('@bugsnag/js').NotifiableError} error + * @param {object} config + * @param {import('@bugsnag/js').Event['severity']} config.severity + * @param {Record>} [config.metadata] + * @returns {Promise} + */ +export declare const reportError: (error: any, config?: {}) => Promise; +//# sourceMappingURL=report-error.d.ts.map \ No newline at end of file diff --git a/dist/utils/telemetry/report-error.d.ts.map b/dist/utils/telemetry/report-error.d.ts.map new file mode 100644 index 00000000000..318df2290ab --- /dev/null +++ b/dist/utils/telemetry/report-error.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"report-error.d.ts","sourceRoot":"","sources":["../../../src/utils/telemetry/report-error.ts"],"names":[],"mappings":"AAcA;;;;;;;GAOG;AAEH,eAAO,MAAM,WAAW,GAAmB,UAAK,EAAE,WAAW,kBAoC5D,CAAA"} \ No newline at end of file diff --git a/dist/utils/telemetry/report-error.js b/dist/utils/telemetry/report-error.js new file mode 100644 index 00000000000..8fd2a952b79 --- /dev/null +++ b/dist/utils/telemetry/report-error.js @@ -0,0 +1,52 @@ +import os from 'os'; +import { dirname, join } from 'path'; +import process, { version as nodejsVersion } from 'process'; +import { fileURLToPath } from 'url'; +import { isCI } from 'ci-info'; +import execa from '../execa.js'; +import getGlobalConfigStore from '../get-global-config-store.js'; +import { cliVersion } from './utils.js'; +const dirPath = dirname(fileURLToPath(import.meta.url)); +/** + * + * @param {import('@bugsnag/js').NotifiableError} error + * @param {object} config + * @param {import('@bugsnag/js').Event['severity']} config.severity + * @param {Record>} [config.metadata] + * @returns {Promise} + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'error' implicitly has an 'any' type. +export const reportError = async function (error, config = {}) { + if (isCI) { + return; + } + // convert a NotifiableError to an error class + const err = error instanceof Error ? error : typeof error === 'string' ? new Error(error) : error; + const globalConfig = await getGlobalConfigStore(); + const options = JSON.stringify({ + type: 'error', + data: { + message: err.message, + name: err.name, + stack: err.stack, + cause: err.cause, + // @ts-expect-error TS(2339) FIXME: Property 'severity' does not exist on type '{}'. + severity: config.severity, + user: { + id: globalConfig.get('userId'), + }, + // @ts-expect-error TS(2339) FIXME: Property 'metadata' does not exist on type '{}'. + metadata: config.metadata, + osName: `${os.platform()}-${os.arch()}`, + cliVersion, + nodejsVersion, + }, + }); + // spawn detached child process to handle send and wait for the http request to finish + // otherwise it can get canceled + await execa(process.execPath, [join(dirPath, 'request.js'), options], { + detached: true, + stdio: 'ignore', + }); +}; +//# sourceMappingURL=report-error.js.map \ No newline at end of file diff --git a/dist/utils/telemetry/report-error.js.map b/dist/utils/telemetry/report-error.js.map new file mode 100644 index 00000000000..94bf22c2e75 --- /dev/null +++ b/dist/utils/telemetry/report-error.js.map @@ -0,0 +1 @@ +{"version":3,"file":"report-error.js","sourceRoot":"","sources":["../../../src/utils/telemetry/report-error.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAA;AACnB,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AACpC,OAAO,OAAO,EAAE,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,SAAS,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAA;AAEnC,OAAO,EAAE,IAAI,EAAE,MAAM,SAAS,CAAA;AAE9B,OAAO,KAAK,MAAM,aAAa,CAAA;AAC/B,OAAO,oBAAoB,MAAM,+BAA+B,CAAA;AAEhE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AAEvC,MAAM,OAAO,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAA;AAEvD;;;;;;;GAOG;AACH,mFAAmF;AACnF,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,WAAW,KAAK,EAAE,MAAM,GAAG,EAAE;IAC3D,IAAI,IAAI,EAAE,CAAC;QACT,OAAM;IACR,CAAC;IAED,8CAA8C;IAC9C,MAAM,GAAG,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAA;IAEjG,MAAM,YAAY,GAAG,MAAM,oBAAoB,EAAE,CAAA;IAEjD,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC;QAC7B,IAAI,EAAE,OAAO;QACb,IAAI,EAAE;YACJ,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,IAAI,EAAE,GAAG,CAAC,IAAI;YACd,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,KAAK,EAAE,GAAG,CAAC,KAAK;YAChB,oFAAoF;YACpF,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,IAAI,EAAE;gBACJ,EAAE,EAAE,YAAY,CAAC,GAAG,CAAC,QAAQ,CAAC;aAC/B;YACD,oFAAoF;YACpF,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,MAAM,EAAE,GAAG,EAAE,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,IAAI,EAAE,EAAE;YACvC,UAAU;YACV,aAAa;SACd;KACF,CAAC,CAAA;IAEF,sFAAsF;IACtF,gCAAgC;IAChC,MAAM,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,EAAE,OAAO,CAAC,EAAE;QACpE,QAAQ,EAAE,IAAI;QACd,KAAK,EAAE,QAAQ;KAChB,CAAC,CAAA;AACJ,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/telemetry/request.d.ts b/dist/utils/telemetry/request.d.ts new file mode 100644 index 00000000000..39a53872f67 --- /dev/null +++ b/dist/utils/telemetry/request.d.ts @@ -0,0 +1,2 @@ +export {}; +//# sourceMappingURL=request.d.ts.map \ No newline at end of file diff --git a/dist/utils/telemetry/request.d.ts.map b/dist/utils/telemetry/request.d.ts.map new file mode 100644 index 00000000000..37096c792e9 --- /dev/null +++ b/dist/utils/telemetry/request.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../../src/utils/telemetry/request.ts"],"names":[],"mappings":""} \ No newline at end of file diff --git a/dist/utils/telemetry/request.js b/dist/utils/telemetry/request.js new file mode 100644 index 00000000000..fa46008104e --- /dev/null +++ b/dist/utils/telemetry/request.js @@ -0,0 +1,41 @@ +// This file is being called by `src/utils/telemetry/telemetry.js` as a child process +// to run as a detached process +import process from 'process'; +import fetch from 'node-fetch'; +import getPackageJson from '../get-cli-package-json.js'; +const { name, version } = await getPackageJson(); +const options = JSON.parse(process.argv[2]); +const CLIENT_ID = 'NETLIFY_CLI'; +const TRACK_URL = process.env.NETLIFY_TEST_TRACK_URL || 'https://cli.netlify.com/telemetry/track'; +const IDENTIFY_URL = process.env.NETLIFY_TEST_IDENTIFY_URL || 'https://cli.netlify.com/telemetry/identify'; +const REPORT_ERROR_URL = process.env.NETLIFY_TEST_ERROR_REPORT_URL || 'https://cli.netlify.com/report-error'; +const getApiUrl = () => { + switch (options.type) { + case 'track': + return TRACK_URL; + case 'error': + return REPORT_ERROR_URL; + default: + return IDENTIFY_URL; + } +}; +// Make telemetry call +const makeRequest = async function () { + try { + await fetch(getApiUrl(), { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + 'X-Netlify-Client': CLIENT_ID, + 'User-Agent': `${name}/${version}`, + }, + body: JSON.stringify(options.data), + }); + process.exit(); + } + catch { + process.exit(1); + } +}; +makeRequest(); +//# sourceMappingURL=request.js.map \ No newline at end of file diff --git a/dist/utils/telemetry/request.js.map b/dist/utils/telemetry/request.js.map new file mode 100644 index 00000000000..fb220946fe7 --- /dev/null +++ b/dist/utils/telemetry/request.js.map @@ -0,0 +1 @@ +{"version":3,"file":"request.js","sourceRoot":"","sources":["../../../src/utils/telemetry/request.ts"],"names":[],"mappings":"AAAA,qFAAqF;AACrF,+BAA+B;AAC/B,OAAO,OAAO,MAAM,SAAS,CAAA;AAE7B,OAAO,KAAK,MAAM,YAAY,CAAA;AAE9B,OAAO,cAAc,MAAM,4BAA4B,CAAA;AAEvD,MAAM,EAAE,IAAI,EAAE,OAAO,EAAE,GAAG,MAAM,cAAc,EAAE,CAAA;AAEhD,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAA;AAE3C,MAAM,SAAS,GAAG,aAAa,CAAA;AAC/B,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,IAAI,yCAAyC,CAAA;AACjG,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,4CAA4C,CAAA;AAC1G,MAAM,gBAAgB,GAAG,OAAO,CAAC,GAAG,CAAC,6BAA6B,IAAI,sCAAsC,CAAA;AAE5G,MAAM,SAAS,GAAG,GAAG,EAAE;IACrB,QAAQ,OAAO,CAAC,IAAI,EAAE,CAAC;QACrB,KAAK,OAAO;YACV,OAAO,SAAS,CAAA;QAClB,KAAK,OAAO;YACV,OAAO,gBAAgB,CAAA;QACzB;YACE,OAAO,YAAY,CAAA;IACvB,CAAC;AACH,CAAC,CAAA;AAED,sBAAsB;AACtB,MAAM,WAAW,GAAG,KAAK;IACvB,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,SAAS,EAAE,EAAE;YACvB,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,cAAc,EAAE,kBAAkB;gBAClC,kBAAkB,EAAE,SAAS;gBAC7B,YAAY,EAAE,GAAG,IAAI,IAAI,OAAO,EAAE;aACnC;YACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC;SACnC,CAAC,CAAA;QACF,OAAO,CAAC,IAAI,EAAE,CAAA;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;AACH,CAAC,CAAA;AAED,WAAW,EAAE,CAAA"} \ No newline at end of file diff --git a/dist/utils/telemetry/telemetry.d.ts b/dist/utils/telemetry/telemetry.d.ts new file mode 100644 index 00000000000..019edc6d6fb --- /dev/null +++ b/dist/utils/telemetry/telemetry.d.ts @@ -0,0 +1,14 @@ +/** + * Tracks a custom event with the provided payload + */ +export declare function track(eventName: string, payload?: { + status?: string; + duration?: number; + [key: string]: unknown; +}): Promise | undefined>; +export declare function identify(payload: { + name?: string; + email?: string; + userId?: string; +}): Promise | undefined>; +//# sourceMappingURL=telemetry.d.ts.map \ No newline at end of file diff --git a/dist/utils/telemetry/telemetry.d.ts.map b/dist/utils/telemetry/telemetry.d.ts.map new file mode 100644 index 00000000000..2d551372e6c --- /dev/null +++ b/dist/utils/telemetry/telemetry.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../../../src/utils/telemetry/telemetry.ts"],"names":[],"mappings":"AA+CA;;GAEG;AACH,wBAAsB,KAAK,CACzB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAA;CAAO,yEAoC7E;AAED,wBAAsB,QAAQ,CAAC,OAAO,EAAE;IAAE,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,iEA0BzF"} \ No newline at end of file diff --git a/dist/utils/telemetry/telemetry.js b/dist/utils/telemetry/telemetry.js new file mode 100644 index 00000000000..2f8c9217176 --- /dev/null +++ b/dist/utils/telemetry/telemetry.js @@ -0,0 +1,94 @@ +import { dirname, join } from 'path'; +import process, { version as nodejsVersion } from 'process'; +import { fileURLToPath } from 'url'; +import { isCI } from 'ci-info'; +import execa from '../execa.js'; +import getGlobalConfigStore from '../get-global-config-store.js'; +import { isTelemetryDisabled, cliVersion } from './utils.js'; +import isValidEventName from './validation.js'; +const dirPath = dirname(fileURLToPath(import.meta.url)); +function send(type, payload) { + const requestFile = join(dirPath, 'request.js'); + const options = JSON.stringify({ + data: payload, + type, + }); + const args = [process.execPath, [requestFile, options]]; + if (process.env.NETLIFY_TEST_TELEMETRY_WAIT === 'true') { + return execa(...args, { + stdio: 'inherit', + }); + } + // spawn detached child process to handle send + execa(...args, { + detached: true, + stdio: 'ignore', + }).unref(); +} +const eventConfig = { + // Namespace of current application + projectName: 'cli', + // Allowed objects + objects: [ + // example cli:sites_created + 'sites', + // example cli:user_signup + 'user', + ], +}; +/** + * Tracks a custom event with the provided payload + */ +export async function track(eventName, payload = {}) { + if (isCI) { + return; + } + const globalConfig = await getGlobalConfigStore(); + if (isTelemetryDisabled(globalConfig)) { + return; + } + const [userId, cliId] = [globalConfig.get('userId'), globalConfig.get('cliId')]; + // automatically add `cli:` prefix if missing + if (!eventName.includes('cli:')) { + eventName = `cli:${eventName}`; + } + // event 'cli:command' bypasses validation + const isValid = eventName === 'cli:command' ? () => true : isValidEventName; + // to ensure clean data, validate event name + if (!isValid(eventName, eventConfig)) { + return false; + } + const { duration, status, ...properties } = payload; + const defaultData = { + event: eventName, + userId, + anonymousId: cliId, + duration, + status, + properties: { ...properties, nodejsVersion, cliVersion }, + }; + return send('track', defaultData); +} +export async function identify(payload) { + if (isCI) { + return; + } + const globalConfig = await getGlobalConfigStore(); + if (isTelemetryDisabled(globalConfig)) { + return; + } + const cliId = globalConfig.get('cliId'); + const { email, name, userId } = payload; + const defaultTraits = { + name, + email, + cliId, + }; + const identifyData = { + anonymousId: cliId, + userId, + traits: { ...defaultTraits, ...payload }, + }; + return send('identify', identifyData); +} +//# sourceMappingURL=telemetry.js.map \ No newline at end of file diff --git a/dist/utils/telemetry/telemetry.js.map b/dist/utils/telemetry/telemetry.js.map new file mode 100644 index 00000000000..d3de3c9450c --- /dev/null +++ b/dist/utils/telemetry/telemetry.js.map @@ -0,0 +1 @@ +{"version":3,"file":"telemetry.js","sourceRoot":"","sources":["../../../src/utils/telemetry/telemetry.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/telemetry/utils.d.ts b/dist/utils/telemetry/utils.d.ts new file mode 100644 index 00000000000..82c47ea99c6 --- /dev/null +++ b/dist/utils/telemetry/utils.d.ts @@ -0,0 +1,3 @@ +export declare const cliVersion: string; +export declare const isTelemetryDisabled: (config: any) => any; +//# sourceMappingURL=utils.d.ts.map \ No newline at end of file diff --git a/dist/utils/telemetry/utils.d.ts.map b/dist/utils/telemetry/utils.d.ts.map new file mode 100644 index 00000000000..e741bc8b8ba --- /dev/null +++ b/dist/utils/telemetry/utils.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/utils/telemetry/utils.ts"],"names":[],"mappings":"AAEA,eAAO,MAAiB,UAAU,QAA8B,CAAA;AAGhE,eAAO,MAAM,mBAAmB,GAAa,WAAM,QAElD,CAAA"} \ No newline at end of file diff --git a/dist/utils/telemetry/utils.js b/dist/utils/telemetry/utils.js new file mode 100644 index 00000000000..4aa7e41f043 --- /dev/null +++ b/dist/utils/telemetry/utils.js @@ -0,0 +1,7 @@ +import getCLIPackageJson from '../get-cli-package-json.js'; +export const { version: cliVersion } = await getCLIPackageJson(); +// @ts-expect-error TS(7006) FIXME: Parameter 'config' implicitly has an 'any' type. +export const isTelemetryDisabled = function (config) { + return config.get('telemetryDisabled'); +}; +//# sourceMappingURL=utils.js.map \ No newline at end of file diff --git a/dist/utils/telemetry/utils.js.map b/dist/utils/telemetry/utils.js.map new file mode 100644 index 00000000000..4bbbbc2738b --- /dev/null +++ b/dist/utils/telemetry/utils.js.map @@ -0,0 +1 @@ +{"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../src/utils/telemetry/utils.ts"],"names":[],"mappings":"AAAA,OAAO,iBAAiB,MAAM,4BAA4B,CAAA;AAE1D,MAAM,CAAC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,GAAG,MAAM,iBAAiB,EAAE,CAAA;AAEhE,oFAAoF;AACpF,MAAM,CAAC,MAAM,mBAAmB,GAAG,UAAU,MAAM;IACjD,OAAO,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAA;AACxC,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/telemetry/validation.d.ts b/dist/utils/telemetry/validation.d.ts new file mode 100644 index 00000000000..f28fdb8720e --- /dev/null +++ b/dist/utils/telemetry/validation.d.ts @@ -0,0 +1,2 @@ +export default function isValidEventName(eventName: any, config: any): boolean; +//# sourceMappingURL=validation.d.ts.map \ No newline at end of file diff --git a/dist/utils/telemetry/validation.d.ts.map b/dist/utils/telemetry/validation.d.ts.map new file mode 100644 index 00000000000..d323828f1db --- /dev/null +++ b/dist/utils/telemetry/validation.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../../src/utils/telemetry/validation.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,SAAS,KAAA,EAAE,MAAM,KAAA,WA0BzD"} \ No newline at end of file diff --git a/dist/utils/telemetry/validation.js b/dist/utils/telemetry/validation.js new file mode 100644 index 00000000000..e32a84c1bdd --- /dev/null +++ b/dist/utils/telemetry/validation.js @@ -0,0 +1,63 @@ +/** + * Utility to validating analytic event names for clean data + */ +import { log } from '../command-helpers.js'; +// @ts-expect-error TS(7006) FIXME: Parameter 'eventName' implicitly has an 'any' type... Remove this comment to see the full error message +export default function isValidEventName(eventName, config) { + const validProject = [config.projectName]; + const validObjects = config.objects || []; + const matches = eventName.match(/([a-zA-Z]*):([a-zA-Z]*)_([a-zA-Z]*$)/); + if (!containsSeparators(eventName) || !matches) { + // @ts-expect-error TS(2554) FIXME: Expected 2 arguments, but got 1. + return formattingWarning(eventName); + } + const [, project, object, action] = matches; + let error; + // if missing any parts of event, exit + if (!project || !object || !action) { + // @ts-expect-error TS(2554) FIXME: Expected 2 arguments, but got 1. + return formattingWarning(eventName); + } + // validate project name + if (!validProject.includes(project)) { + error = `> "${project}" is invalid tracking project. Must be one of ${JSON.stringify(validProject)}`; + return formattingWarning(eventName, error); + } + // validate object name + if (!validObjects.includes(object)) { + error = `> "${object}" is invalid tracking object. Must be one of ${JSON.stringify(validObjects)}`; + return formattingWarning(eventName, error); + } + return true; +} +// @ts-expect-error TS(7006) FIXME: Parameter 'eventName' implicitly has an 'any' type... Remove this comment to see the full error message +const containsSeparators = function (eventName) { + const underscores = (eventName.match(/_/g) || []).length; + if (underscores !== 1) { + log(`Event name must have single underscore. "${eventName}" contains ${underscores}`); + return false; + } + const colons = (eventName.match(/:/g) || []).length; + if (colons !== 1) { + log(`Event name must have single colon. "${eventName}" contains ${colons}`); + return false; + } + return true; +}; +// @ts-expect-error TS(7006) FIXME: Parameter 'eventName' implicitly has an 'any' type... Remove this comment to see the full error message +const formattingWarning = function (eventName, errorMsg) { + log('-----------------------------'); + log('Tracking Error:'); + log(`Incorrect tracking event format: "${eventName}"`); + if (errorMsg) { + log(errorMsg); + } + log('-----------------------------'); + log(`Formatting information: `); + log(`eventName must match 'cli:objectName_actionName'`); + log(`eventName must be camelCased: 'camelCase:camelCase_camelCase'`); + log(`Example: cli:sites_deploySucceeded`); + log('-----------------------------'); + return false; +}; +//# sourceMappingURL=validation.js.map \ No newline at end of file diff --git a/dist/utils/telemetry/validation.js.map b/dist/utils/telemetry/validation.js.map new file mode 100644 index 00000000000..4cc01a4b080 --- /dev/null +++ b/dist/utils/telemetry/validation.js.map @@ -0,0 +1 @@ +{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../../src/utils/telemetry/validation.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/temporary-file.d.ts b/dist/utils/temporary-file.d.ts new file mode 100644 index 00000000000..a7761b73dd7 --- /dev/null +++ b/dist/utils/temporary-file.d.ts @@ -0,0 +1,7 @@ +export declare function temporaryFile({ extension }?: { + extension?: string; +}): string; +export declare function temporaryDirectory({ prefix }?: { + prefix?: string | undefined; +}): string; +//# sourceMappingURL=temporary-file.d.ts.map \ No newline at end of file diff --git a/dist/utils/temporary-file.d.ts.map b/dist/utils/temporary-file.d.ts.map new file mode 100644 index 00000000000..c54b72a426a --- /dev/null +++ b/dist/utils/temporary-file.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"temporary-file.d.ts","sourceRoot":"","sources":["../../src/utils/temporary-file.ts"],"names":[],"mappings":"AASA,wBAAgB,aAAa,CAAC,EAAE,SAAS,EAAE,GAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,MAAM,CAIhF;AAED,wBAAgB,kBAAkB,CAAC,EAAE,MAAW,EAAE;;CAAK,GAAG,MAAM,CAG/D"} \ No newline at end of file diff --git a/dist/utils/temporary-file.js b/dist/utils/temporary-file.js new file mode 100644 index 00000000000..a11c2e39082 --- /dev/null +++ b/dist/utils/temporary-file.js @@ -0,0 +1,16 @@ +import * as path from 'node:path'; +import * as os from 'node:os'; +import * as crypto from 'node:crypto'; +import * as fs from 'node:fs'; +const uniqueString = () => crypto.randomBytes(8).toString('hex'); +const tempDir = os.tmpdir(); +export function temporaryFile({ extension } = {}) { + const baseName = uniqueString(); + const ext = extension ? '.' + extension.replace(/^\./, '') : ''; + return path.join(tempDir, baseName + ext); +} +export function temporaryDirectory({ prefix = '' } = {}) { + const directory = fs.mkdtempSync(`${tempDir}${path.sep}${prefix}`); + return directory; +} +//# sourceMappingURL=temporary-file.js.map \ No newline at end of file diff --git a/dist/utils/temporary-file.js.map b/dist/utils/temporary-file.js.map new file mode 100644 index 00000000000..a3f915411e1 --- /dev/null +++ b/dist/utils/temporary-file.js.map @@ -0,0 +1 @@ +{"version":3,"file":"temporary-file.js","sourceRoot":"","sources":["../../src/utils/temporary-file.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AACjC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAA;AAC7B,OAAO,KAAK,MAAM,MAAM,aAAa,CAAA;AACrC,OAAO,KAAK,EAAE,MAAM,SAAS,CAAA;AAE7B,MAAM,YAAY,GAAG,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAEhE,MAAM,OAAO,GAAG,EAAE,CAAC,MAAM,EAAE,CAAA;AAE3B,MAAM,UAAU,aAAa,CAAC,EAAE,SAAS,KAA6B,EAAE;IACtE,MAAM,QAAQ,GAAG,YAAY,EAAE,CAAA;IAC/B,MAAM,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;IAC/D,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,GAAG,GAAG,CAAC,CAAA;AAC3C,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,EAAE,MAAM,GAAG,EAAE,EAAE,GAAG,EAAE;IACrD,MAAM,SAAS,GAAG,EAAE,CAAC,WAAW,CAAC,GAAG,OAAO,GAAG,IAAI,CAAC,GAAG,GAAG,MAAM,EAAE,CAAC,CAAA;IAClE,OAAO,SAAS,CAAA;AAClB,CAAC"} \ No newline at end of file diff --git a/dist/utils/types.d.ts b/dist/utils/types.d.ts new file mode 100644 index 00000000000..45a676e514a --- /dev/null +++ b/dist/utils/types.d.ts @@ -0,0 +1,205 @@ +import type { Buffer } from 'buffer'; +import type { IncomingMessage } from 'http'; +import type { PollingStrategy } from '@netlify/build-info'; +import type { Match } from 'netlify-redirector'; +export type { GlobalConfigStore } from './get-global-config-store.js'; +export { default as CLIState } from './cli-state.js'; +export type FrameworkNames = '#static' | '#auto' | '#custom' | string; +export type FrameworkInfo = { + build: { + directory: string; + }; + dev: { + commands: string[]; + port: number; + pollingStrategies: PollingStrategy[]; + }; + name: FrameworkNames; + staticAssetsDirectory: string; + env: NodeJS.ProcessEnv; + plugins?: string[]; +}; +export type BaseServerSettings = { + baseDirectory?: string; + dist: string; + /** The command that was provided for the dev config */ + command?: string; + /** If it should be served like static files */ + useStaticServer?: boolean; + /** A port where a proxy can listen to it */ + frameworkPort?: number; + /** The host where a proxy can listen to it */ + frameworkHost?: '127.0.0.1' | '::1'; + /** Try both v4 and v6 IPs */ + detectFrameworkHost?: boolean; + functions?: string; + /** The framework name ('Create React App') */ + framework?: string; + env?: NodeJS.ProcessEnv; + pollingStrategies?: string[]; + plugins?: string[]; + clearPublishDirectory?: boolean; +}; +export type ServerSettings = BaseServerSettings & { + /** default 'secret' */ + jwtSecret: string; + /** default 'app_metadata.authorization.roles' */ + jwtRolePath: string; + /** The port where the dev server is running on */ + port: number; + /** The port where the functions are running on */ + functionsPort: number; + https?: { + key: string; + cert: string; + keyFilePath: string; + certFilePath: string; + }; + clearPublishDirectory?: boolean; + skipWaitPort?: boolean; +}; +export interface Request extends IncomingMessage { + originalBody?: Buffer | null; + protocol?: string; + hostname?: string; +} +export type Rewriter = (req: Request) => Promise; +export interface SiteInfo { + account_id?: string | undefined; + account_name: string; + account_slug: string; + admin_url: string; + build_settings?: { + allowed_branches: string[]; + cmd: string; + deploy_key_id: string; + dir: string; + env?: Record; + id: number; + private_logs: boolean; + provider: string; + public_repo: boolean; + repo_branch: string; + repo_path: string; + repo_url: string; + } | undefined; + capabilities: Record; + created_at: string; + custom_domain: string; + deploy_hook: string; + deploy_url: string; + dev_server_settings?: { + cmd: string; + target_port: number; + } | undefined; + domain_aliases: string[]; + feature_flags?: Record; + force_ssl: boolean; + git_provider: string; + id: string; + managed_dns: boolean; + name: string; + notification_email: string; + password: string; + plan: string; + processing_settings: { + css: { + bundle: boolean; + minify: boolean; + }; + html: Record; + images: Record; + js: { + bundle: boolean; + minify: boolean; + }; + skip: boolean; + }; + published_deploy: { + admin_url: string; + branch: string; + build_id: string; + commit_ref: string; + commit_url: string; + context: string; + created_at: string; + deploy_ssl_url: string; + deploy_url: string; + draft: boolean; + error_message: string; + id: string; + locked: boolean; + name: string; + published_at: string; + required: string[]; + required_functions: string[]; + review_id: number; + review_url: string; + screenshot_url: string; + site_id: string; + skipped: boolean; + ssl_url: string; + state: string; + title: string; + updated_at: string; + url: string; + user_id: string; + } | undefined; + screenshot_url: string; + session_id: string; + ssl: boolean; + ssl_url: string; + state: string; + updated_at: string; + url: string; + user_id: string; +} +export type TokenLocation = 'env' | 'flag' | 'config' | 'not found'; +export type EnvVar = { + key: string; + scopes: string[]; + values: EnvVarValue[]; + updated_at: string; + is_secret: boolean; +}; +type EnvVarValue = { + id: string; + context: string; +}; +export type MinimalAccount = { + id: string; + name: string; + slug: string; + default: boolean; + team_logo_url: string | null; + on_pro_trial: boolean; + organization_id: string | null; + type_name: string; + type_slug: string; + members_count: number; +}; +export interface GitHubRepo { + name: string; + html_url: string; + full_name: string; + archived: boolean; + disabled: boolean; +} +export interface Template { + name: string; + sourceCodeUrl: string; + slug: string; +} +type EnvironmentVariableScope = 'builds' | 'functions' | 'runtime' | 'post_processing'; +export type EnvironmentVariableSource = 'account' | 'addons' | 'configFile' | 'general' | 'internal' | 'ui'; +export type EnvironmentVariables = Record; +export interface Plugin { + origin?: string; + package: string; + pinned_version?: string | undefined; +} +//# sourceMappingURL=types.d.ts.map \ No newline at end of file diff --git a/dist/utils/types.d.ts.map b/dist/utils/types.d.ts.map new file mode 100644 index 00000000000..05069663704 --- /dev/null +++ b/dist/utils/types.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":"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"} \ No newline at end of file diff --git a/dist/utils/types.js b/dist/utils/types.js new file mode 100644 index 00000000000..d15fb9e3375 --- /dev/null +++ b/dist/utils/types.js @@ -0,0 +1,2 @@ +export { default as CLIState } from './cli-state.js'; +//# sourceMappingURL=types.js.map \ No newline at end of file diff --git a/dist/utils/types.js.map b/dist/utils/types.js.map new file mode 100644 index 00000000000..4c4abadfbd4 --- /dev/null +++ b/dist/utils/types.js.map @@ -0,0 +1 @@ +{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/utils/types.ts"],"names":[],"mappings":"AAOA,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,gBAAgB,CAAA"} \ No newline at end of file diff --git a/dist/utils/validation.d.ts b/dist/utils/validation.d.ts new file mode 100644 index 00000000000..c53a76919b3 --- /dev/null +++ b/dist/utils/validation.d.ts @@ -0,0 +1,6 @@ +/** + * @param {string} exampleCommand + * @returns {(value:string, previous: unknown) => unknown} + */ +export declare const getGeoCountryArgParser: (exampleCommand: any) => (arg: any) => any; +//# sourceMappingURL=validation.d.ts.map \ No newline at end of file diff --git a/dist/utils/validation.d.ts.map b/dist/utils/validation.d.ts.map new file mode 100644 index 00000000000..0074d8eab1d --- /dev/null +++ b/dist/utils/validation.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"validation.d.ts","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAEA;;;GAGG;AAEH,eAAO,MAAM,sBAAsB,GAAI,mBAAc,MAAM,QAAG,QAW7D,CAAA"} \ No newline at end of file diff --git a/dist/utils/validation.js b/dist/utils/validation.js new file mode 100644 index 00000000000..a176171ee81 --- /dev/null +++ b/dist/utils/validation.js @@ -0,0 +1,17 @@ +import { BANG, chalk } from './command-helpers.js'; +/** + * @param {string} exampleCommand + * @returns {(value:string, previous: unknown) => unknown} + */ +// @ts-expect-error TS(7006) FIXME: Parameter 'exampleCommand' implicitly has an 'any'... Remove this comment to see the full error message +export const getGeoCountryArgParser = (exampleCommand) => (arg) => { + // Validate that the arg passed is two letters only for country + // See https://en.wikipedia.org/wiki/List_of_ISO_3166_country_codes + if (!/^[a-z]{2}$/i.test(arg)) { + throw new Error(`The geo country code must use a two letter abbreviation. + ${chalk.red(BANG)} Example: + ${exampleCommand}`); + } + return arg.toUpperCase(); +}; +//# sourceMappingURL=validation.js.map \ No newline at end of file diff --git a/dist/utils/validation.js.map b/dist/utils/validation.js.map new file mode 100644 index 00000000000..ede9c043473 --- /dev/null +++ b/dist/utils/validation.js.map @@ -0,0 +1 @@ +{"version":3,"file":"validation.js","sourceRoot":"","sources":["../../src/utils/validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,sBAAsB,CAAA;AAElD;;;GAGG;AACH,2IAA2I;AAC3I,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,cAAc,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,EAAE;IAChE,+DAA+D;IAC/D,mEAAmE;IACnE,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CACb;QACE,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;QACf,cAAc,EAAE,CACnB,CAAA;IACH,CAAC;IACD,OAAO,GAAG,CAAC,WAAW,EAAE,CAAA;AAC1B,CAAC,CAAA"} \ No newline at end of file diff --git a/dist/utils/websockets/index.d.ts b/dist/utils/websockets/index.d.ts new file mode 100644 index 00000000000..0514e0428a9 --- /dev/null +++ b/dist/utils/websockets/index.d.ts @@ -0,0 +1,3 @@ +import WebSocket from 'ws'; +export declare const getWebSocket: (url: string) => WebSocket; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/dist/utils/websockets/index.d.ts.map b/dist/utils/websockets/index.d.ts.map new file mode 100644 index 00000000000..d79ec19ba75 --- /dev/null +++ b/dist/utils/websockets/index.d.ts.map @@ -0,0 +1 @@ +{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/utils/websockets/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,IAAI,CAAA;AAE1B,eAAO,MAAM,YAAY,GAAI,KAAK,MAAM,cAAuB,CAAA"} \ No newline at end of file diff --git a/dist/utils/websockets/index.js b/dist/utils/websockets/index.js new file mode 100644 index 00000000000..8ec6274d54f --- /dev/null +++ b/dist/utils/websockets/index.js @@ -0,0 +1,3 @@ +import WebSocket from 'ws'; +export const getWebSocket = (url) => new WebSocket(url); +//# sourceMappingURL=index.js.map \ No newline at end of file diff --git a/dist/utils/websockets/index.js.map b/dist/utils/websockets/index.js.map new file mode 100644 index 00000000000..d465503dab6 --- /dev/null +++ b/dist/utils/websockets/index.js.map @@ -0,0 +1 @@ +{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/utils/websockets/index.ts"],"names":[],"mappings":"AAAA,OAAO,SAAS,MAAM,IAAI,CAAA;AAE1B,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,GAAW,EAAE,EAAE,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,CAAA"} \ No newline at end of file diff --git a/src/commands/init/ai-rules.ts b/src/commands/init/ai-rules.ts new file mode 100644 index 00000000000..2f18ff12ce1 --- /dev/null +++ b/src/commands/init/ai-rules.ts @@ -0,0 +1,255 @@ +import { resolve } from 'node:path' +import { promises as fs } from 'node:fs' +import type { NetlifyAPI } from '@netlify/api' + +import { chalk, log, logAndThrowError, type APIError } from '../../utils/command-helpers.js' +import { normalizeRepoUrl } from '../../utils/normalize-repo-url.js' +import { runGit } from '../../utils/run-git.js' +import { startSpinner } from '../../lib/spinner.js' +import { detectIDE } from '../../recipes/ai-context/index.js' +import { type ConsumerConfig } from '../../recipes/ai-context/context.js' +import { + generateMcpConfig, + configureMcpForVSCode, + configureMcpForCursor, + configureMcpForWindsurf, + showGenericMcpConfig, +} from '../../utils/mcp-utils.js' +import type BaseCommand from '../base-command.js' +import type { SiteInfo } from '../../utils/types.js' +import inquirer from 'inquirer' + +/** + * Project information interface for AI projects + */ +interface ProjectInfo { + success: boolean + projectId: string + prompt: string +} + +// Trigger IDE-specific MCP configuration +const triggerMcpConfiguration = async (ide: ConsumerConfig, projectPath: string): Promise => { + log(`\n${chalk.blue('šŸ”§ MCP Configuration for')} ${chalk.cyan(ide.presentedName)}`) + + const { shouldConfigure } = await inquirer.prompt<{ shouldConfigure: boolean }>([ + { + type: 'confirm', + name: 'shouldConfigure', + message: `Would you like to automatically configure the MCP server for ${ide.presentedName}?`, + default: true, + }, + ]) + + if (!shouldConfigure) { + log(` ${chalk.gray('You can configure MCP manually later for enhanced AI capabilities:')}`) + log( + ` ${chalk.gray('Documentation:')} ${chalk.cyan( + 'https://docs.netlify.com/welcome/build-with-ai/netlify-mcp-server/', + )}`, + ) + + return false + } + + try { + const config = generateMcpConfig(ide) + + // IDE-specific configuration actions + switch (ide.key) { + case 'vscode': + await configureMcpForVSCode(config, projectPath) + break + case 'cursor': + await configureMcpForCursor(config, projectPath) + break + case 'windsurf': + await configureMcpForWindsurf(config, projectPath) + break + default: + showGenericMcpConfig(config, ide.presentedName) + } + + log(`${chalk.green('āœ…')} MCP configuration completed for ${chalk.cyan(ide.presentedName)}`) + return true + } catch (error) { + log(`${chalk.red('āŒ')} Failed to configure MCP: ${error instanceof Error ? error.message : 'Unknown error'}`) + return false + } +} + +// Helper functions reused from ai-start.ts +const decodeHash = (hash: string): string => { + try { + return atob(hash) + } catch (error) { + throw new Error(`Failed to decode hash: ${error instanceof Error ? error.message : 'Invalid base64 or URL'}`) + } +} + +const fetchProjectInfo = async (url: string): Promise => { + try { + const response = await fetch(url, { + headers: { + 'content-type': 'text/plain', + }, + }) + + const data = (await response.text()) as unknown as string + const parsedData = JSON.parse(data) as unknown as ProjectInfo + return parsedData + } catch (error) { + throw new Error(`Failed to fetch project information: ${error instanceof Error ? error.message : 'Unknown error'}`) + } +} + +const getRepoUrlFromProjectId = async (api: NetlifyAPI, projectId: string): Promise => { + try { + const siteInfo = (await api.getSite({ siteId: projectId })) as SiteInfo + const repoUrl = siteInfo.build_settings?.repo_url + + if (!repoUrl) { + throw new Error(`No repository URL found for project ID: ${projectId}`) + } + + return repoUrl + } catch (error) { + if ((error as APIError).status === 404) { + throw new Error(`Project with ID ${projectId} not found`) + } + throw new Error(`Failed to fetch project data: ${(error as Error).message}`) + } +} + +const savePrompt = async (instructions: string, ntlContext: string | null, targetDir: string): Promise => { + try { + const filePath = resolve(targetDir, 'AI-instructions.md') + await fs.writeFile(filePath, `Context: ${ntlContext ?? ''}\n\n${instructions}`, 'utf-8') + log(`${chalk.green('āœ…')} AI instructions saved to ${chalk.cyan('AI-instructions.md')}`) + } catch (error) { + const errorMessage = error instanceof Error ? error.message : 'Unknown error' + log(`${chalk.yellow('āš ļø')} Warning: Failed to save AI instructions: ${errorMessage}`) + } +} + +const cloneRepo = async (repoUrl: string, targetDir: string, debug: boolean): Promise => { + try { + await runGit(['clone', repoUrl, targetDir], !debug) + } catch (error) { + throw new Error(`Failed to clone repository: ${error instanceof Error ? error.message : error?.toString() ?? ''}`) + } +} + +/** + * Handles AI rules initialization workflow + * This is the experimental --ai-rules functionality for the init command + */ +export const initWithAiRules = async (hash: string, command: BaseCommand): Promise => { + // Authenticate first before any API operations + await command.authenticate() + const { api } = command.netlify + + log(`${chalk.blue('šŸ¤– Initializing AI project')} with rules...`) + log(`${chalk.gray('User:')} ${api.accessToken ? 'Authenticated āœ…' : 'Not authenticated āŒ'}`) + + try { + // Step 1: Decode hash and fetch project information + log('\nšŸ“‹ Extracting project details...') + const decodedUrl = decodeHash(hash) + log(`${chalk.cyan('Decoded URL:')} ${decodedUrl}`) + + log('\nšŸ” Fetching project information...') + const projectInfo = await fetchProjectInfo(decodedUrl) + + log(`${chalk.cyan('Project ID:')} ${projectInfo.projectId}`) + + // Step 2: Get repository URL from project ID via Netlify site API + log('\nšŸ”— Linking to Netlify project and fetching repository...') + const repositoryUrl = await getRepoUrlFromProjectId(api, projectInfo.projectId) + log(`${chalk.cyan('Repository:')} ${repositoryUrl}`) + + // Step 3: Clone repository + const { repoUrl, repoName } = normalizeRepoUrl(repositoryUrl) + const targetDir = `ai-project-${repoName}-${hash.substring(0, 8)}` + + const cloneSpinner = startSpinner({ text: `Cloning repository to ${chalk.cyan(targetDir)}` }) + + await cloneRepo(repoUrl, targetDir, false) + cloneSpinner.success({ text: `Cloned repository to ${chalk.cyan(targetDir)}` }) + + // Step 4: Save AI instructions to file + if (projectInfo.prompt) { + const ntlContext = await fetch( + 'https://docs.netlify.com/ai-context/scoped-context?scopes=serverless,blobs,forms', + { + method: 'GET', + headers: { + 'Content-Type': 'text/plain', + }, + }, + ) + .then((res) => res.text()) + .catch(() => { + return null + }) + log('\nšŸ“ Saving AI instructions...') + await savePrompt(projectInfo.prompt, ntlContext, targetDir) + } + + // Step 5: Detect IDE and configure MCP server + log('\nšŸ” Detecting development environment...') + const detectedIDE = await detectIDE() + let mcpConfigured = false + + if (detectedIDE) { + log(`${chalk.green('āœ…')} Detected development environment: ${chalk.cyan(detectedIDE.presentedName)}`) + mcpConfigured = await triggerMcpConfiguration(detectedIDE, targetDir) + } + + // Update working directory to cloned repo + process.chdir(targetDir) + command.workingDir = targetDir + + // Success message with next steps + log() + log(chalk.green('āœ” Your AI project is ready to go!')) + log(`→ Project ID: ${chalk.cyanBright(projectInfo.projectId)}`) + log(`→ Project cloned to: ${chalk.cyanBright(targetDir)}`) + if (projectInfo.prompt) { + log(`→ AI instructions saved: ${chalk.cyanBright('AI-instructions.md')}`) + } + log() + log(chalk.yellowBright(`šŸ“ Step 1: Enter your project directory`)) + log(` ${chalk.cyanBright(`cd ${targetDir}`)}`) + + if (detectedIDE) { + if (mcpConfigured) { + log(chalk.yellowBright(`šŸ”§ Step 2: MCP Server Configured`)) + log(` ${chalk.green('āœ…')} ${chalk.cyan(detectedIDE.key)} is ready with Netlify MCP server`) + log(` ${chalk.gray('šŸ’” MCP will activate when you reload/restart your development environment')}`) + } else { + log(chalk.yellowBright(`šŸ”§ Step 2: Manual MCP Configuration`)) + log(` ${chalk.cyan(detectedIDE.key)} detected - MCP setup was skipped`) + log(` ${chalk.gray('You can configure MCP manually later for enhanced AI capabilities:')}`) + log( + ` ${chalk.gray('Documentation:')} ${chalk.cyan( + 'https://docs.netlify.com/welcome/build-with-ai/netlify-mcp-server/', + )}`, + ) + } + log() + } + + if (projectInfo.prompt) { + const stepNumber = detectedIDE ? '3' : '2' + log(chalk.yellowBright(`šŸ¤– Step ${stepNumber}: Ask your AI assistant to process the instructions`)) + log() + log(chalk.gray('*'.repeat(60))) + log(chalk.cyan(`Follow ${targetDir}/AI-instructions.md and create a new site`)) + log(chalk.gray('*'.repeat(60))) + log() + } + } catch (error) { + return logAndThrowError(error) + } +} diff --git a/src/commands/init/index.ts b/src/commands/init/index.ts index ff9552ac350..e959cc5745f 100644 --- a/src/commands/init/index.ts +++ b/src/commands/init/index.ts @@ -1,4 +1,4 @@ -import { OptionValues } from 'commander' +import { OptionValues, Option } from 'commander' import terminalLink from 'terminal-link' import BaseCommand from '../base-command.js' @@ -11,6 +11,7 @@ export const createInitCommand = (program: BaseCommand) => ) .option('-m, --manual', 'Manually configure a git remote for CI') .option('--git-remote-name ', 'Name of Git remote to use. e.g. "origin"') + .addOption(new Option('--ai-rules ', 'Initialize with AI project configuration (experimental)').hideHelp()) .addHelpText('after', () => { const docsUrl = 'https://docs.netlify.com/cli/get-started/' return ` @@ -18,6 +19,14 @@ For more information about getting started with Netlify CLI, see ${terminalLink( ` }) .action(async (options: OptionValues, command: BaseCommand) => { + // Check for experimental AI rules flag + if (options.aiRules) { + const { initWithAiRules } = await import('./ai-rules.js') + await initWithAiRules(options.aiRules as string, command) + return + } + + // Standard init flow const { init } = await import('./init.js') await init(options, command) }) diff --git a/src/lib/functions/server.ts b/src/lib/functions/server.ts index 23dac7cad6c..85590f38f2e 100644 --- a/src/lib/functions/server.ts +++ b/src/lib/functions/server.ts @@ -169,7 +169,8 @@ export const createHandler = function (options: GetFunctionsServerOptions): Requ const rawQuery = new URL(request.originalUrl, 'http://example.com').search.slice(1) // TODO(serhalp): Update several tests to pass realistic `config` objects and remove nullish coalescing. const protocol = options.config?.dev?.https ? 'https' : 'http' - const url = new URL(requestPath, `${protocol}://${request.get('host') || 'localhost'}`) + const hostname = request.get('host') || 'localhost' + const url = new URL(requestPath, `${protocol}://${hostname}`) url.search = rawQuery const rawUrl = url.toString() const event = { diff --git a/src/recipes/ai-context/index.ts b/src/recipes/ai-context/index.ts index 8063062075d..376143fef24 100644 --- a/src/recipes/ai-context/index.ts +++ b/src/recipes/ai-context/index.ts @@ -77,7 +77,7 @@ const promptForContextConsumerSelection = async (): Promise => { * Checks if a command belongs to a known IDEs by checking if it includes a specific string. * For example, the command that starts windsurf looks something like "/applications/windsurf.app/contents/...". */ -const getConsumerKeyFromCommand = (command: string): string | null => { +export const getConsumerKeyFromCommand = (command: string): string | null => { // The actual command is something like "/applications/windsurf.app/contents/...", but we are only looking for windsurf const match = cliContextConsumers.find( (consumer) => consumer.consumerProcessCmd && command.includes(consumer.consumerProcessCmd), @@ -88,7 +88,7 @@ const getConsumerKeyFromCommand = (command: string): string | null => { /** * Receives a process ID (pid) and returns both the command that the process was run with and its parent process ID. If the process is a known IDE, also returns information about that IDE. */ -const getCommandAndParentPID = async ( +export const getCommandAndParentPID = async ( pid: number, ): Promise<{ parentPID: number @@ -107,7 +107,10 @@ const getCommandAndParentPID = async ( } } -const getPathByDetectingIDE = async (): Promise => { +/** + * Detects the IDE by walking up the process tree and matching against known consumer processes + */ +export const detectIDE = async (): Promise => { // Go up the chain of ancestor process IDs and find if one of their commands matches an IDE. const ppid = process.ppid let result: Awaited> @@ -142,7 +145,7 @@ export const run = async (runOptions: RunRecipeOptions) => { } if (!consumer && process.env.AI_CONTEXT_SKIP_DETECTION !== 'true') { - consumer = await getPathByDetectingIDE() + consumer = await detectIDE() } if (!consumer) { diff --git a/src/utils/mcp-utils.ts b/src/utils/mcp-utils.ts new file mode 100644 index 00000000000..6eb99c9cb97 --- /dev/null +++ b/src/utils/mcp-utils.ts @@ -0,0 +1,144 @@ +import { resolve } from 'node:path' +import { promises as fs } from 'node:fs' +import { homedir } from 'node:os' +import { chalk, log } from './command-helpers.js' +import type { ConsumerConfig } from '../recipes/ai-context/context.js' + +/** + * Generate MCP configuration for the detected IDE or development environment + */ +export const generateMcpConfig = (ide: ConsumerConfig): Record => { + const configs: Record> = { + vscode: { + servers: { + netlify: { + type: 'stdio', + command: 'npx', + args: ['-y', '@netlify/mcp'], + }, + }, + }, + cursor: { + mcpServers: { + netlify: { + command: 'npx', + args: ['-y', '@netlify/mcp'], + }, + }, + }, + windsurf: { + mcpServers: { + netlify: { + command: 'npx', + args: ['-y', '@netlify/mcp'], + }, + }, + }, + } + + return ( + configs[ide.key] ?? { + mcpServers: { + netlify: { + command: 'npx', + args: ['-y', '@netlify/mcp'], + }, + }, + } + ) +} + +/** + * VS Code specific MCP configuration + */ +export const configureMcpForVSCode = async (config: Record, projectPath: string): Promise => { + const vscodeDirPath = resolve(projectPath, '.vscode') + const configPath = resolve(vscodeDirPath, 'mcp.json') + + try { + // Create .vscode directory if it doesn't exist + await fs.mkdir(vscodeDirPath, { recursive: true }) + + // Write or update mcp.json + let existingConfig: Record = {} + try { + const existingContent = await fs.readFile(configPath, 'utf-8') + existingConfig = JSON.parse(existingContent) as Record + } catch { + // File doesn't exist or is invalid JSON + } + + const updatedConfig = { ...existingConfig, ...config } + + await fs.writeFile(configPath, JSON.stringify(updatedConfig, null, 2), 'utf-8') + log(`${chalk.green('āœ…')} VS Code MCP configuration saved to ${chalk.cyan('.vscode/mcp.json')}`) + } catch (error) { + throw new Error(`Failed to configure VS Code MCP: ${error instanceof Error ? error.message : 'Unknown error'}`) + } +} + +/** + * Cursor specific MCP configuration + */ +export const configureMcpForCursor = async (config: Record, projectPath: string): Promise => { + const configPath = resolve(projectPath, '.cursor', 'mcp.json') + + try { + await fs.mkdir(resolve(projectPath, '.cursor'), { recursive: true }) + await fs.writeFile(configPath, JSON.stringify(config, null, 2), 'utf-8') + log(`${chalk.green('āœ…')} Cursor MCP configuration saved to ${chalk.cyan('.cursor/mcp.json')}`) + } catch (error) { + throw new Error(`Failed to configure Cursor MCP: ${error instanceof Error ? error.message : 'Unknown error'}`) + } +} + +/** + * Windsurf specific MCP configuration + */ +export const configureMcpForWindsurf = async (config: Record, _projectPath: string): Promise => { + const windsurfDirPath = resolve(homedir(), '.codeium', 'windsurf') + const configPath = resolve(windsurfDirPath, 'mcp_config.json') + + try { + // Create .codeium/windsurf directory if it doesn't exist + await fs.mkdir(windsurfDirPath, { recursive: true }) + + // Read existing config or create new one + let existingConfig: Record = {} + try { + const existingContent = await fs.readFile(configPath, 'utf-8') + existingConfig = JSON.parse(existingContent) as Record + } catch { + // File doesn't exist or is invalid JSON + } + + // Merge mcpServers from both configs + const existingServers = (existingConfig.mcpServers as Record | undefined) ?? {} + const newServers = (config.mcpServers as Record | undefined) ?? {} + + const updatedConfig = { + ...existingConfig, + mcpServers: { + ...existingServers, + ...newServers, + }, + } + + await fs.writeFile(configPath, JSON.stringify(updatedConfig, null, 2), 'utf-8') + log(`${chalk.green('āœ…')} Windsurf MCP configuration saved`) + log(`${chalk.gray('šŸ’”')} Restart Windsurf to activate the MCP server`) + } catch (error) { + throw new Error(`Failed to configure Windsurf MCP: ${error instanceof Error ? error.message : 'Unknown error'}`) + } +} + +/** + * Generic MCP configuration display + */ +export const showGenericMcpConfig = (config: Record, ideName: string): void => { + log(`\n${chalk.yellow('šŸ“‹ Manual configuration required')}`) + log(`Please add the following configuration to your ${ideName} settings:`) + log(`\n${chalk.gray('--- Configuration ---')}`) + log(JSON.stringify(config, null, 2)) + log(`${chalk.gray('--- End Configuration ---')}\n`) +}