hereya-cli 0.55.0 → 0.57.0
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.
- package/README.md +94 -36
- package/dist/backend/cloud/cloud-backend.d.ts +5 -1
- package/dist/backend/cloud/cloud-backend.js +208 -0
- package/dist/backend/common.d.ts +64 -2
- package/dist/backend/file.d.ts +5 -1
- package/dist/backend/file.js +24 -0
- package/dist/commands/add/index.js +2 -1
- package/dist/commands/deploy/index.js +50 -24
- package/dist/commands/doc/index.d.ts +17 -0
- package/dist/commands/doc/index.js +154 -0
- package/dist/commands/down/index.js +40 -11
- package/dist/commands/import/index.js +2 -1
- package/dist/commands/publish/index.d.ts +32 -0
- package/dist/commands/publish/index.js +239 -0
- package/dist/commands/remove/index.js +16 -4
- package/dist/commands/undeploy/index.js +45 -17
- package/dist/commands/up/index.js +36 -11
- package/dist/commands/workspace/install/index.js +1 -1
- package/dist/commands/workspace/uninstall/index.js +18 -5
- package/dist/executor/interface.d.ts +5 -0
- package/dist/executor/local.js +3 -3
- package/dist/infrastructure/index.d.ts +2 -0
- package/dist/infrastructure/index.js +8 -8
- package/dist/lib/config/common.d.ts +1 -0
- package/dist/lib/config/simple.js +2 -2
- package/dist/lib/package/cloud.d.ts +19 -0
- package/dist/lib/package/cloud.js +226 -0
- package/dist/lib/package/common.d.ts +1 -0
- package/dist/lib/package/github.d.ts +1 -1
- package/dist/lib/package/github.js +33 -6
- package/dist/lib/package/index.d.ts +9 -4
- package/dist/lib/package/index.js +178 -35
- package/dist/lib/package/local.js +1 -0
- package/oclif.manifest.json +92 -1
- package/package.json +8 -1
package/dist/backend/common.d.ts
CHANGED
|
@@ -7,13 +7,17 @@ export interface Backend {
|
|
|
7
7
|
deleteState(input: DeleteStateInput): Promise<DeleteStateOutput>;
|
|
8
8
|
deleteWorkspace(input: DeleteWorkspaceInput): Promise<DeleteWorkspaceOutput>;
|
|
9
9
|
exportBackend(): Promise<ExportBackendOutput>;
|
|
10
|
+
getPackageByVersion?(name: string, version: string): Promise<GetPackageOutput>;
|
|
11
|
+
getPackageLatest?(name: string): Promise<GetPackageOutput>;
|
|
10
12
|
getProvisioningId(input: GetProvisioningIdInput): Promise<GetProvisioningIdOutput>;
|
|
11
13
|
getState(input: GetStateInput): Promise<GetStateOutput>;
|
|
12
14
|
getWorkspace(workspace: string): Promise<GetWorkspaceOutput>;
|
|
13
15
|
getWorkspaceEnv(input: GetWorkspaceEnvInput): Promise<GetWorkspaceEnvOutput>;
|
|
14
16
|
importBackend(input: ImportBackendInput): Promise<ImportBackendOutput>;
|
|
15
17
|
init(options: InitProjectInput): Promise<InitProjectOutput>;
|
|
18
|
+
listPackageVersions?(name: string): Promise<ListPackageVersionsOutput>;
|
|
16
19
|
listWorkspaces(): Promise<string[]>;
|
|
20
|
+
publishPackage?(input: PublishPackageInput): Promise<PublishPackageOutput>;
|
|
17
21
|
removePackageFromWorkspace(input: RemovePackageFromWorkspaceInput): Promise<RemovePackageFromWorkspaceOutput>;
|
|
18
22
|
saveState(config: Config, workspace?: string): Promise<void>;
|
|
19
23
|
setEnvVar(input: SetEnvVarInput): Promise<SetEnvVarOutput>;
|
|
@@ -45,9 +49,9 @@ export declare const WorkspaceSchema: z.ZodObject<{
|
|
|
45
49
|
version: string;
|
|
46
50
|
parameters?: Record<string, any> | undefined;
|
|
47
51
|
}> | undefined;
|
|
52
|
+
profile?: string | undefined;
|
|
48
53
|
isDeploy?: boolean | undefined;
|
|
49
54
|
mirrorOf?: string | undefined;
|
|
50
|
-
profile?: string | undefined;
|
|
51
55
|
}, {
|
|
52
56
|
name: string;
|
|
53
57
|
id: string;
|
|
@@ -56,9 +60,9 @@ export declare const WorkspaceSchema: z.ZodObject<{
|
|
|
56
60
|
version: string;
|
|
57
61
|
parameters?: Record<string, any> | undefined;
|
|
58
62
|
}> | undefined;
|
|
63
|
+
profile?: string | undefined;
|
|
59
64
|
isDeploy?: boolean | undefined;
|
|
60
65
|
mirrorOf?: string | undefined;
|
|
61
|
-
profile?: string | undefined;
|
|
62
66
|
}>;
|
|
63
67
|
export type Workspace = z.infer<typeof WorkspaceSchema>;
|
|
64
68
|
export type AddPackageToWorkspaceInput = {
|
|
@@ -227,3 +231,61 @@ export type UpdateWorkspaceOutput = {
|
|
|
227
231
|
success: true;
|
|
228
232
|
workspace: Workspace;
|
|
229
233
|
};
|
|
234
|
+
export type PublishPackageInput = {
|
|
235
|
+
commit: string;
|
|
236
|
+
description: string;
|
|
237
|
+
doc?: string;
|
|
238
|
+
iac: string;
|
|
239
|
+
infra: string;
|
|
240
|
+
name: string;
|
|
241
|
+
onDeployPkg?: string;
|
|
242
|
+
onDeployVersion?: string;
|
|
243
|
+
repository: string;
|
|
244
|
+
sha256: string;
|
|
245
|
+
version: string;
|
|
246
|
+
visibility?: 'PRIVATE' | 'PUBLIC';
|
|
247
|
+
};
|
|
248
|
+
export type PublishPackageOutput = {
|
|
249
|
+
package: {
|
|
250
|
+
id: string;
|
|
251
|
+
name: string;
|
|
252
|
+
version: string;
|
|
253
|
+
};
|
|
254
|
+
success: true;
|
|
255
|
+
} | {
|
|
256
|
+
reason: string;
|
|
257
|
+
success: false;
|
|
258
|
+
};
|
|
259
|
+
export type RegistryPackage = {
|
|
260
|
+
commit?: string;
|
|
261
|
+
createdAt?: string;
|
|
262
|
+
description: string;
|
|
263
|
+
doc?: string;
|
|
264
|
+
iac?: string;
|
|
265
|
+
id: string;
|
|
266
|
+
infra?: string;
|
|
267
|
+
name: string;
|
|
268
|
+
onDeploy?: {
|
|
269
|
+
pkg: string;
|
|
270
|
+
version: string;
|
|
271
|
+
};
|
|
272
|
+
repository?: string;
|
|
273
|
+
sha256?: string;
|
|
274
|
+
updatedAt?: string;
|
|
275
|
+
version: string;
|
|
276
|
+
visibility?: 'PRIVATE' | 'PUBLIC';
|
|
277
|
+
};
|
|
278
|
+
export type GetPackageOutput = {
|
|
279
|
+
package: RegistryPackage;
|
|
280
|
+
success: true;
|
|
281
|
+
} | {
|
|
282
|
+
reason: string;
|
|
283
|
+
success: false;
|
|
284
|
+
};
|
|
285
|
+
export type ListPackageVersionsOutput = {
|
|
286
|
+
packages: RegistryPackage[];
|
|
287
|
+
success: true;
|
|
288
|
+
} | {
|
|
289
|
+
reason: string;
|
|
290
|
+
success: false;
|
|
291
|
+
};
|
package/dist/backend/file.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Config } from '../lib/config/common.js';
|
|
2
|
-
import { AddPackageToWorkspaceInput, AddPackageToWorkspaceOutput, Backend, CreateWorkspaceInput, CreateWorkspaceOutput, DeleteStateInput, DeleteStateOutput, DeleteWorkspaceInput, DeleteWorkspaceOutput, ExportBackendOutput, GetProvisioningIdInput, GetProvisioningIdOutput, GetStateInput, GetStateOutput, GetWorkspaceEnvInput, GetWorkspaceEnvOutput, GetWorkspaceOutput, ImportBackendInput, ImportBackendOutput, InitProjectInput, InitProjectOutput, RemovePackageFromWorkspaceInput, RemovePackageFromWorkspaceOutput, SetEnvVarInput, SetEnvVarOutput, UnsetEnvVarInput, UnsetEnvVarOutput, UpdateWorkspaceInput, UpdateWorkspaceOutput } from './common.js';
|
|
2
|
+
import { AddPackageToWorkspaceInput, AddPackageToWorkspaceOutput, Backend, CreateWorkspaceInput, CreateWorkspaceOutput, DeleteStateInput, DeleteStateOutput, DeleteWorkspaceInput, DeleteWorkspaceOutput, ExportBackendOutput, GetPackageOutput, GetProvisioningIdInput, GetProvisioningIdOutput, GetStateInput, GetStateOutput, GetWorkspaceEnvInput, GetWorkspaceEnvOutput, GetWorkspaceOutput, ImportBackendInput, ImportBackendOutput, InitProjectInput, InitProjectOutput, ListPackageVersionsOutput, PublishPackageInput, PublishPackageOutput, RemovePackageFromWorkspaceInput, RemovePackageFromWorkspaceOutput, SetEnvVarInput, SetEnvVarOutput, UnsetEnvVarInput, UnsetEnvVarOutput, UpdateWorkspaceInput, UpdateWorkspaceOutput } from './common.js';
|
|
3
3
|
import { FileStorage } from './file-storage/common.js';
|
|
4
4
|
export declare class FileBackend implements Backend {
|
|
5
5
|
private readonly fileStorage;
|
|
@@ -9,13 +9,17 @@ export declare class FileBackend implements Backend {
|
|
|
9
9
|
deleteState(input: DeleteStateInput): Promise<DeleteStateOutput>;
|
|
10
10
|
deleteWorkspace(input: DeleteWorkspaceInput): Promise<DeleteWorkspaceOutput>;
|
|
11
11
|
exportBackend(): Promise<ExportBackendOutput>;
|
|
12
|
+
getPackageByVersion(_: string, __: string): Promise<GetPackageOutput>;
|
|
13
|
+
getPackageLatest(_: string): Promise<GetPackageOutput>;
|
|
12
14
|
getProvisioningId(input: GetProvisioningIdInput): Promise<GetProvisioningIdOutput>;
|
|
13
15
|
getState(input: GetStateInput): Promise<GetStateOutput>;
|
|
14
16
|
getWorkspace(workspace: string): Promise<GetWorkspaceOutput>;
|
|
15
17
|
getWorkspaceEnv(input: GetWorkspaceEnvInput): Promise<GetWorkspaceEnvOutput>;
|
|
16
18
|
importBackend(_: ImportBackendInput): Promise<ImportBackendOutput>;
|
|
17
19
|
init(options: InitProjectInput): Promise<InitProjectOutput>;
|
|
20
|
+
listPackageVersions(_: string): Promise<ListPackageVersionsOutput>;
|
|
18
21
|
listWorkspaces(): Promise<string[]>;
|
|
22
|
+
publishPackage(_: PublishPackageInput): Promise<PublishPackageOutput>;
|
|
19
23
|
removePackageFromWorkspace(input: RemovePackageFromWorkspaceInput): Promise<RemovePackageFromWorkspaceOutput>;
|
|
20
24
|
saveState(config: Config, workspace?: string): Promise<void>;
|
|
21
25
|
setEnvVar(input: SetEnvVarInput): Promise<SetEnvVarOutput>;
|
package/dist/backend/file.js
CHANGED
|
@@ -180,6 +180,18 @@ export class FileBackend {
|
|
|
180
180
|
success: false,
|
|
181
181
|
};
|
|
182
182
|
}
|
|
183
|
+
async getPackageByVersion(_, __) {
|
|
184
|
+
return {
|
|
185
|
+
reason: 'Package registry operations are only supported with the cloud backend. Please run `hereya login` to use cloud backend.',
|
|
186
|
+
success: false,
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
async getPackageLatest(_) {
|
|
190
|
+
return {
|
|
191
|
+
reason: 'Package registry operations are only supported with the cloud backend. Please run `hereya login` to use cloud backend.',
|
|
192
|
+
success: false,
|
|
193
|
+
};
|
|
194
|
+
}
|
|
183
195
|
async getProvisioningId(input) {
|
|
184
196
|
const idPaths = [`provisioning/${input.logicalId}.yaml`, `provisioning/${input.logicalId}.yml`];
|
|
185
197
|
const newId = `p-${randomUUID()}`;
|
|
@@ -331,6 +343,12 @@ export class FileBackend {
|
|
|
331
343
|
},
|
|
332
344
|
};
|
|
333
345
|
}
|
|
346
|
+
async listPackageVersions(_) {
|
|
347
|
+
return {
|
|
348
|
+
reason: 'Package registry operations are only supported with the cloud backend. Please run `hereya login` to use cloud backend.',
|
|
349
|
+
success: false,
|
|
350
|
+
};
|
|
351
|
+
}
|
|
334
352
|
async listWorkspaces() {
|
|
335
353
|
const workspaces$ = await this.fileStorage.listFileNames({ directory: 'state/workspaces' });
|
|
336
354
|
if (workspaces$.success) {
|
|
@@ -341,6 +359,12 @@ export class FileBackend {
|
|
|
341
359
|
}
|
|
342
360
|
throw new Error(`Could not list workspaces: ${workspaces$.error}`);
|
|
343
361
|
}
|
|
362
|
+
async publishPackage(_) {
|
|
363
|
+
return {
|
|
364
|
+
reason: 'Package registry operations are only supported with the cloud backend. Please run `hereya login` to use cloud backend.',
|
|
365
|
+
success: false,
|
|
366
|
+
};
|
|
367
|
+
}
|
|
344
368
|
async removePackageFromWorkspace(input) {
|
|
345
369
|
const workspace$ = await this.getWorkspace(input.workspace);
|
|
346
370
|
if (!workspace$.found) {
|
|
@@ -147,8 +147,9 @@ export default class Add extends Command {
|
|
|
147
147
|
const configManager = getConfigManager();
|
|
148
148
|
await configManager.addPackage({
|
|
149
149
|
metadata: ctx.provisionOutput.metadata,
|
|
150
|
-
package: ctx.
|
|
150
|
+
package: ctx.provisionOutput.pkgName,
|
|
151
151
|
projectRootDir,
|
|
152
|
+
version: ctx.provisionOutput.version,
|
|
152
153
|
});
|
|
153
154
|
await delay(500);
|
|
154
155
|
},
|
|
@@ -54,8 +54,20 @@ export default class Deploy extends Command {
|
|
|
54
54
|
async task(ctx) {
|
|
55
55
|
// Config already loaded above for validation
|
|
56
56
|
ctx.configOutput = loadConfigOutput;
|
|
57
|
-
|
|
58
|
-
|
|
57
|
+
// Get deploy packages with their versions
|
|
58
|
+
const deployPackages = loadConfigOutput.config.deploy ?? {};
|
|
59
|
+
ctx.deployPackages = Object.entries(deployPackages).map(([name, info]) => ({
|
|
60
|
+
name,
|
|
61
|
+
packageSpec: info.version ? `${name}@${info.version}` : name,
|
|
62
|
+
version: info.version || ''
|
|
63
|
+
}));
|
|
64
|
+
// Get regular packages with their versions
|
|
65
|
+
const packages = loadConfigOutput.config.packages ?? {};
|
|
66
|
+
ctx.packages = Object.entries(packages).map(([name, info]) => ({
|
|
67
|
+
name,
|
|
68
|
+
packageSpec: info.version ? `${name}@${info.version}` : name,
|
|
69
|
+
version: info.version || ''
|
|
70
|
+
}));
|
|
59
71
|
ctx.workspace = flags.workspace;
|
|
60
72
|
await delay(500);
|
|
61
73
|
},
|
|
@@ -97,10 +109,24 @@ export default class Deploy extends Command {
|
|
|
97
109
|
},
|
|
98
110
|
{
|
|
99
111
|
async task(ctx) {
|
|
100
|
-
const savedDeployPackages =
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
112
|
+
const savedDeployPackages = ctx.savedStateOutput?.config.deploy ?? {};
|
|
113
|
+
const currentDeployPackageNames = new Set(ctx.deployPackages.map(pkg => pkg.name));
|
|
114
|
+
ctx.removedDeployPackages = Object.entries(savedDeployPackages)
|
|
115
|
+
.filter(([name]) => !currentDeployPackageNames.has(name))
|
|
116
|
+
.map(([name, info]) => ({
|
|
117
|
+
name,
|
|
118
|
+
packageSpec: info.version ? `${name}@${info.version}` : name,
|
|
119
|
+
version: info.version || ''
|
|
120
|
+
}));
|
|
121
|
+
const savedPackages = ctx.savedStateOutput?.config.packages ?? {};
|
|
122
|
+
const currentPackageNames = new Set(ctx.packages.map(pkg => pkg.name));
|
|
123
|
+
ctx.removedPackages = Object.entries(savedPackages)
|
|
124
|
+
.filter(([name]) => !currentPackageNames.has(name))
|
|
125
|
+
.map(([name, info]) => ({
|
|
126
|
+
name,
|
|
127
|
+
packageSpec: info.version ? `${name}@${info.version}` : name,
|
|
128
|
+
version: info.version || ''
|
|
129
|
+
}));
|
|
104
130
|
await delay(500);
|
|
105
131
|
},
|
|
106
132
|
title: 'Identifying removed packages',
|
|
@@ -108,7 +134,7 @@ export default class Deploy extends Command {
|
|
|
108
134
|
{
|
|
109
135
|
skip: (ctx) => ctx.removedDeployPackages.length === 0,
|
|
110
136
|
task(ctx, task) {
|
|
111
|
-
return task.newListr(ctx.removedDeployPackages.map((
|
|
137
|
+
return task.newListr(ctx.removedDeployPackages.map((pkg) => ({
|
|
112
138
|
rendererOptions: {
|
|
113
139
|
persistentOutput: isDebug(),
|
|
114
140
|
},
|
|
@@ -117,7 +143,7 @@ export default class Deploy extends Command {
|
|
|
117
143
|
const backend = await getBackend();
|
|
118
144
|
const profile = await getProfileFromWorkspace(backend, ctx.workspace, ctx.configOutput.config.project);
|
|
119
145
|
const { parameters } = await parameterManager.getPackageParameters({
|
|
120
|
-
package:
|
|
146
|
+
package: pkg.name,
|
|
121
147
|
profile,
|
|
122
148
|
projectRootDir,
|
|
123
149
|
});
|
|
@@ -129,7 +155,7 @@ export default class Deploy extends Command {
|
|
|
129
155
|
const destroyOutput = await executor.destroy({
|
|
130
156
|
isDeploying: true,
|
|
131
157
|
logger: getLogger(task),
|
|
132
|
-
package:
|
|
158
|
+
package: pkg.packageSpec,
|
|
133
159
|
parameters,
|
|
134
160
|
project: ctx.configOutput.config.project,
|
|
135
161
|
projectEnv: ctx.projectEnv,
|
|
@@ -140,7 +166,7 @@ export default class Deploy extends Command {
|
|
|
140
166
|
throw new Error(destroyOutput.reason);
|
|
141
167
|
}
|
|
142
168
|
},
|
|
143
|
-
title: `Destroying package ${
|
|
169
|
+
title: `Destroying package ${pkg.name}`,
|
|
144
170
|
})), { concurrent: true, rendererOptions: { collapseSubtasks: !isDebug() } });
|
|
145
171
|
},
|
|
146
172
|
title: 'Destroying removed deployment packages',
|
|
@@ -148,7 +174,7 @@ export default class Deploy extends Command {
|
|
|
148
174
|
{
|
|
149
175
|
skip: (ctx) => ctx.removedPackages.length === 0,
|
|
150
176
|
task(ctx, task) {
|
|
151
|
-
return task.newListr(ctx.removedPackages.map((
|
|
177
|
+
return task.newListr(ctx.removedPackages.map((pkg) => ({
|
|
152
178
|
rendererOptions: {
|
|
153
179
|
persistentOutput: isDebug(),
|
|
154
180
|
},
|
|
@@ -157,7 +183,7 @@ export default class Deploy extends Command {
|
|
|
157
183
|
const backend = await getBackend();
|
|
158
184
|
const profile = await getProfileFromWorkspace(backend, ctx.workspace, ctx.configOutput.config.project);
|
|
159
185
|
const { parameters } = await parameterManager.getPackageParameters({
|
|
160
|
-
package:
|
|
186
|
+
package: pkg.name,
|
|
161
187
|
profile,
|
|
162
188
|
projectRootDir,
|
|
163
189
|
});
|
|
@@ -169,7 +195,7 @@ export default class Deploy extends Command {
|
|
|
169
195
|
const destroyOutput = await executor.destroy({
|
|
170
196
|
isDeploying: true,
|
|
171
197
|
logger: getLogger(task),
|
|
172
|
-
package:
|
|
198
|
+
package: pkg.packageSpec,
|
|
173
199
|
parameters,
|
|
174
200
|
project: ctx.configOutput.config.project,
|
|
175
201
|
projectRootDir,
|
|
@@ -180,10 +206,10 @@ export default class Deploy extends Command {
|
|
|
180
206
|
}
|
|
181
207
|
const { env, metadata } = destroyOutput;
|
|
182
208
|
const output = ctx.removed || [];
|
|
183
|
-
output.push({ env, metadata, packageName });
|
|
209
|
+
output.push({ env, metadata, packageName: pkg.name });
|
|
184
210
|
ctx.removed = output;
|
|
185
211
|
},
|
|
186
|
-
title: `Destroying ${
|
|
212
|
+
title: `Destroying ${pkg.name}`,
|
|
187
213
|
})), { concurrent: true, rendererOptions: { collapseSubtasks: !isDebug() } });
|
|
188
214
|
},
|
|
189
215
|
title: 'Destroying removed packages',
|
|
@@ -194,7 +220,7 @@ export default class Deploy extends Command {
|
|
|
194
220
|
if (!ctx.packages || ctx.packages.length === 0) {
|
|
195
221
|
return;
|
|
196
222
|
}
|
|
197
|
-
return task.newListr(ctx.packages.map((
|
|
223
|
+
return task.newListr(ctx.packages.map((pkg) => ({
|
|
198
224
|
rendererOptions: {
|
|
199
225
|
persistentOutput: isDebug(),
|
|
200
226
|
},
|
|
@@ -203,7 +229,7 @@ export default class Deploy extends Command {
|
|
|
203
229
|
const backend = await getBackend();
|
|
204
230
|
const profile = await getProfileFromWorkspace(backend, ctx.workspace, ctx.configOutput.config.project);
|
|
205
231
|
const { parameters } = await parameterManager.getPackageParameters({
|
|
206
|
-
package:
|
|
232
|
+
package: pkg.name,
|
|
207
233
|
profile,
|
|
208
234
|
projectRootDir,
|
|
209
235
|
});
|
|
@@ -215,7 +241,7 @@ export default class Deploy extends Command {
|
|
|
215
241
|
const provisionOutput = await executor.provision({
|
|
216
242
|
isDeploying: true,
|
|
217
243
|
logger: getLogger(task),
|
|
218
|
-
package:
|
|
244
|
+
package: pkg.packageSpec,
|
|
219
245
|
parameters,
|
|
220
246
|
project: ctx.configOutput.config.project,
|
|
221
247
|
projectRootDir,
|
|
@@ -226,10 +252,10 @@ export default class Deploy extends Command {
|
|
|
226
252
|
}
|
|
227
253
|
const { env, metadata } = provisionOutput;
|
|
228
254
|
const output = ctx.added || [];
|
|
229
|
-
output.push({ env, metadata, packageName });
|
|
255
|
+
output.push({ env, metadata, packageName: pkg.name });
|
|
230
256
|
ctx.added = output;
|
|
231
257
|
},
|
|
232
|
-
title: `Provisioning ${
|
|
258
|
+
title: `Provisioning ${pkg.name}`,
|
|
233
259
|
})), { concurrent: true, rendererOptions: { collapseSubtasks: !isDebug() } });
|
|
234
260
|
},
|
|
235
261
|
title: `Provisioning packages`,
|
|
@@ -300,7 +326,7 @@ export default class Deploy extends Command {
|
|
|
300
326
|
throw new Error(getProjectEnvOutput.reason);
|
|
301
327
|
}
|
|
302
328
|
const { env: projectEnv } = getProjectEnvOutput;
|
|
303
|
-
return task.newListr(ctx.deployPackages.map((
|
|
329
|
+
return task.newListr(ctx.deployPackages.map((pkg) => ({
|
|
304
330
|
rendererOptions: {
|
|
305
331
|
persistentOutput: isDebug(),
|
|
306
332
|
},
|
|
@@ -309,7 +335,7 @@ export default class Deploy extends Command {
|
|
|
309
335
|
const backend = await getBackend();
|
|
310
336
|
const profile = await getProfileFromWorkspace(backend, ctx.workspace, ctx.configOutput.config.project);
|
|
311
337
|
const { parameters } = await parameterManager.getPackageParameters({
|
|
312
|
-
package:
|
|
338
|
+
package: pkg.name,
|
|
313
339
|
profile,
|
|
314
340
|
projectRootDir,
|
|
315
341
|
});
|
|
@@ -321,7 +347,7 @@ export default class Deploy extends Command {
|
|
|
321
347
|
const provisionOutput = await executor.provision({
|
|
322
348
|
isDeploying: true,
|
|
323
349
|
logger: getLogger(task),
|
|
324
|
-
package:
|
|
350
|
+
package: pkg.packageSpec,
|
|
325
351
|
parameters,
|
|
326
352
|
project: ctx.configOutput.config.project,
|
|
327
353
|
projectEnv,
|
|
@@ -335,7 +361,7 @@ export default class Deploy extends Command {
|
|
|
335
361
|
.map(([key, value]) => `${key}=${value}`)
|
|
336
362
|
.join('\n'));
|
|
337
363
|
},
|
|
338
|
-
title: `Provisioning package ${
|
|
364
|
+
title: `Provisioning package ${pkg.name}`,
|
|
339
365
|
})), { concurrent: true, rendererOptions: { collapseSubtasks: !isDebug() } });
|
|
340
366
|
},
|
|
341
367
|
title: 'Provisioning deployment packages',
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class Doc extends Command {
|
|
3
|
+
static args: {
|
|
4
|
+
package: import("@oclif/core/interfaces").Arg<string, Record<string, unknown>>;
|
|
5
|
+
};
|
|
6
|
+
static description: string;
|
|
7
|
+
static examples: string[];
|
|
8
|
+
static flags: {
|
|
9
|
+
chdir: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
10
|
+
json: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
11
|
+
'no-doc': import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
12
|
+
};
|
|
13
|
+
run(): Promise<void>;
|
|
14
|
+
private displayMarkdown;
|
|
15
|
+
private displayPackage;
|
|
16
|
+
private parsePackageSpec;
|
|
17
|
+
}
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { Args, Command, Flags } from '@oclif/core';
|
|
2
|
+
import chalk from 'chalk';
|
|
3
|
+
import { marked } from 'marked';
|
|
4
|
+
import { markedTerminal } from 'marked-terminal';
|
|
5
|
+
import { getBackend } from '../../backend/index.js';
|
|
6
|
+
// Configure marked with terminal renderer
|
|
7
|
+
marked.use(markedTerminal({
|
|
8
|
+
reflowText: true,
|
|
9
|
+
showSectionPrefix: false,
|
|
10
|
+
width: 80,
|
|
11
|
+
}));
|
|
12
|
+
export default class Doc extends Command {
|
|
13
|
+
static args = {
|
|
14
|
+
package: Args.string({
|
|
15
|
+
description: 'Package name with optional version (e.g., my-package or my-package@1.0.0)',
|
|
16
|
+
required: true,
|
|
17
|
+
}),
|
|
18
|
+
};
|
|
19
|
+
static description = 'Display documentation for a package from the registry';
|
|
20
|
+
static examples = [
|
|
21
|
+
'<%= config.bin %> <%= command.id %> my-package',
|
|
22
|
+
'<%= config.bin %> <%= command.id %> my-package@1.0.0',
|
|
23
|
+
'<%= config.bin %> <%= command.id %> my-package --json',
|
|
24
|
+
'<%= config.bin %> <%= command.id %> my-package --no-doc',
|
|
25
|
+
];
|
|
26
|
+
static flags = {
|
|
27
|
+
chdir: Flags.directory({
|
|
28
|
+
char: 'C',
|
|
29
|
+
default: '.',
|
|
30
|
+
description: 'directory to run command in',
|
|
31
|
+
helpGroup: 'global',
|
|
32
|
+
}),
|
|
33
|
+
json: Flags.boolean({
|
|
34
|
+
char: 'j',
|
|
35
|
+
description: 'Output in JSON format',
|
|
36
|
+
}),
|
|
37
|
+
'no-doc': Flags.boolean({
|
|
38
|
+
description: 'Show only metadata without the full documentation',
|
|
39
|
+
}),
|
|
40
|
+
};
|
|
41
|
+
async run() {
|
|
42
|
+
const { args, flags } = await this.parse(Doc);
|
|
43
|
+
// Change to specified directory
|
|
44
|
+
if (flags.chdir !== '.') {
|
|
45
|
+
process.chdir(flags.chdir);
|
|
46
|
+
}
|
|
47
|
+
// Parse package name and version
|
|
48
|
+
const { name, version } = this.parsePackageSpec(args.package);
|
|
49
|
+
// Get backend
|
|
50
|
+
const backend = await getBackend();
|
|
51
|
+
// Check if backend supports registry operations
|
|
52
|
+
if (!backend.getPackageLatest || !backend.getPackageByVersion) {
|
|
53
|
+
this.error('Package registry operations are only supported with the cloud backend. Please run `hereya login` to use cloud backend.');
|
|
54
|
+
}
|
|
55
|
+
try {
|
|
56
|
+
// Fetch package information
|
|
57
|
+
const result = version
|
|
58
|
+
? await backend.getPackageByVersion(name, version)
|
|
59
|
+
: await backend.getPackageLatest(name);
|
|
60
|
+
if (!result.success) {
|
|
61
|
+
this.error(result.reason);
|
|
62
|
+
}
|
|
63
|
+
const pkg = result.package;
|
|
64
|
+
// Output JSON if requested
|
|
65
|
+
if (flags.json) {
|
|
66
|
+
this.log(JSON.stringify(pkg, null, 2));
|
|
67
|
+
return;
|
|
68
|
+
}
|
|
69
|
+
// Display package information
|
|
70
|
+
this.displayPackage(pkg, flags['no-doc']);
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
this.error(error instanceof Error ? error.message : 'Failed to fetch package documentation');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
displayMarkdown(content) {
|
|
77
|
+
// Render markdown for terminal display
|
|
78
|
+
const rendered = marked(content);
|
|
79
|
+
// Remove any trailing newlines to avoid extra spacing
|
|
80
|
+
this.log(rendered.trimEnd());
|
|
81
|
+
}
|
|
82
|
+
displayPackage(pkg, noDoc) {
|
|
83
|
+
// Header with package name, version, and visibility
|
|
84
|
+
const visibilityBadge = pkg.visibility === 'PUBLIC'
|
|
85
|
+
? chalk.green('PUBLIC')
|
|
86
|
+
: chalk.yellow('PRIVATE');
|
|
87
|
+
this.log(chalk.bold.cyan(`📦 ${pkg.name}@${pkg.version}`) + ' ' + visibilityBadge);
|
|
88
|
+
this.log('━'.repeat(50));
|
|
89
|
+
// Description
|
|
90
|
+
if (pkg.description) {
|
|
91
|
+
this.log(chalk.bold('Description:') + ' ' + pkg.description);
|
|
92
|
+
this.log();
|
|
93
|
+
}
|
|
94
|
+
// Repository and commit info
|
|
95
|
+
if (pkg.repository) {
|
|
96
|
+
this.log(chalk.bold('Repository:') + ' ' + chalk.blue.underline(pkg.repository));
|
|
97
|
+
}
|
|
98
|
+
if (pkg.commit) {
|
|
99
|
+
this.log(chalk.bold('Commit:') + ' ' + chalk.gray(pkg.commit));
|
|
100
|
+
}
|
|
101
|
+
if (pkg.sha256) {
|
|
102
|
+
this.log(chalk.bold('SHA256:') + ' ' + chalk.gray(pkg.sha256.slice(0, 16) + '...'));
|
|
103
|
+
}
|
|
104
|
+
// Infrastructure details
|
|
105
|
+
if (pkg.iac || pkg.infra) {
|
|
106
|
+
this.log();
|
|
107
|
+
this.log(`${chalk.bold('Infrastructure:')} ${pkg.iac || 'Unknown'} on ${pkg.infra || 'Unknown'}`);
|
|
108
|
+
}
|
|
109
|
+
// OnDeploy hook
|
|
110
|
+
if (pkg.onDeploy) {
|
|
111
|
+
this.log();
|
|
112
|
+
this.log(`${chalk.bold('On Deploy Hook:')} ${pkg.onDeploy.pkg}@${pkg.onDeploy.version}`);
|
|
113
|
+
}
|
|
114
|
+
// Timestamps
|
|
115
|
+
if (pkg.createdAt || pkg.updatedAt) {
|
|
116
|
+
this.log();
|
|
117
|
+
if (pkg.createdAt) {
|
|
118
|
+
const created = new Date(pkg.createdAt).toLocaleString();
|
|
119
|
+
this.log(`${chalk.bold('Created:')} ${chalk.gray(created)}`);
|
|
120
|
+
}
|
|
121
|
+
if (pkg.updatedAt) {
|
|
122
|
+
const updated = new Date(pkg.updatedAt).toLocaleString();
|
|
123
|
+
this.log(`${chalk.bold('Updated:')} ${chalk.gray(updated)}`);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// Documentation content
|
|
127
|
+
if (!noDoc && pkg.doc) {
|
|
128
|
+
this.log();
|
|
129
|
+
this.log(chalk.bold.blue('━━━ Documentation ━━━'));
|
|
130
|
+
this.log();
|
|
131
|
+
this.displayMarkdown(pkg.doc);
|
|
132
|
+
}
|
|
133
|
+
else if (!noDoc && !pkg.doc) {
|
|
134
|
+
this.log();
|
|
135
|
+
this.log(chalk.gray('(No documentation available)'));
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
parsePackageSpec(spec) {
|
|
139
|
+
const atIndex = spec.lastIndexOf('@');
|
|
140
|
+
// Handle scoped packages like @org/package
|
|
141
|
+
if (atIndex > 0) {
|
|
142
|
+
const possibleVersion = spec.slice(atIndex + 1);
|
|
143
|
+
// Check if what comes after @ looks like a version
|
|
144
|
+
if (/^\d+\.\d+\.\d+/.test(possibleVersion)) {
|
|
145
|
+
return {
|
|
146
|
+
name: spec.slice(0, atIndex),
|
|
147
|
+
version: possibleVersion,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// No version specified
|
|
152
|
+
return { name: spec };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
@@ -71,21 +71,50 @@ export default class Down extends Command {
|
|
|
71
71
|
},
|
|
72
72
|
{
|
|
73
73
|
async task(ctx) {
|
|
74
|
-
|
|
74
|
+
// Get packages with their versions from config
|
|
75
|
+
const configPackages = ctx.configOutput.config.packages ?? {};
|
|
76
|
+
let packagesWithVersions = Object.entries(configPackages).map(([name, info]) => ({
|
|
77
|
+
name,
|
|
78
|
+
packageSpec: info.version ? `${name}@${info.version}` : name,
|
|
79
|
+
version: info.version || ''
|
|
80
|
+
}));
|
|
75
81
|
const backend = await getBackend();
|
|
76
82
|
const savedStateOutput = await backend.getState({
|
|
77
83
|
project: ctx.configOutput.config.project,
|
|
78
84
|
workspace: ctx.workspace,
|
|
79
85
|
});
|
|
80
|
-
let
|
|
86
|
+
let removedPackagesWithVersions = [];
|
|
81
87
|
if (savedStateOutput.found) {
|
|
82
|
-
const savedPackages =
|
|
83
|
-
|
|
88
|
+
const savedPackages = savedStateOutput.config.packages ?? {};
|
|
89
|
+
removedPackagesWithVersions = Object.entries(savedPackages)
|
|
90
|
+
.filter(([name]) => !configPackages[name])
|
|
91
|
+
.map(([name, info]) => ({
|
|
92
|
+
name,
|
|
93
|
+
packageSpec: info.version ? `${name}@${info.version}` : name,
|
|
94
|
+
version: info.version || ''
|
|
95
|
+
}));
|
|
84
96
|
}
|
|
97
|
+
// Handle --select flag with version validation
|
|
85
98
|
if (flags.select.length > 0) {
|
|
86
|
-
|
|
99
|
+
const selectedPackages = [];
|
|
100
|
+
for (const selectedPkg of flags.select) {
|
|
101
|
+
// Parse the selected package to extract name and version
|
|
102
|
+
const [selectedName, selectedVersion] = selectedPkg.split('@');
|
|
103
|
+
// Find the package in the config
|
|
104
|
+
const configPkg = packagesWithVersions.find(pkg => pkg.name === selectedName);
|
|
105
|
+
if (!configPkg) {
|
|
106
|
+
throw new Error(`Package ${selectedName} not found in project`);
|
|
107
|
+
}
|
|
108
|
+
// If user specified a version, validate it matches the installed version
|
|
109
|
+
if (selectedVersion && selectedVersion !== configPkg.version) {
|
|
110
|
+
throw new Error(`Package ${selectedName} version mismatch: installed version is ${configPkg.version || 'unspecified'}, but you specified ${selectedVersion}. ` +
|
|
111
|
+
`Please use 'hereya down -s ${selectedName}' to use the installed version.`);
|
|
112
|
+
}
|
|
113
|
+
selectedPackages.push(configPkg);
|
|
114
|
+
}
|
|
115
|
+
packagesWithVersions = selectedPackages;
|
|
87
116
|
}
|
|
88
|
-
ctx.packages = [...
|
|
117
|
+
ctx.packages = [...packagesWithVersions, ...removedPackagesWithVersions];
|
|
89
118
|
await delay(500);
|
|
90
119
|
},
|
|
91
120
|
title: 'Identifying packages to destroy',
|
|
@@ -96,7 +125,7 @@ export default class Down extends Command {
|
|
|
96
125
|
if (!ctx.packages || ctx.packages.length === 0) {
|
|
97
126
|
return;
|
|
98
127
|
}
|
|
99
|
-
return task.newListr(ctx.packages.map((
|
|
128
|
+
return task.newListr(ctx.packages.map((pkg) => ({
|
|
100
129
|
rendererOptions: {
|
|
101
130
|
persistentOutput: isDebug(),
|
|
102
131
|
},
|
|
@@ -105,7 +134,7 @@ export default class Down extends Command {
|
|
|
105
134
|
const backend = await getBackend();
|
|
106
135
|
const profile = await getProfileFromWorkspace(backend, ctx.workspace, ctx.configOutput.config.project);
|
|
107
136
|
const { parameters } = await parameterManager.getPackageParameters({
|
|
108
|
-
package:
|
|
137
|
+
package: pkg.name,
|
|
109
138
|
profile,
|
|
110
139
|
projectRootDir,
|
|
111
140
|
});
|
|
@@ -117,7 +146,7 @@ export default class Down extends Command {
|
|
|
117
146
|
const destroyOutput = await executor.destroy({
|
|
118
147
|
isDeploying: flags.deploy,
|
|
119
148
|
logger: getLogger(task),
|
|
120
|
-
package:
|
|
149
|
+
package: pkg.packageSpec,
|
|
121
150
|
parameters,
|
|
122
151
|
project: ctx.configOutput.config.project,
|
|
123
152
|
projectRootDir,
|
|
@@ -128,10 +157,10 @@ export default class Down extends Command {
|
|
|
128
157
|
}
|
|
129
158
|
const { env, metadata } = destroyOutput;
|
|
130
159
|
const output = ctx.destroyed || [];
|
|
131
|
-
output.push({ env, metadata, packageName });
|
|
160
|
+
output.push({ env, metadata, packageName: pkg.name });
|
|
132
161
|
ctx.destroyed = output;
|
|
133
162
|
},
|
|
134
|
-
title: `Destroying ${
|
|
163
|
+
title: `Destroying ${pkg.name}`,
|
|
135
164
|
})), { concurrent: true, rendererOptions: { collapseSubtasks: !isDebug() } });
|
|
136
165
|
},
|
|
137
166
|
title: `Destroying packages`,
|