@catladder/pipeline 3.18.0 → 3.20.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 (89) hide show
  1. package/dist/catenv/index.d.ts +7 -0
  2. package/dist/catenv/index.js +14 -0
  3. package/dist/catladder-gitlab.js +4 -1
  4. package/dist/constants.js +1 -1
  5. package/dist/index.d.ts +2 -1
  6. package/dist/index.js +2 -1
  7. package/dist/pipeline/createMainPipeline.js +1 -1
  8. package/dist/pipeline/generatePipelineFiles.d.ts +2 -1
  9. package/dist/pipeline/generatePipelineFiles.js +3 -4
  10. package/dist/pipeline/gitlab/gitlabReleaseJobs.d.ts +2 -1
  11. package/dist/pipeline/gitlab/gitlabReleaseJobs.js +48 -3
  12. package/dist/rules/index.d.ts +1 -3
  13. package/dist/rules/index.js +2 -19
  14. package/dist/tsconfig.tsbuildinfo +1 -1
  15. package/dist/types/config.d.ts +10 -0
  16. package/dist/types/hooks.d.ts +26 -0
  17. package/dist/types/hooks.js +5 -0
  18. package/dist/types/release.d.ts +7 -0
  19. package/dist/types/release.js +5 -0
  20. package/dist/utils/writeFiles.d.ts +12 -6
  21. package/dist/utils/writeFiles.js +59 -41
  22. package/examples/__snapshots__/automatic-releases.test.ts.snap +1484 -0
  23. package/examples/__snapshots__/cloud-run-health-check-defaults.test.ts.snap +0 -2
  24. package/examples/__snapshots__/cloud-run-health-check-only-startup.test.ts.snap +0 -2
  25. package/examples/__snapshots__/cloud-run-health-check.test.ts.snap +0 -2
  26. package/examples/__snapshots__/cloud-run-http2.test.ts.snap +0 -2
  27. package/examples/__snapshots__/cloud-run-llama.test.ts.snap +0 -2
  28. package/examples/__snapshots__/cloud-run-memory-limit.test.ts.snap +0 -2
  29. package/examples/__snapshots__/cloud-run-meteor-with-worker.test.ts.snap +0 -2
  30. package/examples/__snapshots__/cloud-run-nextjs.test.ts.snap +0 -2
  31. package/examples/__snapshots__/cloud-run-no-cpu-throttling.test.ts.snap +0 -2
  32. package/examples/__snapshots__/cloud-run-no-service.test.ts.snap +0 -2
  33. package/examples/__snapshots__/cloud-run-non-public.test.ts.snap +0 -2
  34. package/examples/__snapshots__/cloud-run-post-stop-job.test.ts.snap +0 -2
  35. package/examples/__snapshots__/cloud-run-service-custom-vpc-connector.test.ts.snap +0 -2
  36. package/examples/__snapshots__/cloud-run-service-custom-vpc.test.ts.snap +0 -2
  37. package/examples/__snapshots__/cloud-run-service-gen2.test.ts.snap +0 -2
  38. package/examples/__snapshots__/cloud-run-service-increase-timout.test.ts.snap +0 -2
  39. package/examples/__snapshots__/cloud-run-service-with-volumes.test.ts.snap +0 -2
  40. package/examples/__snapshots__/cloud-run-storybook.test.ts.snap +0 -2
  41. package/examples/__snapshots__/cloud-run-with-agents.test.ts.snap +0 -2
  42. package/examples/__snapshots__/cloud-run-with-gpu.test.ts.snap +0 -2
  43. package/examples/__snapshots__/cloud-run-with-ngnix.test.ts.snap +0 -2
  44. package/examples/__snapshots__/cloud-run-with-sql-legacy-jobs.test.ts.snap +0 -2
  45. package/examples/__snapshots__/cloud-run-with-sql-multiple-dbs.test.ts.snap +0 -2
  46. package/examples/__snapshots__/cloud-run-with-sql-reuse-db.test.ts.snap +0 -2
  47. package/examples/__snapshots__/cloud-run-with-sql.test.ts.snap +0 -2
  48. package/examples/__snapshots__/cloud-run-with-worker.test.ts.snap +0 -2
  49. package/examples/__snapshots__/custom-build-job-with-tests.test.ts.snap +0 -2
  50. package/examples/__snapshots__/custom-build-job.test.ts.snap +0 -2
  51. package/examples/__snapshots__/custom-deploy.test.ts.snap +0 -2
  52. package/examples/__snapshots__/custom-envs.test.ts.snap +0 -2
  53. package/examples/__snapshots__/custom-sbom-java.test.ts.snap +0 -2
  54. package/examples/__snapshots__/custom-verify-job.test.ts.snap +0 -2
  55. package/examples/__snapshots__/git-submodule.test.ts.snap +0 -2
  56. package/examples/__snapshots__/kubernetes-application-customization.test.ts.snap +0 -2
  57. package/examples/__snapshots__/kubernetes-with-cloud-sql.test.ts.snap +0 -2
  58. package/examples/__snapshots__/kubernetes-with-jobs.test.ts.snap +0 -2
  59. package/examples/__snapshots__/kubernetes-with-mongodb.test.ts.snap +0 -2
  60. package/examples/__snapshots__/local-dot-env.test.ts.snap +0 -2
  61. package/examples/__snapshots__/meteor-kubernetes.test.ts.snap +0 -2
  62. package/examples/__snapshots__/modify-generated-files.test.ts.snap +640 -0
  63. package/examples/__snapshots__/multiline-var.test.ts.snap +0 -2
  64. package/examples/__snapshots__/native-app.test.ts.snap +0 -2
  65. package/examples/__snapshots__/node-build-with-custom-image.test.ts.snap +0 -2
  66. package/examples/__snapshots__/node-build-with-docker-additions.test.ts.snap +0 -2
  67. package/examples/__snapshots__/override-secrets.test.ts.snap +0 -2
  68. package/examples/__snapshots__/rails-k8s-with-worker-dockerfile.test.ts.snap +0 -2
  69. package/examples/__snapshots__/rails-k8s-with-worker.test.ts.snap +0 -2
  70. package/examples/__snapshots__/referencing-other-vars.test.ts.snap +0 -2
  71. package/examples/__snapshots__/wait-for-other-deploy.test.ts.snap +0 -2
  72. package/examples/__snapshots__/workspace-api-www-turbo-cache.test.ts.snap +0 -2
  73. package/examples/__snapshots__/workspace-api-www.test.ts.snap +0 -2
  74. package/examples/automatic-releases.test.ts +11 -0
  75. package/examples/automatic-releases.ts +28 -0
  76. package/examples/modify-generated-files.test.ts +11 -0
  77. package/examples/modify-generated-files.ts +29 -0
  78. package/package.json +1 -1
  79. package/src/catenv/index.ts +14 -0
  80. package/src/catladder-gitlab.ts +4 -1
  81. package/src/index.ts +1 -0
  82. package/src/pipeline/createMainPipeline.ts +9 -7
  83. package/src/pipeline/generatePipelineFiles.ts +5 -4
  84. package/src/pipeline/gitlab/gitlabReleaseJobs.ts +37 -4
  85. package/src/rules/index.ts +0 -32
  86. package/src/types/config.ts +12 -0
  87. package/src/types/hooks.ts +29 -0
  88. package/src/types/release.ts +7 -0
  89. package/src/utils/writeFiles.ts +58 -34
