|
| 1 | +import * as path from "node:path"; |
| 2 | + |
| 3 | +import enquirer from "enquirer"; |
| 4 | +import * as fs from "fs-extra"; |
| 5 | + |
| 6 | +import BaseCommand from "@/lib/base-command"; |
| 7 | +import { |
| 8 | + PROJECT_CONFIG_FILE_NAME, |
| 9 | + ResourceDirectoriesByType, |
| 10 | +} from "@/lib/helpers/project-config"; |
| 11 | + |
| 12 | +export default class Init extends BaseCommand<typeof Init> { |
| 13 | + protected requiresAuth = false; |
| 14 | + |
| 15 | + static summary = |
| 16 | + "Initialize a new Knock project with a knock.json configuration file."; |
| 17 | + |
| 18 | + static description = |
| 19 | + "Creates a knock.json configuration file in the current directory " + |
| 20 | + "to store project-level settings like the knock resources directory."; |
| 21 | + |
| 22 | + public async run(): Promise<void> { |
| 23 | + const configPath = path.resolve(process.cwd(), PROJECT_CONFIG_FILE_NAME); |
| 24 | + |
| 25 | + // 1. Check if knock.json already exists |
| 26 | + const configExists = await fs.pathExists(configPath); |
| 27 | + if (configExists) { |
| 28 | + this.error( |
| 29 | + `A ${PROJECT_CONFIG_FILE_NAME} file already exists in this directory. Aborting.`, |
| 30 | + ); |
| 31 | + } |
| 32 | + |
| 33 | + // 2. Prompt user for the knock directory location |
| 34 | + const { knockDir } = await enquirer.prompt<{ knockDir: string }>({ |
| 35 | + type: "input", |
| 36 | + name: "knockDir", |
| 37 | + message: "Where do you want to store your Knock resources?", |
| 38 | + initial: ".knock", |
| 39 | + }); |
| 40 | + |
| 41 | + // 3. Create the knock directory and resource subdirectories |
| 42 | + const knockDirPath = path.resolve(process.cwd(), knockDir); |
| 43 | + await fs.ensureDir(knockDirPath); |
| 44 | + |
| 45 | + // Create resource subdirectories with .gitignore files |
| 46 | + for (const resourceDir of Object.values(ResourceDirectoriesByType)) { |
| 47 | + const resourceDirPath = path.resolve(knockDirPath, resourceDir); |
| 48 | + |
| 49 | + // eslint-disable-next-line no-await-in-loop |
| 50 | + await fs.ensureDir(resourceDirPath); |
| 51 | + |
| 52 | + // Create a .gitignore file in each resource directory |
| 53 | + const gitignorePath = path.resolve(resourceDirPath, ".gitignore"); |
| 54 | + |
| 55 | + // eslint-disable-next-line no-await-in-loop |
| 56 | + await fs.writeFile(gitignorePath, ""); |
| 57 | + } |
| 58 | + |
| 59 | + // 4. Write the knock.json configuration file |
| 60 | + await fs.outputJson( |
| 61 | + configPath, |
| 62 | + { |
| 63 | + $schema: "https://schemas.knock.app/cli/knock.json", |
| 64 | + knockDir, |
| 65 | + }, |
| 66 | + { spaces: 2 }, |
| 67 | + ); |
| 68 | + |
| 69 | + this.log(`‣ Successfully initialized Knock project at ${process.cwd()}`); |
| 70 | + this.log(`‣ Resources directory: ${knockDir}`); |
| 71 | + } |
| 72 | +} |
0 commit comments