genomic 4.0.2 → 5.0.1

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.
Files changed (92) hide show
  1. package/README.md +154 -1125
  2. package/cache/cache-manager.d.ts +60 -0
  3. package/cache/cache-manager.js +228 -0
  4. package/cache/types.d.ts +22 -0
  5. package/esm/cache/cache-manager.js +191 -0
  6. package/esm/git/git-cloner.js +92 -0
  7. package/esm/index.js +41 -4
  8. package/esm/licenses.js +120 -0
  9. package/esm/scaffolder/index.js +2 -0
  10. package/esm/scaffolder/template-scaffolder.js +310 -0
  11. package/esm/scaffolder/types.js +1 -0
  12. package/esm/template/extract.js +162 -0
  13. package/esm/template/prompt.js +103 -0
  14. package/esm/template/replace.js +110 -0
  15. package/esm/template/templatizer.js +73 -0
  16. package/esm/template/types.js +1 -0
  17. package/esm/types.js +1 -0
  18. package/esm/utils/npm-version-check.js +52 -0
  19. package/esm/utils/types.js +1 -0
  20. package/git/git-cloner.d.ts +32 -0
  21. package/git/git-cloner.js +129 -0
  22. package/git/types.d.ts +15 -0
  23. package/index.d.ts +29 -4
  24. package/index.js +43 -4
  25. package/licenses-templates/APACHE-2.0.txt +18 -0
  26. package/licenses-templates/BSD-3-CLAUSE.txt +28 -0
  27. package/licenses-templates/CLOSED.txt +20 -0
  28. package/licenses-templates/GPL-3.0.txt +18 -0
  29. package/licenses-templates/ISC.txt +16 -0
  30. package/licenses-templates/MIT.txt +22 -0
  31. package/licenses-templates/MPL-2.0.txt +8 -0
  32. package/licenses-templates/UNLICENSE.txt +22 -0
  33. package/licenses.d.ts +18 -0
  34. package/licenses.js +162 -0
  35. package/package.json +9 -14
  36. package/scaffolder/index.d.ts +2 -0
  37. package/{question → scaffolder}/index.js +1 -0
  38. package/scaffolder/template-scaffolder.d.ts +91 -0
  39. package/scaffolder/template-scaffolder.js +347 -0
  40. package/scaffolder/types.d.ts +191 -0
  41. package/scaffolder/types.js +2 -0
  42. package/template/extract.d.ts +7 -0
  43. package/template/extract.js +198 -0
  44. package/template/prompt.d.ts +19 -0
  45. package/template/prompt.js +107 -0
  46. package/template/replace.d.ts +9 -0
  47. package/template/replace.js +146 -0
  48. package/template/templatizer.d.ts +33 -0
  49. package/template/templatizer.js +110 -0
  50. package/template/types.d.ts +18 -0
  51. package/template/types.js +2 -0
  52. package/types.d.ts +99 -0
  53. package/types.js +2 -0
  54. package/utils/npm-version-check.d.ts +17 -0
  55. package/utils/npm-version-check.js +57 -0
  56. package/utils/types.d.ts +6 -0
  57. package/utils/types.js +2 -0
  58. package/commander.d.ts +0 -21
  59. package/commander.js +0 -57
  60. package/esm/commander.js +0 -50
  61. package/esm/keypress.js +0 -95
  62. package/esm/prompt.js +0 -1024
  63. package/esm/question/index.js +0 -1
  64. package/esm/resolvers/date.js +0 -11
  65. package/esm/resolvers/git.js +0 -26
  66. package/esm/resolvers/index.js +0 -103
  67. package/esm/resolvers/npm.js +0 -24
  68. package/esm/resolvers/workspace.js +0 -141
  69. package/esm/utils.js +0 -12
  70. package/keypress.d.ts +0 -45
  71. package/keypress.js +0 -99
  72. package/prompt.d.ts +0 -116
  73. package/prompt.js +0 -1032
  74. package/question/index.d.ts +0 -1
  75. package/question/types.d.ts +0 -65
  76. package/resolvers/date.d.ts +0 -5
  77. package/resolvers/date.js +0 -14
  78. package/resolvers/git.d.ts +0 -11
  79. package/resolvers/git.js +0 -30
  80. package/resolvers/index.d.ts +0 -63
  81. package/resolvers/index.js +0 -111
  82. package/resolvers/npm.d.ts +0 -10
  83. package/resolvers/npm.js +0 -28
  84. package/resolvers/types.d.ts +0 -12
  85. package/resolvers/workspace.d.ts +0 -6
  86. package/resolvers/workspace.js +0 -144
  87. package/utils.d.ts +0 -2
  88. package/utils.js +0 -16
  89. /package/{question → cache}/types.js +0 -0
  90. /package/esm/{question → cache}/types.js +0 -0
  91. /package/esm/{resolvers → git}/types.js +0 -0
  92. /package/{resolvers → git}/types.js +0 -0