@@ -1523,8 +1523,6 @@ create release:
1523
1523
  - &a5
1524
1524
  if: $CI_PIPELINE_SOURCE == "schedule"
1525
1525
  when: never
1526
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $AUTO_RELEASE == "true"
1527
- when: on_success
1528
1526
  - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
1529
1527
  when: manual
1530
1528
  - if: $CI_COMMIT_BRANCH =~ /^[0-9]+.([0-9]+|x).x$/
@@ -1503,8 +1503,6 @@ create release:
1503
1503
  - &a5
1504
1504
  if: $CI_PIPELINE_SOURCE == "schedule"
1505
1505
  when: never
1506
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $AUTO_RELEASE == "true"
1507
- when: on_success
1508
1506
  - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
1509
1507
  when: manual
1510
1508
  - if: $CI_COMMIT_BRANCH =~ /^[0-9]+.([0-9]+|x).x$/
@@ -4832,8 +4832,6 @@ create release:
4832
4832
  - &a4
4833
4833
  if: $CI_PIPELINE_SOURCE == "schedule"
4834
4834
  when: never
4835
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $AUTO_RELEASE == "true"
4836
- when: on_success
4837
4835
  - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
4838
4836
  when: manual
4839
4837
  - if: $CI_COMMIT_BRANCH =~ /^[0-9]+.([0-9]+|x).x$/
@@ -1503,8 +1503,6 @@ create release:
1503
1503
  - &a4
