hereya-cli 0.55.0 → 0.57.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 +94 -36
- package/dist/backend/cloud/cloud-backend.d.ts +5 -1
- package/dist/backend/cloud/cloud-backend.js +208 -0
- package/dist/backend/common.d.ts +64 -2
- package/dist/backend/file.d.ts +5 -1
- package/dist/backend/file.js +24 -0
- package/dist/commands/add/index.js +2 -1
- package/dist/commands/deploy/index.js +50 -24
- package/dist/commands/doc/index.d.ts +17 -0
- package/dist/commands/doc/index.js +154 -0
- package/dist/commands/down/index.js +40 -11
- package/dist/commands/import/index.js +2 -1
- package/dist/commands/publish/index.d.ts +32 -0
- package/dist/commands/publish/index.js +239 -0
- package/dist/commands/remove/index.js +16 -4
- package/dist/commands/undeploy/index.js +45 -17
- package/dist/commands/up/index.js +36 -11
- package/dist/commands/workspace/install/index.js +1 -1
- package/dist/commands/workspace/uninstall/index.js +18 -5
- package/dist/executor/interface.d.ts +5 -0
- package/dist/executor/local.js +3 -3
- package/dist/infrastructure/index.d.ts +2 -0
- package/dist/infrastructure/index.js +8 -8
- package/dist/lib/config/common.d.ts +1 -0
- package/dist/lib/config/simple.js +2 -2
- package/dist/lib/package/cloud.d.ts +19 -0
- package/dist/lib/package/cloud.js +226 -0
- package/dist/lib/package/common.d.ts +1 -0
- package/dist/lib/package/github.d.ts +1 -1
- package/dist/lib/package/github.js +33 -6
- package/dist/lib/package/index.d.ts +9 -4
- package/dist/lib/package/index.js +178 -35
- package/dist/lib/package/local.js +1 -0
- package/oclif.manifest.json +92 -1
- package/package.json +8 -1
|
@@ -1,42 +1,139 @@
|
|
|
1
1
|
import * as yaml from 'yaml';
|
|
2
2
|
import { z } from 'zod';
|
|
3
|
+
import { getCurrentBackendType } from '../../backend/config.js';
|
|
4
|
+
import { BackendType, getBackend } from '../../backend/index.js';
|
|
3
5
|
import { IacType } from '../../iac/common.js';
|
|
4
6
|
import { InfrastructureType } from '../../infrastructure/common.js';
|
|
7
|
+
import { CloudPackageManager } from './cloud.js';
|
|
5
8
|
import { GitHubPackageManager } from './github.js';
|
|
6
9
|
import { LocalPackageManager } from './local.js';
|
|
7
|
-
export const
|
|
10
|
+
export const githubPackageManager = new GitHubPackageManager();
|
|
8
11
|
export const localPackageManager = new LocalPackageManager();
|
|
9
|
-
export function getPackageManager(protocol) {
|
|
12
|
+
export async function getPackageManager(protocol, logger) {
|
|
10
13
|
if (protocol === 'local') {
|
|
11
14
|
return localPackageManager;
|
|
12
15
|
}
|
|
13
|
-
|
|
16
|
+
if (protocol === 'cloud') {
|
|
17
|
+
const backend = await getBackend();
|
|
18
|
+
return new CloudPackageManager(backend, logger);
|
|
19
|
+
}
|
|
20
|
+
// Default to GitHub
|
|
21
|
+
return githubPackageManager;
|
|
14
22
|
}
|
|
15
23
|
export async function resolvePackage(input) {
|
|
16
|
-
|
|
24
|
+
// Parse package spec to extract name and version
|
|
25
|
+
const { packageName, version } = parsePackageSpec(input.package);
|
|
26
|
+
// Validate package name format
|
|
27
|
+
if (packageName.includes('.')) {
|
|
17
28
|
return { found: false, reason: 'Invalid package format. Package name cannot contain dots (.) nor double dashes (--)' };
|
|
18
29
|
}
|
|
19
|
-
if (
|
|
30
|
+
if (packageName.includes('--')) {
|
|
20
31
|
return { found: false, reason: 'Invalid package format. Package name cannot contain dots (.) nor double dashes (--)' };
|
|
21
32
|
}
|
|
22
|
-
const isLocal =
|
|
33
|
+
const isLocal = packageName.startsWith('local/');
|
|
34
|
+
// Try cloud first if not local and backend is cloud
|
|
35
|
+
if (!isLocal) {
|
|
36
|
+
const backendType = await getCurrentBackendType();
|
|
37
|
+
if (backendType === BackendType.Cloud) {
|
|
38
|
+
const result = await tryCloudResolution(input);
|
|
39
|
+
if (result.found) {
|
|
40
|
+
return result; // Success
|
|
41
|
+
}
|
|
42
|
+
// Failed - check if we should fallback to GitHub or return the error
|
|
43
|
+
if (!packageName.includes('/')) {
|
|
44
|
+
// Simple package names can't fallback to GitHub, return the detailed error
|
|
45
|
+
return result;
|
|
46
|
+
}
|
|
47
|
+
// For owner/repo format, we can fallback to GitHub
|
|
48
|
+
input.logger?.debug(`Package ${packageName} not found in registry, trying GitHub...`);
|
|
49
|
+
input.logger?.debug(`Registry error: ${result.reason}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
// Determine protocol for standard resolution
|
|
53
|
+
const protocol = isLocal ? 'local' : '';
|
|
54
|
+
// Standard resolution (GitHub or local)
|
|
55
|
+
return resolveWithStandardManager(protocol, input, packageName, version);
|
|
56
|
+
}
|
|
57
|
+
export function getPackageCanonicalName(packageName) {
|
|
58
|
+
return packageName.replaceAll('/', '--');
|
|
59
|
+
}
|
|
60
|
+
export async function downloadPackage(pkgUrl, destPath) {
|
|
61
|
+
// Determine protocol based on URL characteristics
|
|
62
|
+
let protocol = '';
|
|
63
|
+
if (pkgUrl.startsWith('local/')) {
|
|
64
|
+
protocol = 'local';
|
|
65
|
+
}
|
|
66
|
+
else if (pkgUrl.includes('#')) {
|
|
67
|
+
// Registry package URLs contain commit SHA
|
|
68
|
+
const backendType = await getCurrentBackendType();
|
|
69
|
+
if (backendType === BackendType.Cloud) {
|
|
70
|
+
protocol = 'cloud';
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
// Otherwise defaults to GitHub
|
|
74
|
+
const packageManager = await getPackageManager(protocol);
|
|
75
|
+
return packageManager.downloadPackage(pkgUrl, destPath);
|
|
76
|
+
}
|
|
77
|
+
export const PackageMetadata = z.object({
|
|
78
|
+
dependencies: z.record(z.string()).optional(),
|
|
79
|
+
deploy: z.boolean().optional(),
|
|
80
|
+
iac: z.nativeEnum(IacType),
|
|
81
|
+
infra: z.nativeEnum(InfrastructureType),
|
|
82
|
+
onDeploy: z
|
|
83
|
+
.object({
|
|
84
|
+
pkg: z.string(),
|
|
85
|
+
version: z.string(),
|
|
86
|
+
})
|
|
87
|
+
.optional(),
|
|
88
|
+
originalInfra: z.nativeEnum(InfrastructureType).optional(),
|
|
89
|
+
});
|
|
90
|
+
// Helper function to parse package spec into name and version
|
|
91
|
+
function parsePackageSpec(spec) {
|
|
92
|
+
const match = spec.match(/^([^@]+)(?:@(.+))?$/);
|
|
93
|
+
if (!match) {
|
|
94
|
+
return { packageName: spec };
|
|
95
|
+
}
|
|
96
|
+
const [, packageName, version] = match;
|
|
97
|
+
return { packageName, version };
|
|
98
|
+
}
|
|
99
|
+
// Helper function to try cloud resolution
|
|
100
|
+
async function tryCloudResolution(input) {
|
|
101
|
+
const cloudManager = await getPackageManager('cloud', input.logger);
|
|
102
|
+
const cloudPackageInfo = await cloudManager.resolvePackage(input.package);
|
|
103
|
+
if (cloudPackageInfo) {
|
|
104
|
+
// Successfully found in registry, now get metadata
|
|
105
|
+
input.logger?.debug(`Found package in registry: ${cloudPackageInfo.name}@${cloudPackageInfo.version}`);
|
|
106
|
+
const result = await resolveCloudPackage(cloudPackageInfo, cloudManager, input);
|
|
107
|
+
input.logger?.debug(`Metadata resolution result: ${result.found ? 'success' : result.reason}`);
|
|
108
|
+
return result; // Return success or failure with detailed reason
|
|
109
|
+
}
|
|
110
|
+
// Package not found in registry at all
|
|
111
|
+
return {
|
|
112
|
+
found: false,
|
|
113
|
+
reason: `Package '${input.package}' not found in cloud registry. Make sure the package name is correct and you have access to it.`
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
// Helper function for standard (GitHub/local) resolution
|
|
117
|
+
async function resolveWithStandardManager(protocol, input, packageName, version) {
|
|
118
|
+
// Standard managers don't support logger yet
|
|
119
|
+
// Parse owner/repo from package name
|
|
23
120
|
let [owner, repo] = ['', ''];
|
|
24
|
-
if (
|
|
121
|
+
if (protocol === 'local') {
|
|
25
122
|
owner = 'local';
|
|
26
|
-
repo =
|
|
123
|
+
repo = packageName.replace('local/', '');
|
|
27
124
|
}
|
|
28
125
|
else {
|
|
29
|
-
const pkgParts =
|
|
126
|
+
const pkgParts = packageName.split('/');
|
|
30
127
|
if (pkgParts.length !== 2) {
|
|
31
|
-
return { found: false, reason: 'Invalid package format. Use owner/repository' };
|
|
128
|
+
return { found: false, reason: 'Invalid package format. Use owner/repository or org/name' };
|
|
32
129
|
}
|
|
33
130
|
;
|
|
34
131
|
[owner, repo] = pkgParts;
|
|
35
132
|
}
|
|
36
|
-
const packageManager = getPackageManager(
|
|
133
|
+
const packageManager = await getPackageManager(protocol);
|
|
37
134
|
const metadataContentCandidates = (await Promise.all([
|
|
38
|
-
packageManager.getRepoContent({ owner, path: 'hereyarc.yaml', projectRootDir: input.projectRootDir, repo }),
|
|
39
|
-
packageManager.getRepoContent({ owner, path: 'hereyarc.yml', projectRootDir: input.projectRootDir, repo }),
|
|
135
|
+
packageManager.getRepoContent({ owner, path: 'hereyarc.yaml', projectRootDir: input.projectRootDir, repo, version }),
|
|
136
|
+
packageManager.getRepoContent({ owner, path: 'hereyarc.yml', projectRootDir: input.projectRootDir, repo, version }),
|
|
40
137
|
])).filter((content$) => content$.found);
|
|
41
138
|
if (metadataContentCandidates.length === 0) {
|
|
42
139
|
return { found: false, reason: `No hereya metadata file found in ${input.package}` };
|
|
@@ -48,37 +145,83 @@ export async function resolvePackage(input) {
|
|
|
48
145
|
return { found: false, reason: 'Package has dependencies but is not a deploy package' };
|
|
49
146
|
}
|
|
50
147
|
if (input.isDeploying && metadata.onDeploy) {
|
|
51
|
-
return resolvePackage({ package: metadata.onDeploy.pkg
|
|
148
|
+
return resolvePackage({ ...input, package: metadata.onDeploy.pkg });
|
|
52
149
|
}
|
|
53
150
|
return {
|
|
54
|
-
canonicalName: getPackageCanonicalName(
|
|
151
|
+
canonicalName: getPackageCanonicalName(packageName),
|
|
55
152
|
found: true,
|
|
56
153
|
metadata,
|
|
57
154
|
packageUri: metadataContent$.pkgUrl,
|
|
58
|
-
pkgName:
|
|
155
|
+
pkgName: packageName,
|
|
156
|
+
version: version || '',
|
|
59
157
|
};
|
|
60
158
|
}
|
|
61
159
|
catch (error) {
|
|
62
160
|
return { found: false, reason: error.message };
|
|
63
161
|
}
|
|
64
162
|
}
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
163
|
+
// Helper function to resolve cloud package metadata
|
|
164
|
+
async function resolveCloudPackage(packageInfo, cloudManager, input) {
|
|
165
|
+
// Parse package name to determine owner/repo for getRepoContent interface
|
|
166
|
+
// For simple names like 'mongo', owner will be empty
|
|
167
|
+
// For org/name format like 'hereya/mongo', split into owner and repo
|
|
168
|
+
const parts = packageInfo.name.split('/');
|
|
169
|
+
const owner = parts.length === 2 ? parts[0] : '';
|
|
170
|
+
const repo = parts.length === 2 ? parts[1] : packageInfo.name;
|
|
171
|
+
// Get metadata using the standard getRepoContent interface
|
|
172
|
+
// CloudPackageManager will reconstruct the package name and look it up in registry
|
|
173
|
+
const metadataContentCandidates = (await Promise.all([
|
|
174
|
+
cloudManager.getRepoContent({
|
|
175
|
+
owner,
|
|
176
|
+
path: 'hereyarc.yaml',
|
|
177
|
+
projectRootDir: input.projectRootDir,
|
|
178
|
+
repo,
|
|
179
|
+
version: packageInfo.version,
|
|
180
|
+
}),
|
|
181
|
+
cloudManager.getRepoContent({
|
|
182
|
+
owner,
|
|
183
|
+
path: 'hereyarc.yml',
|
|
184
|
+
projectRootDir: input.projectRootDir,
|
|
185
|
+
repo,
|
|
186
|
+
version: packageInfo.version,
|
|
187
|
+
}),
|
|
188
|
+
])).filter((content$) => content$.found);
|
|
189
|
+
if (metadataContentCandidates.length === 0) {
|
|
190
|
+
// Try to get more detailed error from the last attempt
|
|
191
|
+
const lastAttempt = await cloudManager.getRepoContent({
|
|
192
|
+
owner,
|
|
193
|
+
path: 'hereyarc.yaml',
|
|
194
|
+
projectRootDir: input.projectRootDir,
|
|
195
|
+
repo,
|
|
196
|
+
});
|
|
197
|
+
const detailedReason = !lastAttempt.found && lastAttempt.reason
|
|
198
|
+
? lastAttempt.reason
|
|
199
|
+
: `No hereya metadata file (hereyarc.yaml or hereyarc.yml) found for package '${packageInfo.name}'`;
|
|
200
|
+
return { found: false, reason: detailedReason };
|
|
201
|
+
}
|
|
202
|
+
const metadataContent$ = metadataContentCandidates[0];
|
|
203
|
+
try {
|
|
204
|
+
const metadata = PackageMetadata.parse(yaml.parse(metadataContent$.content));
|
|
205
|
+
if (!metadata.deploy && metadata.dependencies) {
|
|
206
|
+
return { found: false, reason: 'Package has dependencies but is not a deploy package' };
|
|
207
|
+
}
|
|
208
|
+
if (input.isDeploying && metadata.onDeploy) {
|
|
209
|
+
return resolvePackage({ ...input, package: metadata.onDeploy.pkg });
|
|
210
|
+
}
|
|
211
|
+
// Build packageUri with repository and commit
|
|
212
|
+
const packageUri = packageInfo.registryPackage.commit
|
|
213
|
+
? `${packageInfo.registryPackage.repository}#${packageInfo.registryPackage.commit}`
|
|
214
|
+
: packageInfo.registryPackage.repository || metadataContent$.pkgUrl;
|
|
215
|
+
return {
|
|
216
|
+
canonicalName: getPackageCanonicalName(packageInfo.name),
|
|
217
|
+
found: true,
|
|
218
|
+
metadata,
|
|
219
|
+
packageUri,
|
|
220
|
+
pkgName: packageInfo.name,
|
|
221
|
+
version: packageInfo.version,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
catch (error) {
|
|
225
|
+
return { found: false, reason: error.message };
|
|
226
|
+
}
|
|
71
227
|
}
|
|
72
|
-
export const PackageMetadata = z.object({
|
|
73
|
-
dependencies: z.record(z.string()).optional(),
|
|
74
|
-
deploy: z.boolean().optional(),
|
|
75
|
-
iac: z.nativeEnum(IacType),
|
|
76
|
-
infra: z.nativeEnum(InfrastructureType),
|
|
77
|
-
onDeploy: z
|
|
78
|
-
.object({
|
|
79
|
-
pkg: z.string(),
|
|
80
|
-
version: z.string(),
|
|
81
|
-
})
|
|
82
|
-
.optional(),
|
|
83
|
-
originalInfra: z.nativeEnum(InfrastructureType).optional(),
|
|
84
|
-
});
|
|
@@ -7,6 +7,7 @@ export class LocalPackageManager {
|
|
|
7
7
|
return destPath;
|
|
8
8
|
}
|
|
9
9
|
async getRepoContent({ path: filePath, projectRootDir, repo }) {
|
|
10
|
+
// Local packages don't have versions, version parameter is ignored
|
|
10
11
|
try {
|
|
11
12
|
const pkgRootDir = path.join(projectRootDir ?? process.cwd(), repo);
|
|
12
13
|
const resolvedPath = path.join(pkgRootDir, filePath);
|
package/oclif.manifest.json
CHANGED
|
@@ -193,6 +193,63 @@
|
|
|
193
193
|
"index.js"
|
|
194
194
|
]
|
|
195
195
|
},
|
|
196
|
+
"doc": {
|
|
197
|
+
"aliases": [],
|
|
198
|
+
"args": {
|
|
199
|
+
"package": {
|
|
200
|
+
"description": "Package name with optional version (e.g., my-package or my-package@1.0.0)",
|
|
201
|
+
"name": "package",
|
|
202
|
+
"required": true
|
|
203
|
+
}
|
|
204
|
+
},
|
|
205
|
+
"description": "Display documentation for a package from the registry",
|
|
206
|
+
"examples": [
|
|
207
|
+
"<%= config.bin %> <%= command.id %> my-package",
|
|
208
|
+
"<%= config.bin %> <%= command.id %> my-package@1.0.0",
|
|
209
|
+
"<%= config.bin %> <%= command.id %> my-package --json",
|
|
210
|
+
"<%= config.bin %> <%= command.id %> my-package --no-doc"
|
|
211
|
+
],
|
|
212
|
+
"flags": {
|
|
213
|
+
"chdir": {
|
|
214
|
+
"char": "C",
|
|
215
|
+
"description": "directory to run command in",
|
|
216
|
+
"helpGroup": "global",
|
|
217
|
+
"name": "chdir",
|
|
218
|
+
"default": ".",
|
|
219
|
+
"hasDynamicHelp": false,
|
|
220
|
+
"multiple": false,
|
|
221
|
+
"type": "option"
|
|
222
|
+
},
|
|
223
|
+
"json": {
|
|
224
|
+
"char": "j",
|
|
225
|
+
"description": "Output in JSON format",
|
|
226
|
+
"name": "json",
|
|
227
|
+
"allowNo": false,
|
|
228
|
+
"type": "boolean"
|
|
229
|
+
},
|
|
230
|
+
"no-doc": {
|
|
231
|
+
"description": "Show only metadata without the full documentation",
|
|
232
|
+
"name": "no-doc",
|
|
233
|
+
"allowNo": false,
|
|
234
|
+
"type": "boolean"
|
|
235
|
+
}
|
|
236
|
+
},
|
|
237
|
+
"hasDynamicHelp": false,
|
|
238
|
+
"hiddenAliases": [],
|
|
239
|
+
"id": "doc",
|
|
240
|
+
"pluginAlias": "hereya-cli",
|
|
241
|
+
"pluginName": "hereya-cli",
|
|
242
|
+
"pluginType": "core",
|
|
243
|
+
"strict": true,
|
|
244
|
+
"enableJsonFlag": false,
|
|
245
|
+
"isESM": true,
|
|
246
|
+
"relativePath": [
|
|
247
|
+
"dist",
|
|
248
|
+
"commands",
|
|
249
|
+
"doc",
|
|
250
|
+
"index.js"
|
|
251
|
+
]
|
|
252
|
+
},
|
|
196
253
|
"down": {
|
|
197
254
|
"aliases": [],
|
|
198
255
|
"args": {},
|
|
@@ -507,6 +564,40 @@
|
|
|
507
564
|
"index.js"
|
|
508
565
|
]
|
|
509
566
|
},
|
|
567
|
+
"publish": {
|
|
568
|
+
"aliases": [],
|
|
569
|
+
"args": {},
|
|
570
|
+
"description": "Publish a package to the Hereya registry",
|
|
571
|
+
"examples": [
|
|
572
|
+
"$ hereya publish",
|
|
573
|
+
"$ hereya publish --chdir=/path/to/package"
|
|
574
|
+
],
|
|
575
|
+
"flags": {
|
|
576
|
+
"chdir": {
|
|
577
|
+
"description": "\n Directory where the command will be executed.\n If not specified, it defaults to the current working directory.\n ",
|
|
578
|
+
"name": "chdir",
|
|
579
|
+
"required": false,
|
|
580
|
+
"hasDynamicHelp": false,
|
|
581
|
+
"multiple": false,
|
|
582
|
+
"type": "option"
|
|
583
|
+
}
|
|
584
|
+
},
|
|
585
|
+
"hasDynamicHelp": false,
|
|
586
|
+
"hiddenAliases": [],
|
|
587
|
+
"id": "publish",
|
|
588
|
+
"pluginAlias": "hereya-cli",
|
|
589
|
+
"pluginName": "hereya-cli",
|
|
590
|
+
"pluginType": "core",
|
|
591
|
+
"strict": true,
|
|
592
|
+
"enableJsonFlag": false,
|
|
593
|
+
"isESM": true,
|
|
594
|
+
"relativePath": [
|
|
595
|
+
"dist",
|
|
596
|
+
"commands",
|
|
597
|
+
"publish",
|
|
598
|
+
"index.js"
|
|
599
|
+
]
|
|
600
|
+
},
|
|
510
601
|
"remove": {
|
|
511
602
|
"aliases": [],
|
|
512
603
|
"args": {
|
|
@@ -1786,5 +1877,5 @@
|
|
|
1786
1877
|
]
|
|
1787
1878
|
}
|
|
1788
1879
|
},
|
|
1789
|
-
"version": "0.
|
|
1880
|
+
"version": "0.57.0"
|
|
1790
1881
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hereya-cli",
|
|
3
3
|
"description": "Infrastructure as Package",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.57.0",
|
|
5
5
|
"author": "Hereya Developers",
|
|
6
6
|
"bin": {
|
|
7
7
|
"hereya": "./bin/run.js"
|
|
@@ -19,10 +19,13 @@
|
|
|
19
19
|
"@oclif/core": "^4.2.6",
|
|
20
20
|
"@oclif/plugin-help": "^6.2.25",
|
|
21
21
|
"@oclif/plugin-plugins": "^5.4.31",
|
|
22
|
+
"chalk": "^5.5.0",
|
|
22
23
|
"glob": "^11.0.1",
|
|
23
24
|
"ignore": "^7.0.3",
|
|
24
25
|
"keytar": "^7.9.0",
|
|
25
26
|
"listr2": "^8.2.5",
|
|
27
|
+
"marked": "^16.1.2",
|
|
28
|
+
"marked-terminal": "7.3.0",
|
|
26
29
|
"node-machine-id": "^1.1.12",
|
|
27
30
|
"open": "^10.1.1",
|
|
28
31
|
"simple-git": "^3.27.0",
|
|
@@ -35,10 +38,13 @@
|
|
|
35
38
|
"@oclif/test": "^4.1.9",
|
|
36
39
|
"@types/chai": "^5.0.1",
|
|
37
40
|
"@types/jsonwebtoken": "^9.0.9",
|
|
41
|
+
"@types/marked-terminal": "^6.1.1",
|
|
38
42
|
"@types/mocha": "^10.0.10",
|
|
39
43
|
"@types/mock-fs": "^4.13.4",
|
|
40
44
|
"@types/node": "^22",
|
|
41
45
|
"@types/sinon": "^17.0.3",
|
|
46
|
+
"@types/sinon-chai": "^4.0.0",
|
|
47
|
+
"@types/tar": "^6.1.13",
|
|
42
48
|
"@types/unzip-stream": "^0.3.4",
|
|
43
49
|
"chai": "^5.1.2",
|
|
44
50
|
"eslint": "^9.20.1",
|
|
@@ -52,6 +58,7 @@
|
|
|
52
58
|
"oclif": "^4.17.27",
|
|
53
59
|
"shx": "^0.3.4",
|
|
54
60
|
"sinon": "^19.0.2",
|
|
61
|
+
"sinon-chai": "^4.0.0",
|
|
55
62
|
"tsx": "^4.20.3",
|
|
56
63
|
"typescript": "^5.7.3"
|
|
57
64
|
},
|