hereya-cli 0.17.2 → 0.19.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.
Files changed (61) hide show
  1. package/README.md +24 -24
  2. package/bin/dev.js +1 -1
  3. package/dist/backend/common.d.ts +4 -4
  4. package/dist/backend/local.js +10 -2
  5. package/dist/commands/add/index.d.ts +4 -4
  6. package/dist/commands/add/index.js +12 -21
  7. package/dist/commands/bootstrap/index.d.ts +2 -2
  8. package/dist/commands/deploy/index.d.ts +3 -3
  9. package/dist/commands/deploy/index.js +45 -36
  10. package/dist/commands/down/index.d.ts +4 -4
  11. package/dist/commands/down/index.js +16 -28
  12. package/dist/commands/env/index.d.ts +4 -4
  13. package/dist/commands/env/index.js +6 -2
  14. package/dist/commands/env/set/index.d.ts +4 -4
  15. package/dist/commands/init/index.d.ts +3 -3
  16. package/dist/commands/remove/index.d.ts +3 -3
  17. package/dist/commands/remove/index.js +9 -19
  18. package/dist/commands/run/index.d.ts +3 -3
  19. package/dist/commands/run/index.js +5 -1
  20. package/dist/commands/unbootstrap/index.d.ts +2 -2
  21. package/dist/commands/undeploy/index.d.ts +3 -3
  22. package/dist/commands/undeploy/index.js +21 -24
  23. package/dist/commands/up/index.d.ts +4 -4
  24. package/dist/commands/up/index.js +24 -32
  25. package/dist/commands/workspace/create/index.d.ts +1 -1
  26. package/dist/commands/workspace/delete/index.d.ts +1 -1
  27. package/dist/commands/workspace/env/index.d.ts +3 -3
  28. package/dist/commands/workspace/env/set/index.d.ts +5 -5
  29. package/dist/commands/workspace/env/unset/index.d.ts +2 -2
  30. package/dist/commands/workspace/install/index.d.ts +5 -5
  31. package/dist/commands/workspace/install/index.js +8 -3
  32. package/dist/commands/workspace/uninstall/index.d.ts +5 -5
  33. package/dist/commands/workspace/uninstall/index.js +8 -3
  34. package/dist/executor/index.d.ts +11 -0
  35. package/dist/executor/index.js +8 -0
  36. package/dist/executor/interface.d.ts +41 -0
  37. package/dist/executor/interface.js +1 -0
  38. package/dist/executor/local.d.ts +7 -0
  39. package/dist/executor/local.js +56 -0
  40. package/dist/iac/index.js +5 -5
  41. package/dist/iac/terraform.js +1 -1
  42. package/dist/infrastructure/common.d.ts +2 -2
  43. package/dist/infrastructure/index.d.ts +3 -3
  44. package/dist/infrastructure/index.js +6 -6
  45. package/dist/infrastructure/local.js +1 -1
  46. package/dist/lib/env/index.d.ts +4 -0
  47. package/dist/lib/env/index.js +11 -3
  48. package/dist/lib/env-utils.d.ts +0 -7
  49. package/dist/lib/env-utils.js +0 -18
  50. package/dist/lib/log.js +1 -1
  51. package/dist/lib/package/common.d.ts +1 -0
  52. package/dist/lib/package/github.d.ts +2 -0
  53. package/dist/lib/package/github.js +5 -1
  54. package/dist/lib/package/index.d.ts +4 -1
  55. package/dist/lib/package/index.js +28 -10
  56. package/dist/lib/package/local.d.ts +5 -0
  57. package/dist/lib/package/local.js +45 -0
  58. package/dist/lib/shell.d.ts +1 -3
  59. package/dist/lib/yaml-utils.js +1 -1
  60. package/oclif.manifest.json +40 -40
  61. package/package.json +37 -37
