pgpm 0.2.18 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -34,7 +34,7 @@ eval "$(pgpm env)"
34
34
 
35
35
  ```bash
36
36
  # 1. Create a workspace
37
- pgpm init --workspace
37
+ pgpm init workspace
38
38
  cd my-app
39
39
 
40
40
  # 2. Create your first module
@@ -55,7 +55,7 @@ psql -d mydb1 -c "SELECT faker.city('MI');"
55
55
  ### Getting Started
56
56
 
57
57
  - `pgpm init` - Initialize a new module
58
- - `pgpm init --workspace` - Initialize a new workspace
58
+ - `pgpm init workspace` - Initialize a new workspace
59
59
 
60
60
  ### Development Setup
61
61
 
@@ -98,6 +98,8 @@ psql -d mydb1 -c "SELECT faker.city('MI');"
98
98
  - `pgpm analyze` - Analyze database structure
99
99
  - `pgpm rename` - Rename database changes
100
100
  - `pgpm admin-users` - Manage admin users
101
+ - `pgpm cache clean` - Clear cached template repos used by `pgpm init`
102
+ - `pgpm update` - Install the latest pgpm version from npm
101
103
 
102
104
  ## 💡 Common Workflows
103
105
 
@@ -105,7 +107,7 @@ psql -d mydb1 -c "SELECT faker.city('MI');"
105
107
 
106
108
  ```bash
107
109
  # 1. Create workspace
108
- pgpm init --workspace
110
+ pgpm init workspace
109
111
  cd my-app
110
112
 
111
113
  # 2. Create your first module
@@ -119,6 +121,12 @@ pgpm add some_change
119
121
  pgpm deploy --createdb
120
122
  ```
121
123
 
124
+ ## 🧰 Templates, Caching, and Updates
125
+
126
+ - `pgpm init` now scaffolds workspaces/modules from `https://github.com/launchql/pgpm-boilerplates.git` using `create-gen-app` with a one-week cache (stored under `~/.pgpm/cache/repos`). Override with `--repo`, `--from-branch`, and `--template-path`, or use a local template path.
127
+ - Run `pgpm cache clean` to wipe the cached boilerplates if you need a fresh pull.
128
+ - The CLI performs a lightweight npm version check at most once per week (skipped in CI or when `PGPM_SKIP_UPDATE_CHECK` is set). Use `pgpm update` to upgrade to the latest release.
129
+
122
130
  ### Working with Existing Projects
123
131
 
