@negokaz/excel-cli 0.3.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 negokaz
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,140 @@
1
+ # excel-cli
2
+
3
+ `excel-cli` is a command-line tool for treating Excel workbooks, sheets, and ranges as structured resources.
4
+
5
+ ## Features
6
+
7
+ - Read workbook, sheet, or range data as JSON
8
+ - Read formulas and styles in addition to values
9
+ - Write values, formulas, styles, and sheet properties from JSON
10
+ - Export HTML artifacts under `.excel-cli/` for broad inspection and visual layout checks
11
+
12
+ **🪟Windows only:**
13
+
14
+ - Live edits through OLE automation when Excel is available
15
+ - Export PNG captures under `.excel-cli/` through OLE automation
16
+
17
+ ## Installation
18
+
19
+ Requires Node.js 20 or later.
20
+
21
+ ```sh
22
+ npm install -g @negokaz/excel-cli
23
+ ```
24
+
25
+ ## Installing the Agent Skill
26
+
27
+ This repository also includes an agent skill at [`skills/excel-cli/`](./skills/excel-cli/).
28
+
29
+ You can install the skill with:
30
+
31
+ ```sh
32
+ gh skill install negokaz/excel-cli excel-cli
33
+ ```
34
+
35
+ ## Command Summary
36
+
37
+ ```text
38
+ excel-cli read <file> <path> [--value | --formula | --style]
39
+ excel-cli query <file> <path>
40
+ excel-cli write <file> <path> (--value <json> | --formula <json> | --style <json> | --props <json>)
41
+ excel-cli add <file> <path>
42
+ excel-cli remove <file> <path> [--force]
43
+ excel-cli export <file> <path> --format <html|png> [--formula] [--style]
44
+ ```
45
+
46
+ ## Paths
47
+
48
+ Commands address workbook resources through a canonical `<file> <path>` pair.
49
+
50
+ Supported initial paths:
51
+
52
+ - `/`
53
+ - `/Sheet1`
54
+ - `/Sheet1/A1`
55
+ - `/Sheet1/A1:C3`
56
+
57
+ Path rules:
58
+
59
+ - paths must begin with `/`
60
+ - sheet names use canonical path segments: Unicode characters are preserved, while ASCII characters that require escaping remain percent-encoded
61
+ - range output is canonicalized to uppercase cell references
62
+ - Excel-style references such as `Sheet1!A1:C3` are rejected
63
+
64
+ ## Examples
65
+
66
+ Enumerate sheets:
67
+
68
+ ```sh
69
+ excel-cli query book.xlsx /
70
+ ```
71
+
72
+ ```json
73
+ {
74
+ "path": "/",
75
+ "kind": "sheetCollection",
76
+ "backend": "excelize",
77
+ "items": [
78
+ { "path": "/Data", "kind": "sheet", "name": "Data" },
79
+ { "path": "/Hidden%20Sheet", "kind": "sheet", "name": "Hidden Sheet" }
80
+ ]
81
+ }
82
+ ```
83
+
84
+ Read workbook, sheet, and range resources:
85
+
86
+ ```sh
87
+ excel-cli read book.xlsx /
88
+ excel-cli read book.xlsx /Data
89
+ excel-cli read book.xlsx /Data/A1:C2 --formula
90
+ excel-cli read book.xlsx /Data/A1:C2 --style
91
+ ```
92
+
93
+ Write values, formulas, styles, and sheet properties:
94
+
95
+ ```sh
96
+ excel-cli write book.xlsx /Data/A2:B2 --value '[["Alice",95]]'
97
+ excel-cli write book.xlsx /Data/C2 --formula '[["=SUM(3,4)"]]'
98
+ excel-cli write book.xlsx /Data/A1:B1 --style '[[{"font":{"bold":true}}, null]]'
99
+ excel-cli write book.xlsx /Hidden%20Sheet --props '{"hidden":false}'
100
+ ```
101
+
102
+ Create and remove worksheets:
103
+
104
+ ```sh
105
+ excel-cli add book.xlsx /Sales
106
+ excel-cli remove book.xlsx /Sales
107
+ excel-cli remove book.xlsx /Sales --force
108
+ ```
109
+
110
+ `remove` is a dry-run by default. It validates that the sheet can be removed and returns JSON with `wouldRemove: true`. The workbook is only changed when `--force` is provided.
111
+
112
+ Export derived artifacts:
113
+
114
+ ```sh
115
+ excel-cli export book.xlsx /Data --format html --formula --style
116
+ excel-cli export book.xlsx /Data/A1:C10 --format png
117
+ ```
118
+
119
+ HTML and PNG files are created under `.excel-cli/`.
120
+
121
+ ## Notes
122
+
123
+ - `write --value`, `write --formula`, and `read --value`, `read --formula` are designed to round-trip through the same 2-dimensional JSON shape
124
+ - `write --style` accepts a 2-dimensional array of style objects or `null`
125
+ - `write --props` currently supports only worksheet `hidden`
126
+ - `remove` fails if the target sheet does not exist or if it is the workbook's only worksheet
127
+
128
+ The design notes in [docs/](docs/index.md) are the primary reference for command contracts and migration intent.
129
+
130
+ ## Supported Platforms
131
+
132
+ | Platform | Architecture |
133
+ |----------|--------------|
134
+ | Windows | x64, arm64 |
135
+ | macOS | x64, arm64 |
136
+ | Linux | x64, arm64 |
137
+
138
+ ## License
139
+
140
+ MIT
@@ -0,0 +1 @@
1
+ [{"name":"metadata.json","path":"dist/metadata.json","internal_type":35,"type":"Metadata"},{"name":"excel-cli","path":"dist/excel-cli_darwin_amd64_v1/excel-cli","goos":"darwin","goarch":"amd64","goamd64":"v1","target":"darwin_amd64_v1","internal_type":4,"type":"Binary","extra":{"Binary":"excel-cli","Builder":"go","Ext":"","ID":"excel-cli"}},{"name":"excel-cli","path":"dist/excel-cli_darwin_arm64_v8.0/excel-cli","goos":"darwin","goarch":"arm64","goarm64":"v8.0","target":"darwin_arm64_v8.0","internal_type":4,"type":"Binary","extra":{"Binary":"excel-cli","Builder":"go","Ext":"","ID":"excel-cli"}},{"name":"excel-cli","path":"dist/excel-cli_linux_amd64_v1/excel-cli","goos":"linux","goarch":"amd64","goamd64":"v1","target":"linux_amd64_v1","internal_type":4,"type":"Binary","extra":{"Binary":"excel-cli","Builder":"go","Ext":"","ID":"excel-cli"}},{"name":"excel-cli.exe","path":"dist/excel-cli_windows_arm64_v8.0/excel-cli.exe","goos":"windows","goarch":"arm64","goarm64":"v8.0","target":"windows_arm64_v8.0","internal_type":4,"type":"Binary","extra":{"Binary":"excel-cli","Builder":"go","Ext":".exe","ID":"excel-cli"}},{"name":"excel-cli.exe","path":"dist/excel-cli_windows_amd64_v1/excel-cli.exe","goos":"windows","goarch":"amd64","goamd64":"v1","target":"windows_amd64_v1","internal_type":4,"type":"Binary","extra":{"Binary":"excel-cli","Builder":"go","Ext":".exe","ID":"excel-cli"}},{"name":"excel-cli","path":"dist/excel-cli_linux_arm64_v8.0/excel-cli","goos":"linux","goarch":"arm64","goarm64":"v8.0","target":"linux_arm64_v8.0","internal_type":4,"type":"Binary","extra":{"Binary":"excel-cli","Builder":"go","Ext":"","ID":"excel-cli"}}]
@@ -0,0 +1,150 @@
1
+ version: 2
2
+ project_name: excel-cli
3
+ release:
4
+ disable: "true"
5
+ builds:
6
+ - id: excel-cli
7
+ goos:
8
+ - windows
9
+ - darwin
10
+ - linux
11
+ goarch:
12
+ - amd64
13
+ - arm64
14
+ goamd64:
15
+ - v1
16
+ go386:
17
+ - sse2
18
+ goarm:
19
+ - "6"
20
+ goarm64:
21
+ - v8.0
22
+ gomips:
23
+ - hardfloat
24
+ goppc64:
25
+ - power8
26
+ goriscv64:
27
+ - rva20u64
28
+ targets:
29
+ - windows_amd64_v1
30
+ - windows_arm64_v8.0
31
+ - darwin_amd64_v1
32
+ - darwin_arm64_v8.0
33
+ - linux_amd64_v1
34
+ - linux_arm64_v8.0
35
+ dir: .
36
+ main: .
37
+ binary: excel-cli
38
+ builder: go
39
+ tool: go
40
+ command: build
41
+ ldflags:
42
+ - -s -w
43
+ env:
44
+ - CGO_ENABLED=0
45
+ archives:
46
+ - id: default
47
+ builds_info:
48
+ mode: 493
49
+ name_template: '{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}{{ with .Arm }}v{{ . }}{{ end }}{{ with .Mips }}_{{ . }}{{ end }}{{ if not (eq .Amd64 "v1") }}{{ .Amd64 }}{{ end }}'
50
+ formats:
51
+ - tar.gz
52
+ files:
53
+ - src: license*
54
+ - src: LICENSE*
55
+ - src: readme*
56
+ - src: README*
57
+ - src: changelog*
58
+ - src: CHANGELOG*
59
+ srpm:
60
+ nfpmrpm: {}
61
+ package_name: excel-cli
62
+ file_name_template: '{{ .PackageName }}-{{ .Version }}.src.rpm'
63
+ bins:
64
+ excel-cli: '%{goipath}'
65
+ snapshot:
66
+ version_template: '{{ .Version }}-SNAPSHOT-{{ .ShortCommit }}'
67
+ checksum:
68
+ name_template: '{{ .ProjectName }}_{{ .Version }}_checksums.txt'
69
+ algorithm: sha256
70
+ docker_digest:
71
+ name_template: digests.txt
72
+ changelog:
73
+ format: '{{ .SHA }} {{ .Message }}'
74
+ dist: dist
75
+ env_files:
76
+ github_token: ~/.config/goreleaser/github_token
77
+ gitlab_token: ~/.config/goreleaser/gitlab_token
78
+ gitea_token: ~/.config/goreleaser/gitea_token
79
+ source:
80
+ name_template: '{{ .ProjectName }}-{{ .Version }}'
81
+ format: tar.gz
82
+ gomod:
83
+ gobinary: go
84
+ announce:
85
+ twitter:
86
+ message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
87
+ mastodon:
88
+ message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
89
+ server: ""
90
+ reddit:
91
+ title_template: '{{ .ProjectName }} {{ .Tag }} is out!'
92
+ url_template: '{{ .ReleaseURL }}'
93
+ slack:
94
+ message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
95
+ username: GoReleaser
96
+ discord:
97
+ message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
98
+ author: GoReleaser
99
+ color: "3888754"
100
+ icon_url: https://goreleaser.com/static/avatar.png
101
+ teams:
102
+ title_template: '{{ .ProjectName }} {{ .Tag }} is out!'
103
+ message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
104
+ color: '#2D313E'
105
+ icon_url: https://goreleaser.com/static/avatar.png
106
+ smtp:
107
+ subject_template: '{{ .ProjectName }} {{ .Tag }} is out!'
108
+ body_template: 'You can view details from: {{ .ReleaseURL }}'
109
+ mattermost:
110
+ message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
111
+ title_template: '{{ .ProjectName }} {{ .Tag }} is out!'
112
+ color: '#2D313E'
113
+ username: GoReleaser
114
+ linkedin:
115
+ message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
116
+ telegram:
117
+ message_template: '{{ print .ProjectName " " .Tag " is out! Check it out at " .ReleaseURL | mdv2escape }}'
118
+ parse_mode: MarkdownV2
119
+ webhook:
120
+ message_template: '{ "message": "{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}"}'
121
+ content_type: application/json; charset=utf-8
122
+ expected_status_codes:
123
+ - 200
124
+ - 201
125
+ - 202
126
+ - 204
127
+ opencollective:
128
+ title_template: '{{ .Tag }}'
129
+ message_template: '{{ .ProjectName }} {{ .Tag }} is out!<br/>Check it out at <a href="{{ .ReleaseURL }}">{{ .ReleaseURL }}</a>'
130
+ bluesky:
131
+ message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
132
+ discourse:
133
+ title_template: '{{ .ProjectName }} {{ .Tag }} is out!'
134
+ message_template: '{{ .ProjectName }} {{ .Tag }} is out! Check it out at {{ .ReleaseURL }}'
135
+ username: system
136
+ git:
137
+ tag_sort: -version:refname
138
+ mcp:
139
+ name: ""
140
+ title: ""
141
+ auth:
142
+ type: none
143
+ retry:
144
+ attempts: 10
145
+ delay: 10s
146
+ max_delay: 5m0s
147
+ github_urls:
148
+ download: https://github.com
149
+ gitlab_urls:
150
+ download: https://gitlab.com
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const run_launcher_1 = require("./run-launcher");
5
+ (0, run_launcher_1.executeLauncher)(__dirname, process);
@@ -0,0 +1 @@
1
+ {"project_name":"excel-cli","tag":"v0.3.0","previous_tag":"v0.2.0","version":"0.3.0-SNAPSHOT-577cff9","commit":"577cff9ff59726dd9b0341b1bb7a5b053aaf1d26","date":"2026-06-07T13:17:03.769006632Z","runtime":{"goos":"linux","goarch":"amd64"}}
@@ -0,0 +1,60 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.resolveBinaryPath = resolveBinaryPath;
37
+ const path = __importStar(require("path"));
38
+ const SUPPORTED_TARGETS = [
39
+ { platform: 'win32', arch: 'x64', distributionDir: 'excel-cli_windows_amd64_v1', binaryFileName: 'excel-cli.exe' },
40
+ { platform: 'win32', arch: 'arm64', distributionDir: 'excel-cli_windows_arm64_v8.0', binaryFileName: 'excel-cli.exe' },
41
+ { platform: 'darwin', arch: 'x64', distributionDir: 'excel-cli_darwin_amd64_v1', binaryFileName: 'excel-cli' },
42
+ { platform: 'darwin', arch: 'arm64', distributionDir: 'excel-cli_darwin_arm64_v8.0', binaryFileName: 'excel-cli' },
43
+ { platform: 'linux', arch: 'x64', distributionDir: 'excel-cli_linux_amd64_v1', binaryFileName: 'excel-cli' },
44
+ { platform: 'linux', arch: 'arm64', distributionDir: 'excel-cli_linux_arm64_v8.0', binaryFileName: 'excel-cli' },
45
+ ];
46
+ function getTarget(platform, arch) {
47
+ const target = SUPPORTED_TARGETS.find((entry) => entry.platform === platform && entry.arch === arch);
48
+ if (target === undefined) {
49
+ throw new Error(`Unsupported platform: ${platform}_${arch} (platform=${platform}, arch=${arch})`);
50
+ }
51
+ return target;
52
+ }
53
+ function resolveBinaryPath(platform, arch, baseDir, existsSync) {
54
+ const target = getTarget(platform, arch);
55
+ const binaryPath = path.resolve(baseDir, target.distributionDir, target.binaryFileName);
56
+ if (!existsSync(binaryPath)) {
57
+ throw new Error(`Binary not found: ${binaryPath}`);
58
+ }
59
+ return binaryPath;
60
+ }
@@ -0,0 +1,73 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.executeLauncher = executeLauncher;
37
+ const childProcess = __importStar(require("child_process"));
38
+ const fs = __importStar(require("fs"));
39
+ const resolve_binary_path_1 = require("./resolve-binary-path");
40
+ function formatErrorMessage(error) {
41
+ if (error instanceof Error) {
42
+ return error.message;
43
+ }
44
+ return String(error);
45
+ }
46
+ function runLauncher(baseDir, runtimeProcess, dependencies) {
47
+ const binaryPath = (0, resolve_binary_path_1.resolveBinaryPath)(runtimeProcess.platform, runtimeProcess.arch, baseDir, dependencies.existsSync);
48
+ const result = dependencies.spawnSync(binaryPath, runtimeProcess.argv.slice(2), { stdio: 'inherit' });
49
+ if (result.error !== undefined) {
50
+ throw result.error;
51
+ }
52
+ if (result.signal !== null) {
53
+ throw new Error(`Binary terminated by signal: ${result.signal}`);
54
+ }
55
+ if (typeof result.status !== 'number') {
56
+ throw new Error(`Binary exited without a status code: ${binaryPath}`);
57
+ }
58
+ if (result.status !== 0) {
59
+ runtimeProcess.exit(result.status);
60
+ }
61
+ }
62
+ function executeLauncher(baseDir, runtimeProcess) {
63
+ try {
64
+ runLauncher(baseDir, runtimeProcess, {
65
+ existsSync: fs.existsSync,
66
+ spawnSync: childProcess.spawnSync,
67
+ });
68
+ }
69
+ catch (error) {
70
+ runtimeProcess.stderr.write(`${formatErrorMessage(error)}\n`);
71
+ runtimeProcess.exit(1);
72
+ }
73
+ }
package/package.json ADDED
@@ -0,0 +1,46 @@
1
+ {
2
+ "name": "@negokaz/excel-cli",
3
+ "version": "0.3.0",
4
+ "description": "CLI tool for Excel operations",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/negokaz/excel-cli.git"
9
+ },
10
+ "homepage": "https://github.com/negokaz/excel-cli#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/negokaz/excel-cli/issues"
13
+ },
14
+ "bin": {
15
+ "excel-cli": "dist/launcher.js"
16
+ },
17
+ "files": [
18
+ "dist/"
19
+ ],
20
+ "scripts": {
21
+ "build": "goreleaser build --snapshot --clean && tsc",
22
+ "test": "go test ./... && jest --runInBand",
23
+ "typecheck": "tsc --noEmit"
24
+ },
25
+ "engines": {
26
+ "node": ">=20"
27
+ },
28
+ "publishConfig": {
29
+ "access": "public"
30
+ },
31
+ "devDependencies": {
32
+ "@types/jest": "^29.0.0",
33
+ "@types/node": "^20.0.0",
34
+ "foam-cli": "^0.43.0",
35
+ "jest": "^29.0.0",
36
+ "ts-jest": "^29.0.0",
37
+ "typescript": "^5.0.0"
38
+ },
39
+ "jest": {
40
+ "preset": "ts-jest",
41
+ "testEnvironment": "node",
42
+ "testMatch": [
43
+ "**/launcher/**/*.test.ts"
44
+ ]
45
+ }
46
+ }