Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(compas): add support for
npx compas@latest init
This self inits according to the docs at https://compasjs.com/docs/getting-started.html#installation
- Loading branch information
Showing
4 changed files
with
238 additions
and
9 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,17 +1,48 @@ | ||
#!/usr/bin/env node | ||
|
||
import { existsSync } from "node:fs"; | ||
import { isNil } from "@compas/stdlib"; | ||
import { configLoadEnvironment } from "../config.js"; | ||
import { ciMode } from "../main/ci/index.js"; | ||
import { developmentMode } from "../main/development/index.js"; | ||
import { productionMode } from "../main/production/index.js"; | ||
|
||
const env = await configLoadEnvironment("", !isNil(process.env.NODE_ENV)); | ||
// Just execute some temporary command matching | ||
const args = process.argv.slice(2); | ||
const debug = args.includes("--debug"); | ||
|
||
if (env.isCI) { | ||
await ciMode(env); | ||
} else if (!env.isDevelopment) { | ||
await productionMode(env); | ||
if (debug) { | ||
args.splice(args.indexOf("--debug"), 1); | ||
} | ||
|
||
if (args.length === 0) { | ||
if (!existsSync("./package.json")) { | ||
// eslint-disable-next-line no-console | ||
console.log(`Please run 'npx compas@latest init' to install Compas.`); | ||
} else { | ||
// TODO: check if we are in a project or someone forgot to run 'compas init'. | ||
|
||
// TODO: debug | ||
|
||
const env = await configLoadEnvironment("", !isNil(process.env.NODE_ENV)); | ||
|
||
if (env.isCI) { | ||
const { ciMode } = await import("../main/ci/index.js"); | ||
await ciMode(env); | ||
} else if (!env.isDevelopment) { | ||
const { productionMode } = await import("../main/production/index.js"); | ||
await productionMode(env); | ||
} else { | ||
const { developmentMode } = await import("../main/development/index.js"); | ||
await developmentMode(env); | ||
} | ||
} | ||
} else if (args.length === 1) { | ||
if (args[0] === "init") { | ||
const { initCompas } = await import("../main/init/compas.js"); | ||
await initCompas(); | ||
} | ||
} else { | ||
await developmentMode(env); | ||
// eslint-disable-next-line no-console | ||
console.log(`Unsupported command. Available commands: | ||
- compas | ||
- compas init`); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
import { existsSync } from "node:fs"; | ||
import { readFile, writeFile } from "node:fs/promises"; | ||
import { exec, newLogger, spawn } from "@compas/stdlib"; | ||
import { configLoadReadOnlyEnvironment } from "../../config.js"; | ||
import { logger, loggerEnable } from "../../output/log.js"; | ||
import { packageManagerDetermineInstallCommand } from "../../package-manager.js"; | ||
|
||
export async function initCompas() { | ||
const env = await configLoadReadOnlyEnvironment(); | ||
|
||
loggerEnable( | ||
newLogger({ | ||
ctx: { | ||
type: env.appName, | ||
}, | ||
}), | ||
); | ||
if (env.isCI) { | ||
logger.info({ | ||
message: "Compas init is not supported in CI.", | ||
}); | ||
return; | ||
} | ||
|
||
if (!env.isDevelopment) { | ||
logger.info({ | ||
message: | ||
"Compas init is not supported when NODE_ENV is explicitly set, but is not 'development'.", | ||
}); | ||
return; | ||
} | ||
|
||
if (existsSync("package.json")) { | ||
await initCompasInExistingProject(env); | ||
} else { | ||
await initCompasInNewProject(env); | ||
} | ||
} | ||
|
||
async function initCompasInExistingProject(env) { | ||
const packageJson = JSON.parse(await readFile("package.json", "utf-8")); | ||
|
||
let alreadyInstalled = false; | ||
const compasVersion = env.compasVersion.split("v").pop(); | ||
|
||
if (packageJson.dependencies?.compas) { | ||
alreadyInstalled = packageJson.dependencies.compas === compasVersion; | ||
packageJson.dependencies.compas = compasVersion; | ||
} else if (packageJson.devDependencies?.compas) { | ||
alreadyInstalled = packageJson.devDependencies.compas === compasVersion; | ||
packageJson.devDependencies.compas = compasVersion; | ||
} else { | ||
packageJson.dependencies ??= {}; | ||
packageJson.dependencies.compas = compasVersion; | ||
} | ||
|
||
if (!alreadyInstalled) { | ||
logger.info( | ||
`Patching package.json with ${env.compasVersion} and installing dependencies...`, | ||
); | ||
await writeFile( | ||
"package.json", | ||
`${JSON.stringify(packageJson, null, 2)}\n`, | ||
); | ||
const packageManagerCommand = packageManagerDetermineInstallCommand(); | ||
await spawn(packageManagerCommand[0], packageManagerCommand.slice(1)); | ||
|
||
logger.info(` | ||
Ready to roll! Run 'npx compas' to start the Compas development environment. | ||
Tip: See https://compasjs.com/docs/getting-started.html#development-setup on how to run 'compas' without the 'npx' prefix. | ||
`); | ||
} else { | ||
logger.info("Already up-to-date!"); | ||
} | ||
} | ||
|
||
async function initCompasInNewProject(env) { | ||
const compasVersion = env.compasVersion.split("v").pop(); | ||
const packageJson = { | ||
name: env.appName, | ||
private: true, | ||
version: "0.0.1", | ||
type: "module", | ||
scripts: {}, | ||
keywords: [], | ||
dependencies: { | ||
compas: compasVersion, | ||
}, | ||
}; | ||
|
||
await writeFile("package.json", `${JSON.stringify(packageJson, null, 2)}\n`); | ||
|
||
logger.info("Created a package.json. Installing with npm..."); | ||
|
||
const packageManagerCommand = packageManagerDetermineInstallCommand(); | ||
await spawn(packageManagerCommand[0], packageManagerCommand.slice(1)); | ||
|
||
if (!existsSync(".gitignore")) { | ||
await writeFile( | ||
".gitignore", | ||
`# Compas | ||
.cache | ||
.env.local | ||
generated | ||
# OS | ||
.DS_Store | ||
# IDE | ||
.idea | ||
.vscode | ||
# Dependencies | ||
node_modules | ||
# Log files | ||
*-debug.log | ||
*-error.log | ||
# Tests | ||
coverage | ||
`, | ||
); | ||
} | ||
|
||
if ((await exec("git --version")).exitCode === 0 && !existsSync(".git")) { | ||
logger.info("Initializing a Git repository."); | ||
|
||
await exec("git init"); | ||
await exec("git checkout -b main"); | ||
await exec("git add -A"); | ||
await exec(`git commit -m "Initialized project with ${env.compasVersion}"`); | ||
} | ||
|
||
logger.info(` | ||
Ready to roll! Run 'npx compas' to start the Compas development environment. | ||
You can switch to a different supported package manager like Yarn or pnpm by removing the created package-lock.json and running the equivalent of 'npm install' with your favorite package manager. | ||
Tip: See https://compasjs.com/docs/getting-started.html#development-setup on how to run 'compas' without the 'npx' prefix. | ||
`); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
import { existsSync } from "node:fs"; | ||
|
||
/** | ||
* Determine package manager command to use for installing dependencies. | ||
* | ||
* @returns {string[]} | ||
*/ | ||
export function packageManagerDetermineInstallCommand() { | ||
if (existsSync("package-lock.json")) { | ||
return ["npm", "install"]; | ||
} else if (existsSync("yarn.lock")) { | ||
return ["yarn"]; | ||
} else if (existsSync("pnpm-lock.yaml")) { | ||
return ["pnpm", "install"]; | ||
} | ||
|
||
// Default to NPM | ||
return ["npm", "install"]; | ||
} |