124
132
  ```bash
@@ -400,7 +408,7 @@ Common issues and solutions for pgpm, PostgreSQL, and testing.
400
408
 
401
409
  * [pgpm](https://github.com/constructive-io/constructive/tree/main/packages/pgpm): **🖥️ PostgreSQL Package Manager** for modular Postgres development. Works with database workspaces, scaffolding, migrations, seeding, and installing database packages.
402
410
  * [@launchql/cli](https://github.com/constructive-io/constructive/tree/main/packages/cli): **🖥️ Command-line toolkit** for managing LaunchQL projects—supports database scaffolding, migrations, seeding, code generation, and automation.
403
- * [launchql/launchql-gen](https://github.com/constructive-io/constructive/tree/main/packages/launchql-gen): **✨ Auto-generated GraphQL** mutations and queries dynamically built from introspected schema data.
411
+ * [constructive-io/constructive-gen](https://github.com/constructive-io/constructive/tree/main/packages/launchql-gen): **✨ Auto-generated GraphQL** mutations and queries dynamically built from introspected schema data.
404
412
  * [@launchql/query-builder](https://github.com/constructive-io/constructive/tree/main/packages/query-builder): **🏗️ SQL constructor** providing a robust TypeScript-based query builder for dynamic generation of `SELECT`, `INSERT`, `UPDATE`, `DELETE`, and stored procedure calls—supports advanced SQL features like `JOIN`, `GROUP BY`, and schema-qualified queries.
405
413
  * [@launchql/query](https://github.com/constructive-io/constructive/tree/main/packages/query): **🧩 Fluent GraphQL builder** for PostGraphile schemas. ⚡ Schema-aware via introspection, 🧩 composable and ergonomic for building deeply nested queries.
406
414
 
@@ -0,0 +1,3 @@
1
+ import { CLIOptions, Inquirerer } from 'inquirerer';
2
+ declare const _default: (argv: Partial<Record<string, any>>, _prompter: Inquirerer, _options: CLIOptions) => Promise<Partial<Record<string, any>>>;
3
+ export default _default;
@@ -0,0 +1,32 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const logger_1 = require("@launchql/logger");
4
+ const create_gen_app_1 = require("create-gen-app");
5
+ const cli_error_1 = require("../utils/cli-error");
6
+ const log = new logger_1.Logger('cache');
7
+ const cacheUsageText = `
8
+ Cache Command:
9
+
10
+ pgpm cache clean [OPTIONS]
11
+
12
+ Options:
13
+ --help, -h Show this help message
14
+ --tool <name> Cache namespace to clear (default: pgpm)
15
+ `;
16
+ exports.default = async (argv, _prompter, _options) => {
17
+ if (argv.help || argv.h) {
18
+ console.log(cacheUsageText);
19
+ process.exit(0);
20
+ }
21
+ const action = argv._?.[0] || 'clean';
22
+ if (action !== 'clean') {
23
+ console.log(cacheUsageText);
24
+ await (0, cli_error_1.cliExitWithError)(`Unknown cache action: ${action}`);
25
+ }
26
+ const toolName = argv.tool || 'pgpm';
27
+ const cacheManager = new create_gen_app_1.CacheManager({ toolName });
28
+ cacheManager.clearAll();
29
+ log.success(`Cleared template cache for "${toolName}".`);
30
+ log.debug(`Cache location: ${cacheManager.getReposDir()}`);
31
+ return argv;
32
+ };
@@ -1,4 +1,5 @@
1
1
  import { CLIOptions, Inquirerer } from 'inquirerer';
2
+ export declare const createInitUsageText: (binaryName: string, productLabel?: string) => string;
2
3
  declare const _default: (argv: Partial<Record<string, any>>, prompter: Inquirerer, _options: CLIOptions) => Promise<{
3
4
  [x: string]: any;
4
5
  } | {
@@ -3,45 +3,50 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createInitUsageText = void 0;
6
7
  const module_1 = __importDefault(require("./module"));
7
8
  const workspace_1 = __importDefault(require("./workspace"));
8
- const initUsageText = `
9
+ const createInitUsageText = (binaryName, productLabel) => {
10
+ const displayName = productLabel ?? binaryName;
11
+ return `
9
12
  Init Command:
10
13
 
11
- pgpm init [OPTIONS]
14
+ ${binaryName} init [OPTIONS] [workspace]
12
15
 
13
- Initialize pgpm workspace or module.
16
+ Initialize ${displayName} workspace or module.
14
17
 
15
18
  Options:
16
19
  --help, -h Show this help message
17
- --workspace Initialize workspace instead of module
18
20
  --cwd <directory> Working directory (default: current directory)
19
- --repo <repo> Use templates from GitHub repository (e.g., owner/repo)
20
- --template-path <path> Use templates from local path
21
- --from-branch <branch> Specify branch when using --repo (default: main)
21
+ --repo <repo> Template repo (default: https://github.com/launchql/pgpm-boilerplates.git)
22
+ --template-path <path> Template sub-path (default: workspace/module) or local path override
23
+ --from-branch <branch> Branch/tag to use when cloning repo
22
24
 
23
25
  Examples:
24
- pgpm init Initialize new module in existing workspace
25
- pgpm init --workspace Initialize new workspace
26
- pgpm init --repo owner/repo Use templates from GitHub repository
27
- pgpm init --template-path ./custom-templates Use templates from local path
28
- pgpm init --repo owner/repo --from-branch develop Use specific branch
26
+ ${binaryName} init Initialize new module in existing workspace
27
+ ${binaryName} init workspace Initialize new workspace
28
+ ${binaryName} init --repo owner/repo Use templates from GitHub repository
29
+ ${binaryName} init --template-path ./custom-templates Use templates from local path
30
+ ${binaryName} init --repo owner/repo --from-branch develop Use specific branch
29
31
  `;
32
+ };
33
+ exports.createInitUsageText = createInitUsageText;
30
34
  exports.default = async (argv, prompter, _options) => {
31
35
  // Show usage if explicitly requested
32
36
  if (argv.help || argv.h) {
33
- console.log(initUsageText);
37
+ console.log((0, exports.createInitUsageText)('pgpm'));
34
38
  process.exit(0);
35
39
  }
36
40
  return handlePromptFlow(argv, prompter);
37
41
  };
