hereya-cli 0.8.0 → 0.8.2

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.8.0 linux-x64 node-v20.14.0
23
+ hereya-cli/0.8.2 linux-x64 node-v20.15.0
24
24
  $ hereya --help [COMMAND]
25
25
  USAGE
26
26
  $ hereya COMMAND
@@ -71,7 +71,7 @@ EXAMPLES
71
71
  $ hereya add cloudy/docker_postgres
72
72
  ```
73
73
 
74
- _See code: [src/commands/add/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.0/src/commands/add/index.ts)_
74
+ _See code: [src/commands/add/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.2/src/commands/add/index.ts)_
75
75
 
76
76
  ## `hereya bootstrap INFRASTRUCTURETYPE`
77
77
 
@@ -96,7 +96,7 @@ EXAMPLES
96
96
  $ hereya bootstrap local
97
97
  ```
98
98
 
99
- _See code: [src/commands/bootstrap/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.0/src/commands/bootstrap/index.ts)_
99
+ _See code: [src/commands/bootstrap/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.2/src/commands/bootstrap/index.ts)_
100
100
 
101
101
  ## `hereya deploy`
102
102
 
@@ -117,7 +117,7 @@ EXAMPLES
117
117
  $ hereya deploy
118
118
  ```
119
119
 
120
- _See code: [src/commands/deploy/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.0/src/commands/deploy/index.ts)_
120
+ _See code: [src/commands/deploy/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.2/src/commands/deploy/index.ts)_
121
121
 
122
122
  ## `hereya down`
123
123
 
@@ -139,7 +139,7 @@ EXAMPLES
139
139
  $ hereya down
140
140
  ```
141
141
 
142
- _See code: [src/commands/down/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.0/src/commands/down/index.ts)_
142
+ _See code: [src/commands/down/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.2/src/commands/down/index.ts)_
143
143
 
144
144
  ## `hereya env [NAME]`
145
145
 
@@ -170,7 +170,7 @@ EXAMPLES
170
170
  $ hereya env -w dev -l
171
171
  ```
172
172
 
173
- _See code: [src/commands/env/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.0/src/commands/env/index.ts)_
173
+ _See code: [src/commands/env/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.2/src/commands/env/index.ts)_
174
174
 
175
175
  ## `hereya help [COMMAND]`
176
176
 
@@ -216,7 +216,7 @@ EXAMPLES
216
216
  $ hereya init myProject -w=defaultWorkspace --chdir=./myProject
217
217
  ```
218
218
 
219
- _See code: [src/commands/init/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.0/src/commands/init/index.ts)_
219
+ _See code: [src/commands/init/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.2/src/commands/init/index.ts)_
220
220
 
221
221
  ## `hereya remote exec [PKGPATH]`
222
222
 
@@ -240,7 +240,7 @@ EXAMPLES
240
240
  $ hereya remote exec
241
241
  ```
242
242
 
243
- _See code: [src/commands/remote/exec/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.0/src/commands/remote/exec/index.ts)_
243
+ _See code: [src/commands/remote/exec/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.2/src/commands/remote/exec/index.ts)_
244
244
 
245
245
  ## `hereya remove PACKAGE`
246
246
 
@@ -263,7 +263,7 @@ EXAMPLES
263
263
  $ hereya remove cloudy/docker_postgres
264
264
  ```
265
265
 
266
- _See code: [src/commands/remove/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.0/src/commands/remove/index.ts)_
266
+ _See code: [src/commands/remove/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.2/src/commands/remove/index.ts)_
267
267
 
268
268
  ## `hereya run CMD`
269
269
 
@@ -289,7 +289,7 @@ EXAMPLES
289
289
  $ hereya run -w uat -- node index.js
290
290
  ```
291
291
 
292
- _See code: [src/commands/run/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.0/src/commands/run/index.ts)_
292
+ _See code: [src/commands/run/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.2/src/commands/run/index.ts)_
293
293
 
294
294
  ## `hereya unbootstrap INFRASTRUCTURETYPE`
295
295
 
@@ -314,7 +314,7 @@ EXAMPLES
314
314
  $ hereya unbootstrap local
315
315
  ```
