diff --git a/src/cmd.ts b/src/cmd.ts index 5660e8c..e64aeeb 100644 --- a/src/cmd.ts +++ b/src/cmd.ts @@ -9,7 +9,7 @@ import { parseAppendData, parseConfig } from "./utils" export async function parseCliArgs(args = process.argv.slice(2)) { const pkg = JSON.parse((await fs.readFile(path.join(__dirname, "package.json"))).toString()) - const isConfig = args.includes("--config") || args.includes("-c") + const isConfig = args.includes("--config") || args.includes("-c") || args.includes("--github") || args.includes("-gh") return ( massarg() @@ -29,7 +29,13 @@ export async function parseCliArgs(args = process.argv.slice(2)) { name: "config", aliases: ["c"], description: - "Filename to load config from instead of passing arguments to CLI or using a Node.js script. You may pass a JSON or JS file, with a relative or absolute path, a URL to a repository, or a GitHub path (e.g. username/package). You may also optionally add a key (same as passing --key) to load from inside the config.", + "Filename or https git URL to load config from instead of passing arguments to CLI or using a Node.js script. You may pass a JSON or JS file with a relative or absolute path", + }) + .option({ + name: "github", + aliases: ["gh"], + description: + "GitHub path to load config from instead of passing arguments to CLI or using a Node.js script. You may pass a JSON or JS file, with a relative or absolute path, a URL to a repository, or a GitHub path (e.g. username/package#scaffold.config.js). You may also optionally add a key (same as passing --key) to load from inside the config.", }) .option({ name: "key", diff --git a/src/types.ts b/src/types.ts index a526f74..04fa67d 100644 --- a/src/types.ts +++ b/src/types.ts @@ -338,6 +338,7 @@ export interface ScaffoldCmdConfig { dryRun: boolean config?: string key?: string + github?: string } export type ScaffoldConfigFile = Record diff --git a/src/utils.ts b/src/utils.ts index 7ffaea4..09a11ce 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -409,6 +409,14 @@ function isWrappedWithQuotes(string: string): boolean { /** @internal */ export async function parseConfig(config: ScaffoldCmdConfig & OptionsBase): Promise { let c: ScaffoldConfig = config + if (config.github) { + log(config, LogLevel.Info, `Loading config from github ${config.github}`) + const gitUrl = new URL(`https://github.com/${config.github}`) + if (!gitUrl.pathname.endsWith(".git")) { + gitUrl.pathname += ".git" + } + config.config = gitUrl.toString() + } if (config.config) { const isUrl = config.config.includes("://") @@ -419,6 +427,7 @@ export async function parseConfig(config: ScaffoldCmdConfig & OptionsBase): Prom ? [config.config.substring(0, colonIndex), config.config.substring(colonIndex + 1)] : [config.config, undefined] const key = (config.key ?? templateKey) || "default" + log(config, LogLevel.Info, `Loading config from ${configFile} with key ${key}`) const configImport = await getConfig({ config: configFile, quiet: config.quiet, verbose: config.verbose }) if (!configImport[key]) { throw new Error(`Template "${key}" not found in ${configFile}`) @@ -461,15 +470,16 @@ export async function getConfig( const tmpPath = path.resolve(os.tmpdir(), `scaffold-config-${Date.now()}`) return new Promise((resolve, reject) => { - const clone = spawn("git", ["clone", repoUrl, tmpPath]) + const clone = spawn("git", ["clone", "--depth", "1", repoUrl, tmpPath]) clone.on("error", reject) clone.on("close", async (code) => { if (code === 0) { - log(logConfig, LogLevel.Info, `Loading config from git repo: ${configFile}`) - const absolutePath = path.resolve(tmpPath, url.hash.replace("#", "")) + log(logConfig, LogLevel.Info, `Loading config from git repo: ${repoUrl}`) + const hashPath = url.hash?.replace("#", "") || "scaffold.config.js" + const absolutePath = path.resolve(tmpPath, hashPath) const loadedConfig = (await import(absolutePath)).default as ScaffoldConfigFile - log(logConfig, LogLevel.Info, `Loaded config from git repo`) + log(logConfig, LogLevel.Info, `Loaded config from git`) log(logConfig, LogLevel.Debug, `Raw config:`, loadedConfig) const fixedConfig: ScaffoldConfigFile = Object.fromEntries( Object.entries(loadedConfig).map(([k, v]) => [