@acid-cat/cli 0.10.0 → 0.10.1

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/catalog.js CHANGED
@@ -1,9 +1,9 @@
1
1
  import catalog_schema_default from "./json/catalog.schema.json.js";
2
2
  import { isObject, isRecordOf, isStringArray } from "./json.js";
3
3
  import { canonicalText } from "@acid-cat/catalog";
4
- import { REFERENCE, bundle, eventSchemasOf, schemasOf, viewOf as viewOf$1, visitObjects } from "@acid-cat/spec-ts";
4
+ import { REFERENCE, bundle, eventSchemasOf, resolveType, schemasOf, viewOf, visitObjects } from "@acid-cat/spec-ts";
5
5
  import { Result, Schema, SchemaIssue, SchemaRepresentation } from "effect";
6
- //#region src/catalog.ts
6
+ // src/catalog.ts
7
7
  /**
8
8
  * The catalog operations that the specification defines: the catalog rules, views and bundling.
9
9
  * See spec/catalog.md and spec/conformance.md.
@@ -51,7 +51,7 @@ const decodeCatalog = (() => {
51
51
  return Schema.decodeUnknownResult(Schema.toType(schema));
52
52
  })();
53
53
  /** True if `key` is absent from the object, or if `isMember` is true for its value. */
54
- const optional = (object, key, isMember) => !(key in object) || isMember(object[key]);
54
+ const optional = (object, key, isMember) => !Object.hasOwn(object, key) || isMember(object[key]);
55
55
  const isString = (value) => typeof value === "string";
56
56
  const isTarget = (value) => isObject(value) && isStringArray(value.bindings);
57
57
  const isCapability = (value) => isObject(value) && typeof value.description === "string" && optional(value, "audience", isStringArray) && optional(value, "input", isObject) && optional(value, "output", isObject) && optional(value, "state", isObject) && optional(value, "failures", (failures) => isRecordOf(failures, isObject)) && optional(value, "readOnly", (readOnly) => typeof readOnly === "boolean");
@@ -96,13 +96,13 @@ function ruleErrors(catalog) {
96
96
  entry: event,
97
97
  schemas: eventSchemasOf(event)
98
98
  }))];
99
- for (const id of Object.keys(catalog.events ?? {})) if (id in catalog.capabilities) errors.push(`${id}: the id is both a capability and an event`);
99
+ for (const id of Object.keys(catalog.events ?? {})) if (Object.hasOwn(catalog.capabilities, id)) errors.push(`${id}: the id is both a capability and an event`);
100
100
  for (const { id, entry, schemas } of entries) {
101
- for (const target of entry.audience ?? []) if (!(target in catalog.targets)) errors.push(`${id}: the audience names ${target}, which is not a target`);
101
+ for (const target of entry.audience ?? []) if (!Object.hasOwn(catalog.targets, target)) errors.push(`${id}: the audience names ${target}, which is not a target`);
102
102
  for (const [member, schema] of schemas) {
103
103
  const references = referenceErrors(schema, types);
104
104
  errors.push(...references.map((error) => `${id} ${member} ${error}`));
105
- if ((member === "input" || member === "payload") && references.length === 0 && bundle(schema, types).type !== "object") errors.push(`${id}: the ${member} is not an object`);
105
+ if ((member === "input" || member === "payload") && references.length === 0 && resolveType(schema, types).type !== "object") errors.push(`${id}: the ${member} is not an object`);
106
106
  }
107
107
  }
108
108
  return errors;