316
316
 
317
- _See code: [src/commands/unbootstrap/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.0/src/commands/unbootstrap/index.ts)_
317
+ _See code: [src/commands/unbootstrap/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.2/src/commands/unbootstrap/index.ts)_
318
318
 
319
319
  ## `hereya undeploy`
320
320
 
@@ -335,7 +335,7 @@ EXAMPLES
335
335
  $ hereya undeploy
336
336
  ```
337
337
 
338
- _See code: [src/commands/undeploy/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.0/src/commands/undeploy/index.ts)_
338
+ _See code: [src/commands/undeploy/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.2/src/commands/undeploy/index.ts)_
339
339
 
340
340
  ## `hereya up`
341
341
 
@@ -357,7 +357,7 @@ EXAMPLES
357
357
  $ hereya up
358
358
  ```
359
359
 
360
- _See code: [src/commands/up/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.0/src/commands/up/index.ts)_
360
+ _See code: [src/commands/up/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.2/src/commands/up/index.ts)_
361
361
 
362
362
  ## `hereya workspace create NAME`
363
363
 
@@ -377,7 +377,7 @@ EXAMPLES
377
377
  $ hereya workspace create dev
378
378
  ```
379
379
 
380
- _See code: [src/commands/workspace/create/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.0/src/commands/workspace/create/index.ts)_
380
+ _See code: [src/commands/workspace/create/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.2/src/commands/workspace/create/index.ts)_
381
381
 
382
382
  ## `hereya workspace delete NAME`
383
383
 
@@ -397,7 +397,7 @@ EXAMPLES
397
397
  $ hereya workspace delete dev
398
398
  ```
399
399
 
400
- _See code: [src/commands/workspace/delete/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.0/src/commands/workspace/delete/index.ts)_
400
+ _See code: [src/commands/workspace/delete/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.2/src/commands/workspace/delete/index.ts)_
401
401
 
402
402
  ## `hereya workspace env [NAME]`
403
403
 
@@ -423,7 +423,7 @@ EXAMPLES
423
423
  $ hereya workspace env myEnv -w dev
424
424
  ```
425
425
 
426
- _See code: [src/commands/workspace/env/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.0/src/commands/workspace/env/index.ts)_
426
+ _See code: [src/commands/workspace/env/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.2/src/commands/workspace/env/index.ts)_
427
427
 
428
428
  ## `hereya workspace install PACKAGE`
429
429
 
@@ -449,7 +449,7 @@ EXAMPLES
449
449
  $ hereya workspace install hereya/aws-cognito
450
450
  ```
451
451
 
452
- _See code: [src/commands/workspace/install/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.0/src/commands/workspace/install/index.ts)_
452
+ _See code: [src/commands/workspace/install/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.2/src/commands/workspace/install/index.ts)_
453
453
 
454
454
  ## `hereya workspace uninstall PACKAGE`
455
455
 
@@ -475,5 +475,5 @@ EXAMPLES
475
475
  $ hereya workspace uninstall hereya/aws-cognito
