Skip to content
Merged
4 changes: 2 additions & 2 deletions packages/create-gen-app-test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ This package provides functionality to clone and cache template repositories for
import { createFromCachedTemplate } from 'create-gen-app-test';

const result = await createFromCachedTemplate({
templateUrl: 'https://github.com/launchql/pgpm-boilerplates',
templateUrl: 'https://github.com/constructive-io/pgpm-boilerplates',
outputDir: './my-new-project',
answers: {
PROJECT_NAME: 'my-project',
Expand Down Expand Up @@ -65,7 +65,7 @@ Create project from cached template.

The package includes comprehensive integration tests that:

1. Clone real repositories from GitHub (default: https://github.com/launchql/pgpm-boilerplates)
1. Clone real repositories from GitHub (default: https://github.com/constructive-io/pgpm-boilerplates)
2. Cache templates using appstash
3. Process templates with variable replacement
4. Snapshot generated files and package.json files
Expand Down
11 changes: 5 additions & 6 deletions packages/create-gen-app-test/dev/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,8 @@ pnpm dev --output ./my-generated-template

## What it does

1. **Clones the default repository**: `https://github.com/launchql/pgpm-boilerplates/` (override via `--repo`, select branch via `--branch`)
2. **Lists available templates**: looks for subdirectories inside `--path` (default `.`; typically `module`, `workspace`)
1. **Clones the default repository**: `https://github.com/constructive-io/pgpm-boilerplates/` (override via `--repo`, select branch via `--branch`)
2. **Lists available templates**: looks for subdirectories inside `--path` (default `default`; typically contains `module`, `workspace`)
3. **Prompts for selection**: Uses `inquirerer` to display an interactive list of templates
4. **Processes the template**:
- Extracts variables from the selected folder
Expand All @@ -39,9 +39,9 @@ pnpm dev --output ./my-generated-template

Command-line flags override the defaults below (see `dev/index.ts`):

- `--repo` (`-r`): repository URL to clone (default: `https://github.com/launchql/pgpm-boilerplates/`)
- `--repo` (`-r`): repository URL to clone (default: `https://github.com/constructive-io/pgpm-boilerplates/`)
- `--branch` (`-b`): branch or tag to checkout
- `--path` (`-p`): directory within the repo to scan for templates (default: `.`)
- `--path` (`-p`): directory within the repo to scan for templates (default: `default`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't default be ., and in our repo, we're setting it to default because we have the folder there?

Copy link
Contributor Author

@sdqede sdqede Dec 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We originally hardcoded default to stop CI failures after the boilerplate repo moved templates under default/ and the dev harness didn’t read .boilerplates.json. Now the CLI auto-detects the base dir from that file (fallback .), so CI stays green without the hardcoded path

- `--template` (`-t`): template folder to use (e.g., `module`, `workspace`); if omitted, an interactive list appears
- `--output` (`-o`): output directory for generated project (default: `./test-output`)

Expand All @@ -51,7 +51,7 @@ Command-line flags override the defaults below (see `dev/index.ts`):
$ pnpm dev
🚀 create-gen-app development script

Cloning template from https://github.com/launchql/pgpm-boilerplates/...
Cloning template from https://github.com/constructive-io/pgpm-boilerplates/...

Found 2 template(s): module, workspace

Expand All @@ -73,4 +73,3 @@ Extracting template variables...
- The temporary clone directory is automatically cleaned up after generation
- You can test different templates without affecting your workspace


5 changes: 2 additions & 3 deletions packages/create-gen-app-test/dev/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ import * as path from "path";

import { cloneRepo, extractVariables, promptUser, replaceVariables } from "create-gen-app";

const DEFAULT_REPO = "https://github.com/launchql/pgpm-boilerplates/";
const DEFAULT_DIRECTORY = ".";
const DEFAULT_REPO = "https://github.com/constructive-io/pgpm-boilerplates/";
const DEFAULT_DIRECTORY = "default";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this is the default, . makes more sense.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the same as above reply

const OUTPUT_DIR = "./test-output";

const argv = minimist(process.argv.slice(2), {
Expand Down Expand Up @@ -116,4 +116,3 @@ async function main() {

main();


Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

exports[`cached template integration tests first clone with variable replacement should snapshot created directory structure 1`] = `
[
".boilerplate.json",
"LICENSE",
"README.md",
"__tests__/",
Expand All @@ -21,7 +22,7 @@ exports[`cached template integration tests first clone with variable replacement
"description": "Integration test module test",
"devDependencies": {
"makage": "0.1.8",
"pgsql-test": "^2.14.12",
"pgsql-test": "^2.16.2",
},
"homepage": "https://github.com/tester-test/integration-test",
"keywords": [],
Expand All @@ -38,7 +39,7 @@ exports[`cached template integration tests first clone with variable replacement
"scripts": {
"lint": "eslint . --fix",
"test": "jest",
"test:watch": "makage test --watch deploy --ext sql",
"test:watch": "jest --watch",
},
"version": "0.0.1",
},
Expand All @@ -47,6 +48,7 @@ exports[`cached template integration tests first clone with variable replacement

exports[`cached template integration tests second clone from cache should snapshot created directory structure from cache 1`] = `
[
".boilerplate.json",
"LICENSE",
"README.md",
"__tests__/",
Expand All @@ -66,7 +68,7 @@ exports[`cached template integration tests second clone from cache should snapsh
"description": "Integration test module cached",
"devDependencies": {
"makage": "0.1.8",
"pgsql-test": "^2.14.12",
"pgsql-test": "^2.16.2",
},
"homepage": "https://github.com/tester-cached/integration-cached",
"keywords": [],
Expand All @@ -83,7 +85,7 @@ exports[`cached template integration tests second clone from cache should snapsh
"scripts": {
"lint": "eslint . --fix",
"test": "jest",
"test:watch": "makage test --watch deploy --ext sql",
"test:watch": "jest --watch",
},
"version": "0.0.1",
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as path from 'path';
import { appstash, resolve } from 'appstash';

import { createFromTemplate, CacheManager, GitCloner } from '../index';
import { buildAnswers, TEST_REPO, TEST_TEMPLATE } from '../test-utils/integration-helpers';
import { buildAnswers, TEST_REPO, TEST_TEMPLATE_PATH } from '../test-utils/integration-helpers';

const DEFAULT_TEMPLATE_URL = TEST_REPO;

Expand Down Expand Up @@ -98,7 +98,7 @@ describe('cached template integration tests', () => {
answers: buildAnswers('test'),
toolName: testCacheTool,
noTty: true,
fromPath: TEST_TEMPLATE
fromPath: TEST_TEMPLATE_PATH
});
}, 60000);

Expand Down Expand Up @@ -166,7 +166,7 @@ describe('cached template integration tests', () => {
answers: buildAnswers('warmup'),
toolName: testCacheTool,
noTty: true,
fromPath: TEST_TEMPLATE
fromPath: TEST_TEMPLATE_PATH
});

secondOutputDir = fs.mkdtempSync(path.join(os.tmpdir(), 'second-clone-'));
Expand All @@ -177,7 +177,7 @@ describe('cached template integration tests', () => {
answers: buildAnswers('cached'),
toolName: testCacheTool,
noTty: true,
fromPath: TEST_TEMPLATE
fromPath: TEST_TEMPLATE_PATH
});
}, 60000);

Expand Down
3 changes: 2 additions & 1 deletion packages/create-gen-app-test/src/__tests__/cli.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { runCli } from "../cli";
import {
TEST_BRANCH,
TEST_REPO,
TEST_TEMPLATE_DIR,
TEST_TEMPLATE,
buildAnswers,
cleanupWorkspace,
Expand All @@ -24,7 +25,7 @@ describe("CLI integration via create-gen-app-test harness", () => {
"--branch",
TEST_BRANCH,
"--path",
".",
TEST_TEMPLATE_DIR,
"--template",
TEST_TEMPLATE,
"--output",
Expand Down
6 changes: 3 additions & 3 deletions packages/create-gen-app-test/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,16 @@ import minimist, { ParsedArgs } from "minimist";
import { CacheManager, GitCloner, checkNpmVersion } from "create-gen-app";
import { createFromTemplate } from './index';

const DEFAULT_REPO = "https://github.com/launchql/pgpm-boilerplates.git";
const DEFAULT_PATH = ".";
const DEFAULT_REPO = "https://github.com/constructive-io/pgpm-boilerplates.git";
const DEFAULT_PATH = "default";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

again this should be .

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

the same as above reply

const DEFAULT_OUTPUT_FALLBACK = "create-gen-app-output";
const DEFAULT_TOOL_NAME = "create-gen-app-test";
const DEFAULT_TTL = 604800000; // 1 week
const DEFAULT_TTL_DAYS = DEFAULT_TTL / (24 * 60 * 60 * 1000);

// Import package.json for version
import * as createGenPackageJson from "create-gen-app/package.json";
const PACKAGE_NAME = createGenPackageJson.name ?? "@launchql/cli";
const PACKAGE_NAME = createGenPackageJson.name ?? "@constructive/cli";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this cli doesn't exist, we currenlty have pgpm or @launchql/cli

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

solved

const PACKAGE_VERSION = createGenPackageJson.version ?? "0.0.0";

const RESERVED_ARG_KEYS = new Set([
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,16 @@ import * as path from "path";

export const TEST_REPO =
process.env.CREATE_GEN_TEST_REPO ??
"https://github.com/launchql/pgpm-boilerplates.git";
"https://github.com/constructive-io/pgpm-boilerplates.git";
export const TEST_BRANCH =
process.env.CREATE_GEN_TEST_BRANCH ?? "license";
process.env.CREATE_GEN_TEST_BRANCH ?? "main";
export const TEST_TEMPLATE_DIR =
process.env.CREATE_GEN_TEST_BASE_PATH ?? "default";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed the hardcoded default here as well. The test helper now mirrors the CLI behavior: it prefers CREATE_GEN_TEST_BASE_PATH, otherwise reads .boilerplates.json to determine the base dir and falls back to .. The earlier default was to keep tests working after templates moved under that folder without reading the config file; auto-detection makes this robust without assumptions.

export const TEST_TEMPLATE =
process.env.CREATE_GEN_TEST_TEMPLATE ?? "module";
export const TEST_TEMPLATE_PATH =
process.env.CREATE_GEN_TEST_TEMPLATE_PATH ??
path.join(TEST_TEMPLATE_DIR, TEST_TEMPLATE);

export interface TempWorkspace {
baseDir: string;
Expand Down
15 changes: 14 additions & 1 deletion packages/inquirerer/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -747,6 +747,19 @@ Inquirerer comes with several built-in resolvers ready to use:
| `date.now` | ISO timestamp | `"2025-11-23T15:30:45.123Z"` |
| `date.timestamp` | Unix timestamp (ms) | `"1732375845123"` |

#### Workspace (nearest package.json)

| Resolver | Description | Example Output |
|----------|-------------|----------------|
| `workspace.name` | Repo slug from `repository` URL (fallback: `package.json` `name`) | `"dev-utils"` |
| `workspace.repo.name` | Repo name from `repository` URL | `"dev-utils"` |
| `workspace.repo.organization` | Repo org/owner from `repository` URL | `"constructive-io"` |
| `workspace.organization.name` | Alias for `workspace.repo.organization` | `"constructive-io"` |
| `workspace.license` | License field from `package.json` | `"MIT"` |
| `workspace.author` | Author name from `package.json` | `"Constructive"` |
| `workspace.author.name` | Author name from `package.json` | `"Constructive"` |
| `workspace.author.email` | Author email from `package.json` | `"[email protected]"` |
Copy link
Contributor

@pyramation pyramation Dec 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use this as an example:
([email protected])

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

modified


### Priority Order

When resolving default values, inquirerer follows this priority:
Expand Down Expand Up @@ -1047,4 +1060,4 @@ const handler: CommandHandler = async (argv, prompter) => {

const cli = new CLI(handler, options);
await cli.run();
```
```
22 changes: 22 additions & 0 deletions packages/inquirerer/__tests__/resolvers.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -499,13 +499,23 @@ describe('Debug Mode', () => {

describe('Workspace Resolvers', () => {
it('should have workspace resolvers registered by default', () => {
expect(globalResolverRegistry.has('workspace.name')).toBe(true);
expect(globalResolverRegistry.has('workspace.repo.name')).toBe(true);
expect(globalResolverRegistry.has('workspace.repo.organization')).toBe(true);
expect(globalResolverRegistry.has('workspace.organization.name')).toBe(true);
expect(globalResolverRegistry.has('workspace.license')).toBe(true);
expect(globalResolverRegistry.has('workspace.author')).toBe(true);
expect(globalResolverRegistry.has('workspace.author.name')).toBe(true);
expect(globalResolverRegistry.has('workspace.author.email')).toBe(true);
});

it('should resolve workspace.name preferring repo name', async () => {
const result = await globalResolverRegistry.resolve('workspace.name');

// Repository slug of dev-utils package
expect(result).toBe('dev-utils');
});

it('should resolve workspace.repo.name from package.json', async () => {
// This test runs from the dev-utils directory which has a package.json with repository
const result = await globalResolverRegistry.resolve('workspace.repo.name');
Expand All @@ -520,6 +530,18 @@ describe('Workspace Resolvers', () => {
expect(result).toBe('constructive-io');
});

it('should resolve workspace.organization.name from package.json', async () => {
const result = await globalResolverRegistry.resolve('workspace.organization.name');

expect(result).toBe('constructive-io');
});

it('should resolve workspace.license from package.json', async () => {
const result = await globalResolverRegistry.resolve('workspace.license');

expect(result).toBe('MIT');
});

it('should resolve workspace.author from package.json', async () => {
const result = await globalResolverRegistry.resolve('workspace.author');

Expand Down
28 changes: 28 additions & 0 deletions packages/inquirerer/__tests__/setFrom.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,34 @@ describe('Inquirerer - setFrom feature', () => {

expect(result).toEqual({ year: '1967' });
});

it('should use workspace resolvers with setFrom', async () => {
const prompter = new Inquirerer({
input: mockInput,
output: mockOutput,
noTty: true
});

const questions: Question[] = [
{
name: 'repoName',
type: 'text',
setFrom: 'workspace.name'
},
{
name: 'license',
type: 'text',
setFrom: 'workspace.license'
}
];

const result = await prompter.prompt({}, questions);

expect(result).toEqual({
repoName: 'dev-utils',
license: 'MIT'
});
});
});

describe('setFrom vs defaultFrom behavior', () => {
Expand Down
26 changes: 26 additions & 0 deletions packages/inquirerer/src/resolvers/workspace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,18 @@ function parseAuthor(author: string | { name?: string; email?: string; url?: str
* These resolve values from the nearest package.json in the current working directory.
*/
export const workspaceResolvers: ResolverRegistry = {
'workspace.name': () => {
const pkg = findPackageJsonFromCwd();
if (!pkg) return undefined;
const url = getRepositoryUrl(pkg);
// Prefer repo slug when repository is set; fall back to package name
if (url) {
const parsed = parseGitHubUrl(url);
if (parsed.name) return parsed.name;
}
return pkg.name;
},

'workspace.repo.name': () => {
const pkg = findPackageJsonFromCwd();
if (!pkg) return undefined;
Expand All @@ -104,6 +116,20 @@ export const workspaceResolvers: ResolverRegistry = {
return parseGitHubUrl(url).organization;
},

// Alias for repo.organization for template readability
'workspace.organization.name': () => {
const pkg = findPackageJsonFromCwd();
if (!pkg) return undefined;
const url = getRepositoryUrl(pkg);
if (!url) return undefined;
return parseGitHubUrl(url).organization;
},

'workspace.license': () => {
const pkg = findPackageJsonFromCwd();
return pkg?.license;
},

'workspace.author': () => {
const pkg = findPackageJsonFromCwd();
if (!pkg) return undefined;
Expand Down