Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pgpm/cli/__tests__/init.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
jest.setTimeout(60000);
process.env.PGPM_SKIP_UPDATE_CHECK = 'true';
process.env.PGPM_SKIP_SKILL_INSTALL = 'true';

import { PgpmPackage } from '@pgpmjs/core';
import { existsSync } from 'fs';
Expand Down
2 changes: 1 addition & 1 deletion pgpm/cli/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@
"@pgsql/quotes": "^17.1.0",
"appstash": "^0.7.0",
"find-and-require-package-json": "^0.9.1",
"genomic": "^5.5.0",
"genomic": "^5.6.0",
"inquirerer": "^4.8.1",
"js-yaml": "^4.1.0",
"pg-cache": "workspace:^",
Expand Down
52 changes: 49 additions & 3 deletions pgpm/cli/src/commands/init/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
resolveBoilerplateBaseDir,
scaffoldTemplate,
scanBoilerplates,
SkillInstaller,
sluggify,
} from '@pgpmjs/core';
import { resolveWorkspaceByType } from '@pgpmjs/env';
Expand Down Expand Up @@ -44,6 +45,7 @@ Options:
--template, -t <path> Full template path (e.g., pnpm/module) - combines dir and fromPath
--boilerplate Prompt to select from available boilerplates
--create-workspace, -w Create a workspace first, then create the module inside it
--use-skills Use npx skills CLI for skill installation (slower, writes skills-lock.json)

Examples:
${binaryName} init Initialize new module (default)
Expand Down Expand Up @@ -79,6 +81,7 @@ async function handleInit(argv: Partial<Record<string, any>>, prompter: Inquirer
const noTty = Boolean((argv as any).noTty || argv['no-tty'] || argv.tty === false || process.env.CI === 'true');
const useBoilerplatePrompt = Boolean(argv.boilerplate);
const createWorkspace = Boolean(argv.createWorkspace || argv['create-workspace'] || argv.w);
const useNpxSkills = Boolean(argv.useSkills || argv['use-skills']);

// Get fromPath from first positional arg
const positionalFromPath = argv._?.[0] as string | undefined;
Expand Down Expand Up @@ -110,6 +113,7 @@ async function handleInit(argv: Partial<Record<string, any>>, prompter: Inquirer
dir,
noTty,
cwd,
useNpxSkills,
});
}

Expand Down Expand Up @@ -139,6 +143,7 @@ async function handleInit(argv: Partial<Record<string, any>>, prompter: Inquirer
dir,
noTty,
cwd,
useNpxSkills,
});
}

Expand All @@ -152,6 +157,7 @@ async function handleInit(argv: Partial<Record<string, any>>, prompter: Inquirer
cwd,
requiresWorkspace: inspection.config?.requiresWorkspace,
createWorkspace,
useNpxSkills,
}, wasExplicitModuleRequest);
}

Expand All @@ -162,6 +168,7 @@ interface BoilerplateInitContext {
dir?: string;
noTty: boolean;
cwd: string;
useNpxSkills?: boolean;
}

async function handleBoilerplateInit(
Expand Down Expand Up @@ -243,6 +250,7 @@ async function handleBoilerplateInit(
dir: ctx.dir,
noTty: ctx.noTty,
cwd: ctx.cwd,
useNpxSkills: ctx.useNpxSkills,
});
}

Expand All @@ -256,6 +264,7 @@ async function handleBoilerplateInit(
noTty: ctx.noTty,
cwd: ctx.cwd,
requiresWorkspace: inspection.config?.requiresWorkspace,
useNpxSkills: ctx.useNpxSkills,
}, true);
}

Expand All @@ -275,9 +284,46 @@ interface InitContext {
* If true, create a workspace first, then create the module inside it.
*/
createWorkspace?: boolean;
/**
* If true, use npx skills CLI instead of built-in shallow clone.
*/
useNpxSkills?: boolean;
}

function installSkills(skills: BoilerplateSkill[], cwd: string, useNpxSkills: boolean): void {
if (process.env.PGPM_SKIP_SKILL_INSTALL) return;

if (useNpxSkills) {
installSkillsViaNpx(skills, cwd);
} else {
installSkillsBuiltin(skills, cwd);
}
}

function installSkillsBuiltin(skills: BoilerplateSkill[], cwd: string): void {
const installer = new SkillInstaller({ toolName: DEFAULT_TEMPLATE_TOOL_NAME });
const result = installer.install(skills, cwd);

if (result.installed.length > 0) {
for (const name of result.installed) {
process.stdout.write(` installed ${name}\n`);
}
}

if (result.failed.length > 0) {
process.stdout.write('\n⚠️ Some skills could not be installed automatically.\n');
process.stdout.write('Run the following commands manually:\n\n');
for (const f of result.failed) {
const source = f.source.includes('://')
? f.source
: `https://github.com/${f.source}`;
process.stdout.write(` npx skills add ${source} --skill ${f.skill}\n`);
}
process.stdout.write('\n');
}
}

function installSkills(skills: BoilerplateSkill[], cwd: string): void {
function installSkillsViaNpx(skills: BoilerplateSkill[], cwd: string): void {
const failed: string[] = [];

for (const entry of skills) {
Expand Down Expand Up @@ -373,7 +419,7 @@ async function handleWorkspaceInit(
});
if (templateInfo.config?.skills?.length) {
process.stdout.write('\n📦 Installing skills...\n\n');
installSkills(templateInfo.config.skills, targetPath);
installSkills(templateInfo.config.skills, targetPath, Boolean(ctx.useNpxSkills));
}

const relPath = path.relative(process.cwd(), targetPath);
Expand Down Expand Up @@ -678,7 +724,7 @@ async function handleModuleInit(
if (moduleTemplateInfo.config?.skills?.length) {
const skillsCwd = project.workspacePath || modulePath;
process.stdout.write('\n📦 Installing skills...\n\n');
installSkills(moduleTemplateInfo.config.skills, skillsCwd);
installSkills(moduleTemplateInfo.config.skills, skillsCwd, Boolean(ctx.useNpxSkills));
}

const relPath = path.relative(process.cwd(), modulePath);
Expand Down
2 changes: 1 addition & 1 deletion pgpm/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@
"@pgpmjs/server-utils": "workspace:^",
"@pgpmjs/types": "workspace:^",
"csv-to-pg": "workspace:^",
"genomic": "^5.5.0",
"genomic": "^5.6.0",
"glob": "^13.0.6",
"minimatch": "^10.2.5",
"parse-package-name": "^1.0.0",
Expand Down
2 changes: 2 additions & 0 deletions pgpm/core/src/core/template-scaffold.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import os from 'os';
import path from 'path';
import { TemplateScaffolder, BoilerplateConfig as GenomicBoilerplateConfig } from 'genomic';
export type { BoilerplateSkill } from 'genomic';
export { SkillInstaller } from 'genomic';
export type { SkillInstallOptions, SkillInstallResult, SkillInstallFailure } from 'genomic';
import type { Inquirerer, Question } from 'inquirerer';

/**
Expand Down
Loading
Loading