476
476
  ```
477
477
 
478
- _See code: [src/commands/workspace/uninstall/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.0/src/commands/workspace/uninstall/index.ts)_
478
+ _See code: [src/commands/workspace/uninstall/index.ts](https://github.com/hereya/hereya-cli/blob/v0.8.2/src/commands/workspace/uninstall/index.ts)_
479
479
  <!-- commandsstop -->
@@ -2,5 +2,8 @@ import { ApplyInput, ApplyOutput, DestroyInput, DestroyOutput, Iac } from './com
2
2
  export declare class Terraform implements Iac {
3
3
  apply(input: ApplyInput): Promise<ApplyOutput>;
4
4
  destroy(input: DestroyInput): Promise<DestroyOutput>;
5
+ private downloadTerraform;
5
6
  private getEnv;
7
+ private getTerraformBinary;
8
+ private terraformBinPath;
6
9
  }
@@ -1,16 +1,23 @@
1
+ import fs from 'node:fs';
2
+ import https from 'node:https';
3
+ import os from 'node:os';
4
+ import path from 'node:path';
5
+ import { pipeline } from 'node:stream/promises';
6
+ import { Extract as decompress } from 'unzip-stream';
1
7
  import { mapObject } from '../lib/object-utils.js';
2
8
  import { runShell } from '../lib/shell.js';
3
9
  export class Terraform {
4
10
  async apply(input) {
5
11
  try {
6
- runShell('terraform', ['init'], {
12
+ const terraform = await this.getTerraformBinary();
13
+ runShell(terraform, ['init'], {
7
14
  directory: input.pkgPath,
8
15
  env: {
9
16
  ...input.env,
10
17
  ...mapObject(input.parameters ?? {}, (key, value) => [`TF_VAR_${key}`, value])
11
18
  }
12
19
  });
13
- runShell('terraform', ['apply', '-auto-approve'], {
20
+ runShell(terraform, ['apply', '-auto-approve'], {
14
21
  directory: input.pkgPath,
15
22
  env: {
16
23
  ...input.env,
@@ -31,8 +38,9 @@ export class Terraform {
31
38
  }
32
39
  }
33
40
  async destroy(input) {
41
+ const terraform = await this.getTerraformBinary();
34
42
  try {
35
- runShell('terraform', ['init'], {
43
+ runShell(terraform, ['init'], {
36
44
  directory: input.pkgPath,
37
45
  env: {
38
46
  ...input.env,
@@ -40,7 +48,7 @@ export class Terraform {
40
48
  }
41
49
  });
42
50
  const env = await this.getEnv(input.pkgPath);
43
- runShell('terraform', ['destroy', '-auto-approve'], {
51
+ runShell(terraform, ['destroy', '-auto-approve'], {
44
52
  directory: input.pkgPath,
45
53
  env: {
46
54
  ...input.env,
@@ -59,8 +67,65 @@ export class Terraform {
59
67
  };
60
68
  }
61
69
  }
70
+ async downloadTerraform() {
71
+ const TERRAFORM_DOWNLOAD_URLS = new Map([
72
+ ['darwin_arm64', 'https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_darwin_arm64.zip'],
73
+ ['darwin_x64', 'https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_darwin_amd64.zip'],
74
+ ['freebsd_arm', 'https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_freebsd_arm.zip'],
75
+ ['freebsd_ia32', 'https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_freebsd_386.zip'],
76
+ ['freebsd_x64', 'https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_freebsd_amd64.zip'],
77
+ ['linux_arm', 'https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_linux_arm.zip'],
78
+ ['linux_arm64', 'https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_linux_arm64.zip'],
79
+ ['linux_ia32', 'https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_linux_386.zip'],
80
+ ['linux_x64', 'https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_linux_amd64.zip'],
81
+ ['openbsd_ia32', 'https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_openbsd_386.zip'],
82
+ ['openbsd_x64', 'https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_openbsd_amd64.zip'],
83
+ ['sunos_x64', 'https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_solaris_amd64.zip'],
84
+ ['win32_ia32', 'https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_windows_386.zip'],
85
+ ['win32_x64', 'https://releases.hashicorp.com/terraform/1.5.7/terraform_1.5.7_windows_amd64.zip'],
86
+ ]);
87
+ const tfPath = this.terraformBinPath();
88
+ try {
89
+ await fs.promises.access(tfPath, fs.constants.X_OK);
90
+ return false;
91
+ }
92
+ catch (error) {
93
+ // file does not exist or is corrupted - continue
94
+ if (error.code !== 'ENOENT') {
95
+ await fs.promises.rm(tfPath);
96
+ }
97
+ }
98
+ console.log('Downloading terraform...');
99
+ const binKey = `${os.platform()}_${os.arch()}`;
100
+ const url = TERRAFORM_DOWNLOAD_URLS.get(binKey);
101
+ if (!url) {
102
+ throw new Error('unsupported platform for terraform');
103
+ }
104
+ try {
105
+ await fs.promises.mkdir(path.dirname(tfPath), { recursive: true });
106
+ }
107
+ catch (error) {
108
+ if (error.code !== 'EEXIST') {
109
+ throw new Error(`could not download terraform: ${error}`);
110
+ }
111
+ }
112
+ await new Promise((resolve, reject) => {
113
+ https.get(url, async (response) => {
114
+ try {
115
+ await pipeline(response, decompress({ path: path.dirname(tfPath) }));
116
+ await fs.promises.chmod(tfPath, '0755');
117
+ }
118
+ catch (error) {
119
+ throw new Error(`could not download terraform: ${error}`);
120
+ }
121
+ resolve(null);
122
+ }).on('error', error => reject(error));
123
+ });
124
+ return true;
125
+ }
62
126
  async getEnv(pkgPath) {
63
- const resourceOut = runShell('terraform', ['output', '--json'], {
127
+ const terraform = await this.getTerraformBinary();
128
+ const resourceOut = runShell(terraform, ['output', '--json'], {
64
129
  directory: pkgPath,
65
130
  stdio: 'pipe'
66
131
  });
@@ -76,4 +141,11 @@ export class Terraform {
76
141
  }
77
142
  return tfEnv;
78
143
  }
144
+ async getTerraformBinary() {
145
+ await this.downloadTerraform();
146
+ return this.terraformBinPath();
147
+ }
148
+ terraformBinPath() {
149
+ return path.join(os.homedir(), '.hereya', 'iac', 'terraform', os.platform() === 'win32' ? 'terraform.exe' : 'terraform');
150
+ }
79
151
  }
@@ -87,30 +87,36 @@ export class AwsInfrastructure {
87
87
  return { env, success: true };
88
88
  }
89
89
  async resolveEnv(input) {
90
- const parameterStoreArnPattern = /^arn:aws:ssm:[\da-z-]+:\d{12}:parameter\/[\w./-]+$/;
91
- const ssmClient = new SSMClient({});
92
- if (parameterStoreArnPattern.test(input.value)) {
93
- const response = await ssmClient.send(new GetParameterCommand({
94
- Name: input.value,
95
- WithDecryption: true,
96
- }));
97
- return {
98
- isSecret: response.Parameter?.Type === 'SecureString',
99
- value: response.Parameter?.Value ?? input.value
100
- };
90
+ try {
91
+ const parameterStoreArnPattern = /^arn:aws:ssm:[\da-z-]+:\d{12}:parameter\/[\w./-]+$/;
92
+ const ssmClient = new SSMClient({});
93
+ if (parameterStoreArnPattern.test(input.value)) {
94
+ const response = await ssmClient.send(new GetParameterCommand({
95
+ Name: input.value,
96
+ WithDecryption: true,
97
+ }));
98
+ return {
99
+ isSecret: response.Parameter?.Type === 'SecureString',
100
+ value: response.Parameter?.Value ?? input.value
101
+ };
102
+ }
103
+ const secretManagerArnPattern = /^arn:aws:secretsmanager:[\da-z-]+:\d{12}:secret:[\w-]+/;
104
+ const secretManagerClient = new SecretsManagerClient({});
105
+ if (secretManagerArnPattern.test(input.value)) {
106
+ const response = await secretManagerClient.send(new GetSecretValueCommand({
107
+ SecretId: input.value,
108
+ }));
109
+ return {
110
+ isSecret: true,
111
+ value: response.SecretString ?? input.value
112
+ };
113
+ }
114
+ return { value: input.value };
101
115
  }
102
- const secretManagerArnPattern = /^arn:aws:secretsmanager:[\da-z-]+:\d{12}:secret:[\w-]+/;
103
- const secretManagerClient = new SecretsManagerClient({});
104
- if (secretManagerArnPattern.test(input.value)) {
105
- const response = await secretManagerClient.send(new GetSecretValueCommand({
106
- SecretId: input.value,
107
- }));
108
- return {
109
- isSecret: true,
110
- value: response.SecretString ?? input.value
111
- };
116
+ catch (error) {
117
+ console.warn(`Could not resolve value "${input.value}": ${error.message}. Will return the original value.`);
118
+ return { value: input.value };
112
119
  }
113
- return { value: input.value };
114
120
  }
115
121
  async saveEnv(input) {
116
122
  const key = `/hereya/${input.id}`;
@@ -48,6 +48,45 @@
48
48
  "index.js"
49
49
  ]
50
50
  },
51
+ "bootstrap": {
52
+ "aliases": [],
53
+ "args": {
54
+ "infrastructureType": {
55
+ "description": "infrastructure to bootstrap. Options are local, aws",
56
+ "name": "infrastructureType",
57
+ "required": true
58
+ }
59
+ },
60
+ "description": "Install necessary resources for hereya operations in an infrastructure.",
61
+ "examples": [
62
+ "<%= config.bin %> <%= command.id %> aws",
63
+ "<%= config.bin %> <%= command.id %> local"
64
+ ],
65
+ "flags": {
66
+ "force": {
67
+ "char": "f",
68
+ "description": "redeploy hereya resources if already deployed",
69
+ "name": "force",
70
+ "allowNo": false,
71
+ "type": "boolean"
72
+ }
73
+ },
74
+ "hasDynamicHelp": false,
75
+ "hiddenAliases": [],
76
+ "id": "bootstrap",
77
+ "pluginAlias": "hereya-cli",
78
+ "pluginName": "hereya-cli",
79
+ "pluginType": "core",
80
+ "strict": true,
81
+ "enableJsonFlag": false,
82
+ "isESM": true,
83
+ "relativePath": [
84
+ "dist",
85
+ "commands",
86
+ "bootstrap",
87
+ "index.js"
88
+ ]
89
+ },
51
90
  "deploy": {
52
91
  "aliases": [],
53
92
  "args": {},
@@ -90,45 +129,6 @@
90
129
  "index.js"
91
130
  ]
92
131
  },
93
- "bootstrap": {
94
- "aliases": [],
95
- "args": {
96
- "infrastructureType": {
97
- "description": "infrastructure to bootstrap. Options are local, aws",
98
- "name": "infrastructureType",
99
- "required": true
100
- }
101
- },
102
- "description": "Install necessary resources for hereya operations in an infrastructure.",
103
- "examples": [
104
- "<%= config.bin %> <%= command.id %> aws",
105
- "<%= config.bin %> <%= command.id %> local"
106
- ],
107
- "flags": {
108
- "force": {
109
- "char": "f",
110
- "description": "redeploy hereya resources if already deployed",
111
- "name": "force",
112
- "allowNo": false,
113
- "type": "boolean"
114
- }
115
- },
116
- "hasDynamicHelp": false,
117
- "hiddenAliases": [],
118
- "id": "bootstrap",
119
- "pluginAlias": "hereya-cli",
120
- "pluginName": "hereya-cli",
121
- "pluginType": "core",
122
- "strict": true,
123
- "enableJsonFlag": false,
124
- "isESM": true,
125
- "relativePath": [
126
- "dist",
127
- "commands",
128
- "bootstrap",
129
- "index.js"
130
- ]
131
- },
132
132
  "down": {
133
133
  "aliases": [],
134
134
  "args": {},
@@ -783,5 +783,5 @@
783
783
  ]
784
784
  }
785
785
  },
786
- "version": "0.8.0"
786
+ "version": "0.8.2"
787
787
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "hereya-cli",
3
3
  "description": "Infrastructure as Package",
4
- "version": "0.8.0",
4
+ "version": "0.8.2",
5
5
  "author": "Hereya Developers",
6
6
  "bin": {
7
7
  "hereya": "./bin/run.js"
@@ -23,6 +23,7 @@
23
23
  "glob": "^10.4.1",
24
24
  "ignore": "^5.3.1",
25
25
  "simple-git": "^3.24.0",
26
+ "unzip-stream": "^0.3.4",
26
27
  "yaml": "^2.4.2",
27
28
  "zod": "^3.23.8"
28
29
  },
@@ -34,6 +35,7 @@
34
35
  "@types/mock-fs": "^4.13.4",
35
36
  "@types/node": "^18",
36
37
  "@types/sinon": "^17.0.3",
38
+ "@types/unzip-stream": "^0.3.4",
37
39
  "chai": "^4",
38
40
  "eslint": "^8",
39
41
  "eslint-config-oclif": "^5",