@@ -147,15 +147,14 @@ function schemaWarnings(catalog) {
147
147
  function referenceErrors(schema, types) {
148
148
  const errors = [];
149
149
  visitObjects(schema, (node) => {
150
- if ("$defs" in node) errors.push("has its own $defs; put shared types in the catalog's $defs");
150
+ if (Object.hasOwn(node, "$defs")) errors.push("has its own $defs; put shared types in the catalog's $defs");
151
151
  if (node.$ref === void 0) return;
152
152
  const name = typeof node.$ref === "string" ? REFERENCE.exec(node.$ref)?.[1] : void 0;
153
- if (name === void 0 || !(name in types)) {
153
+ if (name === void 0 || !Object.hasOwn(types, name)) {
154
154
  const reference = typeof node.$ref === "string" ? node.$ref : JSON.stringify(node.$ref);
155
155
  errors.push(`references ${reference}, which is not a type`);
156
156
  }
157
157
  });
158
158
  return errors;
159
159
  }
160
- //#endregion
161
- export { bundle, check, isCatalog, viewOf$1 as viewOf };
160
+ export { bundle, check, isCatalog, viewOf };
@@ -1,9 +1,9 @@
1
- import { isObject } from "../json.js";
2
1
  import fixture_acidcat_default from "../json/fixture.acidcat.json.js";
2
+ import { isObject } from "../json.js";
3
3
  import { CALL_FAILURE_KINDS, isOccurrence, viewOf } from "@acid-cat/spec-ts";
4
4
  import { Schema, SchemaRepresentation } from "effect";
5
5
  import { setTimeout as setTimeout$1 } from "node:timers/promises";
6
- //#region src/conform/check.ts
6
+ // src/conform/check.ts
7
7
  /** The result of one conformance check, and helpers to write checks. */
8
8
  /** The conformance fixture: the catalog that each implementation serves. */
9
9
  const fixture = fixture_acidcat_default;
@@ -149,5 +149,4 @@ function expectEqual(actual, expected, what) {
149
149
  const sorted = (values) => [...values].sort();
150
150
  /** An origin that no deployment allows. */
151
151
  const FORBIDDEN_ORIGIN = "https://not-allowed.acid-cat.invalid";
152
- //#endregion
153
152
  export { Checks, DEADLINE, FORBIDDEN_ORIGIN, abortable, eventIdsOf, expect, expectEqual, expectOccurrence, fixture, idsOf, isOutcome, sorted, until };
@@ -6,7 +6,7 @@ import { mkdtemp, rm } from "node:fs/promises";
6
6
  import { tmpdir } from "node:os";
7
7
  import { join } from "node:path";
8
8
  import { isDeepStrictEqual } from "node:util";
9
- //#region src/conform/cli.ts
9
+ // src/conform/cli.ts
10
10
  /** Conformance checks for the CLI binding (spec/bindings/cli.md). Each check runs the command line as a process. */
11
11
  const RULE = "spec/bindings/cli.md";
12
12
  /** The `usage` of each capability in the view of the fixture, after the name of the program. */
@@ -367,5 +367,4 @@ async function checkWatch(checks, command) {
367
367
  }
368
368
  });
369
369
  }
370
- //#endregion
371
370
  export { checkCli };
@@ -2,7 +2,7 @@ import { isArrayOf, isObject, isStringArray, memberOf, parseJson, readJson } fro
2
2
  import { Checks, FORBIDDEN_ORIGIN, eventIdsOf, expect, expectEqual, expectOccurrence, idsOf, sorted, until } from "./check.js";
3
3
  import { sseReader } from "./sse.js";
4
4
  import { randomUUID } from "node:crypto";
5
- //#region src/conform/http.ts
5
+ // src/conform/http.ts
6
6
  /** Conformance checks for the HTTP binding (spec/bindings/http.md). */
7
7
  const RULE = "spec/bindings/http.md";
8
8
  const isEntry = (value) => isObject(value) && typeof value.id === "string";
@@ -310,5 +310,4 @@ async function checkEvents(checks, base) {
310
310
  }
311
311
  });
312
312
  }
313
- //#endregion
314
313
  export { checkHttp };
@@ -2,11 +2,11 @@ import { DEADLINE, fixture } from "./check.js";
2
2
  import { checkCli } from "./cli.js";
3
3
  import { checkHttp } from "./http.js";
4
4
  import { checkMcp } from "./mcp.js";
5
- import { checkProperties, httpInvoke, mcpInvoke } from "./properties.js";
6
5
  import { checkMcpStdio } from "./mcp-stdio.js";
6
+ import { checkProperties, httpInvoke, mcpInvoke } from "./properties.js";
7
7
  import { browserDriver, checkWebMcp, processDriver } from "./webmcp.js";
8
8
  import { serve } from "./serve.js";
