@causa/workspace-terraform 0.1.0 → 0.2.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/README.md +34 -0
- package/dist/configurations/terraform.d.ts +7 -0
- package/dist/functions/index.js +3 -1
- package/dist/functions/project-init-terraform.d.ts +9 -0
- package/dist/functions/project-init-terraform.js +28 -0
- package/dist/functions/project-lint-terraform.d.ts +11 -0
- package/dist/functions/project-lint-terraform.js +41 -0
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/terraform.d.ts +49 -0
- package/dist/services/terraform.errors.d.ts +9 -0
- package/dist/services/terraform.errors.js +13 -0
- package/dist/services/terraform.js +79 -4
- package/package.json +12 -10
package/README.md
CHANGED
|
@@ -1 +1,35 @@
|
|
|
1
1
|
# `@causa/workspace-terraform` module
|
|
2
|
+
|
|
3
|
+
This repository contains the source code for the `@causa/workspace-terraform` Causa module. It provides Causa features and implementations of `cs` commands for Terraform infrastructure projects. For more information about the Causa CLI `cs`, checkout [its repository](https://github.com/causa-io/cli).
|
|
4
|
+
|
|
5
|
+
## ➕ Requirements
|
|
6
|
+
|
|
7
|
+
The Causa Terraform module requires [Terraform](https://www.terraform.io/) to be installed.
|
|
8
|
+
|
|
9
|
+
## 🎉 Installation
|
|
10
|
+
|
|
11
|
+
Add `@causa/workspace-terraform` to your Causa configuration in `causa.modules`.
|
|
12
|
+
|
|
13
|
+
## 🔧 Configuration
|
|
14
|
+
|
|
15
|
+
For all the configuration in your Causa files related to Terraform, look at [the schema for the `TerraformConfiguration`](./src/configurations/terraform.ts).
|
|
16
|
+
|
|
17
|
+
## ✨ Supported project types and commands
|
|
18
|
+
|
|
19
|
+
This module supports Causa projects with `project.type` set to `infrastructure` and `project.language` set to `terraform`.
|
|
20
|
+
|
|
21
|
+
### Infrastructure commands
|
|
22
|
+
|
|
23
|
+
- `cs infrastructure prepare`: Runs `terraform plan`.
|
|
24
|
+
- `cs infrastructure deploy`: Runs `terraform apply` using a previously computed plan.
|
|
25
|
+
|
|
26
|
+
The dictionary defined in the `infrastructure.variables` configuration can be used to pass input Terraform variables. This dictionary is rendered before being used, meaning it can contain formatting templates referencing other configuration values and secrets.
|
|
27
|
+
|
|
28
|
+
The `terraform.workspace` configuration determines the Terraform workspace set prior to running any operation. Combined with Causa environments, this can be a powerful feature to manage the infrastructure of several deployment environments.
|
|
29
|
+
|
|
30
|
+
### Project commands
|
|
31
|
+
|
|
32
|
+
The Terraform module also supports some of the project-level commands, namely:
|
|
33
|
+
|
|
34
|
+
- `cs init`: Runs `terraform init`.
|
|
35
|
+
- `cs lint`: Runs `terraform validate` and `terraform fmt`. The format operation is run with the `-check` argument, such that it only lints the code without fixing it. This operation applies supports the `project.additionalDirectories` configuration.
|
|
@@ -10,5 +10,12 @@ export type TerraformConfiguration = {
|
|
|
10
10
|
* The Terraform workspace that should be selected prior to performing `plan` and `apply` operations.
|
|
11
11
|
*/
|
|
12
12
|
workspace?: string;
|
|
13
|
+
/**
|
|
14
|
+
* The version of Terraform to use.
|
|
15
|
+
* Can be a semver version, or `latest`.
|
|
16
|
+
* The installed version is considered compatible if it is greater than or equal to the configured version, within
|
|
17
|
+
* the same major version.
|
|
18
|
+
*/
|
|
19
|
+
version?: string;
|
|
13
20
|
};
|
|
14
21
|
};
|
package/dist/functions/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import { InfrastructureDeployForTerraform } from './infrastructure-deploy-terraform.js';
|
|
2
2
|
import { InfrastructurePrepareForTerraform } from './infrastructure-prepare-terraform.js';
|
|
3
|
+
import { ProjectInitForTerraform } from './project-init-terraform.js';
|
|
4
|
+
import { ProjectLintForTerraform } from './project-lint-terraform.js';
|
|
3
5
|
export function registerFunctions(context) {
|
|
4
|
-
context.registerFunctionImplementations(InfrastructureDeployForTerraform, InfrastructurePrepareForTerraform);
|
|
6
|
+
context.registerFunctionImplementations(InfrastructureDeployForTerraform, InfrastructurePrepareForTerraform, ProjectInitForTerraform, ProjectLintForTerraform);
|
|
5
7
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { WorkspaceContext } from '@causa/workspace';
|
|
2
|
+
import { ProjectInit } from '@causa/workspace-core';
|
|
3
|
+
/**
|
|
4
|
+
* Implements the {@link ProjectInit} function for Terraform projects, by running `terraform init`.
|
|
5
|
+
*/
|
|
6
|
+
export declare class ProjectInitForTerraform extends ProjectInit {
|
|
7
|
+
_call(context: WorkspaceContext): Promise<void>;
|
|
8
|
+
_supports(context: WorkspaceContext): boolean;
|
|
9
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { ProjectInit } from '@causa/workspace-core';
|
|
2
|
+
import { rm } from 'fs/promises';
|
|
3
|
+
import { join } from 'path';
|
|
4
|
+
import { TerraformService } from '../services/index.js';
|
|
5
|
+
/**
|
|
6
|
+
* The name of the folder automatically created by Terraform during initialization.
|
|
7
|
+
*/
|
|
8
|
+
const TERRAFORM_DIR = '.terraform';
|
|
9
|
+
/**
|
|
10
|
+
* Implements the {@link ProjectInit} function for Terraform projects, by running `terraform init`.
|
|
11
|
+
*/
|
|
12
|
+
export class ProjectInitForTerraform extends ProjectInit {
|
|
13
|
+
async _call(context) {
|
|
14
|
+
const projectName = context.get('project.name');
|
|
15
|
+
if (this.force) {
|
|
16
|
+
context.logger.info('🔥 Removing Terraform folder.');
|
|
17
|
+
const terraformDir = join(context.getProjectPathOrThrow(), TERRAFORM_DIR);
|
|
18
|
+
await rm(terraformDir, { recursive: true, force: true });
|
|
19
|
+
}
|
|
20
|
+
context.logger.info(`️🎉 Initializing Terraform for project '${projectName}'.`);
|
|
21
|
+
await context.service(TerraformService).init({ logging: 'debug' });
|
|
22
|
+
context.logger.info(`️✅ Successfully initialized Terraform.`);
|
|
23
|
+
}
|
|
24
|
+
_supports(context) {
|
|
25
|
+
return (context.get('project.language') === 'terraform' &&
|
|
26
|
+
context.get('project.type') === 'infrastructure');
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { WorkspaceContext } from '@causa/workspace';
|
|
2
|
+
import { ProjectLint } from '@causa/workspace-core';
|
|
3
|
+
/**
|
|
4
|
+
* Implements the {@link ProjectLint} function for Terraform projects, by running `terraform validate` and
|
|
5
|
+
* `terraform fmt`.
|
|
6
|
+
* The Terraform format check is also run on any additional directories listed in the project configuration.
|
|
7
|
+
*/
|
|
8
|
+
export declare class ProjectLintForTerraform extends ProjectLint {
|
|
9
|
+
_call(context: WorkspaceContext): Promise<void>;
|
|
10
|
+
_supports(context: WorkspaceContext): boolean;
|
|
11
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { ProcessServiceExitCodeError, ProjectLint, } from '@causa/workspace-core';
|
|
2
|
+
import { TerraformService } from '../services/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Implements the {@link ProjectLint} function for Terraform projects, by running `terraform validate` and
|
|
5
|
+
* `terraform fmt`.
|
|
6
|
+
* The Terraform format check is also run on any additional directories listed in the project configuration.
|
|
7
|
+
*/
|
|
8
|
+
export class ProjectLintForTerraform extends ProjectLint {
|
|
9
|
+
async _call(context) {
|
|
10
|
+
const projectPath = context.getProjectPathOrThrow();
|
|
11
|
+
const projectName = context.get('project.name');
|
|
12
|
+
const terraformService = context.service(TerraformService);
|
|
13
|
+
const targets = [
|
|
14
|
+
projectPath,
|
|
15
|
+
...(await context.getProjectAdditionalDirectories()),
|
|
16
|
+
];
|
|
17
|
+
try {
|
|
18
|
+
context.logger.info(`🚨 Validating Terraform code for project '${projectName}'.`);
|
|
19
|
+
await terraformService.validate({
|
|
20
|
+
logging: { stdout: null, stderr: 'info' },
|
|
21
|
+
});
|
|
22
|
+
context.logger.info(`🎨 Checking format of Terraform code for project '${projectName}'.`);
|
|
23
|
+
await terraformService.fmt({
|
|
24
|
+
check: true,
|
|
25
|
+
recursive: true,
|
|
26
|
+
targets,
|
|
27
|
+
logging: 'info',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (error instanceof ProcessServiceExitCodeError) {
|
|
32
|
+
throw new Error('Linting the Terraform project failed.');
|
|
33
|
+
}
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
_supports(context) {
|
|
38
|
+
return (context.get('project.language') === 'terraform' &&
|
|
39
|
+
context.get('project.type') === 'infrastructure');
|
|
40
|
+
}
|
|
41
|
+
}
|
package/dist/services/index.d.ts
CHANGED
package/dist/services/index.js
CHANGED
|
@@ -39,6 +39,11 @@ export declare class TerraformService {
|
|
|
39
39
|
* This is used by {@link TerraformService.wrapWorkspaceOperation} if no workspace is specified.
|
|
40
40
|
*/
|
|
41
41
|
private readonly defaultTerraformWorkspace;
|
|
42
|
+
/**
|
|
43
|
+
* The required Terraform version set in the configuration.
|
|
44
|
+
* Defaults to `latest`.
|
|
45
|
+
*/
|
|
46
|
+
readonly requiredVersion: string;
|
|
42
47
|
constructor(context: WorkspaceContext);
|
|
43
48
|
/**
|
|
44
49
|
* Runs `terraform init`.
|
|
@@ -95,6 +100,32 @@ export declare class TerraformService {
|
|
|
95
100
|
* @returns The standard output of the command, describing the plan.
|
|
96
101
|
*/
|
|
97
102
|
show(path: string, options?: Omit<SpawnOptions, 'capture'>): Promise<string>;
|
|
103
|
+
/**
|
|
104
|
+
* Runs `terraform validate`.
|
|
105
|
+
*
|
|
106
|
+
* @param options Options when running the command.
|
|
107
|
+
*/
|
|
108
|
+
validate(options?: SpawnOptions): Promise<void>;
|
|
109
|
+
/**
|
|
110
|
+
* Runs `terraform fmt`.
|
|
111
|
+
*
|
|
112
|
+
* @param options Options when running the command.
|
|
113
|
+
* @returns The result of the Terraform process.
|
|
114
|
+
*/
|
|
115
|
+
fmt(options?: {
|
|
116
|
+
/**
|
|
117
|
+
* Whether to check if the files are formatted correctly, instead of formatting them.
|
|
118
|
+
*/
|
|
119
|
+
check?: boolean;
|
|
120
|
+
/**
|
|
121
|
+
* Whether to recursively format all files in the current directory and its subdirectories.
|
|
122
|
+
*/
|
|
123
|
+
recursive?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* The list of files or directories to format.
|
|
126
|
+
*/
|
|
127
|
+
targets?: string[];
|
|
128
|
+
} & SpawnOptions): Promise<SpawnedProcessResult>;
|
|
98
129
|
/**
|
|
99
130
|
* Wrap the `fn` function and ensures Terraform is initialized and that the correct Terraform workspace is selected.
|
|
100
131
|
* After `fn` has run, the workspace is reverted back to the previous workspace if necessary.
|
|
@@ -121,5 +152,23 @@ export declare class TerraformService {
|
|
|
121
152
|
* @returns The result of the spawned process.
|
|
122
153
|
*/
|
|
123
154
|
terraform(command: string, args: string[], options?: SpawnOptions): Promise<SpawnedProcessResult>;
|
|
155
|
+
/**
|
|
156
|
+
* Whether the installed Terraform version is compatible with the required version set in the configuration.
|
|
157
|
+
* It is `undefined` before the first call to {@link TerraformService.checkTerraformVersion}.
|
|
158
|
+
*/
|
|
159
|
+
private hasCompatibleTerraformVersion;
|
|
160
|
+
/**
|
|
161
|
+
* A promise that resolves when the installed Terraform version has been checked.
|
|
162
|
+
* It is `undefined` before the first call to {@link TerraformService.checkTerraformVersion}, or if the actual check
|
|
163
|
+
* is not needed.
|
|
164
|
+
*/
|
|
165
|
+
private terraformVersionCheck;
|
|
166
|
+
/**
|
|
167
|
+
* Checks whether the installed Terraform version is compatible with the required version set in the configuration.
|
|
168
|
+
* If the required version is `latest`, the check is skipped.
|
|
169
|
+
* If the installed version is not compatible, an {@link IncompatibleTerraformVersionError} is thrown.
|
|
170
|
+
* The result of the check is cached, and this returns synchronously on subsequent calls.
|
|
171
|
+
*/
|
|
172
|
+
private checkTerraformVersion;
|
|
124
173
|
}
|
|
125
174
|
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An error thrown when the installed Terraform version is incompatible with the required version set in the
|
|
3
|
+
* configuration.
|
|
4
|
+
*/
|
|
5
|
+
export declare class IncompatibleTerraformVersionError extends Error {
|
|
6
|
+
readonly installedVersion: string;
|
|
7
|
+
readonly requiredVersion: string;
|
|
8
|
+
constructor(installedVersion: string, requiredVersion: string);
|
|
9
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* An error thrown when the installed Terraform version is incompatible with the required version set in the
|
|
3
|
+
* configuration.
|
|
4
|
+
*/
|
|
5
|
+
export class IncompatibleTerraformVersionError extends Error {
|
|
6
|
+
installedVersion;
|
|
7
|
+
requiredVersion;
|
|
8
|
+
constructor(installedVersion, requiredVersion) {
|
|
9
|
+
super(`Installed Terraform version ${installedVersion} is incompatible with required version ${requiredVersion}.`);
|
|
10
|
+
this.installedVersion = installedVersion;
|
|
11
|
+
this.requiredVersion = requiredVersion;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { ProcessService, ProcessServiceExitCodeError, } from '@causa/workspace-core';
|
|
2
|
+
import { satisfies } from 'semver';
|
|
3
|
+
import { IncompatibleTerraformVersionError } from './terraform.errors.js';
|
|
2
4
|
/**
|
|
3
5
|
* A service exposing the Terraform CLI.
|
|
4
6
|
*/
|
|
@@ -21,15 +23,20 @@ export class TerraformService {
|
|
|
21
23
|
* This is used by {@link TerraformService.wrapWorkspaceOperation} if no workspace is specified.
|
|
22
24
|
*/
|
|
23
25
|
defaultTerraformWorkspace;
|
|
26
|
+
/**
|
|
27
|
+
* The required Terraform version set in the configuration.
|
|
28
|
+
* Defaults to `latest`.
|
|
29
|
+
*/
|
|
30
|
+
requiredVersion;
|
|
24
31
|
constructor(context) {
|
|
25
32
|
this.processService = context.service(ProcessService);
|
|
26
33
|
this.defaultSpawnOptions = {
|
|
27
34
|
workingDirectory: context.projectPath ?? undefined,
|
|
28
35
|
};
|
|
29
36
|
this.logger = context.logger;
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
37
|
+
const conf = context.asConfiguration();
|
|
38
|
+
this.defaultTerraformWorkspace = conf.get('terraform.workspace');
|
|
39
|
+
this.requiredVersion = conf.get('terraform.version') ?? 'latest';
|
|
33
40
|
}
|
|
34
41
|
/**
|
|
35
42
|
* Runs `terraform init`.
|
|
@@ -115,14 +122,44 @@ export class TerraformService {
|
|
|
115
122
|
});
|
|
116
123
|
return result.stdout ?? '';
|
|
117
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Runs `terraform validate`.
|
|
127
|
+
*
|
|
128
|
+
* @param options Options when running the command.
|
|
129
|
+
*/
|
|
130
|
+
async validate(options = {}) {
|
|
131
|
+
await this.terraform('validate', [], options);
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Runs `terraform fmt`.
|
|
135
|
+
*
|
|
136
|
+
* @param options Options when running the command.
|
|
137
|
+
* @returns The result of the Terraform process.
|
|
138
|
+
*/
|
|
139
|
+
async fmt(options = {}) {
|
|
140
|
+
const args = [];
|
|
141
|
+
if (options.check) {
|
|
142
|
+
args.push('-check');
|
|
143
|
+
}
|
|
144
|
+
if (options.recursive) {
|
|
145
|
+
args.push('-recursive');
|
|
146
|
+
}
|
|
147
|
+
if (options.targets) {
|
|
148
|
+
args.push(...options.targets);
|
|
149
|
+
}
|
|
150
|
+
return await this.terraform('fmt', args, options);
|
|
151
|
+
}
|
|
118
152
|
async wrapWorkspaceOperation(optionsOrFn, fn) {
|
|
119
153
|
const options = fn ? optionsOrFn : {};
|
|
120
154
|
const func = fn ?? optionsOrFn;
|
|
121
155
|
const { skipInit, createWorkspaceIfNeeded, workspace, ...spawnOptions } = options;
|
|
156
|
+
const workspaceToSelect = workspace ?? this.defaultTerraformWorkspace;
|
|
157
|
+
if (workspaceToSelect === undefined) {
|
|
158
|
+
throw new Error('The Terraform workspace for the operation is not configured.');
|
|
159
|
+
}
|
|
122
160
|
if (!skipInit) {
|
|
123
161
|
await this.init(spawnOptions);
|
|
124
162
|
}
|
|
125
|
-
const workspaceToSelect = workspace ?? this.defaultTerraformWorkspace;
|
|
126
163
|
let workspaceToRestore = null;
|
|
127
164
|
try {
|
|
128
165
|
const currentWorkspace = await this.workspaceShow(spawnOptions);
|
|
@@ -155,10 +192,48 @@ export class TerraformService {
|
|
|
155
192
|
* @returns The result of the spawned process.
|
|
156
193
|
*/
|
|
157
194
|
async terraform(command, args, options = {}) {
|
|
195
|
+
await this.checkTerraformVersion();
|
|
158
196
|
const p = this.processService.spawn('terraform', [command, ...args], {
|
|
159
197
|
...this.defaultSpawnOptions,
|
|
160
198
|
...options,
|
|
161
199
|
});
|
|
162
200
|
return await p.result;
|
|
163
201
|
}
|
|
202
|
+
/**
|
|
203
|
+
* Whether the installed Terraform version is compatible with the required version set in the configuration.
|
|
204
|
+
* It is `undefined` before the first call to {@link TerraformService.checkTerraformVersion}.
|
|
205
|
+
*/
|
|
206
|
+
hasCompatibleTerraformVersion;
|
|
207
|
+
/**
|
|
208
|
+
* A promise that resolves when the installed Terraform version has been checked.
|
|
209
|
+
* It is `undefined` before the first call to {@link TerraformService.checkTerraformVersion}, or if the actual check
|
|
210
|
+
* is not needed.
|
|
211
|
+
*/
|
|
212
|
+
terraformVersionCheck;
|
|
213
|
+
/**
|
|
214
|
+
* Checks whether the installed Terraform version is compatible with the required version set in the configuration.
|
|
215
|
+
* If the required version is `latest`, the check is skipped.
|
|
216
|
+
* If the installed version is not compatible, an {@link IncompatibleTerraformVersionError} is thrown.
|
|
217
|
+
* The result of the check is cached, and this returns synchronously on subsequent calls.
|
|
218
|
+
*/
|
|
219
|
+
async checkTerraformVersion() {
|
|
220
|
+
if (this.hasCompatibleTerraformVersion === true) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
if (this.requiredVersion === 'latest') {
|
|
224
|
+
this.hasCompatibleTerraformVersion = true;
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
if (!this.terraformVersionCheck) {
|
|
228
|
+
this.terraformVersionCheck = (async () => {
|
|
229
|
+
const result = await this.processService.spawn('terraform', ['-version', '-json'], { capture: { stdout: true } }).result;
|
|
230
|
+
const version = JSON.parse(result.stdout ?? '').terraform_version;
|
|
231
|
+
this.hasCompatibleTerraformVersion = satisfies(version, `^${this.requiredVersion}`);
|
|
232
|
+
if (!this.hasCompatibleTerraformVersion) {
|
|
233
|
+
throw new IncompatibleTerraformVersionError(version, this.requiredVersion);
|
|
234
|
+
}
|
|
235
|
+
})();
|
|
236
|
+
}
|
|
237
|
+
await this.terraformVersionCheck;
|
|
238
|
+
}
|
|
164
239
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@causa/workspace-terraform",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "The Causa workspace module providing functionalities for infrastructure projects coded in Terraform.",
|
|
5
5
|
"repository": "github:causa-io/workspace-module-terraform",
|
|
6
6
|
"license": "ISC",
|
|
@@ -28,22 +28,24 @@
|
|
|
28
28
|
"test:cov": "npm run test -- --coverage"
|
|
29
29
|
},
|
|
30
30
|
"dependencies": {
|
|
31
|
-
"@causa/
|
|
32
|
-
"@causa/workspace": ">= 0.
|
|
33
|
-
"
|
|
34
|
-
"
|
|
31
|
+
"@causa/workspace": ">= 0.10.0 < 1.0.0",
|
|
32
|
+
"@causa/workspace-core": ">= 0.7.0 < 1.0.0",
|
|
33
|
+
"pino": "^8.14.1",
|
|
34
|
+
"semver": "^7.5.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
37
|
"@tsconfig/node18": "^2.0.1",
|
|
38
|
-
"@types/jest": "^29.5.
|
|
39
|
-
"
|
|
38
|
+
"@types/jest": "^29.5.2",
|
|
39
|
+
"@types/node": "^18.16.14",
|
|
40
|
+
"@typescript-eslint/eslint-plugin": "^5.59.9",
|
|
41
|
+
"eslint": "^8.42.0",
|
|
40
42
|
"eslint-config-prettier": "^8.8.0",
|
|
41
43
|
"eslint-plugin-prettier": "^4.2.1",
|
|
42
44
|
"jest": "^29.5.0",
|
|
43
|
-
"jest-extended": "^
|
|
44
|
-
"rimraf": "^5.0.
|
|
45
|
+
"jest-extended": "^4.0.0",
|
|
46
|
+
"rimraf": "^5.0.1",
|
|
45
47
|
"ts-jest": "^29.1.0",
|
|
46
48
|
"ts-node": "^10.9.1",
|
|
47
|
-
"typescript": "^5.
|
|
49
|
+
"typescript": "^5.1.3"
|
|
48
50
|
}
|
|
49
51
|
}
|