1504
1504
  if: $CI_PIPELINE_SOURCE == "schedule"
1505
1505
  when: never
1506
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $AUTO_RELEASE == "true"
1507
- when: on_success
1508
1506
  - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
1509
1507
  when: manual
1510
1508
  - if: $CI_COMMIT_BRANCH =~ /^[0-9]+.([0-9]+|x).x$/
@@ -2405,8 +2405,6 @@ create release:
2405
2405
  - &a4
2406
2406
  if: $CI_PIPELINE_SOURCE == "schedule"
2407
2407
  when: never
2408
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $AUTO_RELEASE == "true"
2409
- when: on_success
2410
2408
  - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
2411
2409
  when: manual
2412
2410
  - if: $CI_COMMIT_BRANCH =~ /^[0-9]+.([0-9]+|x).x$/
@@ -2397,8 +2397,6 @@ create release:
2397
2397
  - &a4
2398
2398
  if: $CI_PIPELINE_SOURCE == "schedule"
2399
2399
  when: never
2400
- - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH && $AUTO_RELEASE == "true"
2401
- when: on_success
2402
2400
  - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH
2403
2401
  when: manual
2404
2402
  - if: $CI_COMMIT_BRANCH =~ /^[0-9]+.([0-9]+|x).x$/
@@ -0,0 +1,11 @@
1
+ import { createYamlLocalPipeline } from "./__utils__/helpers";
2
+ import config from "./automatic-releases";
3
+
4
+ /**
5
+ * This test is auto-generated.
6
+ * Modifications will be overwritten on every `yarn test` run!
7
+ */
8
+
9
+ it("matches snapshot for automatic-releases local pipeline YAML", async () => {
10
+ expect(await createYamlLocalPipeline(config)).toMatchSnapshot();
11
+ });
@@ -0,0 +1,28 @@
1
+ import type { Config } from "../src";
2
+
3
+ const config = {
4
+ appName: "test-app",
5
+ customerName: "pan",
6
+ releases: {
7
+ when: "auto",
8
+ },
9
+ components: {
10
+ www: {
11
+ dir: "www",
12
+ build: {
13
+ type: "node",
14
+ },
15
+ deploy: {
16
+ type: "google-cloudrun",
17
+ projectId: "google-project-id",
18
+ region: "europe-west6",
19
+ },
20
+ },
21
+ },
22
+ } satisfies Config;
23
+
24
+ export default config;
25
+
26
+ export const information = {
27
+ title: "Automatic Releases on main branch",
28
+ };
@@ -0,0 +1,11 @@
1
+ import { createYamlLocalPipeline } from "./__utils__/helpers";
2
+ import config from "./modify-generated-files";
3
+
4
+ /**
5
+ * This test is auto-generated.
6
+ * Modifications will be overwritten on every `yarn test` run!
7
+ */
8
+
9
+ it("matches snapshot for modify-generated-files local pipeline YAML", async () => {
10
+ expect(await createYamlLocalPipeline(config)).toMatchSnapshot();
11
+ });
@@ -0,0 +1,29 @@
1
+ import type { Config } from "../src";
2
+
3
+ const config = {
4
+ appName: "test-app",
5
+ customerName: "pan",
6
+ components: {
7
+ api: {
8
+ dir: "api",
9
+ build: {
10
+ type: "node",
11
+ },
12
+ deploy: false,
13
+ },
14
+ },
15
+ hooks: {
16
+ transformFileBeforeWrite({ filename, content }) {
17
+ if (filename === ".gitlab-ci.yml") {
18
+ // FIXME: currently not covered by the snapshot test
19
+ return "# modified!\n\n" + content;
20
+ }
21
+ },
22
+ },
23
+ } satisfies Config;
24
+
25
+ export default config;
26
+
27
+ export const information = {
28
+ title: "Custom: Modify Generated Files",
29
+ };
package/package.json CHANGED
@@ -53,7 +53,7 @@
53
53
  }
54
54
  ],
55
55
  "license": "MIT",