9
- //#region src/conform/index.ts
9
+ // src/conform/index.ts
10
10
  /**
11
11
  * `acid-cat conform`: test a running implementation through its bindings (spec/conformance.md). The implementation
12
12
  * serves the conformance fixture (conformance/fixture.acidcat.json), with its switch on.
@@ -53,5 +53,4 @@ async function conform(options) {
53
53
  }
54
54
  return results;
55
55
  }
56
- //#endregion
57
56
  export { DEADLINE, conform, fixture, serve };
@@ -6,7 +6,7 @@ import { spawn } from "node:child_process";
6
6
  import { randomUUID } from "node:crypto";
7
7
  import { Client } from "@modelcontextprotocol/client";
8
8
  import { StdioClientTransport } from "@modelcontextprotocol/client/stdio";
9
- //#region src/conform/mcp-stdio.ts
9
+ // src/conform/mcp-stdio.ts
10
10
  /**
11
11
  * Conformance checks for the MCP binding through standard input and standard output (spec/bindings/mcp.md#stdio). Each
12
12
  * check starts the server as a process. The protocol checks use the official MCP client, once with revision 2026-07-28
@@ -328,5 +328,4 @@ async function checkLines(command, options) {
328
328
  }));
329
329
  return checks;
330
330
  }
331
- //#endregion
332
331
  export { checkMcpStdio };
@@ -1,12 +1,12 @@
1
1
  import { isArrayOf, isObject, isStringArray, memberOf, parseJson, readJson } from "../json.js";
2
2
  import { Checks, FORBIDDEN_ORIGIN, eventIdsOf, expect, expectEqual, expectOccurrence, fixture, idsOf, sorted, until } from "./check.js";
3
- import { sseReader } from "./sse.js";
4
3
  import { checkPoll } from "./poll.js";
4
+ import { sseReader } from "./sse.js";
5
5
  import { checkWebhook } from "./webhook.js";
6
6
  import { MCP_EVENTS_EXTENSION, MCP_SUBSCRIPTION_ID } from "@acid-cat/spec-ts";
7
7
  import { randomUUID } from "node:crypto";
8
8
  import { Client, StreamableHTTPClientTransport } from "@modelcontextprotocol/client";
9
- //#region src/conform/mcp.ts
9
+ // src/conform/mcp.ts
10
10
  /**
11
11
  * Conformance checks for the MCP binding through HTTP (spec/bindings/mcp.md). The protocol checks use the official MCP
12
12
  * client with revision 2026-07-28. With `handshake`, they run again with the `initialize` handshake of revision
@@ -602,5 +602,4 @@ async function checkEvents(checks, channel, options) {
602
602
  }
603
603
  });
604
604
  }
605
- //#endregion
606
605
  export { EVENTS_REVISION, META, checkEvents, checkMcp, checkTools, count, eventRequests, httpChannel, mcpClient, subscriptionOf };
@@ -2,7 +2,7 @@ import { isArrayOf, isObject, memberOf } from "../json.js";
2
2
  import { expect, expectEqual, expectOccurrence, until } from "./check.js";
3
3
  import { eventRequests } from "./mcp.js";
4
4
  import { randomUUID } from "node:crypto";
5
- //#region src/conform/poll.ts
5
+ // src/conform/poll.ts
6
6
  /**
7
7
  * Conformance checks for poll delivery of the MCP events extension (spec/bindings/mcp.md#poll), through a channel. Each
8
8
  * transport runs them. The checks read the state of a lease only through `events/poll` and `fixture.watching`, and wait
@@ -285,5 +285,4 @@ async function checkPoll(checks, channel, settings) {
285
285
  });
286
286
  }
287
287
  }
288
- //#endregion
289
288
  export { checkPoll };
@@ -4,7 +4,7 @@ import { mcpClient } from "./mcp.js";
4
4
  import { randomUUID } from "node:crypto";
5
5
  import { SdkError } from "@modelcontextprotocol/client";
6
6
  import fc from "fast-check";
7
- //#region src/conform/properties.ts
7
+ // src/conform/properties.ts
8
8
  /**
9
9
  * Property-based checks for the guarantees of spec/invocation.md#cancellation-and-concurrency, through each remote
10
10
  * binding. fast-check makes random sets of concurrent calls and cancellations.
@@ -170,5 +170,4 @@ async function checkProperties(binding, invoke, deadline) {
170
170
  });
171
171
  return checks;
172
172
  }
173
- //#endregion
174
173
  export { checkProperties, clientInvoke, heldKeys, httpInvoke, mcpInvoke };
@@ -1,5 +1,5 @@
1
1
  import { createServer } from "node:http";
2
- //#region src/conform/serve.ts
2
+ // src/conform/serve.ts
3
3
  /**
4
4
  * Serve a web request handler, `(request: Request) => Promise<Response>`, on a local port. Implementations use it
5
5
  * to run `acid-cat conform` against their bindings in a test.
@@ -99,5 +99,4 @@ function bodyOf(incoming) {
99
99
  }
100
100
  }, { highWaterMark: 0 });
101
101
  }
102
- //#endregion
103
102
  export { serve };
@@ -1,4 +1,4 @@
1
- //#region src/conform/sse.ts
1
+ // src/conform/sse.ts
2
2
  /**
3
3
  * Read the messages of a response one at a time. `next` skips comment lines, and resolves with `undefined` at the end of
4
4
  * the stream. When the signal of the request aborts, `next` rejects.
@@ -53,5 +53,4 @@ function parse(raw) {
53
53
  data: fields.data.join("\n")
54
54
  };
55
55
  }
56
- //#endregion
57
56
  export { sseReader };
@@ -4,7 +4,7 @@ import { count, eventRequests, httpChannel } from "./mcp.js";
4
4
  import { MCP_WEBHOOK_DEFAULTS, isOccurrence, webhookSignature, webhookSubscriptionId } from "@acid-cat/spec-ts";
5
5
  import { randomBytes, randomUUID } from "node:crypto";
6
6
  import { createServer } from "node:https";
7
- //#region src/conform/webhook.ts
7
+ // src/conform/webhook.ts
8
8
  /**
9
9
  * Conformance checks for webhook delivery of the MCP events extension (spec/bindings/mcp.md#webhook), through HTTP.
10
10
  * conform runs an HTTPS receiver on 127.0.0.1 with the certificate that it gets. The deployment under test must trust
@@ -471,5 +471,4 @@ async function checkWithReceiver(checks, url, settings, receiver) {
471
471
  });
472
472
  }
473
473
  }
474
- //#endregion
475
474
  export { checkWebhook };
@@ -1,7 +1,7 @@
1
1
  import { isArrayOf, isObject, isStringArray, memberOf, parseJson } from "../json.js";
2
2
  import { Checks, abortable, expect, expectEqual, fixture, idsOf, sorted, until } from "./check.js";
3
3
  import { REFERENCE, visitObjects } from "@acid-cat/spec-ts";
4
- //#region src/conform/webmcp.ts
4
+ // src/conform/webmcp.ts
5
5
  /**
6
6
  * Conformance checks for the WebMCP binding (spec/bindings/webmcp.md).
7
7
  *
@@ -152,7 +152,7 @@ function isBundled(schema) {
152
152
  visitObjects(schema, (node) => {
153
153
  if (typeof node.$ref !== "string") return;
154
154
  const name = REFERENCE.exec(node.$ref)?.[1];
155
- if (name === void 0 || !(name in types)) bundled = false;
155
+ if (name === void 0 || !Object.hasOwn(types, name)) bundled = false;
156
156
  });
157
157
  return bundled;
158
158
  }
@@ -249,5 +249,4 @@ async function checkWebMcp(driver, options) {
249
249
  });
250
250
  return checks;
251
251
  }
252
- //#endregion
253
252
  export { browserDriver, checkWebMcp, createTestHost, processDriver };
@@ -1,4 +1,4 @@
1
- //#region ../../schemas/catalog.schema.json
1
+ // ../../schemas/catalog.schema.json
2
2
  var catalog_schema_default = {
3
3
  $schema: "https://json-schema.org/draft/2020-12/schema",
4
4
  $id: "https://acid-cat.dev/schemas/0.1/catalog.schema.json",
@@ -137,5 +137,4 @@ var catalog_schema_default = {
137
137
  }
138
138
  }
139
139
  };
140
- //#endregion
141
140
  export { catalog_schema_default as default };
@@ -1,4 +1,4 @@
1
- //#region conformance/fixture.acidcat.json
1
+ // conformance/fixture.acidcat.json
2
2
  var fixture_acidcat_default = {
3
3
  acidcat: "0.1",
4
4
  title: "AcidCat conformance fixture",
@@ -312,5 +312,4 @@ var fixture_acidcat_default = {
312
312
  }
313
313
  }
314
314
  };
315
- //#endregion
316
315
  export { fixture_acidcat_default as default };
@@ -1,4 +1,3 @@
1
- //#region package.json
2
- var version = "0.10.0";
3
- //#endregion
1
+ // package.json
2
+ var version = "0.10.1";
4
3
  export { version };
package/dist/json.js CHANGED
@@ -1,4 +1,4 @@
1
- //#region src/json.ts
1
+ // src/json.ts
2
2
  /** True if the value is a JSON object: not `null`, and not an array. */