@@ -0,0 +1,347 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.TemplateScaffolder = void 0;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ const cache_manager_1 = require("../cache/cache-manager");
40
+ const git_cloner_1 = require("../git/git-cloner");
41
+ const templatizer_1 = require("../template/templatizer");
42
+ /**
43
+ * High-level orchestrator for template scaffolding operations.
44
+ * Combines CacheManager, GitCloner, and Templatizer into a single, easy-to-use API.
45
+ *
46
+ * @example
47
+ * ```typescript
48
+ * const scaffolder = new TemplateScaffolder({
49
+ * toolName: 'my-cli',
50
+ * defaultRepo: 'https://github.com/org/templates.git',
51
+ * ttlMs: 7 * 24 * 60 * 60 * 1000, // 1 week
52
+ * });
53
+ *
54
+ * await scaffolder.scaffold({
55
+ * outputDir: './my-project',
56
+ * fromPath: 'starter',
57
+ * answers: { name: 'my-project' },
58
+ * });
59
+ * ```
60
+ */
61
+ class TemplateScaffolder {
62
+ config;
63
+ cacheManager;
64
+ gitCloner;
65
+ templatizer;
66
+ constructor(config) {
67
+ if (!config.toolName) {
68
+ throw new Error('TemplateScaffolder requires toolName in config');
69
+ }
70
+ this.config = config;
71
+ this.cacheManager = new cache_manager_1.CacheManager({
72
+ toolName: config.toolName,
73
+ ttl: config.ttlMs,
74
+ baseDir: config.cacheBaseDir,
75
+ });
76
+ this.gitCloner = new git_cloner_1.GitCloner();
77
+ this.templatizer = new templatizer_1.Templatizer();
78
+ }
79
+ /**
80
+ * Scaffold a new project from a template.
81
+ *
82
+ * Handles both local directories and remote git repositories.
83
+ * For remote repos, caching is used to avoid repeated cloning.
84
+ *
85
+ * @param options - Scaffold options
86
+ * @returns Scaffold result with output path and metadata
87
+ */
88
+ async scaffold(options) {
89
+ const template = options.template ?? this.config.defaultRepo;
90
+ if (!template) {
91
+ throw new Error('No template specified and no defaultRepo configured. ' +
92
+ 'Either pass template in options or set defaultRepo in config.');
93
+ }
94
+ const branch = options.branch ?? this.config.defaultBranch;
95
+ const resolvedTemplate = this.resolveTemplatePath(template);
96
+ if (this.isLocalPath(resolvedTemplate) && fs.existsSync(resolvedTemplate)) {
97
+ return this.scaffoldFromLocal(resolvedTemplate, options);
98
+ }
99
+ return this.scaffoldFromRemote(resolvedTemplate, branch, options);
100
+ }
101
+ /**
102
+ * Inspect a template without scaffolding.
103
+ * Clones/caches the template and reads its .boilerplate.json configuration
104
+ * without copying any files to an output directory.
105
+ *
106
+ * This is useful for metadata-driven workflows where you need to know
107
+ * the template's type or other configuration before deciding how to handle it.
108
+ *
109
+ * @param options - Inspect options
110
+ * @returns Inspect result with template metadata
111
+ */
112
+ inspect(options) {
113
+ const template = options.template ?? this.config.defaultRepo;
114
+ if (!template) {
115
+ throw new Error('No template specified and no defaultRepo configured. ' +
116
+ 'Either pass template in options or set defaultRepo in config.');
117
+ }
118
+ const branch = options.branch ?? this.config.defaultBranch;
119
+ const resolvedTemplate = this.resolveTemplatePath(template);
120
+ const useBoilerplatesConfig = options.useBoilerplatesConfig ?? true;
121
+ if (this.isLocalPath(resolvedTemplate) && fs.existsSync(resolvedTemplate)) {
122
+ return this.inspectLocal(resolvedTemplate, options.fromPath, useBoilerplatesConfig);
123
+ }
124
+ return this.inspectRemote(resolvedTemplate, branch, options.fromPath, useBoilerplatesConfig);
125
+ }
126
+ /**
127
+ * Read the .boilerplates.json configuration from a template repository root.
128
+ */
129
+ readBoilerplatesConfig(templateDir) {
130
+ const configPath = path.join(templateDir, '.boilerplates.json');
131
+ if (fs.existsSync(configPath)) {
132
+ try {
133
+ const content = fs.readFileSync(configPath, 'utf-8');
134
+ return JSON.parse(content);
135
+ }
136
+ catch {
137
+ return null;
138
+ }
139
+ }
140
+ return null;
141
+ }
142
+ /**
143
+ * Read the .boilerplate.json configuration from a boilerplate directory.
144
+ */
145
+ readBoilerplateConfig(boilerplatePath) {
146
+ const jsonPath = path.join(boilerplatePath, '.boilerplate.json');
147
+ if (fs.existsSync(jsonPath)) {
148
+ try {
149
+ const content = fs.readFileSync(jsonPath, 'utf-8');
150
+ return JSON.parse(content);
151
+ }
152
+ catch {
153
+ return null;
154
+ }
155
+ }
156
+ return null;
157
+ }
158
+ /**
159
+ * Get the underlying CacheManager instance for advanced cache operations.
160
+ */
161
+ getCacheManager() {
162
+ return this.cacheManager;
163
+ }
164
+ /**
165
+ * Get the underlying GitCloner instance for advanced git operations.
166
+ */
167
+ getGitCloner() {
168
+ return this.gitCloner;
169
+ }
170
+ /**
171
+ * Get the underlying Templatizer instance for advanced template operations.
172
+ */
173
+ getTemplatizer() {
174
+ return this.templatizer;
175
+ }
176
+ inspectLocal(templateDir, fromPath, useBoilerplatesConfig = true) {
177
+ const { fromPath: resolvedFromPath, resolvedTemplatePath } = this.resolveFromPath(templateDir, fromPath, useBoilerplatesConfig);
178
+ const config = this.readBoilerplateConfig(resolvedTemplatePath);
179
+ return {
180
+ templateDir,
181
+ resolvedFromPath,
182
+ resolvedTemplatePath,
183
+ cacheUsed: false,
184
+ cacheExpired: false,
185
+ config,
186
+ };
187
+ }
188
+ inspectRemote(templateUrl, branch, fromPath, useBoilerplatesConfig = true) {
189
+ const normalizedUrl = this.gitCloner.normalizeUrl(templateUrl);
190
+ const cacheKey = this.cacheManager.createKey(normalizedUrl, branch);
191
+ const expiredMetadata = this.cacheManager.checkExpiration(cacheKey);
192
+ if (expiredMetadata) {
193
+ this.cacheManager.clear(cacheKey);
194
+ }
195
+ let templateDir;
196
+ let cacheUsed = false;
197
+ const cachedPath = this.cacheManager.get(cacheKey);
198
+ if (cachedPath && !expiredMetadata) {
199
+ templateDir = cachedPath;
200
+ cacheUsed = true;
201
+ }
202
+ else {
203
+ const tempDest = path.join(this.cacheManager.getReposDir(), cacheKey);
204
+ this.gitCloner.clone(normalizedUrl, tempDest, {
205
+ branch,
206
+ depth: 1,
207
+ singleBranch: true,
208
+ });
209
+ this.cacheManager.set(cacheKey, tempDest);
210
+ templateDir = tempDest;
211
+ }
212
+ const { fromPath: resolvedFromPath, resolvedTemplatePath } = this.resolveFromPath(templateDir, fromPath, useBoilerplatesConfig);
213
+ const config = this.readBoilerplateConfig(resolvedTemplatePath);
214
+ return {
215
+ templateDir,
216
+ resolvedFromPath,
217
+ resolvedTemplatePath,
218
+ cacheUsed,
219
+ cacheExpired: Boolean(expiredMetadata),
220
+ config,
221
+ };
222
+ }
223
+ async scaffoldFromLocal(templateDir, options) {
224
+ const { fromPath, resolvedTemplatePath } = this.resolveFromPath(templateDir, options.fromPath, options.useBoilerplatesConfig ?? true);
225
+ const boilerplateConfig = this.readBoilerplateConfig(resolvedTemplatePath);
226
+ const result = await this.templatizer.process(templateDir, options.outputDir, {
227
+ argv: options.answers,
228
+ noTty: options.noTty,
229
+ fromPath,
230
+ prompter: options.prompter,
231
+ });
232
+ return {
233
+ outputDir: result.outputDir,
234
+ cacheUsed: false,
235
+ cacheExpired: false,
236
+ templateDir,
237
+ fromPath,
238
+ questions: boilerplateConfig?.questions,
239
+ answers: result.answers,
240
+ };
241
+ }
242
+ async scaffoldFromRemote(templateUrl, branch, options) {
243
+ const normalizedUrl = this.gitCloner.normalizeUrl(templateUrl);
244
+ const cacheKey = this.cacheManager.createKey(normalizedUrl, branch);
245
+ const expiredMetadata = this.cacheManager.checkExpiration(cacheKey);
246
+ if (expiredMetadata) {
247
+ this.cacheManager.clear(cacheKey);
248
+ }
249
+ let templateDir;
250
+ let cacheUsed = false;
251
+ const cachedPath = this.cacheManager.get(cacheKey);
252
+ if (cachedPath && !expiredMetadata) {
253
+ templateDir = cachedPath;
254
+ cacheUsed = true;
255
+ }
256
+ else {
257
+ const tempDest = path.join(this.cacheManager.getReposDir(), cacheKey);
258
+ this.gitCloner.clone(normalizedUrl, tempDest, {
259
+ branch,
260
+ depth: 1,
261
+ singleBranch: true,
262
+ });
263
+ this.cacheManager.set(cacheKey, tempDest);
264
+ templateDir = tempDest;
265
+ }
266
+ const { fromPath, resolvedTemplatePath } = this.resolveFromPath(templateDir, options.fromPath, options.useBoilerplatesConfig ?? true);
267
+ const boilerplateConfig = this.readBoilerplateConfig(resolvedTemplatePath);
268
+ const result = await this.templatizer.process(templateDir, options.outputDir, {
269
+ argv: options.answers,
270
+ noTty: options.noTty,
271
+ fromPath,
272
+ prompter: options.prompter,
273
+ });
274
+ return {
275
+ outputDir: result.outputDir,
276
+ cacheUsed,
277
+ cacheExpired: Boolean(expiredMetadata),
278
+ templateDir,
279
+ fromPath,
280
+ questions: boilerplateConfig?.questions,
281
+ answers: result.answers,
282
+ };
283
+ }
284
+ /**
285
+ * Resolve the fromPath using .boilerplates.json convention.
286
+ *
287
+ * Resolution order:
288
+ * 1. If explicit fromPath is provided and exists, use it directly
289
+ * 2. If useBoilerplatesConfig is true and .boilerplates.json exists with a dir field, prepend it to fromPath
290
+ * 3. Return the fromPath as-is
291
+ *
292
+ * @param templateDir - The template repository root directory
293
+ * @param fromPath - The subdirectory path to resolve
294
+ * @param useBoilerplatesConfig - Whether to use .boilerplates.json for fallback resolution (default: true)
295
+ */
296
+ resolveFromPath(templateDir, fromPath, useBoilerplatesConfig = true) {
297
+ if (!fromPath) {
298
+ return {
299
+ fromPath: undefined,
300
+ resolvedTemplatePath: templateDir,
301
+ };
302
+ }
303
+ const directPath = path.isAbsolute(fromPath)
304
+ ? fromPath
305
+ : path.join(templateDir, fromPath);
306
+ if (fs.existsSync(directPath) && fs.statSync(directPath).isDirectory()) {
307
+ return {
308
+ fromPath: path.isAbsolute(fromPath) ? path.relative(templateDir, fromPath) : fromPath,
309
+ resolvedTemplatePath: directPath,
310
+ };
311
+ }
312
+ // Only check .boilerplates.json if useBoilerplatesConfig is true
313
+ if (useBoilerplatesConfig) {
314
+ const rootConfig = this.readBoilerplatesConfig(templateDir);
315
+ if (rootConfig?.dir) {
316
+ const configBasedPath = path.join(templateDir, rootConfig.dir, fromPath);
317
+ if (fs.existsSync(configBasedPath) && fs.statSync(configBasedPath).isDirectory()) {
318
+ return {
319
+ fromPath: path.join(rootConfig.dir, fromPath),
320
+ resolvedTemplatePath: configBasedPath,
321
+ };
322
+ }
323
+ }
324
+ }
325
+ return {
326
+ fromPath,
327
+ resolvedTemplatePath: path.join(templateDir, fromPath),
328
+ };
329
+ }
330
+ isLocalPath(value) {
331
+ return (value.startsWith('.') ||
332
+ value.startsWith('/') ||
333
+ value.startsWith('~') ||
334
+ (process.platform === 'win32' && /^[a-zA-Z]:/.test(value)));
335
+ }
336
+ resolveTemplatePath(template) {
337
+ if (this.isLocalPath(template)) {
338
+ if (template.startsWith('~')) {
339
+ const home = process.env.HOME || process.env.USERPROFILE || '';
340
+ return path.join(home, template.slice(1));
341
+ }
342
+ return path.resolve(template);
343
+ }
344
+ return template;
345
+ }
346
+ }
347
+ exports.TemplateScaffolder = TemplateScaffolder;
@@ -0,0 +1,191 @@
1
+ import { Inquirerer } from 'inquirerer';
2
+ import { Question } from 'inquirerer';
3
+ /**
4
+ * Configuration for TemplateScaffolder instance
5
+ */
6
+ export interface TemplateScaffolderConfig {
7
+ /**
8
+ * Tool name used for cache directory naming (e.g., 'my-cli' -> ~/.my-cli/cache)
9
+ */
10
+ toolName: string;
11
+ /**
12
+ * Default template repository URL or path.
13
+ * Used when scaffold() is called without specifying a template.
14
+ */
15
+ defaultRepo?: string;
16
+ /**
17
+ * Default branch to use when cloning repositories
18
+ */
19
+ defaultBranch?: string;
20
+ /**
21
+ * Cache time-to-live in milliseconds.
22
+ * Cached templates older than this will be re-cloned.
23
+ * Default: no expiration
24
+ */
25
+ ttlMs?: number;
26
+ /**
27
+ * Base directory for cache storage.
28
+ * Useful for tests to avoid touching the real home directory.
29
+ */
30
+ cacheBaseDir?: string;
31
+ }
32
+ /**
33
+ * Options for a single scaffold operation
34
+ */
35
+ export interface ScaffoldOptions {
36
+ /**
37
+ * Template repository URL, local path, or org/repo shorthand.
38
+ * If not provided, uses the defaultRepo from config.
39
+ */
40
+ template?: string;
41
+ /**
42
+ * Branch to clone (for remote repositories)
43
+ */
44
+ branch?: string;
45
+ /**
46
+ * Subdirectory within the template repository to use as the template root.
47
+ * Can be a direct path or a variant name that gets resolved via .boilerplates.json
48
+ */
49
+ fromPath?: string;
50
+ /**
51
+ * Whether to use .boilerplates.json for path resolution fallback.
52
+ * When true (default), if fromPath doesn't exist directly, the resolver
53
+ * will check .boilerplates.json for a base directory to prepend.
54
+ * When false, .boilerplates.json is ignored and fromPath is used as-is.
55
+ * @default true
56
+ */
57
+ useBoilerplatesConfig?: boolean;
58
+ /**
59
+ * Output directory for the generated project
60
+ */
61
+ outputDir: string;
62
+ /**
63
+ * Pre-populated answers to skip prompting for known values
64
+ */
65
+ answers?: Record<string, any>;
66
+ /**
67
+ * Disable TTY mode for non-interactive environments
68
+ */
69
+ noTty?: boolean;
70
+ /**
71
+ * Optional Prompter instance to reuse for prompting.
72
+ * If provided, the caller retains ownership and is responsible for closing it.
73
+ * If not provided, a new instance will be created and closed automatically.
74
+ */
75
+ prompter?: Inquirerer;
76
+ }
77
+ /**
78
+ * Result of a scaffold operation
79
+ */
80
+ export interface ScaffoldResult {
81
+ /**
82
+ * Path to the generated output directory
83
+ */
84
+ outputDir: string;
85
+ /**
86
+ * Whether a cached template was used
87
+ */
88
+ cacheUsed: boolean;
89
+ /**
90
+ * Whether the cache was expired and refreshed
91
+ */
92
+ cacheExpired: boolean;
93
+ /**
94
+ * Path to the cached/cloned template directory
95
+ */
96
+ templateDir: string;
97
+ /**
98
+ * The resolved fromPath used for template processing
99
+ */
100
+ fromPath?: string;
101
+ /**
102
+ * Questions loaded from .boilerplate.json, if any
103
+ */
104
+ questions?: Question[];
105
+ /**
106
+ * Answers collected during prompting
107
+ */
108
+ answers: Record<string, any>;
109
+ }
110
+ /**
111
+ * Root configuration for a boilerplates repository.
112
+ * Stored in `.boilerplates.json` at the repository root.
113
+ */
114
+ export interface BoilerplatesConfig {
115
+ /**
116
+ * Default directory containing boilerplate templates (e.g., "templates", "boilerplates")
117
+ */
118
+ dir?: string;
119
+ }
120
+ /**
121
+ * Configuration for a single boilerplate template.
122
+ * Stored in `.boilerplate.json` within each template directory.
123
+ */
124
+ export interface BoilerplateConfig {
125
+ /**
126
+ * Optional type identifier for the boilerplate
127
+ */
128
+ type?: string;
129
+ /**
130
+ * Questions to prompt the user during scaffolding
131
+ */
132
+ questions?: Question[];
133
+ }
134
+ /**
135
+ * Options for inspecting a template without scaffolding.
136
+ * Used to read template metadata before deciding how to handle it.
137
+ */
138
+ export interface InspectOptions {
139
+ /**
140
+ * Template repository URL, local path, or org/repo shorthand.
141
+ * If not provided, uses the defaultRepo from config.
142
+ */
143
+ template?: string;
144
+ /**
145
+ * Branch to clone (for remote repositories)
146
+ */
147
+ branch?: string;
148
+ /**
149
+ * Subdirectory within the template repository to inspect.
150
+ * Can be a direct path or a variant name that gets resolved via .boilerplates.json
151
+ */
152
+ fromPath?: string;
153
+ /**
154
+ * Whether to use .boilerplates.json for path resolution fallback.
155
+ * When true (default), if fromPath doesn't exist directly, the resolver
156
+ * will check .boilerplates.json for a base directory to prepend.
157
+ * When false, .boilerplates.json is ignored and fromPath is used as-is.
158
+ * @default true
159
+ */
160
+ useBoilerplatesConfig?: boolean;
161
+ }
162
+ /**
163
+ * Result of inspecting a template.
164
+ * Contains metadata about the template without copying any files.
165
+ */
166
+ export interface InspectResult {
167
+ /**
168
+ * Path to the cached/cloned template directory
169
+ */
170
+ templateDir: string;
171
+ /**
172
+ * The resolved fromPath after .boilerplates.json resolution
173
+ */
174
+ resolvedFromPath?: string;
175
+ /**
176
+ * Full path to the resolved template directory
177
+ */
178
+ resolvedTemplatePath: string;
179
+ /**
180
+ * Whether a cached template was used
181
+ */
182
+ cacheUsed: boolean;
183
+ /**
184
+ * Whether the cache was expired and refreshed
185
+ */
186
+ cacheExpired: boolean;
187
+ /**
188
+ * The .boilerplate.json configuration from the template, if present
189
+ */
190
+ config: BoilerplateConfig | null;
191
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,7 @@
1
+ import { ExtractedVariables } from '../types';
2
+ /**
3
+ * Extract all variables from a template directory
4
+ * @param templateDir - Path to the template directory
5
+ * @returns Extracted variables including file replacers, content replacers, and project questions
6
+ */
7
+ export declare function extractVariables(templateDir: string): Promise<ExtractedVariables>;