@catladder/cli 1.102.0 → 1.104.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/package.json CHANGED
@@ -24,7 +24,7 @@
24
24
  "node": ">=12.0.0"
25
25
  },
26
26
  "devDependencies": {
27
- "@catladder/pipeline": "1.102.0",
27
+ "@catladder/pipeline": "1.104.0",
28
28
  "@kubernetes/client-node": "^0.16.2",
29
29
  "@tsconfig/node14": "^1.0.1",
30
30
  "@types/common-tags": "^1.8.0",
@@ -57,5 +57,5 @@
57
57
  "typescript": "^4.5.4",
58
58
  "vorpal": "^1.12.0"
59
59
  },
60
- "version": "1.102.0"
60
+ "version": "1.104.0"
61
61
  }
@@ -1,72 +1,18 @@
1
- import type { Config, ComponentConfig } from "@catladder/pipeline";
2
- import {
3
- getEnvVarsResolved,
4
- getProjectConfig,
5
- } from "../../config/getProjectConfig";
6
- import { getGitRoot } from "../../utils/projects";
7
- import { join } from "path";
8
- const getCurrentComponentName = async (
9
- components: Record<string, ComponentConfig>
10
- ) => {
11
- const gitRoot = await getGitRoot();
12
- const currentDir = process.cwd();
13
- return Object.keys(components).find((c) =>
14
- currentDir.startsWith(join(gitRoot, components[c].dir))
15
- );
16
- };
17
-
18
- const sanitizeEnvVarName = (name: string) => name.replace(/[\s\-.]+/g, "_");
19
-
20
- const getAllVariablesToPrint = async (
21
- config: Config,
22
- choice?: {
23
- env?: string;
24
- componentName?: string;
25
- }
26
- ) => {
27
- const env = choice?.env ?? "local";
28
- const { components } = config;
29
-
30
- const currentComponent =
31
- choice?.componentName ?? (await getCurrentComponentName(components));
1
+ import { getProjectConfig } from "../../config/getProjectConfig";
2
+ import { printVariables } from "./printVariables";
3
+ import type { Choice } from "./types";
4
+ import { writeDotEnvFiles } from "./writeDotEnvFiles";
5
+ import { writeDTsFiles } from "./writeEnvDTs";
32
6
 
33
- let variables = {};
34
- if (currentComponent) {
35
- variables = await getEnvVarsResolved(null, env, currentComponent);
36
- } else {
37
- // when in a monorep and not in a subapp, merge all env vars.
38
- // this is not 100% correct, but better than not exporting any vars at all
39
- // so we also add prefixed variants
40
- variables = await Object.keys(components).reduce(
41
- async (acc, componentName) => {
42
- const subappvars = await getEnvVarsResolved(null, env, componentName);
43
- return {
44
- ...(await acc),
45
- ...subappvars,
46
- // also add prefixed variants in case
47
- ...Object.fromEntries(
48
- Object.entries(subappvars).map(([key, value]) => [
49
- `${sanitizeEnvVarName(componentName.toUpperCase())}_${key}`,
50
- value,
51
- ])
52
- ),
53
- };
54
- },
55
- {}
56
- );
57
- }
58
- return variables;
59
- };
60
- export default async (choice?: { env?: string; componentName?: string }) => {
7
+ export default async (choice?: Choice) => {
61
8
  const config = await getProjectConfig();
62
9
  if (!config) {
63
10
  return;
64
11
  }
65
- const variables = await getAllVariablesToPrint(config, choice);
66
12
 
67
- console.log(
68
- Object.entries(variables)
69
- .map(([key, value]) => `export ${key}='${value}'`)
70
- .join("\n")
71
- );
13
+ await printVariables(config, choice);
14
+
15
+ await writeDotEnvFiles(config, choice);
16
+
17
+ await writeDTsFiles(config, choice);
72
18
  };
@@ -0,0 +1,51 @@
1
+ import type { Config } from "@catladder/pipeline";
2
+ import { getEnvVarsResolved } from "../../config/getProjectConfig";
3
+ import type { Choice, Variables } from "./types";
4
+ import {
5
+ getCurrentComponentAndEnvFromChoice,
6
+ makeKeyValueString,
7
+ sanitizeEnvVarName,
8
+ } from "./utils";
9
+
10
+ const getAllVariablesToPrint = async (config: Config, choice?: Choice) => {
11
+ const { env, currentComponent } = await getCurrentComponentAndEnvFromChoice(
12
+ config,
13
+ choice
14
+ );
15
+
16
+ let variables = {};
17
+ if (currentComponent) {
18
+ variables = await getEnvVarsResolved(null, env, currentComponent);
19
+ } else {
20
+ // when in a monorep and not in a subapp, merge all env vars.
21
+ // this is not 100% correct, but better than not exporting any vars at all
22
+ // so we also add prefixed variants
23
+ variables = await Object.keys(config.components).reduce(
24
+ async (acc, componentName) => {
25
+ const subappvars = await getEnvVarsResolved(null, env, componentName);
26
+ return {
27
+ ...(await acc),
28
+ ...subappvars,
29
+ // also add prefixed variants in case
30
+ ...Object.fromEntries(
31
+ Object.entries(subappvars).map(([key, value]) => [
32
+ `${sanitizeEnvVarName(componentName.toUpperCase())}_${key}`,
33
+ value,
34
+ ])
35
+ ),
36
+ };
37
+ },
38
+ {}
39
+ );
40
+ }
41
+ return variables;
42
+ };
43
+
44
+ export const printVariables = async (config: Config, choice?: Choice) => {
45
+ const variables = await getAllVariablesToPrint(config, choice);
46
+
47
+ console.log(makeExportKeyValuestring(variables));
48
+ };
49
+
50
+ const makeExportKeyValuestring = (variables: Variables) =>
51
+ makeKeyValueString(variables, "export ");
@@ -0,0 +1,6 @@
1
+ export type Choice = {
2
+ env?: string;
3
+ componentName?: string;
4
+ };
5
+
6
+ export type Variables = Record<string, string>;
@@ -0,0 +1,49 @@
1
+ import type { Config } from "@catladder/pipeline";
2
+ import { join } from "path";
3
+ import { getGitRoot } from "../../utils/projects";
4
+ import type { Choice, Variables } from "./types";
5
+ export const getComponentFullPath = (
6
+ gitRoot: string,
7
+ config: Config,
8
+ componentName: string
9
+ ) => {
10
+ return join(gitRoot, config.components[componentName].dir);
11
+ };
12
+ const getCurrentComponentName = async (config: Config) => {
13
+ const gitRoot = await getGitRoot();
14
+ const currentDir = process.cwd();
15
+ return Object.keys(config.components).find((c) =>
16
+ currentDir.startsWith(getComponentFullPath(gitRoot, config, c))
17
+ );
18
+ };
19
+
20
+ export const getCurrentComponentAndEnvFromChoice = async (
21
+ config: Config,
22
+ choice?: Choice
23
+ ) => {
24
+ const env = choice?.env ?? "local";
25
+ const currentComponent =
26
+ choice?.componentName ?? (await getCurrentComponentName(config));
27
+
28
+ return {
29
+ currentComponent,
30
+ env,
31
+ };
32
+ };
33
+
34
+ export const makeKeyValueString = (variables: Variables, keyPrefix = "") =>
35
+ Object.entries(variables)
36
+ .map(([key, value]) => `${keyPrefix}${key}='${value}'`)
37
+ .join("\n");
38
+
39
+ export const sanitizeMultiLine = (variables: Variables) => {
40
+ return Object.fromEntries(
41
+ Object.entries(variables).map(([key, value]) => [
42
+ key,
43
+ value.replaceAll("\n", "\\n"),
44
+ ])
45
+ );
46
+ };
47
+
48
+ export const sanitizeEnvVarName = (name: string) =>
49
+ name.replace(/[\s\-.]+/g, "_");
@@ -0,0 +1,45 @@
1
+ import type { Config } from "@catladder/pipeline";
2
+ import { writeFile } from "fs-extra";
3
+ import { join } from "path";
4
+ import { getEnvVarsResolved } from "../../config/getProjectConfig";
5
+ import { getGitRoot } from "../../utils/projects";
6
+ import type { Choice } from "./types";
7
+ import {
8
+ getComponentFullPath,
9
+ getCurrentComponentAndEnvFromChoice,
10
+ makeKeyValueString,
11
+ sanitizeMultiLine,
12
+ } from "./utils";
13
+
14
+ export const writeDotEnvFiles = async (config: Config, choice?: Choice) => {
15
+ const { env, currentComponent } = await getCurrentComponentAndEnvFromChoice(
16
+ config,
17
+ choice
18
+ );
19
+
20
+ // whether to print .dotenv is currentl configure on the "local" part of the env
21
+
22
+ const componentsWithEnabledDotEnvWrite = Object.entries(config.components)
23
+ .filter(([, component]) => component?.dotEnv)
24
+ .map(([componentName]) => componentName);
25
+
26
+ const componentsToActuallyWriteDotEnvNow = currentComponent
27
+ ? componentsWithEnabledDotEnvWrite.includes(currentComponent)
28
+ ? [currentComponent]
29
+ : []
30
+ : componentsWithEnabledDotEnvWrite;
31
+ const gitRoot = await getGitRoot();
32
+
33
+ for (const componentName of componentsToActuallyWriteDotEnvNow) {
34
+ const variables = await getEnvVarsResolved(null, env, componentName);
35
+ const componentDir = getComponentFullPath(gitRoot, config, componentName);
36
+ const filePath = join(componentDir, ".env");
37
+ // many .dotenv don't like multiline values, so we sanitize them here
38
+ const variablesSanitized = sanitizeMultiLine(variables);
39
+ await writeFile(
40
+ filePath,
41
+ "# automatically created by catladder. Do not modify!\n\n" +
42
+ makeKeyValueString(variablesSanitized)
43
+ );
44
+ }
45
+ };
@@ -0,0 +1,71 @@
1
+ import type { Config } from "@catladder/pipeline";
2
+ import { writeFile } from "fs-extra";
3
+ import { join } from "path";
4
+ import { getEnvironment } from "../../config/getProjectConfig";
5
+ import { getGitRoot } from "../../utils/projects";
6
+ import type { Choice } from "./types";
7
+ import {
8
+ getComponentFullPath,
9
+ getCurrentComponentAndEnvFromChoice,
10
+ } from "./utils";
11
+
12
+ export const writeDTsFiles = async (config: Config, choice?: Choice) => {
13
+ const { env, currentComponent } = await getCurrentComponentAndEnvFromChoice(
14
+ config,
15
+ choice
16
+ );
17
+
18
+ const componentsWithEnabledEnvDTsWrite = Object.entries(config.components)
19
+ .filter(([, component]) => component?.envDTs)
20
+ .map(([componentName]) => componentName);
21
+
22
+ const componentsToActuallyWriteDotEnvNow = currentComponent
23
+ ? componentsWithEnabledEnvDTsWrite.includes(currentComponent)
24
+ ? [currentComponent]
25
+ : []
26
+ : componentsWithEnabledEnvDTsWrite;
27
+ const gitRoot = await getGitRoot();
28
+
29
+ for (const componentName of componentsToActuallyWriteDotEnvNow) {
30
+ const envNames = await getEnvsForDTs(env, componentName);
31
+ const envDTsContent = createEnvDTsContent(envNames);
32
+
33
+ const componentDir = getComponentFullPath(gitRoot, config, componentName);
34
+ const filePath = join(componentDir, "env.d.ts");
35
+ await writeFile(filePath, envDTsContent);
36
+ }
37
+ };
38
+
39
+ async function getEnvsForDTs(
40
+ env: string,
41
+ componentName: string
42
+ ): Promise<string[]> {
43
+ const environment = await getEnvironment(env, componentName);
44
+ const allEnvKeys = Object.keys(environment.envVars);
45
+ const hiddenEnvKeys = new Set(
46
+ environment.secretEnvVarKeys
47
+ .filter((s) => s.hidden)
48
+ .map((s) => s.key)
49
+ .concat(["_ALL_ENV_VAR_KEYS"])
50
+ );
51
+ const dTsEnvKeys = allEnvKeys.filter((k) => !hiddenEnvKeys.has(k));
52
+
53
+ return dTsEnvKeys;
54
+ }
55
+
56
+ function createEnvDTsContent(envNames: string[]) {
57
+ return `/* tslint:disable prettier/prettier */
58
+ /* eslint-disable prettier/prettier */
59
+ /* prettier-ignore */
60
+ // automatically generated by catladder. Do not modify!
61
+ export {}
62
+
63
+ declare global {
64
+ namespace NodeJS {
65
+ interface ProcessEnv {
66
+ ${envNames.map((name) => ` ${name}: string`).join("\n")}
67
+ }
68
+ }
69
+ }
70
+ `;
71
+ }
package/tsconfig.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "compilerOptions": {
3
- "lib": ["es2020", "DOM"],
3
+ "lib": ["es2021", "DOM"],
4
4
  "module": "CommonJS",
5
5
  "declaration": true,
6
6
  "noImplicitAny": true,