@@ -0,0 +1,41 @@
1
+ import { IPackageMetadata } from '../lib/package/index.js';
2
+ export type ExecutorProvisionInput = {
3
+ isDeploying?: boolean;
4
+ package: string;
5
+ parameters?: {
6
+ [key: string]: string;
7
+ };
8
+ project?: string;
9
+ projectEnv?: {
10
+ [key: string]: string;
11
+ };
12
+ projectRootDir?: string;
13
+ skipDeploy?: boolean;
14
+ workspace?: string;
15
+ };
16
+ export type ExecutorProvisionOutput = {
17
+ env: {
18
+ [key: string]: string;
19
+ };
20
+ metadata: IPackageMetadata;
21
+ success: true;
22
+ } | {
23
+ reason: string;
24
+ success: false;
25
+ };
26
+ export type ExecutorDestroyInput = ExecutorProvisionInput;
27
+ export type ExecutorDestroyOutput = ExecutorProvisionOutput;
28
+ export type ExecutorResolveEnvValuesInput = {
29
+ env: {
30
+ [key: string]: string;
31
+ };
32
+ markSecret?: boolean;
33
+ };
34
+ export type ExecutorResolveEnvValuesOutput = {
35
+ [key: string]: string;
36
+ };
37
+ export interface Executor {
38
+ destroy(input: ExecutorDestroyInput): Promise<ExecutorDestroyOutput>;
39
+ provision(input: ExecutorProvisionInput): Promise<ExecutorProvisionOutput>;
40
+ resolveEnvValues(input: ExecutorResolveEnvValuesInput): Promise<ExecutorResolveEnvValuesOutput>;
41
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,7 @@
1
+ import { Executor, ExecutorDestroyInput, ExecutorDestroyOutput, ExecutorProvisionInput, ExecutorProvisionOutput, ExecutorResolveEnvValuesInput, ExecutorResolveEnvValuesOutput } from './interface.js';
2
+ export declare class LocalExecutor implements Executor {
3
+ destroy(input: ExecutorDestroyInput): Promise<ExecutorDestroyOutput>;
4
+ provision(input: ExecutorProvisionInput): Promise<ExecutorProvisionOutput>;
5
+ resolveEnvValues(input: ExecutorResolveEnvValuesInput): Promise<ExecutorResolveEnvValuesOutput>;
6
+ private getWorkspaceEnv;
7
+ }
@@ -0,0 +1,56 @@
1
+ import { getBackend } from '../backend/index.js';
2
+ import { destroyPackage, getInfrastructure, provisionPackage } from '../infrastructure/index.js';
3
+ export class LocalExecutor {
4
+ async destroy(input) {
5
+ const getWorkspaceEnvOutput = await this.getWorkspaceEnv({
6
+ project: input.project,
7
+ workspace: input.workspace,
8
+ });
9
+ if (!getWorkspaceEnvOutput.success) {
10
+ return { reason: getWorkspaceEnvOutput.reason, success: false };
11
+ }
12
+ return destroyPackage({
13
+ ...input,
14
+ env: getWorkspaceEnvOutput.env,
15
+ });
16
+ }
17
+ async provision(input) {
18
+ const getWorkspaceEnvOutput = await this.getWorkspaceEnv({
19
+ project: input.project,
20
+ workspace: input.workspace,
21
+ });
22
+ if (!getWorkspaceEnvOutput.success) {
23
+ return { reason: getWorkspaceEnvOutput.reason, success: false };
24
+ }
25
+ return provisionPackage({
26
+ ...input,
27
+ env: getWorkspaceEnvOutput.env,
28
+ });
29
+ }
30
+ async resolveEnvValues(input) {
31
+ return Object.fromEntries(await Promise.all(Object.entries(input.env).map(async ([key, value]) => {
32
+ const infraType = value.split(':')[0];
33
+ const infra$ = getInfrastructure({ type: infraType });
34
+ if (!infra$.supported) {
35
+ throw new Error(infra$.reason);
36
+ }
37
+ const { infrastructure } = infra$;
38
+ const valueWithoutInfra = value.split(':').slice(1).join(':');
39
+ const { isSecret, value: resolvedValue } = await infrastructure.resolveEnv({
40
+ value: valueWithoutInfra,
41
+ });
42
+ const finalValue = input.markSecret && isSecret ? `secret://${resolvedValue}` : resolvedValue;
43
+ return [key, finalValue];
44
+ })));
45
+ }
46
+ async getWorkspaceEnv({ project, workspace, }) {
47
+ if (!workspace || !project) {
48
+ return { env: {}, success: true };
49
+ }
50
+ const backend = await getBackend();
51
+ return backend.getWorkspaceEnv({
52
+ project,
53
+ workspace,
54
+ });
55
+ }
56
+ }
package/dist/iac/index.js CHANGED
@@ -5,21 +5,21 @@ export const terraform = new Terraform();
5
5
  export const cdk = new Cdk();
6
6
  export function getIac({ type }) {
7
7
  switch (type) {
8
- case IacType.terraform: {
8
+ case IacType.cdk: {
9
+ return { iac: cdk, supported: true };
10
+ }
11
+ case IacType.opentf: {
9
12
  return { iac: terraform, supported: true };
10
13
  }
11
14
  case IacType.opentofu: {
12
15
  return { iac: terraform, supported: true };
13
16
  }
14
- case IacType.opentf: {
17
+ case IacType.terraform: {
15
18
  return { iac: terraform, supported: true };
16
19
  }
17
20
  case IacType.tofu: {
18
21
  return { iac: terraform, supported: true };
19
22
  }
20
- case IacType.cdk: {
21
- return { iac: cdk, supported: true };
22
- }
23
23
  default: {
24
24
  return { reason: `Iac type ${type} is not supported yet!`, supported: false };
25
25
  }
@@ -119,8 +119,8 @@ export class Terraform {
119
119
  ['freebsd_arm', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_freebsd_arm.zip'],
120
120
  ['freebsd_ia32', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_freebsd_386.zip'],
121
121
  ['freebsd_x64', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_freebsd_amd64.zip'],
122
- ['linux_arm', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_linux_arm.zip'],
123
122
  ['linux_arm64', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_linux_arm64.zip'],
123
+ ['linux_arm', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_linux_arm.zip'],
124
124
  ['linux_ia32', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_linux_386.zip'],
125
125
  ['linux_x64', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_linux_amd64.zip'],
126
126
  ['openbsd_ia32', 'https://github.com/opentofu/opentofu/releases/download/v1.9.0/tofu_1.9.0_openbsd_386.zip'],
@@ -44,12 +44,12 @@ export type ProvisionOutput = {
44
44
  };
45
45
  export type DestroyInput = ProvisionInput;
46
46
  export type DestroyOutput = ProvisionOutput;
47
- export type DeployInput = {
47
+ export type DeployInput = ProvisionInput & {
48
48
  projectEnv: {
49
49
  [key: string]: string;
50
50
  };
51
51
  projectRootDir: string;
52
- } & ProvisionInput;
52
+ };
53
53
  export type DeployOutput = ProvisionOutput;
54
54
  export type UndeployInput = DeployInput;
55
55
  export type UndeployOutput = DeployOutput;
@@ -41,10 +41,10 @@ export type GetInfrastructureInput = {
41
41
  type: InfrastructureType;
42
42
  };
43
43
  export type GetInfrastructureOutput = {
44
- reason: string;
45
- supported: false;
46
- } | {
47
44
  infrastructure: Infrastructure;
48
45
  supported: true;
46
+ } | {
47
+ reason: string;
48
+ supported: false;
49
49
  };
50
50
  export type PackageMetadata = z.infer<typeof PackageMetadata>;
@@ -7,15 +7,15 @@ export const localInfrastructure = new LocalInfrastructure();
7
7
  export const awsInfrastructure = new AwsInfrastructure();
8
8
  export function getInfrastructure(input) {
9
9
  switch (input.type) {
10
- case InfrastructureType.local: {
10
+ case InfrastructureType.aws: {
11
11
  return {
12
- infrastructure: localInfrastructure,
12
+ infrastructure: awsInfrastructure,
13
13
  supported: true,
14
14
  };
15
15
  }
16
- case InfrastructureType.aws: {
16
+ case InfrastructureType.local: {
17
17
  return {
18
- infrastructure: awsInfrastructure,
18
+ infrastructure: localInfrastructure,
19
19
  supported: true,
20
20
  };
21
21
  }
@@ -28,7 +28,7 @@ export function getInfrastructure(input) {
28
28
  }
29
29
  }
30
30
  export async function destroyPackage(input) {
31
- const resolvePackageOutput = await resolvePackage({ isDeploying: input.isDeploying, package: input.package });
31
+ const resolvePackageOutput = await resolvePackage({ isDeploying: input.isDeploying, package: input.package, projectRootDir: input.projectRootDir });
32
32
  if (!resolvePackageOutput.found) {
33
33
  return { reason: resolvePackageOutput.reason, success: false };
34
34
  }
@@ -91,7 +91,7 @@ export async function destroyPackage(input) {
91
91
  return { env: destroyOutput.env, metadata, success: true };
92
92
  }
93
93
  export async function provisionPackage(input) {
94
- const resolvePackageOutput = await resolvePackage({ isDeploying: input.isDeploying, package: input.package });
94
+ const resolvePackageOutput = await resolvePackage({ isDeploying: input.isDeploying, package: input.package, projectRootDir: input.projectRootDir });
95
95
  if (!resolvePackageOutput.found) {
96
96
  return { reason: resolvePackageOutput.reason, success: false };
97
97
  }
@@ -1,6 +1,6 @@
1
1
  import * as fs from 'node:fs/promises';
2
2
  import * as os from 'node:os';
3
- import * as path from 'node:path';
3
+ import path from 'node:path';
4
4
  import { getIac } from '../iac/index.js';
5
5
  import { downloadPackage } from '../lib/package/index.js';
6
6
  export class LocalInfrastructure {
@@ -26,4 +26,8 @@ export type GetProjectEnvOutput = {
26
26
  env: {
27
27
  [key: string]: string;
28
28
  };
29
+ success: true;
30
+ } | {
31
+ reason: string;
32
+ success: false;
29
33
  };
@@ -1,5 +1,5 @@
1
1
  import path from 'node:path';
2
- import { resolveEnvValues } from '../env-utils.js';
2
+ import { getExecutor } from '../../executor/index.js';
3
3
  import { getAnyPath } from '../filesystem.js';
4
4
  import { load, save } from '../yaml-utils.js';
5
5
  export class EnvManager {
@@ -14,8 +14,16 @@ export class EnvManager {
14
14
  const envPath = await this.getEnvPath(input);
15
15
  const { data: env, found } = await load(envPath);
16
16
  let resolvedEnv = {};
17
+ const executor$ = getExecutor();
18
+ if (!executor$.success) {
19
+ return {
20
+ reason: executor$.reason,
21
+ success: false,
22
+ };
23
+ }
24
+ const { executor } = executor$;
17
25
  if (found) {
18
- resolvedEnv = await resolveEnvValues(env, { markSecret: input.markSecret });
26
+ resolvedEnv = await executor.resolveEnvValues({ env, markSecret: input.markSecret });
19
27
  }
20
28
  const userEnvs = await this.getUserEnvPaths(input).then((paths) => Promise.all(paths.map((path) => load(path))));
21
29
  let userMergedEnv = {};
@@ -23,7 +31,7 @@ export class EnvManager {
23
31
  userMergedEnv = { ...userMergedEnv, ...data };
24
32
  }
25
33
  const finalEnv = { ...resolvedEnv, ...userMergedEnv };
26
- return { env: finalEnv };
34
+ return { env: finalEnv, success: true };
27
35
  }
28
36
  async removeProjectEnv(input) {
29
37
  const envPath = await this.getEnvPath(input);
@@ -1,10 +1,3 @@
1
1
  export declare function logEnv(env: {
2
2
  [key: string]: string;
3
3
  }, logFn?: (_: string) => void): void;
4
- export declare function resolveEnvValues(env: {
5
- [key: string]: string;
6
- }, options?: {
7
- markSecret?: boolean;
8
- }): Promise<{
9
- [key: string]: string;
10
- }>;
@@ -1,23 +1,5 @@
1
- import { getInfrastructure } from '../infrastructure/index.js';
2
1
  export function logEnv(env, logFn = console.log) {
3
2
  for (const [key, value] of Object.entries(env)) {
4
3
  logFn(`${key}=${value}`);
5
4
  }
6
5
  }
7
- export async function resolveEnvValues(env, options = {}) {
8
- return Object.fromEntries(await Promise.all(Object.entries(env)
9
- .map(async ([key, value]) => {
10
- const infraType = value.split(':')[0];
11
- const infra$ = getInfrastructure({ type: infraType });
12
- if (!infra$.supported) {
13
- throw new Error(infra$.reason);
14
- }
15
- const { infrastructure } = infra$;
16
- const valueWithoutInfra = value.split(':').slice(1).join(':');
17
- const { isSecret, value: resolvedValue } = await infrastructure.resolveEnv({
18
- value: valueWithoutInfra
19
- });
20
- const finalValue = options.markSecret && isSecret ? `secret://${resolvedValue}` : resolvedValue;
21
- return [key, finalValue];
22
- })));
23
- }
package/dist/lib/log.js CHANGED
@@ -1,4 +1,4 @@
1
- import { ListrLogLevels, ListrLogger } from 'listr2';
1
+ import { ListrLogger, ListrLogLevels } from 'listr2';
2
2
  const myLogger = new ListrLogger({ useIcons: false });
3
3
  const logger = {
4
4
  done(message) {
@@ -5,6 +5,7 @@ export interface PackageManager {
5
5
  export type GetRepoContentInput = {
6
6
  owner: string;
7
7
  path: string;
8
+ projectRootDir?: string;
8
9
  repo: string;
9
10
  };
10
11
  export type GetRepoContentOutput = {
@@ -1,5 +1,7 @@
1
1
  import type { GetRepoContentInput, GetRepoContentOutput, PackageManager } from './common.js';
2
2
  export declare class GitHubPackageManager implements PackageManager {
3
+ private readonly registryUrl;
4
+ constructor(registryUrl?: string);
3
5
  downloadPackage(pkgUrl: string, destPath: string): Promise<string>;
4
6
  getRepoContent({ owner, path: filePath, repo }: GetRepoContentInput): Promise<GetRepoContentOutput>;
5
7
  }
@@ -11,6 +11,10 @@ import { simpleGit } from 'simple-git';
11
11
  import { BackOffPolicy, Retryable } from 'typescript-retry-decorator';
12
12
  import { isNotEmpty } from '../filesystem.js';
13
13
  export class GitHubPackageManager {
14
+ registryUrl;
15
+ constructor(registryUrl = process.env.HEREYA_REGISTRY_URL || 'https://github.com') {
16
+ this.registryUrl = registryUrl;
17
+ }
14
18
  // eslint-disable-next-line new-cap
15
19
  async downloadPackage(pkgUrl, destPath) {
16
20
  if (await isNotEmpty(destPath)) {
@@ -24,7 +28,7 @@ export class GitHubPackageManager {
24
28
  return destPath;
25
29
  }
26
30
  async getRepoContent({ owner, path: filePath, repo }) {
27
- const pkgUrl = `https://github.com/${owner}/${repo}`;
31
+ const pkgUrl = `${this.registryUrl}/${owner}/${repo}`;
28
32
  const tmpFolder = path.join(os.tmpdir(), 'hereya', 'github', owner, repo);
29
33
  try {
30
34
  const destPath = await this.downloadPackage(pkgUrl, tmpFolder);
@@ -2,14 +2,17 @@ import { z } from 'zod';
2
2
  import { IacType } from '../../iac/common.js';
3
3
  import { InfrastructureType } from '../../infrastructure/common.js';
4
4
  import { PackageManager } from './common.js';
5
+ import { LocalPackageManager } from './local.js';
5
6
  export declare const packageManager: PackageManager;
6
- export declare function getPackageManager(): PackageManager;
7
+ export declare const localPackageManager: LocalPackageManager;
8
+ export declare function getPackageManager(protocol: string): PackageManager;
7
9
  export declare function resolvePackage(input: ResolvePackageInput): Promise<ResolvePackageOutput>;
8
10
  export declare function getPackageCanonicalName(packageName: string): string;
9
11
  export declare function downloadPackage(pkgUrl: string, destPath: string): Promise<string>;
10
12
  export type ResolvePackageInput = {
11
13
  isDeploying?: boolean;
12
14
  package: string;
15
+ projectRootDir?: string;
13
16
  };
14
17
  export type ResolvePackageOutput = {
15
18
  canonicalName: string;
@@ -3,20 +3,34 @@ import { z } from 'zod';
3
3
  import { IacType } from '../../iac/common.js';
4
4
  import { InfrastructureType } from '../../infrastructure/common.js';
5
5
  import { GitHubPackageManager } from './github.js';
6
+ import { LocalPackageManager } from './local.js';
6
7
  export const packageManager = new GitHubPackageManager();
7
- export function getPackageManager() {
8
+ export const localPackageManager = new LocalPackageManager();
9
+ export function getPackageManager(protocol) {
10
+ if (protocol === 'local') {
11
+ return localPackageManager;
12
+ }
8
13
  return packageManager;
9
14
  }
10
15
  export async function resolvePackage(input) {
11
- const pkgParts = input.package.split('/');
12
- if (pkgParts.length !== 2) {
13
- return { found: false, reason: 'Invalid package format. Use owner/repository' };
16
+ const isLocal = input.package.startsWith('local://');
17
+ let [owner, repo] = ['', ''];
18
+ if (isLocal) {
19
+ ;
20
+ [owner, repo] = input.package.split('://');
21
+ }
22
+ else {
23
+ const pkgParts = input.package.split('/');
24
+ if (pkgParts.length !== 2) {
25
+ return { found: false, reason: 'Invalid package format. Use owner/repository' };
26
+ }
27
+ ;
28
+ [owner, repo] = pkgParts;
14
29
  }
15
- const [owner, repo] = pkgParts;
16
- const packageManager = getPackageManager();
30
+ const packageManager = getPackageManager(isLocal ? 'local' : '');
17
31
  const metadataContentCandidates = (await Promise.all([
18
- packageManager.getRepoContent({ owner, path: 'hereyarc.yaml', repo }),
19
- packageManager.getRepoContent({ owner, path: 'hereyarc.yml', repo }),
32
+ packageManager.getRepoContent({ owner, path: 'hereyarc.yaml', projectRootDir: input.projectRootDir, repo }),
33
+ packageManager.getRepoContent({ owner, path: 'hereyarc.yml', projectRootDir: input.projectRootDir, repo }),
20
34
  ])).filter((content$) => content$.found);
21
35
  if (metadataContentCandidates.length === 0) {
22
36
  return { found: false, reason: `No hereya metadata file found in ${input.package}` };
@@ -28,7 +42,7 @@ export async function resolvePackage(input) {
28
42
  return { found: false, reason: 'Package has dependencies but is not a deploy package' };
29
43
  }
30
44
  if (input.isDeploying && metadata.onDeploy) {
31
- return resolvePackage({ package: metadata.onDeploy.pkg });
45
+ return resolvePackage({ package: metadata.onDeploy.pkg, projectRootDir: input.projectRootDir });
32
46
  }
33
47
  return {
34
48
  canonicalName: getPackageCanonicalName(input.package),
@@ -43,10 +57,14 @@ export async function resolvePackage(input) {
43
57
  }
44
58
  }
45
59
  export function getPackageCanonicalName(packageName) {
60
+ const isLocal = packageName.startsWith('local://');
61
+ if (isLocal) {
62
+ return packageName.replace('local://', 'local--').replace('/', '-');
63
+ }
46
64
  return packageName.replace('/', '-');
47
65
  }
48
66
  export async function downloadPackage(pkgUrl, destPath) {
49
- const packageManager = getPackageManager();
67
+ const packageManager = getPackageManager(pkgUrl.startsWith('local://') ? 'local' : '');
50
68
  return packageManager.downloadPackage(pkgUrl, destPath);
51
69
  }
52
70
  export const PackageMetadata = z.object({
@@ -0,0 +1,5 @@
1
+ import { GetRepoContentInput, GetRepoContentOutput, PackageManager } from './common.js';
2
+ export declare class LocalPackageManager implements PackageManager {
3
+ downloadPackage(pkgUrl: string, destPath: string): Promise<string>;
4
+ getRepoContent({ path: filePath, projectRootDir, repo }: GetRepoContentInput): Promise<GetRepoContentOutput>;
5
+ }
@@ -0,0 +1,45 @@
1
+ import fs from 'node:fs/promises';
2
+ import path from 'node:path';
3
+ export class LocalPackageManager {
4
+ async downloadPackage(pkgUrl, destPath) {
5
+ const [, source] = pkgUrl.split('://');
6
+ await copyRecursive(source, destPath);
7
+ return destPath;
8
+ }
9
+ async getRepoContent({ path: filePath, projectRootDir, repo }) {
10
+ try {
11
+ const pkgRootDir = path.join(projectRootDir ?? process.cwd(), repo);
12
+ const resolvedPath = path.join(pkgRootDir, filePath);
13
+ if (await fs.stat(resolvedPath)) {
14
+ const content = await fs.readFile(resolvedPath, 'utf8');
15
+ return {
16
+ content,
17
+ found: true,
18
+ pkgUrl: `local://${pkgRootDir}`,
19
+ };
20
+ }
21
+ return {
22
+ found: false,
23
+ reason: `File ${filePath} not found in ${repo}`,
24
+ };
25
+ }
26
+ catch (error) {
27
+ return {
28
+ found: false,
29
+ reason: error.message,
30
+ };
31
+ }
32
+ }
33
+ }
34
+ async function copyRecursive(src, dest) {
35
+ // Ensure the destination directory exists.
36
+ await fs.mkdir(dest, { recursive: true });
37
+ // Read the contents of the source directory.
38
+ const entries = await fs.readdir(src, { withFileTypes: true });
39
+ // Loop through each entry in the directory.
40
+ await Promise.all(entries.map(async (entry) => {
41
+ const srcPath = path.join(src, entry.name);
42
+ const destPath = path.join(dest, entry.name);
43
+ return entry.isDirectory() ? copyRecursive(srcPath, destPath) : fs.copyFile(srcPath, destPath);
44
+ }));
45
+ }
@@ -1,6 +1,4 @@
1
- /// <reference types="node" resolution-mode="require"/>
2
- /// <reference types="node" resolution-mode="require"/>
3
- import { StdioOptions, spawnSync } from 'node:child_process';
1
+ import { spawnSync, StdioOptions } from 'node:child_process';
4
2
  export declare function setDebug(value: boolean): void;
5
3
  export declare function isDebug(): boolean;
6
4
  export type RunShellOptions = {
@@ -1,5 +1,5 @@
1
1
  import { mkdir, readFile, writeFile } from 'node:fs/promises';
2
- import * as path from 'node:path';
2
+ import path from 'node:path';
3
3
  import { parse, stringify } from 'yaml';
4
4
  export async function save(content, file) {
5
5
  try {
@@ -54,6 +54,45 @@
54
54
  "index.js"
55
55
  ]
56
56
  },
57
+ "bootstrap": {
58
+ "aliases": [],
59
+ "args": {
60
+ "infrastructureType": {
61
+ "description": "infrastructure to bootstrap. Options are local, aws",
62
+ "name": "infrastructureType",
63
+ "required": true
64
+ }
65
+ },
66
+ "description": "Install necessary resources for hereya operations in an infrastructure.",
67
+ "examples": [
68
+ "<%= config.bin %> <%= command.id %> aws",
69
+ "<%= config.bin %> <%= command.id %> local"
70
+ ],
71
+ "flags": {
72
+ "force": {
73
+ "char": "f",
74
+ "description": "redeploy hereya resources if already deployed",
75
+ "name": "force",
76
+ "allowNo": false,
77
+ "type": "boolean"
78
+ }
79
+ },
80
+ "hasDynamicHelp": false,
81
+ "hiddenAliases": [],
82
+ "id": "bootstrap",
83
+ "pluginAlias": "hereya-cli",
84
+ "pluginName": "hereya-cli",
85
+ "pluginType": "core",
86
+ "strict": true,
87
+ "enableJsonFlag": false,
88
+ "isESM": true,
89
+ "relativePath": [
90
+ "dist",
91
+ "commands",
92
+ "bootstrap",
93
+ "index.js"
94
+ ]
95
+ },
57
96
  "deploy": {
58
97
  "aliases": [],
59
98
  "args": {},
@@ -102,45 +141,6 @@
102
141
  "index.js"
103
142
  ]
104
143
  },
105
- "bootstrap": {
106
- "aliases": [],
107
- "args": {
108
- "infrastructureType": {
109
- "description": "infrastructure to bootstrap. Options are local, aws",
110
- "name": "infrastructureType",
111
- "required": true
112
- }
113
- },
114
- "description": "Install necessary resources for hereya operations in an infrastructure.",
115
- "examples": [
116
- "<%= config.bin %> <%= command.id %> aws",
117
- "<%= config.bin %> <%= command.id %> local"
118
- ],
119
- "flags": {
120
- "force": {
121
- "char": "f",
122
- "description": "redeploy hereya resources if already deployed",
123
- "name": "force",
124
- "allowNo": false,
125
- "type": "boolean"
126
- }
127
- },
128
- "hasDynamicHelp": false,
129
- "hiddenAliases": [],
130
- "id": "bootstrap",
131
- "pluginAlias": "hereya-cli",
132
- "pluginName": "hereya-cli",
133
- "pluginType": "core",
134
- "strict": true,
135
- "enableJsonFlag": false,
136
- "isESM": true,
137
- "relativePath": [
138
- "dist",
139
- "commands",
140
- "bootstrap",
141
- "index.js"
142
- ]
143
- },
144
144
  "down": {
145
145
  "aliases": [],
146
146
  "args": {},
@@ -954,5 +954,5 @@
954
954
  ]
955
955
  }
956
956
  },
957
- "version": "0.17.2"
957
+ "version": "0.19.0"
958
958
  }