@shipworthy/openapi-validator 0.0.1 → 1.0.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 CHANGED
@@ -13,14 +13,14 @@ of calling this package.
13
13
  ## Installation
14
14
 
15
15
  ```sh
16
- bun add @shipworthy/openapi-validator effect@^4.0.0
16
+ bun add @shipworthy/openapi-validator effect@4.1.4
17
17
  ```
18
18
 
19
19
  ### Requirements
20
20
 
21
- - **Effect 4.** `effect` `^4.0.0` is a peer dependency. The public API is an Effect
22
- `Context.Service` and an Effect `Schema` error. Install a compatible version so
23
- every package shares one Effect instance.
21
+ - **Effect 4.** The package depends on `effect` `4.1.4`. The public API is an Effect
22
+ `Context.Service` and an Effect `Schema` error. Add a compatible version to your
23
+ app so every package resolves to one Effect instance.
24
24
  - **ESM only.** The package is `"type": "module"` and has no CommonJS build.
25
25
  - **Node.js `>=22.19.0` or Bun.** The package ships compiled JavaScript and `.d.ts`
26
26
  declarations in `dist/`. No TypeScript loader or bundler is needed. Its public
@@ -301,7 +301,7 @@ custom rulesets, or per-rule overrides.
301
301
  - Output goes through Effect `Console` (`error` for blocking diagnostics, `warn`
302
302
  otherwise). Color is used only on a TTY without `NO_COLOR`.
303
303
  - Requirements: ESM only, compiled JavaScript and `.d.ts` declarations in `dist/`,
304
- Node.js `>=22.19.0` or Bun, and peer dependency `effect@^4.0.0`.
304
+ Node.js `>=22.19.0` or Bun, and a dependency on `effect@4.1.4`.
305
305
  - The CLI equivalent is `openapi lint [--strict] <file-or-url>` from
306
306
  `@shipworthy/openapi-cli`.
307
307
 
package/dist/errors.d.ts CHANGED
@@ -12,7 +12,9 @@ declare const LintError_base: Schema.Class<LintError, Schema.TaggedStruct<"LintE
12
12
  readonly path: Schema.$Array<Schema.Union<readonly [Schema.String, Schema.Finite]>>;
13
13
  }>>;
14
14
  readonly cause: Schema.optional<Schema.Defect>;
15
- }>, import("effect/Cause").YieldableError>;
15
+ }>, import("effect/Cause").YieldableError & {
16
+ readonly brand: unique symbol;
17
+ }>;
16
18
  export declare class LintError extends LintError_base {
17
19
  }
18
20
  export {};
package/dist/lint.js CHANGED
@@ -3,7 +3,7 @@ import { oas3 } from "@stoplight/spectral-formats";
3
3
  // spectral-parsers is CommonJS without statically detectable named exports, so Node needs a default import.
4
4
  import spectralParsers from "@stoplight/spectral-parsers";
5
5
  import { oas } from "@stoplight/spectral-rulesets";
6
- import { Array as EffectArray, Config, Console, Context, Effect, Layer, Predicate } from "effect";
6
+ import { Array as EffectArray, Config, Console, Context, Effect, Layer, pipe, Predicate, Record, String as EffectString, } from "effect";
7
7
  import { LintError } from "./errors.js";
8
8
  /** Same TTY and `NO_COLOR` check as `CliOutput.defaultFormatter`. */
