0
# Programmatic API
1
2
Comprehensive APIs for plugin development, programmatic project creation, and extending Vue CLI functionality through generators and prompt modules.
3
4
## Capabilities
5
6
### GeneratorAPI
7
8
Core API provided to plugin generators for modifying projects and extending functionality.
9
10
```typescript { .api }
11
/**
12
* API exposed to plugin generators for project modification and extension
13
*/
14
class GeneratorAPI {
15
constructor(id: string, generator: Generator, options: any, rootOptions: Preset);
16
17
/**
18
* Resolve path for a project relative to project root
19
* @param paths - Path segments to resolve
20
* @returns Absolute path within project
21
*/
22
resolve(...paths: string[]): string;
23
24
/**
25
* Assert CLI version requirement for plugin compatibility
26
* @param range - Semver range for required CLI version
27
* @throws Error if CLI version doesn't satisfy range
28
*/
29
assertCliVersion(range: number | string): void;
30
31
/**
32
* Assert CLI service version requirement for plugin compatibility
33
* @param range - Semver range for required CLI service version
34
* @throws Error if CLI service version doesn't satisfy range
35
*/
36
assertCliServiceVersion(range: number | string): void;
37
38
/**
39
* Check if the project has a given plugin
40
* @param id - Plugin id, can omit the (@vue/|vue-|@scope/vue)-cli-plugin- prefix
41
* @param versionRange - Plugin version range. Defaults to '*'
42
* @returns Whether plugin exists and matches version range
43
*/
44
hasPlugin(id: string, versionRange?: string): boolean;
45
46
/**
47
* Configure how config files are extracted from package.json
48
* @param key - Config key in package.json
49
* @param options - File descriptor options for extraction
50
*/
51
addConfigTransform(key: string, options: ConfigTransformOptions): void;
52
53
/**
54
* Extend the package.json of the project with dependency resolution
55
* @param fields - Fields to merge or function returning fields
56
* @param options - Options for extending/merging fields
57
*/
58
extendPackage(
59
fields: object | ((pkg: Record<string, any>) => object),
60
options?: ExtendPackageOptions
61
): void;
62
63
/**
64
* Render template files into the virtual files tree object
65
* @param source - Template source (directory, object mapping, or middleware)
66
* @param additionalData - Additional data available to templates
67
* @param ejsOptions - Options for EJS template engine
68
*/
69
render(
70
source: string | RenderFile | FileMiddleware,
71
additionalData?: object,
72
ejsOptions?: object
73
): void;
74
75
/**
76
* Push a file middleware that will be applied after all normal file middlewares
77
* @param cb - Callback function to process files
78
*/
79
postProcessFiles(cb: PostProcessFilesCallback): void;
80
81
/**
82
* Push a callback to be called when the files have been written to disk
83
* @param cb - Callback function for completion
84
*/
85
onCreateComplete(cb: (...args: any[]) => any): void;
86
87
/**
88
* Same as onCreateComplete - callback for when files are written
89
* @param cb - Callback function for after invoke
90
*/
91
afterInvoke(cb: (...args: any[]) => any): void;
92
93
/**
94
* Push callback for when files have been written from non-invoked plugins
95
* @param cb - Callback function for after any invoke
96
*/
97
afterAnyInvoke(cb: (...args: any[]) => any): void;
98
99
/**
100
* Add a message to be printed when the generator exits
101
* @param msg - String or value to print after generation is completed
102
* @param type - Type of message (log, info, done, warn, error)
103
*/
104
exitLog(msg: any, type?: 'log' | 'info' | 'done' | 'warn' | 'error'): void;
105
106
/**
107
* Convenience method for generating a JS config file from JSON
108
* @param value - Value to convert to JS config
109
* @returns JavaScript config string
110
*/
111
genJSConfig(value: any): string;
112
113
/**
114
* Turn a string expression into executable JS for JS configs
115
* @param str - JS expression as a string
116
* @returns Expression function for JS configs
117
*/
118
makeJSOnlyValue(str: string): ExpressionFunction;
119
120
/**
121
* Run codemod on a script file or the script part of a .vue file
122
* @param file - Path to file to transform
123
* @param codemod - Codemod module to run
124
* @param options - Additional options for the codemod
125
*/
126
transformScript(file: string, codemod: TransformModule, options?: TransformOptions): void;
127
128
/**
129
* Add import statements to a file
130
* @param file - Target file path
131
* @param imports - Import statement(s) to add
132
*/
133
injectImports(file: string, imports: string | string[]): void;
134
135
/**
136
* Add options to the root Vue instance (detected by `new Vue`)
137
* @param file - Target file path
138
* @param options - Options to inject into root Vue instance
139
*/
140
injectRootOptions(file: string, options: string | string[]): void;
141
142
// Read-only properties
143
readonly cliVersion: string;
144
readonly cliServiceVersion: string;
145
readonly entryFile: 'src/main.ts' | 'src/main.js';
146
readonly invoking: boolean;
147
}
148
```
149
150
**Usage Examples:**
151
152
```typescript
153
// Example plugin generator using GeneratorAPI
154
module.exports = (api, options, rootOptions) => {
155
// Check CLI version compatibility
156
api.assertCliVersion('^5.0.0');
157
158
// Check if router plugin is installed
159
if (api.hasPlugin('router')) {
160
// Add navigation component if router exists
161
api.render('./templates/with-router');
162
} else {
163
// Add simple component without routing
164
api.render('./templates/without-router');
165
}
166
167
// Extend package.json with dependencies
168
api.extendPackage({
169
dependencies: {
170
'my-library': '^1.0.0'
171
},
172
scripts: {
173
'custom-command': 'my-library build'
174
}
175
});
176
177
// Add import to main entry file
178
api.injectImports(api.entryFile, "import MyPlugin from 'my-library'");
179
180
// Add plugin to Vue root instance
181
api.injectRootOptions(api.entryFile, 'MyPlugin');
182
183
// Post-process files after rendering
184
api.postProcessFiles((files) => {
185
// Modify generated files
186
Object.keys(files).forEach(filename => {
187
if (filename.endsWith('.vue')) {
188
files[filename] = files[filename].replace(/placeholder/g, options.replacement);
189
}
190
});
191
});
192
193
// Add completion message
194
api.exitLog('My plugin successfully installed!', 'done');
195
};
196
```
197
198
### PromptModuleAPI
199
200
API for creating interactive prompts during project creation.
201
202
```typescript { .api }
203
/**
204
* API for plugin prompt modules to inject interactive prompts
205
*/
206
class PromptModuleAPI {
207
constructor(creator: Creator);
208
209
/**
210
* Inject checkbox choice for feature prompt during project creation
211
* @param feature - Checkbox choice configuration
212
*/
213
injectFeature<T = Answers>(feature: CheckboxChoiceOptions<T>): void;
214
215
/**
216
* Inject additional prompt into the prompt sequence
217
* @param prompt - Inquirer prompt configuration
218
*/
219
injectPrompt<T = Answers>(prompt: DistinctQuestion<T>): void;
220
221
/**
222
* Inject option for existing prompt by name
223
* @param name - Name of existing prompt to extend
224
* @param option - Choice option to add
225
*/
226
injectOptionForPrompt(name: string, option: ChoiceOptions): void;
227
228
/**
229
* Register callback to run when prompts are completed
230
* @param cb - Callback receiving answers and additional options
231
*/
232
onPromptComplete<T = Answers>(cb: OnPromptCompleteCb<T>): void;
233
}
234
```
235
236
**Usage Examples:**
237
238
```typescript
239
// Example prompt module
240
module.exports = (api) => {
241
// Add feature checkbox
242
api.injectFeature({
243
name: 'my-feature',
244
value: 'my-feature',
245
description: 'Add my custom feature',
246
link: 'https://example.com/docs'
247
});
248
249
// Add conditional prompt
250
api.injectPrompt({
251
name: 'myFeatureConfig',
252
when: answers => answers.features.includes('my-feature'),
253
type: 'list',
254
message: 'Choose configuration for my feature:',
255
choices: [
256
{ name: 'Basic', value: 'basic' },
257
{ name: 'Advanced', value: 'advanced' }
258
]
259
});
260
261
// Add option to existing prompt
262
api.injectOptionForPrompt('cssPreprocessor', {
263
name: 'My Custom CSS',
264
value: 'my-css'
265
});
266
267
// Handle prompt completion
268
api.onPromptComplete((answers, options) => {
269
if (answers.features.includes('my-feature')) {
270
options.plugins['my-plugin'] = {
271
config: answers.myFeatureConfig
272
};
273
}
274
});
275
};
276
```
277
278
### Generator Class
279
280
File generation and project setup handler.
281
282
```typescript { .api }
283
/**
284
* Handles file generation and project setup coordination
285
*/
286
class Generator {
287
constructor(context: string, options: GeneratorOptions);
288
289
/**
290
* Initialize all plugins in the project
291
*/
292
async initPlugins(): Promise<void>;
293
294
/**
295
* Generate project files using all configured plugins
296
* @param options - Generation options
297
*/
298
async generate(options?: GenerateOptions): Promise<void>;
299
300
/**
301
* Extract configuration files from package.json to separate files
302
* @param extractAll - Whether to extract all configs
303
* @param checkExisting - Whether to check for existing config files
304
*/
305
extractConfigFiles(extractAll?: boolean, checkExisting?: boolean): void;
306
307
/**
308
* Sort package.json fields in standard order
309
*/
310
sortPkg(): void;
311
312
/**
313
* Resolve all plugins in the project
314
* @returns Array of resolved plugin configurations
315
*/
316
resolveAllPlugins(): PluginDescriptor[];
317
318
/**
319
* Resolve all file middlewares from plugins
320
*/
321
async resolveFiles(): Promise<void>;
322
323
/**
324
* Check if project has a specific plugin
325
* @param id - Plugin ID
326
* @param versionRange - Version range to check
327
* @returns Whether plugin exists
328
*/
329
hasPlugin(id: string, versionRange?: string): boolean;
330
331
/**
332
* Print exit log messages from plugins
333
*/
334
printExitLogs(): void;
335
336
// Properties
337
readonly context: string;
338
readonly plugins: PluginDescriptor[];
339
readonly pkg: PackageJson;
340
readonly files: RenderFile;
341
readonly imports: Record<string, Set<string>>;
342
readonly rootOptions: Record<string, Set<string>>;
343
}
344
```
345
346
### ConfigTransform Class
347
348
Configuration file transformation and extraction.
349
350
```typescript { .api }
351
/**
352
* Handles transformation of configuration from package.json to separate files
353
*/
354
class ConfigTransform {
355
constructor(options: ConfigTransformOptions);
356
357
/**
358
* Transform configuration value to appropriate file format
359
* @param value - Configuration value to transform
360
* @param checkExisting - Whether to check for existing files
361
* @param files - Virtual file tree
362
* @param context - Project context path
363
* @returns Transformation result
364
*/
365
transform(
366
value: any,
367
checkExisting: boolean,
368
files: RenderFile,
369
context: string
370
): TransformResult;
371
372
/**
373
* Find existing configuration file in project
374
* @param files - Virtual file tree
375
* @returns Found file info or null
376
*/
377
findFile(files: RenderFile): FileInfo | null;
378
379
/**
380
* Get default configuration file name
381
* @returns Default file name
382
*/
383
getDefaultFile(): string;
384
}
385
```
386
387
### Supporting Types
388
389
Type definitions for the programmatic API.
390
391
```typescript { .api }
392
interface ConfigTransformOptions {
393
/** File descriptor mapping file types to filenames */
394
file: {
395
js?: string[];
396
json?: string[];
397
yaml?: string[];
398
lines?: string[];
399
};
400
}
401
402
interface ExtendPackageOptions {
403
/** Remove null or undefined fields after merging */
404
prune?: boolean;
405
/** Deep-merge nested fields */
406
merge?: boolean;
407
/** Output warning if dependency version ranges don't intersect */
408
warnIncompatibleVersions?: boolean;
409
/** Force using dependency version from first argument */
410
forceOverwrite?: boolean;
411
}
412
413
interface TransformModule {
414
default?: Transform;
415
parser?: string | Parser;
416
}
417
418
interface TransformOptions {
419
parser?: string | Parser;
420
[prop: string]: any;
421
}
422
423
interface ExpressionFunction {
424
(): void;
425
__expression: string;
426
}
427
428
interface RenderFile {
429
[path: string]: string | Buffer;
430
}
431
432
type FileMiddleware = (files: RenderFile, render: typeof ejs.render) => void;
433
type PostProcessFilesCallback = (files: RenderFile) => void;
434
435
interface OnPromptCompleteCb<T = any> {
436
(
437
answers: T,
438
options: {
439
useConfigFiles: boolean;
440
plugins: Record<string, any>;
441
}
442
): void;
443
}
444
445
interface PluginDescriptor {
446
id: string;
447
apply: GeneratorPlugin;
448
options: any;
449
}
450
451
type GeneratorPlugin = (
452
api: GeneratorAPI,
453
options: any,
454
rootOptions: Preset,
455
invoking: boolean
456
) => any;
457
```
458
459
### Utility Functions
460
461
Helper functions for plugin development and project management.
462
463
```typescript { .api }
464
/**
465
* Write virtual file tree to disk
466
* @param dir - Target directory
467
* @param files - Virtual file tree
468
* @param previousFiles - Previous file state for comparison
469
*/
470
async function writeFileTree(
471
dir: string,
472
files: RenderFile,
473
previousFiles?: RenderFile
474
): Promise<void>;
475
476
/**
477
* Generate README.md content for project
478
* @param pkg - Package.json content
479
* @param packageManager - Package manager being used
480
* @returns Generated README content
481
*/
482
function generateReadme(pkg: PackageJson, packageManager: string): string;
483
484
/**
485
* Sort object keys in consistent order
486
* @param obj - Object to sort
487
* @param keyOrder - Preferred key order
488
* @param dontSortByUnicode - Don't sort remaining keys by unicode
489
* @returns Sorted object
490
*/
491
function sortObject(
492
obj: Record<string, any>,
493
keyOrder?: string[],
494
dontSortByUnicode?: boolean
495
): Record<string, any>;
496
497
/**
498
* Stringify JavaScript object for config files
499
* @param value - Value to stringify
500
* @param replacer - Replacer function
501
* @param space - Indentation
502
* @returns JavaScript code string
503
*/
504
function stringifyJS(
505
value: any,
506
replacer?: (key: string, value: any) => any,
507
space?: string | number
508
): string;
509
```