@enactprotocol/cli 2.0.4 → 2.0.6

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.
@@ -3,6 +3,7 @@
3
3
  */
4
4
 
5
5
  import { describe, expect, test } from "bun:test";
6
+ import type { ToolVersionInfo } from "@enactprotocol/api";
6
7
  import { Command } from "commander";
7
8
  import { configureGetCommand } from "../../src/commands/get";
8
9
 
@@ -42,24 +43,26 @@ describe("get command", () => {
42
43
  expect(args[0]?.name()).toBe("tool");
43
44
  });
44
45
 
45
- test("has --version option", () => {
46
+ test("has --ver option for specifying version", () => {
46
47
  const program = new Command();
47
48
  configureGetCommand(program);
48
49
 
49
50
  const getCmd = program.commands.find((cmd) => cmd.name() === "get");
50
51
  const opts = getCmd?.options ?? [];
51
- const versionOpt = opts.find((o) => o.long === "--version");
52
- expect(versionOpt).toBeDefined();
52
+ const verOpt = opts.find((o) => o.long === "--ver");
53
+ expect(verOpt).toBeDefined();
53
54
  });
54
55
 
55
- test("has -v short option for version", () => {
56
+ test("has -v short option for verbose (not version)", () => {
56
57
  const program = new Command();
57
58
  configureGetCommand(program);
58
59
 
59
60
  const getCmd = program.commands.find((cmd) => cmd.name() === "get");
60
61
  const opts = getCmd?.options ?? [];
61
- const versionOpt = opts.find((o) => o.short === "-v");
62
- expect(versionOpt).toBeDefined();
62
+ // -v is for verbose, not version (--ver is for version)
63
+ const verboseOpt = opts.find((o) => o.short === "-v");
64
+ expect(verboseOpt).toBeDefined();
65
+ expect(verboseOpt?.long).toBe("--verbose");
63
66
  });
64
67
 
65
68
  test("has --json option", () => {
@@ -176,4 +179,87 @@ describe("get command", () => {
176
179
  expect(trustLevels).toContain("full");
177
180
  });
178
181
  });
182
+
183
+ describe("verbose mode displays enact.md", () => {
184
+ test("ToolVersionInfo type includes rawManifest field for enact.md content", () => {
185
+ // Test that the type includes rawManifest field for enact.md content
186
+ const mockVersion: ToolVersionInfo = {
187
+ name: "test/tool",
188
+ version: "1.0.0",
189
+ description: "Test tool",
190
+ license: "MIT",
191
+ yanked: false,
192
+ manifest: { enact: "2.0.0" },
193
+ rawManifest: "---\\nenact: 2.0.0\\n---\\n# Test Tool\\n\\nThis is a test tool.",
194
+ bundle: {
195
+ hash: "sha256:abc123",
196
+ size: 1024,
197
+ downloadUrl: "https://example.com/bundle.tar.gz",
198
+ },
199
+ attestations: [],
200
+ publishedBy: { username: "testuser" },
201
+ publishedAt: new Date(),
202
+ downloads: 100,
203
+ };
204
+
205
+ expect(mockVersion.rawManifest).toBeDefined();
206
+ expect(mockVersion.rawManifest).toContain("# Test Tool");
207
+ });
208
+
209
+ test("ToolVersionInfo allows undefined rawManifest", () => {
210
+ const mockVersion: ToolVersionInfo = {
211
+ name: "test/tool",
212
+ version: "1.0.0",
213
+ description: "Test tool",
214
+ license: "MIT",
215
+ yanked: false,
216
+ manifest: { enact: "2.0.0" },
217
+ // rawManifest is optional - not provided
218
+ bundle: {
219
+ hash: "sha256:abc123",
220
+ size: 1024,
221
+ downloadUrl: "https://example.com/bundle.tar.gz",
222
+ },
223
+ attestations: [],
224
+ publishedBy: { username: "testuser" },
225
+ publishedAt: new Date(),
226
+ downloads: 100,
227
+ };
228
+
229
+ expect(mockVersion.rawManifest).toBeUndefined();
230
+ });
231
+
232
+ test("enact.md content should contain frontmatter and markdown", () => {
233
+ const enactMdContent = `---
234
+ enact: 2.0.0
235
+ name: test/tool
236
+ version: 1.0.0
237
+ ---
238
+
239
+ # Test Tool
240
+
241
+ Documentation here.`;
242
+
243
+ // Verify frontmatter is present
244
+ expect(enactMdContent).toContain("---");
245
+ expect(enactMdContent).toContain("enact: 2.0.0");
246
+
247
+ // Verify markdown content
248
+ expect(enactMdContent).toContain("# Test Tool");
249
+ expect(enactMdContent).toContain("Documentation here.");
250
+ });
251
+
252
+ test("verbose option is available on get command", () => {
253
+ const program = new Command();
254
+ configureGetCommand(program);
255
+
256
+ const getCmd = program.commands.find((cmd) => cmd.name() === "get");
257
+ const opts = getCmd?.options ?? [];
258
+
259
+ // Check both short and long form exist
260
+ const verboseOpt = opts.find((o) => o.long === "--verbose");
261
+ expect(verboseOpt).toBeDefined();
262
+ expect(verboseOpt?.short).toBe("-v");
263
+ });
264
+ });
179
265
  });
@@ -161,4 +161,63 @@ command: "echo hello"
161
161
  expect(predicateType).toContain("tool");
162
162
  });