9
9
  const colorsEnabled = Effect.gen(function* () {
@@ -26,7 +26,7 @@ function spectralRules(strict) {
26
26
  };
27
27
  if (strict)
28
28
  return rules;
29
- for (const [id, rule] of Object.entries(oas.rules ?? {})) {
29
+ for (const [id, rule] of Record.toEntries(oas.rules ?? {})) {
30
30
  if (id === "operation-operationId-unique")
31
31
  continue;
32
32
  if (Predicate.isObject(rule) && "severity" in rule && rule.severity === 0) {
@@ -37,7 +37,7 @@ function spectralRules(strict) {
37
37
  }
38
38
  function isExampleRefRead(result) {
39
39
  return (result.code === "invalid-ref" &&
40
- result.message.startsWith("ReadError:") &&
40
+ EffectString.startsWith("ReadError:")(result.message) &&
41
41
  result.path.includes("examples"));
42
42
  }
43
43
  function makeSpectral(strict) {
@@ -56,7 +56,7 @@ function makeSpectral(strict) {
56
56
  function spectralTarget(source, sourceUrl) {
57
57
  if (typeof source !== "string")
58
58
  return source;
59
- if (source.trimStart().startsWith("{")) {
59
+ if (pipe(source, EffectString.trimStart, EffectString.startsWith("{"))) {
60
60
  return new Document(source, spectralParsers.Json, sourceUrl);
61
61
  }
62
62
  return new Document(source, spectralParsers.Yaml, sourceUrl);
@@ -65,7 +65,7 @@ function thrownMessage(cause) {
65
65
  return cause instanceof Error ? cause.message : String(cause);
66
66
  }
67
67
  function pathSegments(path) {
68
- return path.filter((segment) => Predicate.isString(segment) || Predicate.isNumber(segment));
68
+ return EffectArray.filter(path, (segment) => Predicate.isString(segment) || Predicate.isNumber(segment));
69
69
  }
70
70
  export class Linter extends Context.Service()("@shipworthy/openapi-validator/Linter") {
71
71
  static layer = Layer.sync(Linter, () => {
@@ -97,7 +97,9 @@ export class Linter extends Context.Service()("@shipworthy/openapi-validator/Lin
97
97
  const red = paint("31", useColors);
98
98
  const yellow = paint("33", useColors);
99
99
  const failures = yield* Effect.forEach(results, Effect.fnUntraced(function* (result) {
100
- const location = result.path.length ? ` at #/${result.path.join("/")}` : "";
100
+ const location = result.path.length
101
+ ? ` at #/${pipe(result.path, EffectArray.map((segment) => `${segment}`), EffectArray.join("/"))}`
102
+ : "";
101
103
  const message = `${result.message}${location}`;
102
104
  // Spectral's parser rejects merge tags this repo accepts, and example payloads
103
105
  // use `$ref` as data. Those diagnostics are not document errors unless strict.
@@ -115,7 +117,7 @@ export class Linter extends Context.Service()("@shipworthy/openapi-validator/Lin
115
117
  })).pipe(Effect.map(EffectArray.filter(Predicate.isNotUndefined)));
116
118
  if (failures.length > 0) {
117
119
  return yield* new LintError({
118
- message: failures.map((diagnostic) => diagnostic.message).join("\n"),
120
+ message: EffectArray.join(EffectArray.map(failures, (diagnostic) => diagnostic.message), "\n"),
119
121
  diagnostics: failures,
120
122
  });
121
123
  }
package/package.json CHANGED
@@ -1,17 +1,15 @@
1
1
  {
2
2
  "name": "@shipworthy/openapi-validator",
3
- "version": "0.0.1",
3
+ "version": "1.0.0",
4
4
  "files": [
5
5
  "dist"
6
6
  ],
7
7
  "dependencies": {
8
- "@stoplight/spectral-core": "1.24.0",
8
+ "@stoplight/spectral-core": "1.24.1",
9
9
  "@stoplight/spectral-formats": "1.9.0",
10
10
  "@stoplight/spectral-parsers": "1.0.5",
11
- "@stoplight/spectral-rulesets": "1.23.0"
12
- },
13
- "peerDependencies": {
14
- "effect": "^4.0.0"
11
+ "@stoplight/spectral-rulesets": "1.23.1",
12
+ "effect": "4.1.4"
15
13
  },
16
14
  "description": "Lint an OpenAPI document.",
17
15
  "license": "MIT",
@@ -33,12 +31,11 @@
33
31
  "build": "rm -rf dist && tsc -p tsconfig.build.json"
34
32
  },
35
33
  "devDependencies": {
36
- "@effect/vitest": "4.0.0",
34
+ "@effect/vitest": "4.1.4",
37
35
  "@shipworthy/typescript-config": "0.0.1",
38
- "@types/node": "^24.10.3",
39
- "effect": "^4.0.0",
36
+ "@types/node": "^26.6.6",
40
37
  "typescript": "^7.0.2",
41
- "vitest": "5.0.3"
38
+ "vitest": "5.1.0"
42
39
  },
43
40
  "engines": {
44
41
  "node": ">=22.19.0"