56
- "version": "3.18.0",
56
+ "version": "3.20.0",
57
57
  "scripts": {
58
58
  "build:tsc": "yarn tsc",
59
59
  "build": "yarn build:compile && yarn build:inline-variables",
@@ -0,0 +1,14 @@
1
+ import type { Config } from "../types";
2
+ import { FileWriter } from "../utils/writeFiles";
3
+
4
+ export type CatenvContext = {
5
+ config: Config;
6
+ fileWriter: FileWriter;
7
+ };
8
+
9
+ export const createCatenvContext = (config: Config): CatenvContext => {
10
+ return {
11
+ config,
12
+ fileWriter: FileWriter.create(config),
13
+ };
14
+ };
@@ -1,10 +1,13 @@
1
1
  import { readConfig } from "./config";
2
2
  import { generatePipelineFiles } from "./pipeline/generatePipelineFiles";
3
+ import { createCatenvContext } from "./catenv";
3
4
 
4
5
  readConfig().then(async (result) => {
5
6
  if (!result?.config) {
6
7
  throw new Error("no catladder config found");
7
8
  }
8
9
 
9
- await generatePipelineFiles(result.config, "gitlab");
10
+ const context = createCatenvContext(result.config);
11
+
12
+ await generatePipelineFiles(context, "gitlab");
10
13
  });
package/src/index.ts CHANGED
@@ -9,3 +9,4 @@ export * from "./deploy";
9
9
  export * from "./utils/writeFiles";
10
10
  export * from "./variables/VariableValue";
11
11
  export * from "./bash";
12
+ export * from "./catenv";
@@ -99,13 +99,15 @@ export const createMainPipeline = async <T extends PipelineType>(
99
99
  jobs: {
100
100
  ...allJobs,
101
101
  ...Object.fromEntries(
102
- Object.entries(getGitlabReleaseJobs()).map(([name, gitlabJob]) => [
103
- name,
104
- {
105
- gitlabJob,
106
- context: null,
107
- },
108
- ]),
102
+ Object.entries(getGitlabReleaseJobs(config)).map(
103
+ ([name, gitlabJob]) => [
104
+ name,
105
+ {
106
+ gitlabJob,
107
+ context: null,
108
+ },
109
+ ],
110
+ ),
109
111
  ),
110
112
  },
111
113
  variables: config.runnerVariables,
@@ -1,9 +1,10 @@
1
1
  import { mkdir, rm } from "fs/promises";
2
2
  import { dirname } from "path";
3
3
  import type { Config, GitlabJobDef, PipelineType } from "../types";
4
- import { writeYamlfile } from "../utils/writeFiles";
4
+
5
5
  import { createMainPipeline } from "./createMainPipeline";
6
6
  import { sortGitLabJobDefProps } from "./gitlab/sortGitLabJobDefProps";
7
+ import type { CatenvContext } from "../catenv";
7
8
 
8
9
  const CATLADDER_GENERATED_FOLDER = ".catladder-generated";
9
10
 
@@ -14,13 +15,13 @@ type YamlFile = {
14
15
  content: Record<string, unknown>;
15
16
  };
16
17
  export async function generatePipelineFiles<T extends PipelineType>(
17
- config: Config,
18
+ context: CatenvContext,
18
19
  pipelineType: T,
19
20
  ) {
20
21
  if (pipelineType !== "gitlab") {
21
22
  throw new Error("Pipeline type not supported");
22
23
  }
23
- const includes = await getGitlabPipelineIncludes(config);
24
+ const includes = await getGitlabPipelineIncludes(context.config);
24
25
 
25
26
  const mainFile: YamlFile = {
26
27
  path: ".gitlab-ci.yml",
@@ -37,7 +38,7 @@ export async function generatePipelineFiles<T extends PipelineType>(
37
38
  await Promise.all(
38
39
  files.map(async ({ path, content }) => {
39
40
  await mkdir(dirname(path), { recursive: true });
40
- await writeYamlfile(path, content);
41
+ await context.fileWriter.writeYamlfile(path, content);
41
42
  }),
42
43
  );
43
44
  }
@@ -1,23 +1,56 @@
1
- import { RULES_MANUAL_RELEASE, RULES_RELEASE } from "../../rules";
1
+ import {
2
+ RULE_CONDITION_HOTFIX_BRANCH,
3
+ RULE_CONDITION_MAIN_BRANCH,
4
+ RULE_NEVER_ON_AGENT_TRIGGER,
5
+ RULE_NEVER_ON_RELEASE_COMMIT,
6
+ RULE_NEVER_ON_SCHEDULE,
7
+ } from "../../rules";
2
8
  import { getRunnerImage } from "../../runner";
9
+ import type { Config } from "../../types/config";
10
+ import type { GitlabRule } from "../../types";
3
11
 
4
12
  const EXPIRED_TOKEN_HELP =
5
13
  "echo '👉 The project access token might be invald - run `project-renew-token` in catladder CLI to fix.'";
6
14
 
7
- export const getGitlabReleaseJobs = () => {
15
+ const baseReleaseRules = [
16
+ RULE_NEVER_ON_RELEASE_COMMIT,
17
+ RULE_NEVER_ON_AGENT_TRIGGER,
18
+ RULE_NEVER_ON_SCHEDULE,
19
+ ];
20
+ export const getGitlabReleaseJobs = (config: Config) => {
8
21
  return {
9
22
  ["create release"]: {
10
23
  stage: "release",
11
24
  image: getRunnerImage("semantic-release"),
12
25
  script: ["semanticRelease", EXPIRED_TOKEN_HELP],
13
- rules: RULES_RELEASE,
26
+ rules: [
27
+ ...baseReleaseRules,
28
+ {
29
+ if: RULE_CONDITION_MAIN_BRANCH,
30
+ when: config.releases?.when === "auto" ? "on_success" : "manual",
31
+ },
32
+ {
33
+ if: RULE_CONDITION_HOTFIX_BRANCH,
34
+ when: "manual",
35
+ },
36
+ ] satisfies GitlabRule[],
14
37
  },
15
38
  ["⚠️ force create release"]: {
16
39
  stage: "release",
17
40
  image: getRunnerImage("semantic-release"),
18
41
  script: ["semanticRelease", EXPIRED_TOKEN_HELP],
19
42
  needs: [],
20
- rules: RULES_MANUAL_RELEASE,
43
+ rules: [
44
+ ...baseReleaseRules,
45
+ {
46
+ if: RULE_CONDITION_MAIN_BRANCH,
47
+ when: "manual",
48
+ },
49
+ {
50
+ if: RULE_CONDITION_HOTFIX_BRANCH,
51
+ when: "manual",
52
+ },
53
+ ] satisfies GitlabRule[],
21
54
  },
22
55
  };
23
56
  };
@@ -39,35 +39,3 @@ export const RULE_IS_TAGGED_RELEASE: GitlabRule = {
39
39
 
40
40
  export const RULE_CONDITION_HOTFIX_BRANCH =
41
41
  "$CI_COMMIT_BRANCH =~ /^[0-9]+.([0-9]+|x).x$/";
42
-
43
- export const RULES_RELEASE: GitlabRule[] = [
44
- RULE_NEVER_ON_RELEASE_COMMIT,
45
- RULE_NEVER_ON_AGENT_TRIGGER,
46
- RULE_NEVER_ON_SCHEDULE,
47
- {
48
- if: RULE_CONDITION_MAIN_BRANCH + ' && $AUTO_RELEASE == "true"',
49
- when: "on_success",
50
- },
51
- {
52
- if: RULE_CONDITION_MAIN_BRANCH,
53
- when: "manual",
54
- },
55
- {
56
- if: RULE_CONDITION_HOTFIX_BRANCH,
57
- when: "manual",
58
- },
59
- ];
60
-
61
- export const RULES_MANUAL_RELEASE: GitlabRule[] = [
62
- RULE_NEVER_ON_RELEASE_COMMIT,
63
- RULE_NEVER_ON_AGENT_TRIGGER,
64
- RULE_NEVER_ON_SCHEDULE,
65
- {
66
- if: RULE_CONDITION_MAIN_BRANCH,
67
- when: "manual",
68
- },
69
- {
70
- if: RULE_CONDITION_HOTFIX_BRANCH,
71
- when: "manual",
72
- },
73
- ];
@@ -6,6 +6,8 @@ import type { ComponentContext } from "./context";
6
6
  import type { PartialDeep } from "./utils";
7
7
  import type { PipelineType, WorkspaceBuildConfig } from "..";
8
8
  import type { AgentConfig } from "./agent";
9
+ import type { Hooks } from "./hooks";
10
+ import type { ReleaseConfig } from "./release";
9
11
 
10
12
  export const ALL_PIPELINE_TRIGGERS = [
11
13
  "mainBranch",
@@ -231,4 +233,14 @@ export type Config<C extends ConfigProps = never> = {
231
233
  * additional vars only for the runner in all jobs.
232
234
  */
233
235
  runnerVariables?: Record<string, string>;
236
+
237
+ /**
238
+ * hook into catladder generation
239
+ */
240
+ hooks?: Hooks;
241
+
242
+ /**
243
+ * configure tagged releases
244
+ */
245
+ releases?: ReleaseConfig;
234
246
  };
@@ -0,0 +1,29 @@
1
+ export type FileHookContext = {
2
+ /**
3
+ * the filename of the file
4
+ */
5
+ filename: string;
6
+ /**
7
+ * the extension of the file
8
+ */
9
+ extension: string;
10
+ /**
11
+ * the path of the file
12
+ */
13
+ path: string;
14
+
15
+ /**
16
+ * the content of the file
17
+ */
18
+ content: string;
19
+ };
20
+
21
+ type MaybePromise<T> = T | Promise<T>;
22
+ export type Hooks = {
23
+ /**
24
+ * transform the file before it is written. If undefined is returned, the file is not modified
25
+ */
26
+ transformFileBeforeWrite: (
27
+ fileHookContext: FileHookContext,
28
+ ) => MaybePromise<string | undefined>;
29
+ };
@@ -0,0 +1,7 @@
1
+ export type ReleaseConfig = {
2
+ /**
3
+ * Whether to release automatically or manually on main branch.
4
+ * Defaults to "manuel"
5
+ */
6
+ when?: "manual" | "auto";
7
+ };
@@ -1,35 +1,9 @@
1
1
  import { writeFile } from "fs/promises";
2
2
  import { stringify } from "yaml";
3
+ import type { Config } from "../types";
3
4
 
4
- export const getAutoGeneratedHeader = (commentChar: string) => {
5
- return [
6
- "-------------------------------------------------",
7
- `🐱 🔨 This file is generated by catladder`,
8
- `🚨 Do not edit this file manually 🚨`,
9
- "-------------------------------------------------",
10
- ]
11
- .map((line) => `${commentChar} ${line}`)
12
- .join("\n")
13
- .concat("\n");
14
- };
15
-
16
- export const writeGeneratedFile = async (
17
- path: string,
18
- content: string,
19
- {
20
- commentChar,
21
- }: {
22
- commentChar: string;
23
- },
24
- ) => {
25
- await writeFile(
26
- path,
27
- // need to spread out the jobs, forgot why
28
- [getAutoGeneratedHeader(commentChar), content].join("\n"),
29
- {
30
- encoding: "utf-8",
31
- },
32
- );
5
+ type WriteFileOptions = {
6
+ commentChar: string;
33
7
  };
34
8
 
35
9
  type StringifyOptions = Exclude<
@@ -45,8 +19,58 @@ export const yamlStringifyOptions: StringifyOptions = {
45
19
  singleQuote: true,
46
20
  };
47
21
 
48
- export const writeYamlfile = async (path: string, data: any) => {
49
- await writeGeneratedFile(path, stringify(data, yamlStringifyOptions), {
50
- commentChar: "#",
51
- });
52
- };
22
+ export class FileWriter {
23
+ public static create(config: Config) {
24
+ return new FileWriter(config);
25
+ }
26
+
27
+ constructor(private readonly config: Config) {
28
+ this.config = config;
29
+ }
30
+
31
+ protected async writeTheFile(path: string, content: string) {
32
+ const transformedContent =
33
+ await this.config.hooks?.transformFileBeforeWrite({
34
+ filename: path,
35
+ content,
36
+ extension: path.split(".").pop() ?? "",
37
+ path,
38
+ });
39
+ await writeFile(path, transformedContent ?? content, {
40
+ encoding: "utf-8",
41
+ });
42
+ }
43
+
44
+ public async writeGeneratedFile(
45
+ path: string,
46
+ content: string,
47
+ options: WriteFileOptions,
48
+ ) {
49
+ await this.writeTheFile(
50
+ path,
51
+ [this.getAutoGeneratedHeader(options.commentChar), content].join("\n"),
52
+ );
53
+ }
54
+
55
+ public writeYamlfile(path: string, data: any) {
56
+ return this.writeGeneratedFile(
57
+ path,
58
+ stringify(data, yamlStringifyOptions),
59
+ {
60
+ commentChar: "#",
61
+ },
62
+ );
63
+ }
64
+
65
+ protected getAutoGeneratedHeader(commentChar: string) {
66
+ return [
67
+ "-------------------------------------------------",
68
+ `🐱 🔨 This file is generated by catladder`,
69
+ `🚨 Do not edit this file manually 🚨`,
70
+ "-------------------------------------------------",
71
+ ]
72
+ .map((line) => `${commentChar} ${line}`)
73
+ .join("\n")
74
+ .concat("\n");
75
+ }
76
+ }