hereya-cli 0.39.0 → 0.40.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.
package/README.md CHANGED
@@ -20,7 +20,7 @@ $ npm install -g hereya-cli
20
20
  $ hereya COMMAND
21
21
  running command...
22
22
  $ hereya (--version)
23
- hereya-cli/0.39.0 linux-x64 node-v22.16.0
23
+ hereya-cli/0.40.1 linux-x64 node-v22.16.0
24
24
  $ hereya --help [COMMAND]
25
25
  USAGE
26
26
  $ hereya COMMAND
@@ -40,6 +40,7 @@ USAGE
40
40
  * [`hereya env [NAME]`](#hereya-env-name)
41
41
  * [`hereya env set [NAME]`](#hereya-env-set-name)
42
42
  * [`hereya help [COMMAND]`](#hereya-help-command)
43
+ * [`hereya import PACKAGE`](#hereya-import-package)
43
44
  * [`hereya init PROJECT`](#hereya-init-project)
44
45
  * [`hereya login [URL]`](#hereya-login-url)
45
46
  * [`hereya logout`](#hereya-logout)
@@ -88,7 +89,7 @@ EXAMPLES
88
89
  $ hereya add cloudy/docker_postgres
89
90
  ```
90
91
 
91
- _See code: [src/commands/add/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/add/index.ts)_
92
+ _See code: [src/commands/add/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/add/index.ts)_
92
93
 
93
94
  ## `hereya bootstrap INFRASTRUCTURETYPE`
94
95
 
@@ -113,7 +114,7 @@ EXAMPLES
113
114
  $ hereya bootstrap local
114
115
  ```
115
116
 
116
- _See code: [src/commands/bootstrap/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/bootstrap/index.ts)_
117
+ _See code: [src/commands/bootstrap/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/bootstrap/index.ts)_
117
118
 
118
119
  ## `hereya config export-backend [FILE]`
119
120
 
@@ -135,7 +136,7 @@ EXAMPLES
135
136
  $ hereya config export-backend ./path/to/export.json
136
137
  ```
137
138
 
138
- _See code: [src/commands/config/export-backend/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/config/export-backend/index.ts)_
139
+ _See code: [src/commands/config/export-backend/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/config/export-backend/index.ts)_
139
140
 
140
141
  ## `hereya config get-backend`
141
142
 
@@ -152,7 +153,7 @@ EXAMPLES
152
153
  $ hereya config get-backend
153
154
  ```
154
155
 
155
- _See code: [src/commands/config/get-backend/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/config/get-backend/index.ts)_
156
+ _See code: [src/commands/config/get-backend/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/config/get-backend/index.ts)_
156
157
 
157
158
  ## `hereya config import-backend FILE`
158
159
 
@@ -172,7 +173,7 @@ EXAMPLES
172
173
  $ hereya config import-backend ./path/to/cloud-backend.json
173
174
  ```
174
175
 
175
- _See code: [src/commands/config/import-backend/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/config/import-backend/index.ts)_
176
+ _See code: [src/commands/config/import-backend/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/config/import-backend/index.ts)_
176
177
 
177
178
  ## `hereya config use-backend TYPE`
178
179
 
@@ -194,7 +195,7 @@ EXAMPLES
194
195
  $ hereya config use-backend local
195
196
  ```
196
197
 
197
- _See code: [src/commands/config/use-backend/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/config/use-backend/index.ts)_
198
+ _See code: [src/commands/config/use-backend/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/config/use-backend/index.ts)_
198
199
 
199
200
  ## `hereya deploy`
200
201
 
@@ -219,7 +220,7 @@ EXAMPLES
219
220
  $ hereya deploy
220
221
  ```
221
222
 
222
- _See code: [src/commands/deploy/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/deploy/index.ts)_
223
+ _See code: [src/commands/deploy/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/deploy/index.ts)_
223
224
 
224
225
  ## `hereya down`
225
226
 
@@ -246,7 +247,7 @@ EXAMPLES
246
247
  $ hereya down
247
248
  ```
248
249
 
249
- _See code: [src/commands/down/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/down/index.ts)_
250
+ _See code: [src/commands/down/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/down/index.ts)_
250
251
 
251
252
  ## `hereya env [NAME]`
252
253
 
@@ -277,7 +278,7 @@ EXAMPLES
277
278
  $ hereya env -w dev -l
278
279
  ```
279
280
 
280
- _See code: [src/commands/env/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/env/index.ts)_
281
+ _See code: [src/commands/env/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/env/index.ts)_
281
282
 
282
283
  ## `hereya env set [NAME]`
283
284
 
@@ -304,7 +305,7 @@ EXAMPLES
304
305
  $ hereya env set FOO -v bar -w dev
305
306
  ```
306
307
 
307
- _See code: [src/commands/env/set/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/env/set/index.ts)_
308
+ _See code: [src/commands/env/set/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/env/set/index.ts)_
308
309
 
309
310
  ## `hereya help [COMMAND]`
310
311
 
@@ -326,6 +327,43 @@ DESCRIPTION
326
327
 
327
328
  _See code: [@oclif/plugin-help](https://github.com/oclif/plugin-help/blob/v6.2.25/src/commands/help.ts)_
328
329
 
330
+ ## `hereya import PACKAGE`
331
+
332
+ Import a package resource into your project
333
+
334
+ ```
335
+ USAGE
336
+ $ hereya import PACKAGE -f <value> [--chdir <value>] [--debug] [-p <value>...] [-w <value>]
337
+
338
+ ARGUMENTS
339
+ PACKAGE The package to import, specified as a GitHub repository in the format owner/repository.
340
+ To change the registry URL, set the HEREYA_REGISTRY_URL environment variable, so that it points to
341
+ $HEREYA_REGISTRY_URL/owner/repository.
342
+ For local packages, use the format local://path/to/package where path/to/package is the path to the package
343
+ on your local machine.
344
+
345
+ FLAGS
346
+ -f, --stateFile=<value> (required) state file to use
347
+ -p, --parameter=<value>... [default: ] parameters for the package, in the form of 'key=value'. Can be specified
348
+ multiple times.
349
+ -w, --workspace=<value> workspace to import into
350
+ --chdir=<value> Directory where the command will be executed.
351
+ If not specified, it defaults to the current working directory.
352
+ Alternatively, you can define the project root by setting the HEREYA_PROJECT_ROOT_DIR
353
+ environment variable.
354
+ --debug enable debug mode
355
+
356
+ DESCRIPTION
357
+ Import a package resource into your project
358
+
359
+ EXAMPLES
360
+ $ hereya import hereya/my-package -f state.tfstate
361
+
362
+ $ hereya import org/my-package -f state.tfstate -w my-workspace
363
+ ```
364
+
365
+ _See code: [src/commands/import/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/import/index.ts)_
366
+
329
367
  ## `hereya init PROJECT`
330
368
 
331
369
  Initialize hereya in a project directory.
@@ -350,7 +388,7 @@ EXAMPLES
350
388
  $ hereya init myProject -w=defaultWorkspace --chdir=./myProject
351
389
  ```
352
390
 
353
- _See code: [src/commands/init/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/init/index.ts)_
391
+ _See code: [src/commands/init/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/init/index.ts)_
354
392
 
355
393
  ## `hereya login [URL]`
356
394
 
@@ -379,7 +417,7 @@ EXAMPLES
379
417
  $ hereya login --token=your-token https://cloud.hereya.dev
380
418
  ```
381
419
 
382
- _See code: [src/commands/login/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/login/index.ts)_
420
+ _See code: [src/commands/login/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/login/index.ts)_
383
421
 
384
422
  ## `hereya logout`
385
423
 
@@ -396,7 +434,7 @@ EXAMPLES
396
434
  $ hereya logout
397
435
  ```
398
436
 
399
- _See code: [src/commands/logout/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/logout/index.ts)_
437
+ _See code: [src/commands/logout/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/logout/index.ts)_
400
438
 
401
439
  ## `hereya remove PACKAGE`
402
440
 
@@ -423,7 +461,7 @@ EXAMPLES
423
461
  $ hereya remove cloudy/docker_postgres
424
462
  ```
425
463
 
426
- _See code: [src/commands/remove/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/remove/index.ts)_
464
+ _See code: [src/commands/remove/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/remove/index.ts)_
427
465
 
428
466
  ## `hereya run CMD`
429
467
 
@@ -449,7 +487,7 @@ EXAMPLES
449
487
  $ hereya run -w uat -- node index.js
450
488
  ```
451
489
 
452
- _See code: [src/commands/run/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/run/index.ts)_
490
+ _See code: [src/commands/run/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/run/index.ts)_
453
491
 
454
492
  ## `hereya unbootstrap INFRASTRUCTURETYPE`
455
493
 
@@ -474,7 +512,7 @@ EXAMPLES
474
512
  $ hereya unbootstrap local
475
513
  ```
476
514
 
477
- _See code: [src/commands/unbootstrap/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/unbootstrap/index.ts)_
515
+ _See code: [src/commands/unbootstrap/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/unbootstrap/index.ts)_
478
516
 
479
517
  ## `hereya undeploy`
480
518
 
@@ -499,7 +537,7 @@ EXAMPLES
499
537
  $ hereya undeploy
500
538
  ```
501
539
 
502
- _See code: [src/commands/undeploy/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/undeploy/index.ts)_
540
+ _See code: [src/commands/undeploy/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/undeploy/index.ts)_
503
541
 
504
542
  ## `hereya up`
505
543
 
@@ -526,7 +564,7 @@ EXAMPLES
526
564
  $ hereya up
527
565
  ```
528
566
 
529
- _See code: [src/commands/up/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/up/index.ts)_
567
+ _See code: [src/commands/up/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/up/index.ts)_
530
568
 
531
569
  ## `hereya workspace create NAME`
532
570
 
@@ -549,7 +587,7 @@ EXAMPLES
549
587
  $ hereya workspace create dev
550
588
  ```
551
589
 
552
- _See code: [src/commands/workspace/create/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/workspace/create/index.ts)_
590
+ _See code: [src/commands/workspace/create/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/workspace/create/index.ts)_
553
591
 
554
592
  ## `hereya workspace delete NAME`
555
593
 
@@ -569,7 +607,7 @@ EXAMPLES
569
607
  $ hereya workspace delete dev
570
608
  ```
571
609
 
572
- _See code: [src/commands/workspace/delete/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/workspace/delete/index.ts)_
610
+ _See code: [src/commands/workspace/delete/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/workspace/delete/index.ts)_
573
611
 
574
612
  ## `hereya workspace env [NAME]`
575
613
 
@@ -595,7 +633,7 @@ EXAMPLES
595
633
  $ hereya workspace env myEnv -w dev
596
634
  ```
597
635
 
598
- _See code: [src/commands/workspace/env/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/workspace/env/index.ts)_
636
+ _See code: [src/commands/workspace/env/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/workspace/env/index.ts)_
599
637
 
600
638
  ## `hereya workspace env set`
601
639
 
@@ -619,7 +657,7 @@ EXAMPLES
619
657
  $ hereya workspace env set -w my-workspace -n myVar -v my-value -i aws -s
620
658
  ```
621
659
 
622
- _See code: [src/commands/workspace/env/set/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/workspace/env/set/index.ts)_
660
+ _See code: [src/commands/workspace/env/set/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/workspace/env/set/index.ts)_
623
661
 
624
662
  ## `hereya workspace env unset`
625
663
 
@@ -640,7 +678,7 @@ EXAMPLES
640
678
  $ hereya workspace env unset -w my-workspace -n myVar
641
679
  ```
642
680
 
643
- _See code: [src/commands/workspace/env/unset/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/workspace/env/unset/index.ts)_
681
+ _See code: [src/commands/workspace/env/unset/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/workspace/env/unset/index.ts)_
644
682
 
645
683
  ## `hereya workspace install PACKAGE`
646
684
 
@@ -667,7 +705,7 @@ EXAMPLES
667
705
  $ hereya workspace install hereya/aws-cognito
668
706
  ```
669
707
 
670
- _See code: [src/commands/workspace/install/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/workspace/install/index.ts)_
708
+ _See code: [src/commands/workspace/install/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/workspace/install/index.ts)_
671
709
 
672
710
  ## `hereya workspace list`
673
711
 
@@ -684,7 +722,7 @@ EXAMPLES
684
722
  $ hereya workspace list
685
723
  ```
686
724
 
687
- _See code: [src/commands/workspace/list/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/workspace/list/index.ts)_
725
+ _See code: [src/commands/workspace/list/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/workspace/list/index.ts)_
688
726
 
689
727
  ## `hereya workspace uninstall PACKAGE`
690
728
 
@@ -711,5 +749,5 @@ EXAMPLES
711
749
  $ hereya workspace uninstall hereya/aws-cognito
712
750
  ```
713
751
 
714
- _See code: [src/commands/workspace/uninstall/index.ts](https://github.com/hereya/hereya-cli/blob/v0.39.0/src/commands/workspace/uninstall/index.ts)_
752
+ _See code: [src/commands/workspace/uninstall/index.ts](https://github.com/hereya/hereya-cli/blob/v0.40.1/src/commands/workspace/uninstall/index.ts)_
715
753
  <!-- commandsstop -->
@@ -148,7 +148,7 @@ async function waitForAuthorizationCode(port) {
148
148
  });
149
149
  }
150
150
  export async function refreshToken(url, refreshToken) {
151
- const response = await fetch(`${url}/auth/refresh`, {
151
+ const response = await fetch(`${url}/auth/cli/refresh`, {
152
152
  headers: {
153
153
  Authorization: `Bearer ${refreshToken}`,
154
154
  },
@@ -0,0 +1,16 @@
1
+ import { Command } from '@oclif/core';
2
+ export default class Import 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 | undefined, import("@oclif/core/interfaces").CustomOptions>;
10
+ debug: import("@oclif/core/interfaces").BooleanFlag<boolean>;
11
+ parameter: import("@oclif/core/interfaces").OptionFlag<string[] | undefined, import("@oclif/core/interfaces").CustomOptions>;
12
+ stateFile: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
13
+ workspace: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
14
+ };
15
+ run(): Promise<void>;
16
+ }
@@ -0,0 +1,172 @@
1
+ import { Args, Command, Flags } from '@oclif/core';
2
+ import { Listr, ListrLogger, ListrLogLevels } from 'listr2';
3
+ import { getBackend } from '../../backend/index.js';
4
+ import { getExecutor } from '../../executor/index.js';
5
+ import { getConfigManager } from '../../lib/config/index.js';
6
+ import { logEnv } from '../../lib/env-utils.js';
7
+ import { getLogPath, isDebug, setDebug } from '../../lib/log.js';
8
+ import { arrayOfStringToObject } from '../../lib/object-utils.js';
9
+ import { getParameterManager } from '../../lib/parameter/index.js';
10
+ import { delay } from '../../lib/shell.js';
11
+ export default class Import extends Command {
12
+ static args = {
13
+ package: Args.string({
14
+ description: `
15
+ The package to import, specified as a GitHub repository in the format owner/repository.
16
+ To change the registry URL, set the HEREYA_REGISTRY_URL environment variable, so that it points to $HEREYA_REGISTRY_URL/owner/repository.
17
+ For local packages, use the format local://path/to/package where path/to/package is the path to the package on your local machine.
18
+ `,
19
+ required: true,
20
+ }),
21
+ };
22
+ static description = 'Import a package resource into your project';
23
+ static examples = [
24
+ '<%= config.bin %> <%= command.id %> hereya/my-package -f state.tfstate',
25
+ '<%= config.bin %> <%= command.id %> org/my-package -f state.tfstate -w my-workspace',
26
+ ];
27
+ static flags = {
28
+ chdir: Flags.string({
29
+ description: `
30
+ Directory where the command will be executed.
31
+ If not specified, it defaults to the current working directory.
32
+ Alternatively, you can define the project root by setting the HEREYA_PROJECT_ROOT_DIR environment variable.
33
+ `,
34
+ required: false,
35
+ }),
36
+ debug: Flags.boolean({
37
+ default: false,
38
+ description: 'enable debug mode',
39
+ }),
40
+ parameter: Flags.string({
41
+ char: 'p',
42
+ default: [],
43
+ description: "parameters for the package, in the form of 'key=value'. Can be specified multiple times.",
44
+ multiple: true,
45
+ required: false,
46
+ }),
47
+ stateFile: Flags.string({
48
+ char: 'f',
49
+ description: 'state file to use',
50
+ required: true,
51
+ }),
52
+ workspace: Flags.string({
53
+ char: 'w',
54
+ description: 'workspace to import into',
55
+ required: false,
56
+ }),
57
+ };
58
+ async run() {
59
+ const { args, flags } = await this.parse(Import);
60
+ setDebug(flags.debug);
61
+ const projectRootDir = flags.chdir || process.env.HEREYA_PROJECT_ROOT_DIR;
62
+ const myLogger = new ListrLogger({ useIcons: false });
63
+ const task = new Listr([
64
+ {
65
+ async task(ctx, task) {
66
+ return task.newListr([
67
+ {
68
+ async task(ctx) {
69
+ ctx.package = args.package;
70
+ ctx.userSpecifiedParameters = flags.parameter || [];
71
+ },
72
+ },
73
+ {
74
+ async task(ctx, task) {
75
+ const configManager = getConfigManager();
76
+ const loadConfigOutput = await configManager.loadConfig({ projectRootDir });
77
+ if (!loadConfigOutput.found) {
78
+ throw new Error("Project not initialized. Run 'hereya init' first.");
79
+ }
80
+ ctx.configOutput = loadConfigOutput;
81
+ ctx.workspace = flags.workspace || loadConfigOutput.config.workspace;
82
+ task.output = `Loaded project config`;
83
+ await delay(500);
84
+ },
85
+ title: 'Loading project config',
86
+ },
87
+ {
88
+ async task(ctx) {
89
+ const userSpecifiedParameters = arrayOfStringToObject(ctx.userSpecifiedParameters);
90
+ const parameterManager = getParameterManager();
91
+ const parametersOutput = await parameterManager.getPackageParameters({
92
+ package: ctx.package,
93
+ projectRootDir,
94
+ userSpecifiedParameters,
95
+ workspace: ctx.workspace,
96
+ });
97
+ ctx.parametersOutput = parametersOutput;
98
+ await delay(500);
99
+ },
100
+ title: 'Resolving package parameters',
101
+ },
102
+ {
103
+ async task(ctx) {
104
+ const executor$ = getExecutor();
105
+ if (!executor$.success) {
106
+ throw new Error(executor$.reason);
107
+ }
108
+ const { executor } = executor$;
109
+ const importOutput = await executor.import({
110
+ package: ctx.package,
111
+ project: ctx.configOutput.config.project,
112
+ projectRootDir,
113
+ stateFile: flags.stateFile,
114
+ workspace: ctx.workspace,
115
+ });
116
+ if (!importOutput.success) {
117
+ throw new Error(importOutput.reason);
118
+ }
119
+ ctx.importOutput = importOutput;
120
+ },
121
+ },
122
+ {
123
+ skip: (ctx) => Boolean(flags.workspace) && flags.workspace !== ctx.configOutput.config.workspace,
124
+ async task(ctx) {
125
+ const configManager = getConfigManager();
126
+ await configManager.addPackage({
127
+ metadata: ctx.importOutput.metadata,
128
+ package: ctx.package,
129
+ projectRootDir,
130
+ });
131
+ await delay(500);
132
+ },
133
+ title: 'Adding package to hereya manifest',
134
+ },
135
+ {
136
+ async task(ctx) {
137
+ const backend = await getBackend();
138
+ const configManager = getConfigManager();
139
+ const { config: newConfig } = await configManager.loadConfig({ projectRootDir });
140
+ await backend.saveState(newConfig);
141
+ const parameterManager = getParameterManager();
142
+ const { filePath, saved } = await parameterManager.savePackageParameters({
143
+ package: ctx.package,
144
+ parameters: ctx.parametersOutput.parameters,
145
+ projectRootDir,
146
+ workspace: ctx.workspace,
147
+ });
148
+ await delay(500);
149
+ if (saved) {
150
+ myLogger.log(ListrLogLevels.COMPLETED, `Saved the following parameters for the package in ${filePath}:`);
151
+ logEnv(ctx.parametersOutput.parameters, (msg) => myLogger.log(ListrLogLevels.COMPLETED, msg));
152
+ }
153
+ },
154
+ title: 'Saving state',
155
+ },
156
+ ], { concurrent: false, rendererOptions: { collapseSubtasks: !isDebug() } });
157
+ },
158
+ title: `Importing ${args.package} into workspace ${flags.workspace}`,
159
+ },
160
+ ], { concurrent: false });
161
+ try {
162
+ await task.run();
163
+ myLogger.log(ListrLogLevels.COMPLETED, 'Package imported successfully. You can now run `hereya up` to inject exported environment variables.');
164
+ }
165
+ catch (error) {
166
+ this.error(`${error.message}
167
+
168
+ See ${getLogPath()} for more details
169
+ `);
170
+ }
171
+ }
172
+ }
@@ -60,8 +60,23 @@ export type ExecutorUnsetEnvVarInput = {
60
60
  name: string;
61
61
  workspace: string;
62
62
  };
63
+ export type ExecutorImportInput = {
64
+ package: string;
65
+ project: string;
66
+ projectRootDir?: string;
67
+ stateFile: string;
68
+ workspace: string;
69
+ };
70
+ export type ExecutorImportOutput = {
71
+ metadata: IPackageMetadata;
72
+ success: true;
73
+ } | {
74
+ reason: string;
75
+ success: false;
76
+ };
63
77
  export interface Executor {
64
78
  destroy(input: ExecutorDestroyInput): Promise<ExecutorDestroyOutput>;
79
+ import(input: ExecutorImportInput): Promise<ExecutorImportOutput>;
65
80
  provision(input: ExecutorProvisionInput): Promise<ExecutorProvisionOutput>;
66
81
  resolveEnvValues(input: ExecutorResolveEnvValuesInput): Promise<ExecutorResolveEnvValuesOutput>;
67
82
  setEnvVar(input: ExecutorSetEnvVarInput): Promise<ExecutorSetEnvVarOutput>;
@@ -1,6 +1,7 @@
1
- import { Executor, ExecutorDestroyInput, ExecutorDestroyOutput, ExecutorProvisionInput, ExecutorProvisionOutput, ExecutorResolveEnvValuesInput, ExecutorResolveEnvValuesOutput, ExecutorSetEnvVarInput, ExecutorSetEnvVarOutput, ExecutorUnsetEnvVarInput, ExecutorUnsetEnvVarOutput } from './interface.js';
1
+ import { Executor, ExecutorDestroyInput, ExecutorDestroyOutput, ExecutorImportInput, ExecutorImportOutput, ExecutorProvisionInput, ExecutorProvisionOutput, ExecutorResolveEnvValuesInput, ExecutorResolveEnvValuesOutput, ExecutorSetEnvVarInput, ExecutorSetEnvVarOutput, ExecutorUnsetEnvVarInput, ExecutorUnsetEnvVarOutput } from './interface.js';
2
2
  export declare class LocalExecutor implements Executor {
3
3
  destroy(input: ExecutorDestroyInput): Promise<ExecutorDestroyOutput>;
4
+ import(input: ExecutorImportInput): Promise<ExecutorImportOutput>;
4
5
  provision(input: ExecutorProvisionInput): Promise<ExecutorProvisionOutput>;
5
6
  resolveEnvValues(input: ExecutorResolveEnvValuesInput): Promise<ExecutorResolveEnvValuesOutput>;
6
7
  setEnvVar(input: ExecutorSetEnvVarInput): Promise<ExecutorSetEnvVarOutput>;
@@ -1,5 +1,6 @@
1
1
  import { getBackend } from '../backend/index.js';
2
- import { destroyPackage, getInfrastructure, provisionPackage } from '../infrastructure/index.js';
2
+ import { destroyPackage, getInfrastructure, getProvisioningLogicalId, provisionPackage } from '../infrastructure/index.js';
3
+ import { resolvePackage } from '../lib/package/index.js';
3
4
  export class LocalExecutor {
4
5
  async destroy(input) {
5
6
  const getWorkspaceEnvOutput = await this.getWorkspaceEnv({
@@ -15,6 +16,38 @@ export class LocalExecutor {
15
16
  logger: input.logger,
16
17
  });
17
18
  }
19
+ async import(input) {
20
+ const resolvePackageOutput = await resolvePackage({ package: input.package, projectRootDir: input.projectRootDir });
21
+ if (!resolvePackageOutput.found) {
22
+ return { reason: resolvePackageOutput.reason, success: false };
23
+ }
24
+ const { canonicalName, metadata, pkgName } = resolvePackageOutput;
25
+ const backend = await getBackend();
26
+ const id$ = await backend.getProvisioningId({
27
+ logicalId: getProvisioningLogicalId({ pkg: pkgName, project: input.project, workspace: input.workspace }),
28
+ packageCanonicalName: canonicalName,
29
+ project: input.project,
30
+ workspace: input.workspace,
31
+ });
32
+ if (!id$.success) {
33
+ return { reason: id$.reason, success: false };
34
+ }
35
+ const { id } = id$;
36
+ const infrastructure$ = getInfrastructure({ type: metadata.infra });
37
+ if (!infrastructure$.supported) {
38
+ return { reason: infrastructure$.reason, success: false };
39
+ }
40
+ const { infrastructure } = infrastructure$;
41
+ const uploadStateFileOutput = await infrastructure.uploadStateFile({
42
+ iacType: metadata.iac,
43
+ provisioningId: id,
44
+ stateFile: input.stateFile,
45
+ });
46
+ if (!uploadStateFileOutput.success) {
47
+ return { reason: uploadStateFileOutput.reason, success: false };
48
+ }
49
+ return { metadata, success: true };
50
+ }
18
51
  async provision(input) {
19
52
  const getWorkspaceEnvOutput = await this.getWorkspaceEnv({
20
53
  project: input.project,
package/dist/iac/cdk.d.ts CHANGED
@@ -1,7 +1,8 @@
1
- import { ApplyInput, ApplyOutput, DestroyInput, DestroyOutput, Iac } from './common.js';
1
+ import { ApplyInput, ApplyOutput, DestroyInput, DestroyOutput, GetStateLocationInput, GetStateLocationOutput, Iac } from './common.js';
2
2
  export declare class Cdk implements Iac {
3
3
  apply(input: ApplyInput): Promise<ApplyOutput>;
4
4
  destroy(input: DestroyInput): Promise<DestroyOutput>;
5
+ getStateLocation(_: GetStateLocationInput): Promise<GetStateLocationOutput>;
5
6
  private getEnv;
6
7
  private getParameterNames;
7
8
  private getStack;
package/dist/iac/cdk.js CHANGED
@@ -7,13 +7,11 @@ export class Cdk {
7
7
  async apply(input) {
8
8
  try {
9
9
  const { remainingEnv, serializedParameters, serializedWorkspaceEnv } = await this.serializedParametersAndContext(input);
10
- await runShell('npx', [
11
- 'aws-cdk', 'deploy', '--require-approval', 'never', ...serializedWorkspaceEnv, ...serializedParameters,
12
- ], {
10
+ await runShell('npx', ['aws-cdk', 'deploy', '--require-approval', 'never', ...serializedWorkspaceEnv, ...serializedParameters], {
13
11
  directory: input.pkgPath,
14
12
  env: {
15
13
  ...remainingEnv,
16
- STACK_NAME: input.id
14
+ STACK_NAME: input.id,
17
15
  },
18
16
  logger: input.logger,
19
17
  });
@@ -28,13 +26,11 @@ export class Cdk {
28
26
  try {
29
27
  const env = await this.getEnv(input.id);
30
28
  const { remainingEnv, serializedParameters, serializedWorkspaceEnv } = await this.serializedParametersAndContext(input);
31
- await runShell('npx', [
32
- 'aws-cdk', 'destroy', '--force', ...serializedWorkspaceEnv, ...serializedParameters
33
- ], {
29
+ await runShell('npx', ['aws-cdk', 'destroy', '--force', ...serializedWorkspaceEnv, ...serializedParameters], {
34
30
  directory: input.pkgPath,
35
31
  env: {
36
32
  ...remainingEnv,
37
- STACK_NAME: input.id
33
+ STACK_NAME: input.id,
38
34
  },
39
35
  logger: input.logger,
40
36
  });
@@ -44,10 +40,16 @@ export class Cdk {
44
40
  return { reason: error.message, success: false };
45
41
  }
46
42
  }
43
+ async getStateLocation(_) {
44
+ return {
45
+ reason: 'CDK does not support state location',
46
+ success: false,
47
+ };
48
+ }
47
49
  async getEnv(stackName) {
48
50
  const stack = await this.getStack(stackName);
49
51
  const env = {};
50
- for (const output of stack?.Outputs?.filter(output => output.OutputKey) ?? []) {
52
+ for (const output of stack?.Outputs?.filter((output) => output.OutputKey) ?? []) {
51
53
  env[output.OutputKey] = output.OutputValue;
52
54
  }
53
55
  return env;
@@ -55,16 +57,12 @@ export class Cdk {
55
57
  async getParameterNames(input) {
56
58
  const workDir = input.pkgPath;
57
59
  await runShell('npm', ['install'], { directory: workDir });
58
- await runShell('npx', [
59
- 'aws-cdk', 'synth',
60
- ], {
60
+ await runShell('npx', ['aws-cdk', 'synth'], {
61
61
  directory: workDir,
62
62
  env: { ...input.env, ...input.parameters },
63
63
  logger: input.logger,
64
64
  });
65
- const result = await runShell('npx', [
66
- 'aws-cdk', 'synth',
67
- ], {
65
+ const result = await runShell('npx', ['aws-cdk', 'synth'], {
68
66
  directory: workDir,
69
67
  env: { ...input.env, ...input.parameters },
70
68
  logger: input.logger,
@@ -2,6 +2,7 @@ import { Logger } from '../lib/log.js';
2
2
  export interface Iac {
3
3
  apply(input: ApplyInput): Promise<ApplyOutput>;
4
4
  destroy(input: DestroyInput): Promise<DestroyOutput>;
5
+ getStateLocation(input: GetStateLocationInput): Promise<GetStateLocationOutput>;
5
6
  }
6
7
  export declare enum IacType {
7
8
  cdk = "cdk",
@@ -37,3 +38,20 @@ export type ApplyOutput = {
37
38
  };
38
39
  export type DestroyInput = ApplyInput;
39
40
  export type DestroyOutput = ApplyOutput;
41
+ export type GetStateLocationInput = {
42
+ id: string;
43
+ infraConfig: {
44
+ terraformStateBucketName: string;
45
+ terraformStateBucketRegion?: string;
46
+ terraformStateLockTableName: string;
47
+ };
48
+ };
49
+ export type GetStateLocationOutput = {
50
+ bucket: string;
51
+ key: string;
52
+ region: string;
53
+ success: true;
54
+ } | {
55
+ reason: string;
56
+ success: false;
57
+ };
@@ -1,9 +1,10 @@
1
1
  import { Logger } from '../lib/log.js';
2
- import { ApplyInput, ApplyOutput, DestroyInput, DestroyOutput, Iac } from './common.js';
2
+ import { ApplyInput, ApplyOutput, DestroyInput, DestroyOutput, GetStateLocationInput, GetStateLocationOutput, Iac } from './common.js';
3
3
  export declare class Terraform implements Iac {
4
4
  apply(input: ApplyInput): Promise<ApplyOutput>;
5
5
  destroy(input: DestroyInput): Promise<DestroyOutput>;
6
6
  downloadTerraform(logger?: Logger): Promise<boolean>;
7
+ getStateLocation(input: GetStateLocationInput): Promise<GetStateLocationOutput>;
7
8
  private getEnv;
8
9
  private getTerraformBinary;
9
10
  private getWithRedirect;
@@ -176,6 +176,14 @@ export class Terraform {
176
176
  });
177
177
  return true;
178
178
  }
179
+ async getStateLocation(input) {
180
+ return {
181
+ bucket: input.infraConfig.terraformStateBucketName,
182
+ key: `${input.id}/terraform.tfstate`,
183
+ region: input.infraConfig.terraformStateBucketRegion ?? '',
184
+ success: true,
185
+ };
186
+ }
179
187
  async getEnv(pkgPath, logger) {
180
188
  const terraform = await this.getTerraformBinary(logger);
181
189
  const resourceOut = await runShell(terraform, ['output', '--json'], {
@@ -1,4 +1,4 @@
1
- import { BootstrapInput, DeployInput, DeployOutput, DestroyInput, DestroyOutput, Infrastructure, ProvisionInput, ProvisionOutput, ResolveEnvInput, ResolveEnvOutput, SaveEnvInput, SaveEnvOutput, StoreEnvInput, StoreEnvOutput, UndeployInput, UndeployOutput, UnstoreEnvInput, UnstoreEnvOutput } from './common.js';
1
+ import { BootstrapInput, DeployInput, DeployOutput, DestroyInput, DestroyOutput, Infrastructure, ProvisionInput, ProvisionOutput, ResolveEnvInput, ResolveEnvOutput, SaveEnvInput, SaveEnvOutput, StoreEnvInput, StoreEnvOutput, UndeployInput, UndeployOutput, UnstoreEnvInput, UnstoreEnvOutput, UploadStateFileInput, UploadStateFileOutput } from './common.js';
2
2
  export declare class AwsInfrastructure implements Infrastructure {
3
3
  bootstrap(_: BootstrapInput): Promise<void>;
4
4
  deploy(input: DeployInput): Promise<DeployOutput>;
@@ -10,4 +10,5 @@ export declare class AwsInfrastructure implements Infrastructure {
10
10
  unbootstrap(_: BootstrapInput): Promise<void>;
11
11
  undeploy(input: UndeployInput): Promise<UndeployOutput>;
12
12
  unstoreEnv(input: UnstoreEnvInput): Promise<UnstoreEnvOutput>;
13
+ uploadStateFile(input: UploadStateFileInput): Promise<UploadStateFileOutput>;
13
14
  }
@@ -1,8 +1,9 @@
1
+ import { PutObjectCommand, S3Client } from '@aws-sdk/client-s3';
1
2
  import { GetSecretValueCommand, SecretsManagerClient } from '@aws-sdk/client-secrets-manager';
2
3
  import { DeleteParameterCommand, GetParameterCommand, PutParameterCommand, SSMClient } from '@aws-sdk/client-ssm';
3
4
  import { GetCallerIdentityCommand, STSClient } from '@aws-sdk/client-sts';
4
5
  import { randomUUID } from 'node:crypto';
5
- import fs from 'node:fs/promises';
6
+ import fs from 'node:fs';
6
7
  import { getIac } from '../iac/index.js';
7
8
  import { downloadPackage } from '../lib/package/index.js';
8
9
  import { runShell } from '../lib/shell.js';
@@ -70,7 +71,7 @@ export class AwsInfrastructure {
70
71
  return { reason: output.reason, success: false };
71
72
  }
72
73
  // Remove downloaded package
73
- await fs.rm(downloadPath, { recursive: true });
74
+ await fs.promises.rm(downloadPath, { recursive: true });
74
75
  return { env: output.env, success: true };
75
76
  }
76
77
  async provision(input) {
@@ -220,4 +221,38 @@ export class AwsInfrastructure {
220
221
  }));
221
222
  return { success: true };
222
223
  }
224
+ async uploadStateFile(input) {
225
+ const iac$ = getIac({ type: input.iacType });
226
+ if (!iac$.supported) {
227
+ return { reason: iac$.reason, success: false };
228
+ }
229
+ const { iac } = iac$;
230
+ const config = await getAwsConfig();
231
+ const terraformStateBucketRegion = config.terraformStateBucketRegion || process.env.AWS_REGION || process.env.AWS_DEFAULT_REGION;
232
+ const infraConfig = {
233
+ ...config,
234
+ terraformStateBucketRegion,
235
+ };
236
+ if (!infraConfig.terraformStateBucketName || !infraConfig.terraformStateLockTableName) {
237
+ return {
238
+ reason: 'could not find AWS infrastructure config. Did you run `hereya bootstrap aws`?',
239
+ success: false,
240
+ };
241
+ }
242
+ const stateLocation$ = await iac.getStateLocation({
243
+ id: input.provisioningId,
244
+ infraConfig,
245
+ });
246
+ if (!stateLocation$.success) {
247
+ return { reason: stateLocation$.reason, success: false };
248
+ }
249
+ const { bucket, key } = stateLocation$;
250
+ const s3Client = new S3Client({});
251
+ await s3Client.send(new PutObjectCommand({
252
+ Body: fs.createReadStream(input.stateFile),
253
+ Bucket: bucket,
254
+ Key: key,
255
+ }));
256
+ return { success: true };
257
+ }
223
258
  }
@@ -17,6 +17,7 @@ export interface Infrastructure {
17
17
  unbootstrap(input: BootstrapInput): Promise<void>;
18
18
  undeploy(input: UndeployInput): Promise<UndeployOutput>;
19
19
  unstoreEnv(input: UnstoreEnvInput): Promise<UnstoreEnvOutput>;
20
+ uploadStateFile(input: UploadStateFileInput): Promise<UploadStateFileOutput>;
20
21
  }
21
22
  export declare function getPackageDownloadPath(input: {
22
23
  id: string;
@@ -99,3 +100,14 @@ export type UnstoreEnvOutput = {
99
100
  } | {
100
101
  success: true;
101
102
  };
103
+ export type UploadStateFileInput = {
104
+ iacType: IacType;
105
+ provisioningId: string;
106
+ stateFile: string;
107
+ };
108
+ export type UploadStateFileOutput = {
109
+ reason: string;
110
+ success: false;
111
+ } | {
112
+ success: true;
113
+ };
@@ -9,6 +9,11 @@ export declare const awsInfrastructure: AwsInfrastructure;
9
9
  export declare function getInfrastructure(input: GetInfrastructureInput): GetInfrastructureOutput;
10
10
  export declare function destroyPackage(input: DestroyPackageInput): Promise<DestroyPackageOutput>;
11
11
  export declare function provisionPackage(input: ProvisionPackageInput): Promise<ProvisionPackageOutput>;
12
+ export declare function getProvisioningLogicalId({ pkg, project, workspace }: {
13
+ pkg: string;
14
+ project?: string;
15
+ workspace?: string;
16
+ }): string;
12
17
  export type DestroyPackageInput = ProvisionPackageInput;
13
18
  export type DestroyPackageOutput = ProvisionPackageOutput;
14
19
  export type ProvisionPackageInput = {
@@ -168,6 +168,6 @@ export async function provisionPackage(input) {
168
168
  }
169
169
  return { env: provisionOutput.env, metadata, success: true };
170
170
  }
171
- function getProvisioningLogicalId({ pkg, project, workspace }) {
171
+ export function getProvisioningLogicalId({ pkg, project, workspace }) {
172
172
  return [pkg.replaceAll('/', '.'), workspace, project].filter(Boolean).join('.');
173
173
  }
@@ -1,4 +1,4 @@
1
- import { DeployInput, DeployOutput, Infrastructure, ProvisionInput, ProvisionOutput, SaveEnvInput, SaveEnvOutput, StoreEnvInput, StoreEnvOutput, UndeployInput, UndeployOutput, UnstoreEnvInput, UnstoreEnvOutput } from './common.js';
1
+ import { DeployInput, DeployOutput, Infrastructure, ProvisionInput, ProvisionOutput, SaveEnvInput, SaveEnvOutput, StoreEnvInput, StoreEnvOutput, UndeployInput, UndeployOutput, UnstoreEnvInput, UnstoreEnvOutput, UploadStateFileInput, UploadStateFileOutput } from './common.js';
2
2
  export declare class LocalInfrastructure implements Infrastructure {
3
3
  bootstrap(): Promise<void>;
4
4
  deploy(input: DeployInput): Promise<DeployOutput>;
@@ -14,4 +14,5 @@ export declare class LocalInfrastructure implements Infrastructure {
14
14
  unbootstrap(): Promise<void>;
15
15
  undeploy(input: UndeployInput): Promise<UndeployOutput>;
16
16
  unstoreEnv(_: UnstoreEnvInput): Promise<UnstoreEnvOutput>;
17
+ uploadStateFile(_: UploadStateFileInput): Promise<UploadStateFileOutput>;
17
18
  }
@@ -80,4 +80,7 @@ export class LocalInfrastructure {
80
80
  async unstoreEnv(_) {
81
81
  return { success: true };
82
82
  }
83
+ uploadStateFile(_) {
84
+ throw new Error(`Uploading state file is not supported for local infrastructure`);
85
+ }
83
86
  }
@@ -264,6 +264,80 @@
264
264
  "index.js"
265
265
  ]
266
266
  },
267
+ "import": {
268
+ "aliases": [],
269
+ "args": {
270
+ "package": {
271
+ "description": "\n The package to import, specified as a GitHub repository in the format owner/repository.\n To change the registry URL, set the HEREYA_REGISTRY_URL environment variable, so that it points to $HEREYA_REGISTRY_URL/owner/repository.\n For local packages, use the format local://path/to/package where path/to/package is the path to the package on your local machine.\n ",
272
+ "name": "package",
273
+ "required": true
274
+ }
275
+ },
276
+ "description": "Import a package resource into your project",
277
+ "examples": [
278
+ "<%= config.bin %> <%= command.id %> hereya/my-package -f state.tfstate",
279
+ "<%= config.bin %> <%= command.id %> org/my-package -f state.tfstate -w my-workspace"
280
+ ],
281
+ "flags": {
282
+ "chdir": {
283
+ "description": "\n Directory where the command will be executed.\n If not specified, it defaults to the current working directory.\n Alternatively, you can define the project root by setting the HEREYA_PROJECT_ROOT_DIR environment variable.\n ",
284
+ "name": "chdir",
285
+ "required": false,
286
+ "hasDynamicHelp": false,
287
+ "multiple": false,
288
+ "type": "option"
289
+ },
290
+ "debug": {
291
+ "description": "enable debug mode",
292
+ "name": "debug",
293
+ "allowNo": false,
294
+ "type": "boolean"
295
+ },
296
+ "parameter": {
297
+ "char": "p",
298
+ "description": "parameters for the package, in the form of 'key=value'. Can be specified multiple times.",
299
+ "name": "parameter",
300
+ "required": false,
301
+ "default": [],
302
+ "hasDynamicHelp": false,
303
+ "multiple": true,
304
+ "type": "option"
305
+ },
306
+ "stateFile": {
307
+ "char": "f",
308
+ "description": "state file to use",
309
+ "name": "stateFile",
310
+ "required": true,
311
+ "hasDynamicHelp": false,
312
+ "multiple": false,
313
+ "type": "option"
314
+ },
315
+ "workspace": {
316
+ "char": "w",
317
+ "description": "workspace to import into",
318
+ "name": "workspace",
319
+ "required": false,
320
+ "hasDynamicHelp": false,
321
+ "multiple": false,
322
+ "type": "option"
323
+ }
324
+ },
325
+ "hasDynamicHelp": false,
326
+ "hiddenAliases": [],
327
+ "id": "import",
328
+ "pluginAlias": "hereya-cli",
329
+ "pluginName": "hereya-cli",
330
+ "pluginType": "core",
331
+ "strict": true,
332
+ "enableJsonFlag": false,
333
+ "isESM": true,
334
+ "relativePath": [
335
+ "dist",
336
+ "commands",
337
+ "import",
338
+ "index.js"
339
+ ]
340
+ },
267
341
  "init": {
268
342
  "aliases": [],
269
343
  "args": {
@@ -1194,5 +1268,5 @@
1194
1268
  ]
1195
1269
  }
1196
1270
  },
1197
- "version": "0.39.0"
1271
+ "version": "0.40.1"
1198
1272
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "hereya-cli",
3
3
  "description": "Infrastructure as Package",
4
- "version": "0.39.0",
4
+ "version": "0.40.1",
5
5
  "author": "Hereya Developers",
6
6
  "bin": {
7
7
  "hereya": "./bin/run.js"