Skip to content

Commit 1e19b14

Browse files
authored
feat: Add Package Parameter to Init (#254)
* Add Package Parameter * Add 'specifier' Parameter to provide Version
1 parent f277c77 commit 1e19b14

File tree

5 files changed

+303
-69
lines changed

5 files changed

+303
-69
lines changed

.vscode/launch.json

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,21 @@
11
{
22
"version": "0.2.0",
33
"configurations": [
4+
{
5+
"type": "node",
6+
"request": "launch",
7+
"name": "Debug CLI - init all",
8+
"cwd": "${workspaceFolder}/vehicle-app-repo",
9+
"program": "${workspaceFolder}/bin/dev",
10+
"args": ["init"]
11+
},
412
{
513
"name": "Run tests",
14+
"type": "node",
615
"request": "launch",
7-
"runtimeArgs": [
8-
"test",
9-
],
16+
"runtimeArgs": ["test"],
1017
"runtimeExecutable": "npm",
11-
"skipFiles": [
12-
"<node_internals>/**"
13-
],
14-
"type": "node"
18+
"skipFiles": ["<node_internals>/**"]
1519
}
1620
]
1721
}

README.md

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -309,12 +309,14 @@ Initializes Velocitas Vehicle App
309309

310310
```
311311
USAGE
312-
$ velocitas init [-v] [-f] [--no-hooks]
312+
$ velocitas init [-p PACKAGE] [-s VERSION_SPECIFIER] [-v] [-f] [--no-hooks]
313313
314314
FLAGS
315-
-f, --force Force (re-)download packages
316-
-v, --verbose Enable verbose logging
317-
--no-hooks Skip post init hooks
315+
-p, --package Package to initialize
316+
-s, --specifier Version specifier for the specified package
317+
-f, --force Force (re-)download packages
318+
-v, --verbose Enable verbose logging
319+
--no-hooks Skip post init hooks
318320
319321
DESCRIPTION
320322
Initializes Velocitas Vehicle App
@@ -327,6 +329,18 @@ EXAMPLES
327329
... Downloading package: 'devenv-runtimes:vx.x.x'
328330
... Downloading package: 'devenv-github-templates:vx.x.x'
329331
... Downloading package: 'devenv-github-workflows:vx.x.x'
332+
333+
$ velocitas init -p devenv-runtimes
334+
Initializing Velocitas packages ...
335+
... Package 'devenv-runtimes:vx.x.x' added to .velocitas.json
336+
... Downloading package: 'devenv-runtimes:vx.x.x'
337+
... > Running post init hook for ...'
338+
339+
$ velocitas init -p devenv-runtimes -s v3.0.0
340+
Initializing Velocitas packages ...
341+
... Package 'devenv-runtimes:v3.0.0' added to .velocitas.json
342+
... Downloading package: 'devenv-runtimes:v3.0.0'
343+
... > Running post init hook for ...
330344
```
331345

332346
_See code: [src/commands/init/index.ts](src/commands/init/index.ts)_

src/commands/init/index.ts

Lines changed: 112 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,19 @@ import { Command, Flags, ux } from '@oclif/core';
1616
import { APP_MANIFEST_PATH_VARIABLE, AppManifest } from '../../modules/app-manifest';
1717
import { ComponentContext, ExecSpec } from '../../modules/component';
1818
import { ExecExitError, runExecSpec } from '../../modules/exec';
19+
import { PackageConfig } from '../../modules/package';
1920
import { ProjectConfig, ProjectConfigLock } from '../../modules/project-config';
2021
import { resolveVersionIdentifier } from '../../modules/semver';
2122
import { createEnvVars } from '../../modules/variables';
2223

24+
interface InitFlags {
25+
verbose: boolean;
26+
force: boolean;
27+
['no-hooks']: boolean;
28+
package: string;
29+
specifier: string;
30+
}
31+
2332
export default class Init extends Command {
2433
static description = 'Initializes Velocitas Vehicle App';
2534

@@ -31,6 +40,16 @@ export default class Init extends Command {
3140
... Downloading package: 'devenv-runtimes:vx.x.x'
3241
... Downloading package: 'devenv-github-templates:vx.x.x'
3342
... Downloading package: 'devenv-github-workflows:vx.x.x'`,
43+
`$ velocitas init -p devenv-runtimes
44+
Initializing Velocitas packages ...
45+
... Package 'devenv-runtimes:vx.x.x' added to .velocitas.json
46+
... Downloading package: 'devenv-runtimes:vx.x.x'
47+
... > Running post init hook for ...'`,
48+
`$ velocitas init -p devenv-runtimes -s v3.0.0
49+
Initializing Velocitas packages ...
50+
... Package 'devenv-runtimes:v3.0.0' added to .velocitas.json
51+
... Downloading package: 'devenv-runtimes:v3.0.0'
52+
... > Running post init hook for ...`,
3453
];
3554

3655
static flags = {
@@ -47,26 +66,87 @@ export default class Init extends Command {
4766
required: false,
4867
default: false,
4968
}),
69+
package: Flags.string({
70+
char: 'p',
71+
aliases: ['package'],
72+
description: `Package to initialize`,
73+
required: false,
74+
default: '',
75+
}),
76+
specifier: Flags.string({
77+
char: 's',
78+
aliases: ['specifier'],
79+
description: `Version specifier for the specified package`,
80+
required: false,
81+
default: '',
82+
dependsOn: ['package'],
83+
}),
5084
};
5185

5286
async run(): Promise<void> {
53-
const { flags } = await this.parse(Init);
87+
const { flags }: { flags: InitFlags } = await this.parse(Init);
5488
this.log(`Initializing Velocitas packages ...`);
55-
const projectConfig = this.initializeOrReadProject();
89+
const projectConfig = this._initializeOrReadProject();
90+
91+
if (flags.package) {
92+
await this._handleSinglePackageInit(projectConfig, flags);
93+
} else {
94+
await this._handleCompletePackageInit(projectConfig, flags);
95+
}
5696

57-
const appManifestData = AppManifest.read(projectConfig.getVariableMappings().get(APP_MANIFEST_PATH_VARIABLE));
97+
this._createProjectLockFile(projectConfig, flags.verbose);
98+
}
5899

59-
await this.ensurePackagesAreDownloaded(projectConfig, flags.force, flags.verbose);
100+
private async _handleCompletePackageInit(projectConfig: ProjectConfig, flags: InitFlags) {
101+
await this._ensurePackagesAreDownloaded(projectConfig.getPackages(), flags);
60102
projectConfig.validateUsedComponents();
61103

62104
if (!flags['no-hooks']) {
63-
await this.runPostInitHooks(projectConfig, appManifestData, flags.verbose);
105+
await this._runPostInitHooks(projectConfig.getComponents(), projectConfig, flags.verbose);
106+
}
107+
}
108+
109+
private async _handleSinglePackageInit(projectConfig: ProjectConfig, flags: InitFlags): Promise<void> {
110+
const requestedPackageConfig = new PackageConfig({ repo: flags.package, version: flags.specifier });
111+
await this._resolveVersion(requestedPackageConfig, flags.verbose);
112+
113+
const packageUpdated = projectConfig.updatePackageConfig(requestedPackageConfig);
114+
if (packageUpdated) {
115+
this.log(
116+
`... Updating '${requestedPackageConfig.getPackageName()}' to version '${requestedPackageConfig.version}' in .velocitas.json`,
117+
);
118+
} else {
119+
const isAdded = projectConfig.addPackageConfig(requestedPackageConfig);
120+
if (isAdded) {
121+
this.log(
122+
`... Package '${requestedPackageConfig.getPackageName()}:${requestedPackageConfig.version}' added to .velocitas.json`,
123+
);
124+
}
125+
}
126+
127+
await this._ensurePackagesAreDownloaded([requestedPackageConfig], flags);
128+
this._finalizeSinglePackageInit(requestedPackageConfig, projectConfig);
129+
130+
if (!flags['no-hooks']) {
131+
await this._runPostInitHooks(projectConfig.getComponentsForPackageConfig(requestedPackageConfig), projectConfig, flags.verbose);
132+
}
133+
}
134+
135+
private _finalizeSinglePackageInit(requestedPackageConfig: PackageConfig, projectConfig: ProjectConfig): void {
136+
const providedComponents = requestedPackageConfig.readPackageManifest().components;
137+
const enabledComponentIds = projectConfig.getComponents(undefined, true).map((comp) => comp.config.id);
138+
const areComponentsExisting = providedComponents.some((comp) => enabledComponentIds.includes(comp.id));
139+
140+
if (!areComponentsExisting) {
141+
providedComponents.forEach((providedComponent) => {
142+
projectConfig.addComponent(providedComponent.id);
143+
});
64144
}
65145

66-
this.createProjectLockFile(projectConfig, flags.verbose);
146+
projectConfig.write();
67147
}
68148

69-
initializeOrReadProject(): ProjectConfig {
149+
private _initializeOrReadProject(): ProjectConfig {
70150
let projectConfig: ProjectConfig;
71151

72152
if (!ProjectConfig.isAvailable()) {
@@ -79,30 +159,34 @@ export default class Init extends Command {
79159
return projectConfig;
80160
}
81161

82-
async ensurePackagesAreDownloaded(projectConfig: ProjectConfig, force: boolean, verbose: boolean) {
83-
for (const packageConfig of projectConfig.getPackages()) {
84-
const packageVersions = await packageConfig.getPackageVersions();
85-
const packageVersion = resolveVersionIdentifier(packageVersions, packageConfig.version);
162+
private async _resolveVersion(packageConfig: PackageConfig, verbose: boolean): Promise<void> {
163+
const packageVersions = await packageConfig.getPackageVersions();
164+
const packageVersion = resolveVersionIdentifier(packageVersions, packageConfig.version);
86165

87-
if (verbose) {
88-
this.log(`... Resolved '${packageConfig.getPackageName()}:${packageConfig.version}' to version: '${packageVersion}'`);
89-
}
166+
if (verbose) {
167+
this.log(`... Resolved '${packageConfig.getPackageName()}:${packageConfig.version}' to version: '${packageVersion}'`);
168+
}
169+
170+
packageConfig.setPackageVersion(packageVersion);
171+
}
90172

91-
packageConfig.setPackageVersion(packageVersion);
173+
private async _ensurePackagesAreDownloaded(packageConfigs: PackageConfig[], flags: InitFlags) {
174+
for (const packageConfig of packageConfigs) {
175+
await this._resolveVersion(packageConfig, flags.verbose);
92176

93-
if (!force && packageConfig.isPackageInstalled()) {
177+
if (!flags.force && packageConfig.isPackageInstalled()) {
94178
this.log(`... '${packageConfig.getPackageName()}:${packageConfig.version}' already installed.`);
95179
continue;
96180
}
97181

98182
this.log(`... Downloading package: '${packageConfig.getPackageName()}:${packageConfig.version}'`);
99-
await packageConfig.downloadPackageVersion(verbose);
183+
await packageConfig.downloadPackageVersion(flags.verbose);
100184
}
101185
}
102186

103-
async runSinglePostInitHook(
187+
private async _runSinglePostInitHook(
104188
execSpec: ExecSpec,
105-
componentContext: ComponentContext,
189+
currentComponentContext: ComponentContext,
106190
projectConfig: ProjectConfig,
107191
appManifest: any,
108192
verbose: boolean,
@@ -114,11 +198,11 @@ export default class Init extends Command {
114198
this.log(message);
115199
}
116200
const envVars = createEnvVars(
117-
componentContext.packageConfig.getPackageDirectoryWithVersion(),
118-
projectConfig.getVariableCollection(componentContext),
201+
currentComponentContext.packageConfig.getPackageDirectoryWithVersion(),
202+
projectConfig.getVariableCollection(currentComponentContext),
119203
appManifest,
120204
);
121-
await runExecSpec(execSpec, componentContext.manifest.id, projectConfig, envVars, {
205+
await runExecSpec(execSpec, currentComponentContext.manifest.id, projectConfig, envVars, {
122206
writeStdout: verbose,
123207
verbose: verbose,
124208
});
@@ -127,8 +211,10 @@ export default class Init extends Command {
127211
}
128212
}
129213

130-
async runPostInitHooks(projectConfig: ProjectConfig, appManifest: any, verbose: boolean) {
131-
for (const componentContext of projectConfig.getComponents()) {
214+
private async _runPostInitHooks(components: ComponentContext[], projectConfig: ProjectConfig, verbose: boolean): Promise<void> {
215+
const appManifest = AppManifest.read(projectConfig.getVariableMappings().get(APP_MANIFEST_PATH_VARIABLE));
216+
217+
for (const componentContext of components) {
132218
if (!componentContext.manifest.onPostInit || componentContext.manifest.onPostInit.length === 0) {
133219
continue;
134220
}
@@ -137,7 +223,7 @@ export default class Init extends Command {
137223

138224
for (const execSpec of componentContext.manifest.onPostInit) {
139225
try {
140-
await this.runSinglePostInitHook(execSpec, componentContext, projectConfig, appManifest, verbose);
226+
await this._runSinglePostInitHook(execSpec, componentContext, projectConfig, appManifest, verbose);
141227
} catch (e) {
142228
if (e instanceof ExecExitError) {
143229
throw e;
@@ -151,7 +237,7 @@ export default class Init extends Command {
151237
}
152238
}
153239

154-
createProjectLockFile(projectConfig: ProjectConfig, verbose: boolean): void {
240+
private _createProjectLockFile(projectConfig: ProjectConfig, verbose: boolean): void {
155241
if (verbose && !ProjectConfigLock.isAvailable()) {
156242
this.log('... No .velocitas-lock.json found. Creating it at the root of your repository.');
157243
}

0 commit comments

Comments
 (0)