@catladder/pipeline 1.170.0 → 2.0.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/dist/bash/BashExpression.d.ts +2 -6
- package/dist/bash/BashExpression.js +5 -15
- package/dist/bash/bashEscape.d.ts +34 -0
- package/dist/bash/bashEscape.js +114 -0
- package/dist/bash/bashYaml.js +25 -2
- package/dist/bash/getInjectVarsScript.js +4 -2
- package/dist/bash/index.d.ts +2 -0
- package/dist/bash/index.js +26 -0
- package/dist/build/base/createAppBuildJob.js +3 -3
- package/dist/build/base/writeDotEnv.js +6 -4
- package/dist/build/custom/testJob.js +12 -12
- package/dist/build/docker.d.ts +3 -3
- package/dist/build/node/buildJob.js +1 -1
- package/dist/build/node/cache.d.ts +2 -4
- package/dist/build/node/cache.js +3 -24
- package/dist/build/node/testJob.js +11 -11
- package/dist/build/rails/build.js +1 -1
- package/dist/build/rails/test.js +8 -8
- package/dist/build/types.d.ts +0 -10
- package/dist/constants.js +1 -1
- package/dist/context/createComponentContext.js +0 -1
- package/dist/context/getEnvConfig.js +2 -1
- package/dist/context/getEnvironment.js +1 -2
- package/dist/context/getEnvironmentVariables.d.ts +5 -6
- package/dist/context/getEnvironmentVariables.js +50 -38
- package/dist/deploy/base/deploy.js +3 -3
- package/dist/deploy/cloudRun/createJobs/getCloudRunDeployScripts.js +2 -2
- package/dist/deploy/cloudRun/index.js +2 -2
- package/dist/deploy/cloudRun/utils/getServiceName.d.ts +1 -1
- package/dist/deploy/kubernetes/cloudSql/index.d.ts +2 -2
- package/dist/deploy/kubernetes/cloudSql/index.js +3 -14
- package/dist/deploy/kubernetes/deployJob.js +1 -3
- package/dist/deploy/kubernetes/index.js +2 -2
- package/dist/deploy/kubernetes/kubeEnv.d.ts +3 -3
- package/dist/deploy/kubernetes/kubeValues.d.ts +3 -4
- package/dist/deploy/kubernetes/kubeValues.js +2 -3
- package/dist/deploy/types/base.d.ts +0 -6
- package/dist/deploy/types/kubernetes.d.ts +1 -34
- package/dist/globalScriptFunctions/index.d.ts +14 -0
- package/dist/globalScriptFunctions/index.js +37 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/pipeline/gitlab/createGitlabJobs.js +3 -5
- package/dist/pipeline/gitlab/createGitlabPipeline.d.ts +1 -0
- package/dist/pipeline/gitlab/createGitlabPipeline.js +38 -2
- package/dist/pipeline/packageManager.js +1 -1
- package/dist/runner/index.d.ts +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/dist/types/config.d.ts +6 -9
- package/dist/types/context.d.ts +2 -9
- package/dist/types/gitlab-types.d.ts +1 -0
- package/dist/types/jobs.d.ts +0 -8
- package/dist/utils/gitlab.js +4 -1
- package/dist/utils/writeFiles.js +1 -7
- package/dist/variables/VariableValue.d.ts +3 -0
- package/dist/variables/VariableValue.js +5 -0
- package/dist/variables/VariableValueContainingReferences.d.ts +24 -0
- package/dist/variables/VariableValueContainingReferences.js +97 -0
- package/dist/variables/__tests__/resolveAllReferences.test.js +219 -0
- package/dist/variables/__tests__/resolveAllReferencesOnce.test.d.ts +1 -0
- package/dist/variables/__tests__/resolveAllReferencesOnce.test.js +171 -0
- package/dist/variables/__tests__/resolveReferencesOnce.test.d.ts +1 -0
- package/dist/variables/__tests__/resolveReferencesOnce.test.js +202 -0
- package/dist/variables/__tests__/variableValue.test.d.ts +1 -0
- package/dist/variables/__tests__/variableValue.test.js +36 -0
- package/dist/variables/resolveAllReferences.d.ts +3 -0
- package/dist/{bash/replaceAsync.js → variables/resolveAllReferences.js} +60 -41
- package/dist/variables/resolveAllReferencesOnce.d.ts +5 -0
- package/dist/variables/resolveAllReferencesOnce.js +191 -0
- package/dist/variables/resolveReferencesOnce.d.ts +8 -0
- package/dist/variables/resolveReferencesOnce.js +22 -0
- package/examples/__snapshots__/cloud-run-http2.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-memory-limit.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-meteor-with-worker.test.ts.snap +312 -222
- package/examples/__snapshots__/cloud-run-nextjs.test.ts.snap +1436 -0
- package/examples/__snapshots__/cloud-run-no-cpu-throttling.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-no-service.test.ts.snap +316 -238
- package/examples/__snapshots__/cloud-run-non-public.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-post-stop-job.test.ts.snap +313 -238
- package/examples/__snapshots__/cloud-run-service-custom-vpc-connector.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-service-custom-vpc.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-service-gen2.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-service-increase-timout.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-service-with-volumes.test.ts.snap +316 -238
- package/examples/__snapshots__/cloud-run-storybook.test.ts.snap +294 -220
- package/examples/__snapshots__/cloud-run-with-ngnix.test.ts.snap +312 -238
- package/examples/__snapshots__/cloud-run-with-sql-reuse-db.test.ts.snap +652 -486
- package/examples/__snapshots__/cloud-run-with-sql.test.ts.snap +282 -288
- package/examples/__snapshots__/cloud-run-with-worker.test.ts.snap +312 -238
- package/examples/__snapshots__/custom-build-job-with-tests.test.ts.snap +284 -194
- package/examples/__snapshots__/custom-build-job.test.ts.snap +278 -188
- package/examples/__snapshots__/custom-deploy.test.ts.snap +220 -154
- package/examples/__snapshots__/custom-envs.test.ts.snap +216 -126
- package/examples/__snapshots__/custom-sbom-java.test.ts.snap +278 -188
- package/examples/__snapshots__/git-submodule.test.ts.snap +312 -238
- package/examples/__snapshots__/kubernetes-application-customization.test.ts.snap +231 -253
- package/examples/__snapshots__/kubernetes-with-cloud-sql.test.ts.snap +240 -262
- package/examples/__snapshots__/kubernetes-with-jobs.test.ts.snap +504 -506
- package/examples/__snapshots__/kubernetes-with-mongodb.test.ts.snap +239 -261
- package/examples/__snapshots__/local-dot-env.test.ts.snap +236 -238
- package/examples/__snapshots__/meteor-kubernetes.test.ts.snap +236 -242
- package/examples/__snapshots__/multiline-var.test.ts.snap +1355 -973
- package/examples/__snapshots__/native-app.test.ts.snap +438 -392
- package/examples/__snapshots__/node-build-with-custom-image.test.ts.snap +312 -238
- package/examples/__snapshots__/node-build-with-docker-additions.test.ts.snap +312 -238
- package/examples/__snapshots__/rails-k8s-with-worker-dockerfile.test.ts.snap +186 -188
- package/examples/__snapshots__/rails-k8s-with-worker.test.ts.snap +162 -164
- package/examples/__snapshots__/referencing-other-vars.test.ts.snap +4741 -0
- package/examples/__snapshots__/wait-for-other-deploy.test.ts.snap +330 -228
- package/examples/__snapshots__/{workspace-api-www-custom-cache.test.ts.snap → workspace-api-www-turbo-cache.test.ts.snap} +457 -499
- package/examples/__snapshots__/workspace-api-www.test.ts.snap +452 -482
- package/examples/{workspace-api-www-custom-cache.test.ts → cloud-run-nextjs.test.ts} +2 -2
- package/examples/cloud-run-nextjs.ts +28 -0
- package/examples/cloud-run-with-sql.ts +0 -1
- package/examples/kubernetes-application-customization.ts +1 -0
- package/examples/kubernetes-with-cloud-sql.ts +1 -0
- package/examples/kubernetes-with-jobs.ts +1 -0
- package/examples/kubernetes-with-mongodb.ts +1 -0
- package/examples/meteor-kubernetes.ts +1 -1
- package/examples/native-app.ts +10 -7
- package/examples/rails-k8s-with-worker.ts +7 -1
- package/examples/{kubernetes-with-cloud-sql-legacy.test.ts → referencing-other-vars.test.ts} +2 -2
- package/examples/referencing-other-vars.ts +83 -0
- package/examples/workspace-api-www-turbo-cache.test.ts +11 -0
- package/examples/{workspace-api-www-custom-cache.ts → workspace-api-www-turbo-cache.ts} +4 -3
- package/examples/workspace-api-www.ts +3 -2
- package/package.json +2 -6
- package/src/bash/BashExpression.ts +10 -13
- package/src/bash/bashEscape.ts +158 -0
- package/src/bash/bashYaml.ts +36 -2
- package/src/bash/getInjectVarsScript.ts +11 -2
- package/src/bash/index.ts +2 -0
- package/src/build/base/createAppBuildJob.ts +0 -1
- package/src/build/base/writeDotEnv.ts +6 -6
- package/src/build/custom/testJob.ts +0 -1
- package/src/build/node/buildJob.ts +2 -2
- package/src/build/node/cache.ts +0 -29
- package/src/build/node/testJob.ts +0 -1
- package/src/build/rails/build.ts +0 -1
- package/src/build/rails/test.ts +0 -1
- package/src/build/types.ts +0 -13
- package/src/context/createComponentContext.ts +0 -1
- package/src/context/getEnvConfig.ts +2 -2
- package/src/context/getEnvironment.ts +1 -1
- package/src/context/getEnvironmentContext.ts +1 -1
- package/src/context/getEnvironmentVariables.ts +44 -51
- package/src/deploy/base/deploy.ts +1 -1
- package/src/deploy/cloudRun/createJobs/getCloudRunDeployScripts.ts +4 -12
- package/src/deploy/cloudRun/index.ts +2 -2
- package/src/deploy/kubernetes/cloudSql/index.ts +3 -16
- package/src/deploy/kubernetes/deployJob.ts +0 -2
- package/src/deploy/kubernetes/index.ts +2 -2
- package/src/deploy/kubernetes/kubeEnv.ts +3 -3
- package/src/deploy/kubernetes/kubeValues.ts +5 -8
- package/src/deploy/types/base.ts +0 -6
- package/src/deploy/types/kubernetes.ts +1 -36
- package/src/globalScriptFunctions/index.ts +30 -0
- package/src/index.ts +2 -0
- package/src/pipeline/gitlab/createGitlabJobs.ts +1 -4
- package/src/pipeline/gitlab/createGitlabPipeline.ts +8 -1
- package/src/pipeline/packageManager.ts +7 -5
- package/src/runner/index.ts +0 -1
- package/src/types/config.ts +6 -9
- package/src/types/context.ts +3 -9
- package/src/types/gitlab-types.ts +1 -0
- package/src/types/jobs.ts +0 -8
- package/src/utils/gitlab.ts +19 -2
- package/src/utils/writeFiles.ts +1 -2
- package/src/variables/VariableValue.ts +6 -0
- package/src/variables/VariableValueContainingReferences.ts +89 -0
- package/src/variables/__tests__/resolveAllReferences.test.ts +110 -0
- package/src/variables/__tests__/resolveAllReferencesOnce.test.ts +64 -0
- package/src/variables/__tests__/resolveReferencesOnce.test.ts +117 -0
- package/src/variables/__tests__/variableValue.test.ts +73 -0
- package/src/variables/resolveAllReferences.ts +46 -0
- package/src/variables/resolveAllReferencesOnce.ts +44 -0
- package/src/variables/resolveReferencesOnce.ts +29 -0
- package/bin/catladder-gitlab-dev.js +0 -3
- package/bin/catladder-gitlab.js +0 -3
- package/dist/bash/replaceAsync.d.ts +0 -2
- package/dist/bundles/catladder-gitlab/index.js +0 -15
- package/dist/context/__tests__/resolveReferences.test.js +0 -368
- package/dist/context/resolveReferences.d.ts +0 -6
- package/dist/context/resolveReferences.js +0 -286
- package/dist/deploy/kubernetes/processSecretsAsFiles.d.ts +0 -85
- package/dist/deploy/kubernetes/processSecretsAsFiles.js +0 -33
- package/examples/__snapshots__/kubernetes-with-cloud-sql-legacy.test.ts.snap +0 -1795
- package/examples/kubernetes-with-cloud-sql-legacy.ts +0 -35
- package/scripts/bundle +0 -2
- package/src/bash/replaceAsync.ts +0 -54
- package/src/context/__tests__/resolveReferences.test.ts +0 -148
- package/src/context/resolveReferences.ts +0 -93
- package/src/deploy/kubernetes/processSecretsAsFiles.ts +0 -35
- /package/dist/{context/__tests__/resolveReferences.test.d.ts → variables/__tests__/resolveAllReferences.test.d.ts} +0 -0
package/src/runner/index.ts
CHANGED
package/src/types/config.ts
CHANGED
|
@@ -73,14 +73,6 @@ export type EnvVars = {
|
|
|
73
73
|
* secret env vars. These vars can be managed with catladder/cli
|
|
74
74
|
*/
|
|
75
75
|
secret?: string[];
|
|
76
|
-
/**
|
|
77
|
-
* @deprecated, use ${componentName:variableName} instead
|
|
78
|
-
*
|
|
79
|
-
* With fromComponents you can inject env vars from other components.
|
|
80
|
-
*/
|
|
81
|
-
fromComponents?: {
|
|
82
|
-
[otherApp: string]: Record<string, string>;
|
|
83
|
-
};
|
|
84
76
|
};
|
|
85
77
|
|
|
86
78
|
export type DefaultEnvConfig = {
|
|
@@ -169,12 +161,14 @@ export type ComponentConfig<C extends ConfigProps = never> = {
|
|
|
169
161
|
* Use this in combination with @dotenvx/dotenvx or node 20 to start apps locally with .env files
|
|
170
162
|
* During build and runtime, it relies on the env vars set in the environment
|
|
171
163
|
*
|
|
164
|
+
* @defaultValue true
|
|
165
|
+
*
|
|
172
166
|
*/
|
|
173
167
|
dotEnv?: boolean | "local";
|
|
174
168
|
/**
|
|
175
169
|
* whether to create a env.d.ts localy and during build jobs
|
|
176
170
|
*
|
|
177
|
-
*
|
|
171
|
+
* @defaultValue true
|
|
178
172
|
*/
|
|
179
173
|
envDTs?: boolean;
|
|
180
174
|
} & DefaultEnvConfig;
|
|
@@ -184,6 +178,9 @@ export type ConfigProps = {
|
|
|
184
178
|
};
|
|
185
179
|
|
|
186
180
|
export type Config<C extends ConfigProps = never> = {
|
|
181
|
+
/**
|
|
182
|
+
* the pipeline type to generate, defaults to gitlab
|
|
183
|
+
*/
|
|
187
184
|
pipelineType?: PipelineType;
|
|
188
185
|
|
|
189
186
|
/**
|
package/src/types/context.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
} from "../build";
|
|
7
7
|
import type { PredefinedVariables, SecretEnvVar } from "../context";
|
|
8
8
|
import type { DeployConfig } from "../deploy";
|
|
9
|
+
import type { VariableValue } from "../variables/VariableValue";
|
|
9
10
|
import type {
|
|
10
11
|
ComponentConfig,
|
|
11
12
|
Config,
|
|
@@ -17,7 +18,7 @@ import type { PipelineType } from "./pipeline";
|
|
|
17
18
|
|
|
18
19
|
export type UnspecifiedEnvVars = Record<
|
|
19
20
|
string,
|
|
20
|
-
|
|
21
|
+
VariableValue | undefined | null
|
|
21
22
|
>;
|
|
22
23
|
|
|
23
24
|
export type EnvironmentEnvVars<
|
|
@@ -46,10 +47,7 @@ export type Environment = {
|
|
|
46
47
|
* the full name of the app. We use this as RELEASE_NAME in kubernetes and the service name in google cloud run
|
|
47
48
|
*/
|
|
48
49
|
fullName: StringOrBashExpression;
|
|
49
|
-
|
|
50
|
-
* @deprecated this is the same as context.env, use that instead
|
|
51
|
-
*/
|
|
52
|
-
shortName: string;
|
|
50
|
+
|
|
53
51
|
/**
|
|
54
52
|
* the environment slug without component name.
|
|
55
53
|
*/
|
|
@@ -158,10 +156,6 @@ export type ComponentContext<
|
|
|
158
156
|
* the name of the component
|
|
159
157
|
*/
|
|
160
158
|
name: string;
|
|
161
|
-
/**
|
|
162
|
-
* @deprecated use name instead
|
|
163
|
-
*/
|
|
164
|
-
componentName: string;
|
|
165
159
|
|
|
166
160
|
/**
|
|
167
161
|
* the merged component config.
|
package/src/types/jobs.ts
CHANGED
|
@@ -70,14 +70,6 @@ export type CatladderJob<S = BaseStage> = {
|
|
|
70
70
|
*/
|
|
71
71
|
needs?: Array<CatladderJobNeed>;
|
|
72
72
|
|
|
73
|
-
/**
|
|
74
|
-
* @deprecated set `componentName` to `needs` if you want to wait for a job from another component
|
|
75
|
-
*/
|
|
76
|
-
needsOtherComponent?: Array<{
|
|
77
|
-
componentName: string;
|
|
78
|
-
job: string;
|
|
79
|
-
artifacts: boolean;
|
|
80
|
-
}>;
|
|
81
73
|
/**
|
|
82
74
|
* cache config, we use here the same shape as gitlab itself
|
|
83
75
|
*/
|
package/src/utils/gitlab.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { registerGlobalScriptFunction } from "../globalScriptFunctions";
|
|
2
|
+
|
|
1
3
|
export const allowFailureInScripts = (script: string[]): string[] => [
|
|
2
4
|
"set +e", // disable fail job on error
|
|
3
5
|
...script,
|
|
@@ -22,12 +24,27 @@ export const repeatOnFailure = (
|
|
|
22
24
|
`;
|
|
23
25
|
};
|
|
24
26
|
|
|
27
|
+
const start = registerGlobalScriptFunction(
|
|
28
|
+
"collapseable_section_start",
|
|
29
|
+
`local section_title="\${1}"
|
|
30
|
+
local section_description="\${2:-$section_title}"
|
|
31
|
+
echo -e "section_start:\`date +%s\`:\${section_title}[collapsed=true]\\r\\e[0K$\{section_description}"
|
|
32
|
+
`,
|
|
33
|
+
);
|
|
34
|
+
|
|
35
|
+
const end = registerGlobalScriptFunction(
|
|
36
|
+
"collapseable_section_end",
|
|
37
|
+
`local section_title="\${1}"
|
|
38
|
+
echo -e "section_end:\`date +%s\`:\${section_title}\\r\\e[0K"
|
|
39
|
+
`,
|
|
40
|
+
);
|
|
41
|
+
|
|
25
42
|
export const collapseableSection =
|
|
26
43
|
(name: string, header: string) =>
|
|
27
44
|
(commands: string[]): string[] => {
|
|
28
45
|
return [
|
|
29
|
-
`
|
|
46
|
+
start.invoke(`"${name}"`, `"${header}"`),
|
|
30
47
|
...commands,
|
|
31
|
-
`
|
|
48
|
+
end.invoke(`"${name}"`),
|
|
32
49
|
];
|
|
33
50
|
};
|
package/src/utils/writeFiles.ts
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { writeFile } from "fs/promises";
|
|
2
2
|
import { stringify } from "yaml";
|
|
3
|
-
import packageInfos from "../packageInfos";
|
|
4
3
|
|
|
5
4
|
export const getAutoGeneratedHeader = (commentChar: string) => {
|
|
6
5
|
return [
|
|
7
6
|
"-------------------------------------------------",
|
|
8
|
-
`🐱 🔨 This file is generated by catladder
|
|
7
|
+
`🐱 🔨 This file is generated by catladder`,
|
|
9
8
|
`🚨 Do not edit this file manually 🚨`,
|
|
10
9
|
"-------------------------------------------------",
|
|
11
10
|
]
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { BashExpression } from "../bash/BashExpression";
|
|
2
|
+
import type { EscapeOptions } from "../bash/bashEscape";
|
|
3
|
+
import { escapeBashExpression, escapeString } from "../bash/bashEscape";
|
|
4
|
+
|
|
5
|
+
export class UnresolvableReference {
|
|
6
|
+
constructor(public reference: VariableReference) {}
|
|
7
|
+
public toString() {
|
|
8
|
+
return `Unresolvable reference: ${this.reference.toString()}`;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export class VariableReference {
|
|
12
|
+
public componentName: string;
|
|
13
|
+
public variableName: string;
|
|
14
|
+
|
|
15
|
+
constructor(componentName: string, variableName: string) {
|
|
16
|
+
this.componentName = componentName;
|
|
17
|
+
this.variableName = variableName;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
public toString() {
|
|
21
|
+
return `\${${this.componentName}:${this.variableName}}`;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
type VariableValuePart =
|
|
26
|
+
| string
|
|
27
|
+
| BashExpression
|
|
28
|
+
| VariableReference
|
|
29
|
+
| UnresolvableReference;
|
|
30
|
+
|
|
31
|
+
type MaybeArray<T> = T | T[];
|
|
32
|
+
export class VariableValueContainingReferences {
|
|
33
|
+
public parts: VariableValuePart[];
|
|
34
|
+
constructor(
|
|
35
|
+
parts: MaybeArray<VariableValuePart | VariableValueContainingReferences>,
|
|
36
|
+
) {
|
|
37
|
+
this.parts = (Array.isArray(parts) ? parts : [parts]).flatMap((part) =>
|
|
38
|
+
part instanceof VariableValueContainingReferences
|
|
39
|
+
? part.parts
|
|
40
|
+
: part === ""
|
|
41
|
+
? []
|
|
42
|
+
: [part],
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
public toString(
|
|
47
|
+
options: EscapeOptions = {
|
|
48
|
+
quotes: false,
|
|
49
|
+
},
|
|
50
|
+
) {
|
|
51
|
+
return this.parts
|
|
52
|
+
.map((part) => {
|
|
53
|
+
if (typeof part === "string") {
|
|
54
|
+
return escapeString(part, options);
|
|
55
|
+
} else if (part instanceof BashExpression) {
|
|
56
|
+
return escapeBashExpression(part, options);
|
|
57
|
+
} else {
|
|
58
|
+
return part.toString();
|
|
59
|
+
}
|
|
60
|
+
})
|
|
61
|
+
.join("");
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// regex to resolve references in catladder variables
|
|
66
|
+
// those expressions have the pattern ${componentName:variableName}
|
|
67
|
+
const REGEX = /\$\{(([^:}]+):)?([^}]+)}/gm;
|
|
68
|
+
export const createVariableValueContainingReferencesFromString = (
|
|
69
|
+
value: string,
|
|
70
|
+
options: { componentName: string },
|
|
71
|
+
) => {
|
|
72
|
+
const parts: Array<VariableValuePart> = [];
|
|
73
|
+
let match: any;
|
|
74
|
+
let lastIndex = 0;
|
|
75
|
+
while ((match = REGEX.exec(value)) !== null) {
|
|
76
|
+
const [fullMatch, _, otherComponentName, variableName] = match;
|
|
77
|
+
|
|
78
|
+
parts.push(value.slice(lastIndex, match.index));
|
|
79
|
+
parts.push(
|
|
80
|
+
new VariableReference(
|
|
81
|
+
otherComponentName || options.componentName,
|
|
82
|
+
variableName,
|
|
83
|
+
),
|
|
84
|
+
);
|
|
85
|
+
lastIndex = REGEX.lastIndex;
|
|
86
|
+
}
|
|
87
|
+
parts.push(value.slice(lastIndex));
|
|
88
|
+
return new VariableValueContainingReferences(parts);
|
|
89
|
+
};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import {
|
|
2
|
+
VariableValueContainingReferences,
|
|
3
|
+
createVariableValueContainingReferencesFromString,
|
|
4
|
+
} from "../VariableValueContainingReferences";
|
|
5
|
+
import { resolveAllReferences } from "../resolveAllReferences";
|
|
6
|
+
|
|
7
|
+
describe("replaceAllReferences", () => {
|
|
8
|
+
it("should replace all references recursivly", async () => {
|
|
9
|
+
const values = {
|
|
10
|
+
myVar: createVariableValueContainingReferencesFromString(
|
|
11
|
+
"the 2nd component has ${component2:variable1} and self reference ${variable2}",
|
|
12
|
+
{
|
|
13
|
+
componentName: "component1",
|
|
14
|
+
},
|
|
15
|
+
),
|
|
16
|
+
myOtherVar: createVariableValueContainingReferencesFromString(
|
|
17
|
+
"the third component has ${component3:variable1}, isn't that cool?",
|
|
18
|
+
{
|
|
19
|
+
componentName: "component1",
|
|
20
|
+
},
|
|
21
|
+
),
|
|
22
|
+
myThirdVar: createVariableValueContainingReferencesFromString(
|
|
23
|
+
"value from component3: ${component3:variable3}",
|
|
24
|
+
{
|
|
25
|
+
componentName: "component1",
|
|
26
|
+
},
|
|
27
|
+
),
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const getEnvVars = async (componentName: string) => {
|
|
31
|
+
return {
|
|
32
|
+
variable1: createVariableValueContainingReferencesFromString(
|
|
33
|
+
`i am variable1 from ${componentName}`,
|
|
34
|
+
{ componentName },
|
|
35
|
+
),
|
|
36
|
+
variable2: createVariableValueContainingReferencesFromString(
|
|
37
|
+
`foo from ${componentName}`,
|
|
38
|
+
{
|
|
39
|
+
componentName,
|
|
40
|
+
},
|
|
41
|
+
),
|
|
42
|
+
variable3: createVariableValueContainingReferencesFromString(
|
|
43
|
+
`i am referencing \${component1:variable1}`,
|
|
44
|
+
{ componentName },
|
|
45
|
+
),
|
|
46
|
+
};
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
const result = await resolveAllReferences(values, getEnvVars);
|
|
50
|
+
expect(result).toEqual({
|
|
51
|
+
myVar: new VariableValueContainingReferences([
|
|
52
|
+
"the 2nd component has ",
|
|
53
|
+
"i am variable1 from component2",
|
|
54
|
+
" and self reference ",
|
|
55
|
+
"foo from component1",
|
|
56
|
+
]),
|
|
57
|
+
myOtherVar: new VariableValueContainingReferences([
|
|
58
|
+
"the third component has ",
|
|
59
|
+
"i am variable1 from component3",
|
|
60
|
+
", isn't that cool?",
|
|
61
|
+
]),
|
|
62
|
+
myThirdVar: new VariableValueContainingReferences([
|
|
63
|
+
"value from component3: ",
|
|
64
|
+
"i am referencing ",
|
|
65
|
+
"i am variable1 from component1",
|
|
66
|
+
]),
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("detects infinte loop", async () => {
|
|
71
|
+
const values = {
|
|
72
|
+
myVar: createVariableValueContainingReferencesFromString(
|
|
73
|
+
"i am referencing ${component2:variable1}",
|
|
74
|
+
{
|
|
75
|
+
componentName: "component1",
|
|
76
|
+
},
|
|
77
|
+
),
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
const getEnvVars = async (componentName: string) => {
|
|
81
|
+
if (componentName === "component2") {
|
|
82
|
+
return {
|
|
83
|
+
variable1: createVariableValueContainingReferencesFromString(
|
|
84
|
+
`i am referencing \${component3:variable1}`,
|
|
85
|
+
{ componentName },
|
|
86
|
+
),
|
|
87
|
+
};
|
|
88
|
+
} else if (componentName === "component3") {
|
|
89
|
+
return {
|
|
90
|
+
variable1: createVariableValueContainingReferencesFromString(
|
|
91
|
+
`i am referencing \${component1:variable1}`,
|
|
92
|
+
{ componentName },
|
|
93
|
+
),
|
|
94
|
+
};
|
|
95
|
+
} else {
|
|
96
|
+
return {
|
|
97
|
+
variable1: createVariableValueContainingReferencesFromString(
|
|
98
|
+
`i am referencing \${component2:variable1}`,
|
|
99
|
+
{ componentName },
|
|
100
|
+
),
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// expect to throw an error
|
|
106
|
+
await expect(resolveAllReferences(values, getEnvVars)).rejects.toThrow(
|
|
107
|
+
"Infinite loop detected in these variables: myVar (last reference: ${component1:variable1})",
|
|
108
|
+
);
|
|
109
|
+
});
|
|
110
|
+
});
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import {
|
|
2
|
+
VariableReference,
|
|
3
|
+
VariableValueContainingReferences,
|
|
4
|
+
createVariableValueContainingReferencesFromString,
|
|
5
|
+
} from "../VariableValueContainingReferences";
|
|
6
|
+
import { resolveAllReferencesOnce } from "../resolveAllReferencesOnce";
|
|
7
|
+
|
|
8
|
+
describe("resolveAllReferencesOnce", () => {
|
|
9
|
+
it("should replace all references", async () => {
|
|
10
|
+
const values = {
|
|
11
|
+
myVar: createVariableValueContainingReferencesFromString(
|
|
12
|
+
"the 2nd component has ${component2:variable1} and self reference ${variable2}",
|
|
13
|
+
{ componentName: "component1" },
|
|
14
|
+
),
|
|
15
|
+
myOtherVar: createVariableValueContainingReferencesFromString(
|
|
16
|
+
"the third component has ${component3:variable1}, isn't that cool?",
|
|
17
|
+
{ componentName: "component1" },
|
|
18
|
+
),
|
|
19
|
+
myThirdVar: createVariableValueContainingReferencesFromString(
|
|
20
|
+
"value from component3: ${component3:variable3}",
|
|
21
|
+
{ componentName: "component1" },
|
|
22
|
+
),
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
const getEnvVars = async (componentName: string) => {
|
|
26
|
+
return {
|
|
27
|
+
variable1: createVariableValueContainingReferencesFromString(
|
|
28
|
+
`i am variable1 from ${componentName}`,
|
|
29
|
+
{ componentName },
|
|
30
|
+
),
|
|
31
|
+
variable2: createVariableValueContainingReferencesFromString(
|
|
32
|
+
`foo from ${componentName}`,
|
|
33
|
+
{
|
|
34
|
+
componentName,
|
|
35
|
+
},
|
|
36
|
+
),
|
|
37
|
+
variable3: createVariableValueContainingReferencesFromString(
|
|
38
|
+
`i am referencing \${component1:variable1}`,
|
|
39
|
+
{ componentName },
|
|
40
|
+
),
|
|
41
|
+
};
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
const result = await resolveAllReferencesOnce(values, getEnvVars);
|
|
45
|
+
expect(result).toEqual({
|
|
46
|
+
myVar: new VariableValueContainingReferences([
|
|
47
|
+
"the 2nd component has ",
|
|
48
|
+
"i am variable1 from component2",
|
|
49
|
+
" and self reference ",
|
|
50
|
+
"foo from component1",
|
|
51
|
+
]),
|
|
52
|
+
myOtherVar: new VariableValueContainingReferences([
|
|
53
|
+
"the third component has ",
|
|
54
|
+
"i am variable1 from component3",
|
|
55
|
+
", isn't that cool?",
|
|
56
|
+
]),
|
|
57
|
+
myThirdVar: new VariableValueContainingReferences([
|
|
58
|
+
"value from component3: ",
|
|
59
|
+
"i am referencing ",
|
|
60
|
+
new VariableReference("component1", "variable1"),
|
|
61
|
+
]),
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
});
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import {
|
|
2
|
+
UnresolvableReference,
|
|
3
|
+
VariableReference,
|
|
4
|
+
createVariableValueContainingReferencesFromString,
|
|
5
|
+
} from "../VariableValueContainingReferences";
|
|
6
|
+
import { resolveReferencesOnce } from "../resolveReferencesOnce";
|
|
7
|
+
|
|
8
|
+
describe("resolveReferencesOnce", () => {
|
|
9
|
+
it("should replace a reference to another component", async () => {
|
|
10
|
+
const value = createVariableValueContainingReferencesFromString(
|
|
11
|
+
"the other component has ${otherComponent:variableName}, isn't that cool?",
|
|
12
|
+
{
|
|
13
|
+
componentName: "myComponent",
|
|
14
|
+
},
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
const result = resolveReferencesOnce(
|
|
18
|
+
value,
|
|
19
|
+
({ componentName, variableName }) => {
|
|
20
|
+
return createVariableValueContainingReferencesFromString(
|
|
21
|
+
`replaced ${componentName}:${variableName}`,
|
|
22
|
+
{ componentName },
|
|
23
|
+
);
|
|
24
|
+
},
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
expect(result.parts).toEqual([
|
|
28
|
+
"the other component has ",
|
|
29
|
+
"replaced otherComponent:variableName",
|
|
30
|
+
", isn't that cool?",
|
|
31
|
+
]);
|
|
32
|
+
});
|
|
33
|
+
it("should keep references in replacement", async () => {
|
|
34
|
+
const value = createVariableValueContainingReferencesFromString(
|
|
35
|
+
"the other component has ${otherComponent:variableName}, isn't that cool?",
|
|
36
|
+
{
|
|
37
|
+
componentName: "myComponent",
|
|
38
|
+
},
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
const result = resolveReferencesOnce(
|
|
42
|
+
value,
|
|
43
|
+
({ componentName, variableName }) => {
|
|
44
|
+
return createVariableValueContainingReferencesFromString(
|
|
45
|
+
`replaced ${componentName}:${variableName}, contains reference to \${thirdComponent:x}`,
|
|
46
|
+
{ componentName },
|
|
47
|
+
);
|
|
48
|
+
},
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
expect(result.parts).toEqual([
|
|
52
|
+
"the other component has ",
|
|
53
|
+
|
|
54
|
+
"replaced otherComponent:variableName, contains reference to ",
|
|
55
|
+
new VariableReference("thirdComponent", "x"),
|
|
56
|
+
", isn't that cool?",
|
|
57
|
+
]);
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
it("can be run multiple times", async () => {
|
|
61
|
+
const value = createVariableValueContainingReferencesFromString(
|
|
62
|
+
"the other component has ${otherComponent:variableName}, isn't that cool?",
|
|
63
|
+
{
|
|
64
|
+
componentName: "myComponent",
|
|
65
|
+
},
|
|
66
|
+
);
|
|
67
|
+
const replacer = ({
|
|
68
|
+
componentName,
|
|
69
|
+
variableName,
|
|
70
|
+
}: {
|
|
71
|
+
componentName: string;
|
|
72
|
+
variableName: string;
|
|
73
|
+
}) => {
|
|
74
|
+
return createVariableValueContainingReferencesFromString(
|
|
75
|
+
componentName === "thirdComponent"
|
|
76
|
+
? "value from third component"
|
|
77
|
+
: `replaced ${componentName}:${variableName}, contains reference to \${thirdComponent:x}`,
|
|
78
|
+
{ componentName },
|
|
79
|
+
);
|
|
80
|
+
};
|
|
81
|
+
const result = resolveReferencesOnce(
|
|
82
|
+
resolveReferencesOnce(value, replacer),
|
|
83
|
+
replacer,
|
|
84
|
+
);
|
|
85
|
+
|
|
86
|
+
expect(result.parts).toEqual([
|
|
87
|
+
"the other component has ",
|
|
88
|
+
"replaced otherComponent:variableName, contains reference to ",
|
|
89
|
+
"value from third component",
|
|
90
|
+
", isn't that cool?",
|
|
91
|
+
]);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("flags unresolveable", async () => {
|
|
95
|
+
const value = createVariableValueContainingReferencesFromString(
|
|
96
|
+
"the other component has ${otherComponent:variableName}, isn't that cool?",
|
|
97
|
+
{
|
|
98
|
+
componentName: "myComponent",
|
|
99
|
+
},
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const result = resolveReferencesOnce(
|
|
103
|
+
value,
|
|
104
|
+
({ componentName, variableName }) => {
|
|
105
|
+
return null;
|
|
106
|
+
},
|
|
107
|
+
);
|
|
108
|
+
|
|
109
|
+
expect(result.parts).toEqual([
|
|
110
|
+
"the other component has ",
|
|
111
|
+
new UnresolvableReference(
|
|
112
|
+
new VariableReference("otherComponent", "variableName"),
|
|
113
|
+
),
|
|
114
|
+
", isn't that cool?",
|
|
115
|
+
]);
|
|
116
|
+
});
|
|
117
|
+
});
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import {
|
|
2
|
+
VariableReference,
|
|
3
|
+
createVariableValueContainingReferencesFromString,
|
|
4
|
+
} from "../VariableValueContainingReferences";
|
|
5
|
+
|
|
6
|
+
describe("createVarialeValueFromString", () => {
|
|
7
|
+
it("should create a VariableValue from a simple string", () => {
|
|
8
|
+
const stringValue = "hello world";
|
|
9
|
+
|
|
10
|
+
const result = createVariableValueContainingReferencesFromString(
|
|
11
|
+
stringValue,
|
|
12
|
+
{
|
|
13
|
+
componentName: "myComponent",
|
|
14
|
+
},
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
expect(result.parts).toEqual([stringValue]);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it("extracts references to other components", () => {
|
|
21
|
+
const stringValue =
|
|
22
|
+
"the other component has ${otherComponent:variableName}, isn't that cool?";
|
|
23
|
+
|
|
24
|
+
const result = createVariableValueContainingReferencesFromString(
|
|
25
|
+
stringValue,
|
|
26
|
+
{
|
|
27
|
+
componentName: "myComponent",
|
|
28
|
+
},
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
expect(result.parts).toEqual([
|
|
32
|
+
"the other component has ",
|
|
33
|
+
new VariableReference("otherComponent", "variableName"),
|
|
34
|
+
", isn't that cool?",
|
|
35
|
+
]);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("extracts self references", () => {
|
|
39
|
+
const stringValue = "my component has ${variableName}!";
|
|
40
|
+
|
|
41
|
+
const result = createVariableValueContainingReferencesFromString(
|
|
42
|
+
stringValue,
|
|
43
|
+
{
|
|
44
|
+
componentName: "myComponent",
|
|
45
|
+
},
|
|
46
|
+
);
|
|
47
|
+
|
|
48
|
+
expect(result.parts).toEqual([
|
|
49
|
+
"my component has ",
|
|
50
|
+
new VariableReference("myComponent", "variableName"),
|
|
51
|
+
"!",
|
|
52
|
+
]);
|
|
53
|
+
});
|
|
54
|
+
it("extracts multiple references", () => {
|
|
55
|
+
const stringValue =
|
|
56
|
+
"my component has ${variableName} and the other component has ${otherComponent:variableName}!";
|
|
57
|
+
|
|
58
|
+
const result = createVariableValueContainingReferencesFromString(
|
|
59
|
+
stringValue,
|
|
60
|
+
{
|
|
61
|
+
componentName: "myComponent",
|
|
62
|
+
},
|
|
63
|
+
);
|
|
64
|
+
|
|
65
|
+
expect(result.parts).toEqual([
|
|
66
|
+
"my component has ",
|
|
67
|
+
new VariableReference("myComponent", "variableName"),
|
|
68
|
+
" and the other component has ",
|
|
69
|
+
new VariableReference("otherComponent", "variableName"),
|
|
70
|
+
"!",
|
|
71
|
+
]);
|
|
72
|
+
});
|
|
73
|
+
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { VariableValue } from "./VariableValue";
|
|
2
|
+
import type { VariableValueContainingReferences } from "./VariableValueContainingReferences";
|
|
3
|
+
import { VariableReference } from "./VariableValueContainingReferences";
|
|
4
|
+
import { resolveAllReferencesOnce as resolveAllReferencesOnce } from "./resolveAllReferencesOnce";
|
|
5
|
+
|
|
6
|
+
export const resolveAllReferences = async (
|
|
7
|
+
values: Record<string, VariableValueContainingReferences>,
|
|
8
|
+
getEnvVars: (
|
|
9
|
+
componentName: string,
|
|
10
|
+
) => Promise<Record<string, VariableValue | null | undefined>>,
|
|
11
|
+
) => {
|
|
12
|
+
// replace until there aren't any references left
|
|
13
|
+
let result = values;
|
|
14
|
+
|
|
15
|
+
let i = 0;
|
|
16
|
+
|
|
17
|
+
while (
|
|
18
|
+
Object.values(result).some((value) =>
|
|
19
|
+
value.parts.some((part) => part instanceof VariableReference),
|
|
20
|
+
)
|
|
21
|
+
) {
|
|
22
|
+
const replaced = await resolveAllReferencesOnce(result, getEnvVars);
|
|
23
|
+
|
|
24
|
+
result = replaced;
|
|
25
|
+
i++;
|
|
26
|
+
if (i > 1000) {
|
|
27
|
+
const unresolved = Object.entries(result).filter(([key, value]) =>
|
|
28
|
+
value.parts.some((part) => part instanceof VariableReference),
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
throw new Error(
|
|
32
|
+
"Infinite loop detected in these variables: " +
|
|
33
|
+
unresolved
|
|
34
|
+
.map(
|
|
35
|
+
([key, value]) =>
|
|
36
|
+
`${key} (last reference: ${value.parts.find(
|
|
37
|
+
(part) => part instanceof VariableReference,
|
|
38
|
+
)})`,
|
|
39
|
+
)
|
|
40
|
+
.join(", "),
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
return result;
|
|
46
|
+
};
|