38
42
  async function handlePromptFlow(argv, prompter) {
39
- const { workspace } = argv;
40
- switch (workspace) {
41
- case true:
42
- return (0, workspace_1.default)(argv, prompter);
43
- case false:
44
- default:
45
- return (0, module_1.default)(argv, prompter);
43
+ const firstArg = argv._?.[0] || undefined;
44
+ if (firstArg === 'workspace') {
45
+ const nextArgv = {
46
+ ...argv,
47
+ _: (argv._ ?? []).slice(1)
48
+ };
49
+ return (0, workspace_1.default)(nextArgv, prompter);
46
50
  }
51
+ return (0, module_1.default)(argv, prompter);
47
52
  }
@@ -6,7 +6,6 @@ const logger_1 = require("@launchql/logger");
6
6
  const types_1 = require("@launchql/types");
7
7
  const log = new logger_1.Logger('module-init');
8
8
  async function runModuleSetup(argv, prompter) {
9
- const { email, username } = (0, types_1.getGitConfigInfo)();
10
9
  const { cwd = process.cwd() } = argv;
11
10
  const project = new core_1.LaunchQLPackage(cwd);
12
11
  if (!project.workspacePath) {
@@ -20,7 +19,7 @@ async function runModuleSetup(argv, prompter) {
20
19
  const availExtensions = project.getAvailableModules();
21
20
  const moduleQuestions = [
22
21
  {
23
- name: 'MODULENAME',
22
+ name: 'moduleName',
24
23
  message: 'Enter the module name',
25
24
  required: true,
26
25
  type: 'text',
@@ -35,36 +34,31 @@ async function runModuleSetup(argv, prompter) {
35
34
  },
36
35
  ];
37
36
  const answers = await prompter.prompt(argv, moduleQuestions);
38
- const modName = (0, core_1.sluggify)(answers.MODULENAME);
37
+ const modName = (0, core_1.sluggify)(answers.moduleName);
38
+ // Avoid overlapping readline listeners with create-gen-app's prompts.
39
+ prompter.close();
39
40
  const extensions = answers.extensions
40
41
  .filter((opt) => opt.selected)
41
42
  .map((opt) => opt.name);
42
- // Determine template source
43
- let templateSource;
44
- if (argv.repo) {
45
- templateSource = {
46
- type: 'github',
47
- path: argv.repo,
48
- branch: argv.fromBranch
49
- };
50
- log.info(`Loading templates from GitHub repository: ${argv.repo}`);
51
- }
52
- else if (argv.templatePath) {
53
- templateSource = {
54
- type: 'local',
55
- path: argv.templatePath
56
- };
57
- log.info(`Loading templates from local path: ${argv.templatePath}`);
58
- }
59
- project.initModule({
43
+ const templateRepo = argv.repo ?? core_1.DEFAULT_TEMPLATE_REPO;
44
+ const templatePath = argv.templatePath;
45
+ const templateAnswers = {
60
46
  ...argv,
61
47
  ...answers,
48
+ moduleName: modName,
49
+ packageIdentifier: argv.packageIdentifier || modName
50
+ };
51
+ await project.initModule({
62
52
  name: modName,
63
- // @ts-ignore
64
- USERFULLNAME: username,
65
- USEREMAIL: email,
53
+ description: answers.description || modName,
54
+ author: answers.author || modName,
66
55
  extensions,
67
- templateSource
56
+ templateRepo,
57
+ templatePath,
58
+ branch: argv.fromBranch,
59
+ toolName: core_1.DEFAULT_TEMPLATE_TOOL_NAME,
60
+ answers: templateAnswers,
61
+ noTty: Boolean(argv.noTty || argv['no-tty'] || process.env.CI === 'true')
68
62
  });
69
63
  log.success(`Initialized module: ${modName}`);
70
64
  return { ...argv, ...answers };
@@ -6,9 +6,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.default = runWorkspaceSetup;
7
7
  const core_1 = require("@launchql/core");
8
8
  const logger_1 = require("@launchql/logger");
9
- // @ts-ignore - TypeScript module resolution issue with @launchql/templatizer
10
- const templatizer_1 = require("@launchql/templatizer");
11
- const fs_1 = require("fs");
12
9
  const path_1 = __importDefault(require("path"));
13
10
  const log = new logger_1.Logger('workspace-init');
14
11
  async function runWorkspaceSetup(argv, prompter) {
@@ -17,36 +14,35 @@ async function runWorkspaceSetup(argv, prompter) {
17
14
  name: 'name',
18
15
  message: 'Enter workspace name',
19
16
  required: true,
20
- type: 'text',
17
+ type: 'text'
21
18
  }
22
19
  ];
23
20
  const answers = await prompter.prompt(argv, workspaceQuestions);
24
- const { cwd } = argv;
21
+ const { cwd = process.cwd() } = argv;
25
22
  const targetPath = path_1.default.join(cwd, (0, core_1.sluggify)(answers.name));
26
- (0, fs_1.mkdirSync)(targetPath, { recursive: true });
27
- log.success(`Created workspace directory: ${targetPath}`);
28
- // Determine template source
29
- let templates = templatizer_1.workspaceTemplate;
30
- if (argv.repo) {
31
- const source = {
32
- type: 'github',
33
- path: argv.repo,
34
- branch: argv.fromBranch
35
- };
36
- log.info(`Loading templates from GitHub repository: ${argv.repo}`);
37
- const compiledTemplates = (0, templatizer_1.loadTemplates)(source, 'workspace');
38
- templates = compiledTemplates.map((t) => t.render);
39
- }
40
- else if (argv.templatePath) {
41
- const source = {
42
- type: 'local',
43
- path: argv.templatePath
44
- };
45
- log.info(`Loading templates from local path: ${argv.templatePath}`);
46
- const compiledTemplates = (0, templatizer_1.loadTemplates)(source, 'workspace');
47
- templates = compiledTemplates.map((t) => t.render);
48
- }
49
- (0, templatizer_1.writeRenderedTemplates)(templates, targetPath, { ...argv, ...answers });
23
+ // Prevent double-echoed keystrokes by closing our prompter before template prompts.
24
+ prompter.close();
25
+ const templateRepo = argv.repo ?? core_1.DEFAULT_TEMPLATE_REPO;
26
+ const templatePath = argv.templatePath ?? 'workspace';
27
+ const scaffoldResult = await (0, core_1.scaffoldTemplate)({
28
+ type: 'workspace',
29
+ outputDir: targetPath,
30
+ templateRepo,
31
+ branch: argv.fromBranch,
32
+ templatePath,
33
+ answers: {
34
+ ...argv,
35
+ ...answers,
36
+ workspaceName: answers.name
37
+ },
38
+ toolName: core_1.DEFAULT_TEMPLATE_TOOL_NAME,
39
+ noTty: Boolean(argv.noTty || argv['no-tty'] || process.env.CI === 'true'),
40
+ cwd
41
+ });
42
+ const cacheMessage = scaffoldResult.cacheUsed
43
+ ? `Using cached templates from ${scaffoldResult.templateDir}`
44
+ : `Fetched templates into ${scaffoldResult.templateDir}`;
45
+ log.success(cacheMessage);
50
46
  log.success('Workspace templates rendered.');
51
47
  return { ...argv, ...answers, cwd: targetPath };
52
48
  }
@@ -0,0 +1,3 @@
1
+ import { CLIOptions, Inquirerer } from 'inquirerer';
2
+ declare const _default: (argv: Partial<Record<string, any>>, _prompter: Inquirerer, _options: CLIOptions) => Promise<Partial<Record<string, any>>>;
3
+ export default _default;
@@ -0,0 +1,69 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const logger_1 = require("@launchql/logger");
4
+ const child_process_1 = require("child_process");
5
+ const package_1 = require("../package");
6
+ const npm_version_1 = require("../utils/npm-version");
7
+ const cli_error_1 = require("../utils/cli-error");
8
+ const log = new logger_1.Logger('update');
9
+ const updateUsageText = `
10
+ Update Command:
11
+
12
+ pgpm update [OPTIONS]
13
+
14
+ Install the latest version of pgpm from npm.
15
+
16
+ Options:
17
+ --help, -h Show this help message
18
+ --package <name> Override the package name (default: package.json name)
19
+ --registry <url> Use a custom npm registry
20
+ --dry-run Print the npm command without executing it
21
+ `;
22
+ const runNpmInstall = (pkgName, registry) => {
23
+ return new Promise((resolve, reject) => {
24
+ const args = ['install', '-g', pkgName];
25
+ if (registry) {
26
+ args.push('--registry', registry);
27
+ }
28
+ const child = (0, child_process_1.spawn)('npm', args, { stdio: 'inherit' });
29
+ child.on('error', reject);
30
+ child.on('exit', (code) => {
31
+ if (code === 0) {
32
+ resolve();
33
+ }
34
+ else {
35
+ reject(new Error(`npm install exited with code ${code}`));
36
+ }
37
+ });
38
+ });
39
+ };
40
+ exports.default = async (argv, _prompter, _options) => {
41
+ if (argv.help || argv.h) {
42
+ console.log(updateUsageText);
43
+ process.exit(0);
44
+ }
45
+ const pkgJson = (0, package_1.readAndParsePackageJson)();
46
+ const pkgName = argv.package || pkgJson.name || 'pgpm';
47
+ const registry = argv.registry;
48
+ const dryRun = Boolean(argv['dry-run']);
49
+ const npmCommand = `npm install -g ${pkgName}${registry ? ` --registry ${registry}` : ''}`;
50
+ if (dryRun) {
51
+ log.info(`[dry-run] ${npmCommand}`);
52
+ return argv;
53
+ }
54
+ log.info(`Running: ${npmCommand}`);
55
+ try {
56
+ await runNpmInstall(pkgName, registry);
57
+ const latest = await (0, npm_version_1.fetchLatestVersion)(pkgName);
58
+ if (latest) {
59
+ log.success(`Successfully updated ${pkgName} to version ${latest}.`);
60
+ }
61
+ else {
62
+ log.success(`npm install completed for ${pkgName}.`);
63
+ }
64
+ }
65
+ catch (error) {
66
+ await (0, cli_error_1.cliExitWithError)(error instanceof Error ? error.message : String(error), { package: pkgName, registry });
67
+ }
68
+ return argv;
69
+ };
package/commands.js CHANGED
@@ -8,6 +8,7 @@ const pg_cache_1 = require("pg-cache");
8
8
  const add_1 = __importDefault(require("./commands/add"));
9
9
  const admin_users_1 = __importDefault(require("./commands/admin-users"));
10
10
  const analyze_1 = __importDefault(require("./commands/analyze"));
11
+ const cache_1 = __importDefault(require("./commands/cache"));
11
12
  const clear_1 = __importDefault(require("./commands/clear"));
12
13
  const deploy_1 = __importDefault(require("./commands/deploy"));
13
14
  const docker_1 = __importDefault(require("./commands/docker"));
@@ -20,6 +21,7 @@ const kill_1 = __importDefault(require("./commands/kill"));
20
21
  const migrate_1 = __importDefault(require("./commands/migrate"));
21
22
  const package_1 = __importDefault(require("./commands/package"));
22
23
  const plan_1 = __importDefault(require("./commands/plan"));
24
+ const update_1 = __importDefault(require("./commands/update"));
23
25
  const remove_1 = __importDefault(require("./commands/remove"));
24
26
  const rename_1 = __importDefault(require("./commands/rename"));
25
27
  const revert_1 = __importDefault(require("./commands/revert"));
@@ -28,6 +30,7 @@ const verify_1 = __importDefault(require("./commands/verify"));
28
30
  const package_2 = require("./package");
29
31
  const utils_1 = require("./utils");
30
32
  const cli_error_1 = require("./utils/cli-error");
33
+ const update_check_1 = require("./utils/update-check");
31
34
  const withPgTeardown = (fn, skipTeardown = false) => async (...args) => {
32
35
  try {
33
36
  await fn(...args);
@@ -60,7 +63,9 @@ const createPgpmCommandMap = (skipPgTeardown = false) => {
60
63
  install: pgt(install_1.default),
61
64
  migrate: pgt(migrate_1.default),
62
65
  analyze: pgt(analyze_1.default),
63
- rename: pgt(rename_1.default)
66
+ rename: pgt(rename_1.default),
67
+ cache: cache_1.default,
68
+ update: update_1.default
64
69
  };
65
70
  };
66
71
  exports.createPgpmCommandMap = createPgpmCommandMap;
@@ -91,6 +96,15 @@ const commands = async (argv, prompter, options) => {
91
96
  ]);
92
97
  command = answer.command;
93
98
  }
99
+ try {
100
+ await (0, update_check_1.checkForUpdates)({
101
+ command,
102
+ pkgVersion: (0, package_2.readAndParsePackageJson)().version
103
+ });
104
+ }
105
+ catch {
106
+ // ignore update check failures
107
+ }
94
108
  newArgv = await prompter.prompt(newArgv, [
95
109
  {
96
110
  type: 'text',
@@ -0,0 +1,30 @@
1
+ import { Logger } from '@launchql/logger';
2
+ import { CacheManager } from 'create-gen-app';
3
+ import { cliExitWithError } from '../utils/cli-error';
4
+ const log = new Logger('cache');
5
+ const cacheUsageText = `
6
+ Cache Command:
7
+
8
+ pgpm cache clean [OPTIONS]
9
+
10
+ Options:
11
+ --help, -h Show this help message
12
+ --tool <name> Cache namespace to clear (default: pgpm)
13
+ `;
14
+ export default async (argv, _prompter, _options) => {
15
+ if (argv.help || argv.h) {
16
+ console.log(cacheUsageText);
17
+ process.exit(0);
18
+ }
19
+ const action = argv._?.[0] || 'clean';
20
+ if (action !== 'clean') {
21
+ console.log(cacheUsageText);
22
+ await cliExitWithError(`Unknown cache action: ${action}`);
23
+ }
24
+ const toolName = argv.tool || 'pgpm';
25
+ const cacheManager = new CacheManager({ toolName });
26
+ cacheManager.clearAll();
27
+ log.success(`Cleared template cache for "${toolName}".`);
28
+ log.debug(`Cache location: ${cacheManager.getReposDir()}`);
29
+ return argv;
30
+ };
@@ -1,42 +1,45 @@
1
1
  import runModuleSetup from './module';
2
2
  import runWorkspaceSetup from './workspace';
3
- const initUsageText = `
3
+ export const createInitUsageText = (binaryName, productLabel) => {
4
+ const displayName = productLabel ?? binaryName;
5
+ return `
4
6
  Init Command:
5
7
 
6
- pgpm init [OPTIONS]
8
+ ${binaryName} init [OPTIONS] [workspace]
7
9
 
8
- Initialize pgpm workspace or module.
10
+ Initialize ${displayName} workspace or module.
9
11
 
10
12
  Options:
11
13
  --help, -h Show this help message
12
- --workspace Initialize workspace instead of module
13
14
  --cwd <directory> Working directory (default: current directory)
14
- --repo <repo> Use templates from GitHub repository (e.g., owner/repo)
15
- --template-path <path> Use templates from local path
16
- --from-branch <branch> Specify branch when using --repo (default: main)
15
+ --repo <repo> Template repo (default: https://github.com/launchql/pgpm-boilerplates.git)
16
+ --template-path <path> Template sub-path (default: workspace/module) or local path override
17
+ --from-branch <branch> Branch/tag to use when cloning repo
17
18
 
18
19
  Examples:
19
- pgpm init Initialize new module in existing workspace
20
- pgpm init --workspace Initialize new workspace
21
- pgpm init --repo owner/repo Use templates from GitHub repository
22
- pgpm init --template-path ./custom-templates Use templates from local path
23
- pgpm init --repo owner/repo --from-branch develop Use specific branch
20
+ ${binaryName} init Initialize new module in existing workspace
21
+ ${binaryName} init workspace Initialize new workspace
22
+ ${binaryName} init --repo owner/repo Use templates from GitHub repository
23
+ ${binaryName} init --template-path ./custom-templates Use templates from local path
24
+ ${binaryName} init --repo owner/repo --from-branch develop Use specific branch
24
25
  `;
26
+ };
25
27
  export default async (argv, prompter, _options) => {
26
28
  // Show usage if explicitly requested
27
29
  if (argv.help || argv.h) {
28
- console.log(initUsageText);
30
+ console.log(createInitUsageText('pgpm'));
29
31
  process.exit(0);
30
32
  }
31
33
  return handlePromptFlow(argv, prompter);
32
34
  };
33
35
  async function handlePromptFlow(argv, prompter) {
34
- const { workspace } = argv;
35
- switch (workspace) {
36
- case true:
37
- return runWorkspaceSetup(argv, prompter);
38
- case false:
39
- default:
40
- return runModuleSetup(argv, prompter);
36
+ const firstArg = argv._?.[0] || undefined;
37
+ if (firstArg === 'workspace') {
38
+ const nextArgv = {
39
+ ...argv,
40
+ _: (argv._ ?? []).slice(1)
41
+ };
42
+ return runWorkspaceSetup(nextArgv, prompter);
41
43
  }
44
+ return runModuleSetup(argv, prompter);
42
45
  }
@@ -1,9 +1,8 @@
1
- import { LaunchQLPackage, sluggify } from '@launchql/core';
1
+ import { DEFAULT_TEMPLATE_REPO, DEFAULT_TEMPLATE_TOOL_NAME, LaunchQLPackage, sluggify } from '@launchql/core';
2
2
  import { Logger } from '@launchql/logger';
3
- import { errors, getGitConfigInfo } from '@launchql/types';
3
+ import { errors } from '@launchql/types';
4
4
  const log = new Logger('module-init');
5
5
  export default async function runModuleSetup(argv, prompter) {
6
- const { email, username } = getGitConfigInfo();
7
6
  const { cwd = process.cwd() } = argv;
8
7
  const project = new LaunchQLPackage(cwd);
9
8
  if (!project.workspacePath) {
@@ -17,7 +16,7 @@ export default async function runModuleSetup(argv, prompter) {
17
16
  const availExtensions = project.getAvailableModules();
18
17
  const moduleQuestions = [
19
18
  {
20
- name: 'MODULENAME',
19
+ name: 'moduleName',
21
20
  message: 'Enter the module name',
22
21
  required: true,
23
22
  type: 'text',
@@ -32,36 +31,31 @@ export default async function runModuleSetup(argv, prompter) {
32
31
  },
33
32
  ];
34
33
  const answers = await prompter.prompt(argv, moduleQuestions);
35
- const modName = sluggify(answers.MODULENAME);
34
+ const modName = sluggify(answers.moduleName);
35
+ // Avoid overlapping readline listeners with create-gen-app's prompts.
36
+ prompter.close();
36
37
  const extensions = answers.extensions
37
38
  .filter((opt) => opt.selected)
38
39
  .map((opt) => opt.name);
39
- // Determine template source
40
- let templateSource;
41
- if (argv.repo) {
42
- templateSource = {
43
- type: 'github',
44
- path: argv.repo,
45
- branch: argv.fromBranch
46
- };
47
- log.info(`Loading templates from GitHub repository: ${argv.repo}`);
48
- }
49
- else if (argv.templatePath) {
50
- templateSource = {
51
- type: 'local',
52
- path: argv.templatePath
53
- };
54
- log.info(`Loading templates from local path: ${argv.templatePath}`);
55
- }
56
- project.initModule({
40
+ const templateRepo = argv.repo ?? DEFAULT_TEMPLATE_REPO;
41
+ const templatePath = argv.templatePath;
42
+ const templateAnswers = {
57
43
  ...argv,
58
44
  ...answers,
45
+ moduleName: modName,
46
+ packageIdentifier: argv.packageIdentifier || modName
47
+ };
48
+ await project.initModule({
59
49
  name: modName,
60
- // @ts-ignore
61
- USERFULLNAME: username,
62
- USEREMAIL: email,
50
+ description: answers.description || modName,
51
+ author: answers.author || modName,
63
52
  extensions,
64
- templateSource
53
+ templateRepo,
54
+ templatePath,
55
+ branch: argv.fromBranch,
56
+ toolName: DEFAULT_TEMPLATE_TOOL_NAME,
57
+ answers: templateAnswers,
58
+ noTty: Boolean(argv.noTty || argv['no-tty'] || process.env.CI === 'true')
65
59
  });
66
60
  log.success(`Initialized module: ${modName}`);
67
61
  return { ...argv, ...answers };