163
163
  });
164
+
165
+ describe("remote tool reference parsing", () => {
166
+ test("parses simple remote tool reference with version", () => {
167
+ const ref = "alice/greeter@1.2.0";
168
+ const atIndex = ref.lastIndexOf("@");
169
+ const name = ref.slice(0, atIndex);
170
+ const version = ref.slice(atIndex + 1);
171
+
172
+ expect(name).toBe("alice/greeter");
173
+ expect(version).toBe("1.2.0");
174
+ });
175
+
176
+ test("parses namespaced tool reference with version", () => {
177
+ const ref = "org/utils/greeter@2.0.0";
178
+ const atIndex = ref.lastIndexOf("@");
179
+ const name = ref.slice(0, atIndex);
180
+ const version = ref.slice(atIndex + 1);
181
+
182
+ expect(name).toBe("org/utils/greeter");
183
+ expect(version).toBe("2.0.0");
184
+ });
185
+
186
+ test("detects remote vs local tool reference", () => {
187
+ const isRemoteToolRef = (path: string): boolean => {
188
+ // Remote refs contain @ for version and don't start with . or /
189
+ return (
190
+ !path.startsWith(".") && !path.startsWith("/") && path.includes("@") && path.includes("/")
191
+ );
192
+ };
193
+
194
+ expect(isRemoteToolRef("alice/greeter@1.0.0")).toBe(true);
195
+ expect(isRemoteToolRef("./local-tool")).toBe(false);
196
+ expect(isRemoteToolRef("/absolute/path/tool")).toBe(false);
197
+ expect(isRemoteToolRef("examples/hello-python")).toBe(false);
198
+ });
199
+
200
+ test("requires version in remote tool reference", () => {
201
+ const hasVersion = (ref: string): boolean => {
202
+ return ref.includes("@") && ref.lastIndexOf("@") > 0;
203
+ };
204
+
205
+ expect(hasVersion("alice/greeter@1.0.0")).toBe(true);
206
+ expect(hasVersion("alice/greeter")).toBe(false);
207
+ });
208
+
209
+ test("validates semver version format", () => {
210
+ const isValidSemver = (version: string): boolean => {
211
+ const semverRegex = /^\d+\.\d+\.\d+(-[\w.]+)?(\+[\w.]+)?$/;
212
+ return semverRegex.test(version);
213
+ };
214
+
215
+ expect(isValidSemver("1.0.0")).toBe(true);
216
+ expect(isValidSemver("2.1.3")).toBe(true);
217
+ expect(isValidSemver("1.0.0-alpha")).toBe(true);
218
+ expect(isValidSemver("1.0.0-beta.1")).toBe(true);
219
+ expect(isValidSemver("invalid")).toBe(false);
220
+ expect(isValidSemver("1.0")).toBe(false);
221
+ });
222
+ });
164
223
  });