UNPKG

limgen

Version:

Infrastructure as Code generator

106 lines (90 loc) 3.09 kB
import { ProjectType } from "@/project"; import { dockerfileExists, getDockerfilePort } from "../../docker"; import { cliInteger } from "../../schema"; import ejs from "ejs"; import fs from "fs/promises"; export const inputs = async (cmdArgs: any, projectInput: any) => { return [ { name: 'port', message: 'Port to expose', schema: cliInteger().optional(), } ] } export const collectInput = async (cmdArgs: any, projectInput: any, frameworkArgs: any) => { let port = frameworkArgs.port; if (!port || port === 'unknown') { const dockerfilePort = await getDockerfilePort(); if (dockerfilePort === null) { port = 3000; } } return { projectType: projectInput.projectType, port, } } export interface NextJSFrameworkInput { projectType: ProjectType; port: number; } export default async function nextJsFramework(opts: NextJSFrameworkInput) { await Promise.all([ ensureDockerfile(opts), updateNextConfig(opts.projectType), updateDockerignore(opts) ]) } const updateDockerignore = async (opts: NextJSFrameworkInput) => { if (!isFullstack(opts.projectType)) { return; } const contents = await fs.readFile('.dockerignore', 'utf-8'); if (!contents.includes('node_modules')) { await fs.appendFile('.dockerignore', 'node_modules\n'); } } const ensureDockerfile = async (opts: NextJSFrameworkInput) => { if (!isFullstack(opts.projectType)) { return; } if (await dockerfileExists()) { return; } try { const result = await ejs.renderFile(`${__dirname}/Dockerfile.ejs.t`, opts) await fs.writeFile('Dockerfile', result) } catch (error) { console.error('Unable to render Dockerfile', error) throw error } } const updateNextConfig = async (projectType: ProjectType) => { // get next.config.js or next.config.ts let nextConfigFile = 'next.config.js'; try { await fs.access('next.config.ts'); nextConfigFile = 'next.config.ts'; } catch (error) { } const nextConfig = await fs.readFile(nextConfigFile, 'utf-8'); // update next.config.ts, detect const nextConfig: NextConfig = { const nextConfigMatch = nextConfig.match(/const nextConfig: NextConfig = {/); if (nextConfigMatch) { // find a section matching output: 'standalone' const outputMatch = nextConfig.match(/output: *('|")(.+)('|")/); const desiredOutputType = isFullstack(projectType) ? 'standalone' : 'export'; if (!outputMatch) { const updatedNextConfig = nextConfig.replace( /const nextConfig: NextConfig = {/, `const nextConfig: NextConfig = {\n output: '${desiredOutputType}',\n` ); await fs.writeFile(nextConfigFile, updatedNextConfig); } else if (outputMatch[2] !== desiredOutputType) { throw new Error( `Your NextJS config 'output' property is not set to '${desiredOutputType}'.\n\n` + `Limgen currently requires '${desiredOutputType}' to be set for ${projectType} compatibility.`); } } } export const isFullstack = (projectType: ProjectType) => projectType.startsWith('fullstack');