Skip to content

Commit f5109d7

Browse files
committed
Title: Add workspace resolvers for boilerplate defaults
add workspace.name, workspace.organization.name, and workspace.license resolvers using repo URL/pkg license fallback ensure workspace name prefers repo slug with package name fallback expand resolver and setFrom tests to cover new workspace keys document workspace resolver list in README
1 parent b22eaa5 commit f5109d7

File tree

4 files changed

+90
-1
lines changed

4 files changed

+90
-1
lines changed

packages/inquirerer/README.md

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -747,6 +747,19 @@ Inquirerer comes with several built-in resolvers ready to use:
747747
| `date.now` | ISO timestamp | `"2025-11-23T15:30:45.123Z"` |
748748
| `date.timestamp` | Unix timestamp (ms) | `"1732375845123"` |
749749

750+
#### Workspace (nearest package.json)
751+
752+
| Resolver | Description | Example Output |
753+
|----------|-------------|----------------|
754+
| `workspace.name` | Repo slug from `repository` URL (fallback: `package.json` `name`) | `"dev-utils"` |
755+
| `workspace.repo.name` | Repo name from `repository` URL | `"dev-utils"` |
756+
| `workspace.repo.organization` | Repo org/owner from `repository` URL | `"constructive-io"` |
757+
| `workspace.organization.name` | Alias for `workspace.repo.organization` | `"constructive-io"` |
758+
| `workspace.license` | License field from `package.json` | `"MIT"` |
759+
| `workspace.author` | Author name from `package.json` | `"Constructive"` |
760+
| `workspace.author.name` | Author name from `package.json` | `"Constructive"` |
761+
| `workspace.author.email` | Author email from `package.json` | `"[email protected]"` |
762+
750763
### Priority Order
751764

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

10481061
const cli = new CLI(handler, options);
10491062
await cli.run();
1050-
```
1063+
```

packages/inquirerer/__tests__/resolvers.test.ts

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,13 +499,23 @@ describe('Debug Mode', () => {
499499

500500
describe('Workspace Resolvers', () => {
501501
it('should have workspace resolvers registered by default', () => {
502+
expect(globalResolverRegistry.has('workspace.name')).toBe(true);
502503
expect(globalResolverRegistry.has('workspace.repo.name')).toBe(true);
503504
expect(globalResolverRegistry.has('workspace.repo.organization')).toBe(true);
505+
expect(globalResolverRegistry.has('workspace.organization.name')).toBe(true);
506+
expect(globalResolverRegistry.has('workspace.license')).toBe(true);
504507
expect(globalResolverRegistry.has('workspace.author')).toBe(true);
505508
expect(globalResolverRegistry.has('workspace.author.name')).toBe(true);
506509
expect(globalResolverRegistry.has('workspace.author.email')).toBe(true);
507510
});
508511

512+
it('should resolve workspace.name preferring repo name', async () => {
513+
const result = await globalResolverRegistry.resolve('workspace.name');
514+
515+
// Repository slug of dev-utils package
516+
expect(result).toBe('dev-utils');
517+
});
518+
509519
it('should resolve workspace.repo.name from package.json', async () => {
510520
// This test runs from the dev-utils directory which has a package.json with repository
511521
const result = await globalResolverRegistry.resolve('workspace.repo.name');
@@ -520,6 +530,18 @@ describe('Workspace Resolvers', () => {
520530
expect(result).toBe('constructive-io');
521531
});
522532

533+
it('should resolve workspace.organization.name from package.json', async () => {
534+
const result = await globalResolverRegistry.resolve('workspace.organization.name');
535+
536+
expect(result).toBe('constructive-io');
537+
});
538+
539+
it('should resolve workspace.license from package.json', async () => {
540+
const result = await globalResolverRegistry.resolve('workspace.license');
541+
542+
expect(result).toBe('MIT');
543+
});
544+
523545
it('should resolve workspace.author from package.json', async () => {
524546
const result = await globalResolverRegistry.resolve('workspace.author');
525547

packages/inquirerer/__tests__/setFrom.test.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,34 @@ describe('Inquirerer - setFrom feature', () => {
149149

150150
expect(result).toEqual({ year: '1967' });
151151
});
152+
153+
it('should use workspace resolvers with setFrom', async () => {
154+
const prompter = new Inquirerer({
155+
input: mockInput,
156+
output: mockOutput,
157+
noTty: true
158+
});
159+
160+
const questions: Question[] = [
161+
{
162+
name: 'repoName',
163+
type: 'text',
164+
setFrom: 'workspace.name'
165+
},
166+
{
167+
name: 'license',
168+
type: 'text',
169+
setFrom: 'workspace.license'
170+
}
171+
];
172+
173+
const result = await prompter.prompt({}, questions);
174+
175+
expect(result).toEqual({
176+
repoName: 'dev-utils',
177+
license: 'MIT'
178+
});
179+
});
152180
});
153181

154182
describe('setFrom vs defaultFrom behavior', () => {

packages/inquirerer/src/resolvers/workspace.ts

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,18 @@ function parseAuthor(author: string | { name?: string; email?: string; url?: str
8888
* These resolve values from the nearest package.json in the current working directory.
8989
*/
9090
export const workspaceResolvers: ResolverRegistry = {
91+
'workspace.name': () => {
92+
const pkg = findPackageJsonFromCwd();
93+
if (!pkg) return undefined;
94+
const url = getRepositoryUrl(pkg);
95+
// Prefer repo slug when repository is set; fall back to package name
96+
if (url) {
97+
const parsed = parseGitHubUrl(url);
98+
if (parsed.name) return parsed.name;
99+
}
100+
return pkg.name;
101+
},
102+
91103
'workspace.repo.name': () => {
92104
const pkg = findPackageJsonFromCwd();
93105
if (!pkg) return undefined;
@@ -104,6 +116,20 @@ export const workspaceResolvers: ResolverRegistry = {
104116
return parseGitHubUrl(url).organization;
105117
},
106118

119+
// Alias for repo.organization for template readability
120+
'workspace.organization.name': () => {
121+
const pkg = findPackageJsonFromCwd();
122+
if (!pkg) return undefined;
123+
const url = getRepositoryUrl(pkg);
124+
if (!url) return undefined;
125+
return parseGitHubUrl(url).organization;
126+
},
127+
128+
'workspace.license': () => {
129+
const pkg = findPackageJsonFromCwd();
130+
return pkg?.license;
131+
},
132+
107133
'workspace.author': () => {
108134
const pkg = findPackageJsonFromCwd();
109135
if (!pkg) return undefined;

0 commit comments

Comments
 (0)