3
3
  const isObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
4
4
  /** True if the value is an array of strings. */
@@ -17,5 +17,4 @@ async function readJson(response) {
17
17
  }
18
18
  /** True if the value is an array, and `isItem` is true for each of its items. */
19
19
  const isArrayOf = (value, isItem) => Array.isArray(value) && value.every(isItem);
20
- //#endregion
21
20
  export { isArrayOf, isObject, isRecordOf, isStringArray, memberOf, parseJson, readJson };
package/dist/main.js CHANGED
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
- import { parseJson } from "./json.js";
2
+ import { version } from "./json/package.json.js";
3
3
  import { check, isCatalog, viewOf } from "./catalog.js";
4
4
  import { DEADLINE } from "./conform/check.js";
5
5
  import { conform } from "./conform/index.js";
6
- import { version } from "./json/package.json.js";
6
+ import { parseJson } from "./json.js";
7
7
  import { canonicalText } from "@acid-cat/catalog";
8
8
  import { Console, Effect, FileSystem, Option } from "effect";
9
9
  import { NodeRuntime, NodeServices } from "@effect/platform-node";
10
10
  import { Argument, Command, Flag } from "effect/cli";
11
- //#region src/main.ts
11
+ // src/main.ts
12
12
  /**
13
13
  * `acid-cat`: check, format and view AcidCat catalogs.
14
14
  *
@@ -61,7 +61,7 @@ const viewCommand = Command.make("view", {
61
61
  yield* Console.error(`${file}: error: the file is not a catalog; run \`acid-cat check ${file}\``);
62
62
  return yield* fail;
63
63
  }
64
- if (!(target in catalog.targets)) {
64
+ if (!Object.hasOwn(catalog.targets, target)) {
65
65
  yield* Console.error(`${file}: error: there is no target ${target}`);
66
66
  return yield* fail;
67
67
  }
@@ -150,5 +150,4 @@ Command.make("acid-cat").pipe(Command.withDescription("Check, format and view Ac
150
150
  viewCommand,
151
151
  conformCommand
152
152
  ])).pipe(Command.run({ version }), Effect.provide(NodeServices.layer), NodeRuntime.runMain);
153
- //#endregion
154
153
  export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@acid-cat/cli",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "description": "The AcidCat command line: check, format and view catalogs, and test implementations.",
5
5
  "keywords": [
6
6
  "acidcat",
@@ -37,12 +37,12 @@
37
37
  "access": "public"
38
38
  },
39
39
  "dependencies": {
40
- "@acid-cat/catalog": "0.10.0",
41
- "@acid-cat/spec-ts": "0.10.0",
42
- "@effect/platform-node": "^4.1.1",
43
- "@effect/platform-node-shared": "^4.1.1",
44
- "@modelcontextprotocol/client": "2.3.1",
45
- "effect": "^4.1.1",
40
+ "@acid-cat/catalog": "0.10.1",
41
+ "@acid-cat/spec-ts": "0.10.1",
42
+ "@effect/platform-node": "^4.1.3",
43
+ "@effect/platform-node-shared": "^4.1.3",
44
+ "@modelcontextprotocol/client": "2.4.0",
45
+ "effect": "^4.1.3",
46
46
  "fast-check": "4.10.2"
47
47
  },
48
48
  "peerDependencies": {
@@ -54,8 +54,8 @@
54
54
  }
55
55
  },
56
56
  "devDependencies": {
57
- "@types/node": "26.6.5",
58
- "playwright": "1.64.0",
57
+ "@types/node": "26.6.6",
58
+ "playwright": "1.65.0",
59
59
  "typescript": "7.0.2"
60
60
  }
61
61
  }