@opsydyn/elysia-spectral 0.5.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/CHANGELOG.md +18 -0
- package/README.md +204 -51
- package/dist/core/index.d.mts +2 -2
- package/dist/core/index.mjs +2 -2
- package/dist/{core-DTKNy6TU.mjs → core-BIi33eA1.mjs} +15 -2
- package/dist/{index-B4fxn0G6.d.mts → index--_yjTKg8.d.mts} +3 -2
- package/dist/index.d.mts +2 -2
- package/dist/index.mjs +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,23 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [1.0.0](https://github.com/opsydyn/elysia-spectral/compare/v0.5.2...v1.0.0) (2026-04-15)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### ⚠ BREAKING CHANGES
|
|
7
|
+
|
|
8
|
+
* result.artifacts paths are now relative (e.g. "./artifacts/openapi-lint.json") rather than absolute. Callers that used the path directly to open the file should resolve it with path.resolve().
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
* add durationMs, failOn to LintRunResult; relativise artifact paths ([421a20f](https://github.com/opsydyn/elysia-spectral/commit/421a20f6bf655432bceff8369c63bf4762edbc24))
|
|
13
|
+
|
|
14
|
+
## [0.5.2](https://github.com/opsydyn/elysia-spectral/compare/v0.5.1...v0.5.2) (2026-04-15)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
### Bug Fixes
|
|
18
|
+
|
|
19
|
+
* replace export * with named exports in core/index.ts for stable public API ([d0ef1c9](https://github.com/opsydyn/elysia-spectral/commit/d0ef1c95618ecd5a83e8224f2ba831b226a7ab38))
|
|
20
|
+
|
|
3
21
|
## [0.5.1](https://github.com/opsydyn/elysia-spectral/compare/v0.5.0...v0.5.1) (2026-04-15)
|
|
4
22
|
|
|
5
23
|
|
package/README.md
CHANGED
|
@@ -63,6 +63,35 @@ Current package scope:
|
|
|
63
63
|
- reusable runtime for CI and tests
|
|
64
64
|
- opt-in healthcheck endpoint for cached and fresh runs
|
|
65
65
|
|
|
66
|
+
## Data flow
|
|
67
|
+
|
|
68
|
+
```mermaid
|
|
69
|
+
flowchart TD
|
|
70
|
+
A["Elysia routes\n(TypeScript + t.Object schemas)"]
|
|
71
|
+
B["@elysiajs/openapi\ngenerates OpenAPI spec at runtime"]
|
|
72
|
+
C["PublicSpecProvider\nfetches /openapi/json"]
|
|
73
|
+
D["lintOpenApi\nSpectral rules engine"]
|
|
74
|
+
E["LintRunResult\n{ ok, source, summary, findings }"]
|
|
75
|
+
|
|
76
|
+
F["Console output"]
|
|
77
|
+
G["JSON report\nopenapi-lint.json"]
|
|
78
|
+
H["OpenAPI snapshot\n*.open-api.json"]
|
|
79
|
+
I["SARIF\nGitHub code scanning"]
|
|
80
|
+
J["JUnit\nCI test reporters"]
|
|
81
|
+
K["Bruno collection\n.yml / .json"]
|
|
82
|
+
|
|
83
|
+
A -->|"route schemas are\nthe source of truth"| B
|
|
84
|
+
B -->|"spec JSON"| C
|
|
85
|
+
C -->|"spec JSON"| D
|
|
86
|
+
D -->|"findings + summary"| E
|
|
87
|
+
E --> F
|
|
88
|
+
E --> G
|
|
89
|
+
E --> H
|
|
90
|
+
E --> I
|
|
91
|
+
E --> J
|
|
92
|
+
E --> K
|
|
93
|
+
```
|
|
94
|
+
|
|
66
95
|
## Tutorial
|
|
67
96
|
|
|
68
97
|
### Add OpenAPI linting to an Elysia app
|
|
@@ -153,6 +182,10 @@ bun run src/index.ts
|
|
|
153
182
|
- `./artifacts/openapi-lint.json` contains the full lint result
|
|
154
183
|
- `./<package-name>.open-api.json` contains the generated OpenAPI snapshot
|
|
155
184
|
|
|
185
|
+
A passing run:
|
|
186
|
+
|
|
187
|
+

|
|
188
|
+
|
|
156
189
|
If startup fails, the terminal output includes:
|
|
157
190
|
|
|
158
191
|
- the failing rule code
|
|
@@ -160,6 +193,8 @@ If startup fails, the terminal output includes:
|
|
|
160
193
|
- a fix hint when one is known
|
|
161
194
|
- a spec reference in `open-api.json#/json/pointer` form
|
|
162
195
|
|
|
196
|
+

|
|
197
|
+
|
|
163
198
|
### Choose a preset
|
|
164
199
|
|
|
165
200
|
Three first-party presets are available. Import them directly or set `preset` in the plugin options.
|
|
@@ -565,17 +600,19 @@ git commit -m "chore: add openapi snapshot"
|
|
|
565
600
|
|
|
566
601
|
If the snapshot has changed, the CI step fails and the diff is visible in the logs. Deliberate API changes are acknowledged by updating the committed snapshot — accidental ones are caught before they ship.
|
|
567
602
|
|
|
568
|
-
### Generate a typed client
|
|
603
|
+
### Generate a typed client
|
|
569
604
|
|
|
570
|
-
|
|
605
|
+
**If your consumer is a TypeScript project that can import from your Elysia app, use [Eden Treaty](https://elysiajs.com/eden/treaty/overview) instead.** It derives types directly from the app instance with no codegen, no snapshot, and no drift.
|
|
571
606
|
|
|
572
|
-
|
|
607
|
+
```ts
|
|
608
|
+
import { treaty } from '@elysiajs/eden'
|
|
609
|
+
import type { App } from '../server'
|
|
573
610
|
|
|
574
|
-
|
|
575
|
-
|
|
611
|
+
const client = treaty<App>('localhost:3000')
|
|
612
|
+
// fully typed — zero codegen
|
|
576
613
|
```
|
|
577
614
|
|
|
578
|
-
|
|
615
|
+
For vendor-agnostic consumers — cross-repo TypeScript, non-TypeScript clients, or a published SDK — use the committed OpenAPI snapshot as input to [`openapi-ts`](https://openapi-ts.dev):
|
|
579
616
|
|
|
580
617
|
```json
|
|
581
618
|
{
|
|
@@ -585,7 +622,7 @@ bun add -d @hey-api/openapi-ts
|
|
|
585
622
|
}
|
|
586
623
|
```
|
|
587
624
|
|
|
588
|
-
|
|
625
|
+
Chain it after the lint step in CI and guard against drift:
|
|
589
626
|
|
|
590
627
|
```yaml
|
|
591
628
|
- name: Lint OpenAPI spec
|
|
@@ -598,7 +635,7 @@ bun add -d @hey-api/openapi-ts
|
|
|
598
635
|
run: git diff --exit-code src/generated/client/
|
|
599
636
|
```
|
|
600
637
|
|
|
601
|
-
The lint gate runs first — if the spec is invalid the codegen step never runs.
|
|
638
|
+
The lint gate runs first — if the spec is invalid the codegen step never runs.
|
|
602
639
|
|
|
603
640
|
### Work on this repository locally
|
|
604
641
|
|
|
@@ -630,66 +667,38 @@ That example uses `startup.mode: 'report'`, so the app still boots while the pac
|
|
|
630
667
|
### Package API
|
|
631
668
|
|
|
632
669
|
```ts
|
|
633
|
-
|
|
670
|
+
// ── Vocabulary types ──────────────────────────────────────────────────────────
|
|
634
671
|
|
|
672
|
+
type PresetName = 'recommended' | 'server' | 'strict'
|
|
673
|
+
type LintSeverity = 'error' | 'warn' | 'info' | 'hint'
|
|
635
674
|
type SeverityThreshold = 'error' | 'warn' | 'info' | 'hint' | 'never'
|
|
636
|
-
|
|
637
675
|
type StartupLintMode = 'enforce' | 'report' | 'off'
|
|
638
|
-
|
|
676
|
+
type LintRunSource = 'startup' | 'healthcheck' | 'manual'
|
|
639
677
|
type ArtifactWriteFailureMode = 'warn' | 'error'
|
|
678
|
+
type OpenApiLintRuntimeStatus = 'idle' | 'running' | 'passed' | 'failed'
|
|
640
679
|
|
|
641
|
-
|
|
642
|
-
jsonReportPath?: string
|
|
643
|
-
junitReportPath?: string
|
|
644
|
-
sarifReportPath?: string
|
|
645
|
-
specSnapshotPath?: string
|
|
646
|
-
brunoCollectionPath?: string
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
type OpenApiLintSink = {
|
|
650
|
-
name: string
|
|
651
|
-
write: (
|
|
652
|
-
result: LintRunResult,
|
|
653
|
-
context: {
|
|
654
|
-
spec: Record<string, unknown>
|
|
655
|
-
logger: SpectralLogger
|
|
656
|
-
}
|
|
657
|
-
) => undefined | Partial<OpenApiLintArtifacts> | Promise<undefined | Partial<OpenApiLintArtifacts>>
|
|
658
|
-
}
|
|
659
|
-
|
|
660
|
-
type RulesetResolver = (
|
|
661
|
-
input: string | RulesetDefinition | Record<string, unknown> | undefined,
|
|
662
|
-
context: {
|
|
663
|
-
baseDir: string
|
|
664
|
-
defaultRuleset: RulesetDefinition
|
|
665
|
-
mergeAutodiscoveredWithDefault: boolean
|
|
666
|
-
}
|
|
667
|
-
) => Promise<LoadedRuleset | undefined>
|
|
668
|
-
|
|
669
|
-
type LoadResolvedRulesetOptions = {
|
|
670
|
-
baseDir?: string
|
|
671
|
-
resolvers?: RulesetResolver[]
|
|
672
|
-
mergeAutodiscoveredWithDefault?: boolean
|
|
673
|
-
/** Override the base ruleset used for autodiscovery merging and the fallback when no ruleset is configured. */
|
|
674
|
-
defaultRuleset?: RulesetDefinition
|
|
675
|
-
}
|
|
680
|
+
// ── Plugin options ────────────────────────────────────────────────────────────
|
|
676
681
|
|
|
677
682
|
type SpectralPluginOptions = {
|
|
678
683
|
/** First-party governance preset. Sets the base ruleset and autodiscovery merge target. */
|
|
679
684
|
preset?: PresetName
|
|
680
685
|
/** Custom ruleset path, object, or inline definition. Merged on top of preset when both are set. */
|
|
681
686
|
ruleset?: string | RulesetDefinition | Record<string, unknown>
|
|
687
|
+
/** Severity level at which the lint run is considered failed. Defaults to 'error'. */
|
|
682
688
|
failOn?: SeverityThreshold
|
|
683
689
|
healthcheck?: false | { path?: string }
|
|
684
690
|
output?: {
|
|
691
|
+
/** Print findings to the console. Default: true. */
|
|
685
692
|
console?: boolean
|
|
686
693
|
jsonReportPath?: string
|
|
687
694
|
junitReportPath?: string
|
|
688
695
|
sarifReportPath?: string
|
|
696
|
+
/** true derives the path from the consuming app's package name. */
|
|
689
697
|
specSnapshotPath?: string | true
|
|
690
698
|
/** .yml/.yaml → OpenCollection YAML (Bruno v3+), .json → Bruno collection JSON */
|
|
691
699
|
brunoCollectionPath?: string
|
|
692
700
|
pretty?: boolean
|
|
701
|
+
/** Whether artifact write failures throw or warn. Default: 'warn'. */
|
|
693
702
|
artifactWriteFailures?: ArtifactWriteFailureMode
|
|
694
703
|
sinks?: OpenApiLintSink[]
|
|
695
704
|
}
|
|
@@ -697,16 +706,160 @@ type SpectralPluginOptions = {
|
|
|
697
706
|
specPath?: string
|
|
698
707
|
baseUrl?: string
|
|
699
708
|
}
|
|
700
|
-
|
|
709
|
+
/**
|
|
710
|
+
* Controls startup lint behaviour.
|
|
711
|
+
* startup.mode takes precedence over the legacy enabled option.
|
|
712
|
+
* 'enforce' — lint runs at startup and throws on threshold failure (default)
|
|
713
|
+
* 'report' — lint runs at startup, prints findings, but never blocks boot
|
|
714
|
+
* 'off' — startup lint is skipped entirely
|
|
715
|
+
*/
|
|
701
716
|
startup?: {
|
|
702
717
|
mode?: StartupLintMode
|
|
703
718
|
}
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
719
|
+
/**
|
|
720
|
+
* Legacy enable flag. Prefer startup.mode for new code.
|
|
721
|
+
* false or () => false is equivalent to startup.mode: 'off'.
|
|
722
|
+
* The function form receives process.env for environment-based toggling.
|
|
723
|
+
*/
|
|
724
|
+
enabled?: boolean | ((env: Record<string, string | undefined>) => boolean)
|
|
725
|
+
logger?: SpectralLogger
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
// ── Result types ──────────────────────────────────────────────────────────────
|
|
729
|
+
|
|
730
|
+
type LintFinding = {
|
|
731
|
+
code: string
|
|
732
|
+
message: string
|
|
733
|
+
severity: LintSeverity
|
|
734
|
+
path: Array<string | number>
|
|
735
|
+
documentPointer?: string
|
|
736
|
+
recommendation?: string
|
|
737
|
+
source?: string
|
|
738
|
+
range?: {
|
|
739
|
+
start?: { line: number; character: number }
|
|
740
|
+
end?: { line: number; character: number }
|
|
741
|
+
}
|
|
742
|
+
operation?: {
|
|
743
|
+
method?: string
|
|
744
|
+
path?: string
|
|
745
|
+
operationId?: string
|
|
708
746
|
}
|
|
709
747
|
}
|
|
748
|
+
|
|
749
|
+
type LintRunResult = {
|
|
750
|
+
/** True when no findings meet or exceed the configured failOn threshold. */
|
|
751
|
+
ok: boolean
|
|
752
|
+
generatedAt: string
|
|
753
|
+
/** Where the lint run was triggered from. */
|
|
754
|
+
source: LintRunSource
|
|
755
|
+
summary: {
|
|
756
|
+
error: number
|
|
757
|
+
warn: number
|
|
758
|
+
info: number
|
|
759
|
+
hint: number
|
|
760
|
+
total: number
|
|
761
|
+
}
|
|
762
|
+
artifacts?: OpenApiLintArtifacts
|
|
763
|
+
findings: LintFinding[]
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
type OpenApiLintArtifacts = {
|
|
767
|
+
jsonReportPath?: string
|
|
768
|
+
junitReportPath?: string
|
|
769
|
+
sarifReportPath?: string
|
|
770
|
+
specSnapshotPath?: string
|
|
771
|
+
brunoCollectionPath?: string
|
|
772
|
+
}
|
|
773
|
+
|
|
774
|
+
type OpenApiLintRuntimeFailure = {
|
|
775
|
+
name: string
|
|
776
|
+
message: string
|
|
777
|
+
generatedAt: string
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
// ── Runtime ───────────────────────────────────────────────────────────────────
|
|
781
|
+
|
|
782
|
+
type OpenApiLintRuntime = {
|
|
783
|
+
status: OpenApiLintRuntimeStatus
|
|
784
|
+
startedAt: string | null
|
|
785
|
+
completedAt: string | null
|
|
786
|
+
durationMs: number | null
|
|
787
|
+
latest: LintRunResult | null
|
|
788
|
+
lastSuccess: LintRunResult | null
|
|
789
|
+
lastFailure: OpenApiLintRuntimeFailure | null
|
|
790
|
+
running: boolean
|
|
791
|
+
run: (app: AnyElysia, source?: LintRunSource) => Promise<LintRunResult>
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
function createOpenApiLintRuntime(options?: SpectralPluginOptions): OpenApiLintRuntime
|
|
795
|
+
|
|
796
|
+
// ── Extension points (advanced) ───────────────────────────────────────────────
|
|
797
|
+
|
|
798
|
+
type SpectralLogger = {
|
|
799
|
+
info: (message: string) => void
|
|
800
|
+
warn: (message: string) => void
|
|
801
|
+
error: (message: string) => void
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
type OpenApiLintSinkContext = {
|
|
805
|
+
spec: Record<string, unknown>
|
|
806
|
+
logger: SpectralLogger
|
|
807
|
+
}
|
|
808
|
+
|
|
809
|
+
type OpenApiLintSink = {
|
|
810
|
+
name: string
|
|
811
|
+
write: (
|
|
812
|
+
result: LintRunResult,
|
|
813
|
+
context: OpenApiLintSinkContext,
|
|
814
|
+
) => undefined | Partial<OpenApiLintArtifacts> | Promise<undefined | Partial<OpenApiLintArtifacts>>
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
type RulesetResolver = (
|
|
818
|
+
input: string | RulesetDefinition | Record<string, unknown> | undefined,
|
|
819
|
+
context: RulesetResolverContext,
|
|
820
|
+
) => Promise<ResolvedRulesetCandidate | undefined>
|
|
821
|
+
|
|
822
|
+
type RulesetResolverContext = {
|
|
823
|
+
baseDir: string
|
|
824
|
+
defaultRuleset: RulesetDefinition
|
|
825
|
+
mergeAutodiscoveredWithDefault: boolean
|
|
826
|
+
}
|
|
827
|
+
|
|
828
|
+
type ResolvedRulesetCandidate = {
|
|
829
|
+
ruleset: unknown
|
|
830
|
+
source?: LoadedRuleset['source']
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
type LoadedRuleset = {
|
|
834
|
+
ruleset: RulesetDefinition
|
|
835
|
+
source?: {
|
|
836
|
+
path: string
|
|
837
|
+
autodiscovered: boolean
|
|
838
|
+
mergedWithDefault: boolean
|
|
839
|
+
}
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
type LoadResolvedRulesetOptions = {
|
|
843
|
+
baseDir?: string
|
|
844
|
+
resolvers?: RulesetResolver[]
|
|
845
|
+
mergeAutodiscoveredWithDefault?: boolean
|
|
846
|
+
/** Override the base ruleset used for autodiscovery merging and the fallback when no ruleset is configured. */
|
|
847
|
+
defaultRuleset?: RulesetDefinition
|
|
848
|
+
}
|
|
849
|
+
|
|
850
|
+
// ── Error classes ─────────────────────────────────────────────────────────────
|
|
851
|
+
|
|
852
|
+
class OpenApiLintThresholdError extends Error {
|
|
853
|
+
readonly threshold: SeverityThreshold
|
|
854
|
+
readonly result: LintRunResult
|
|
855
|
+
}
|
|
856
|
+
|
|
857
|
+
class OpenApiLintArtifactWriteError extends Error {
|
|
858
|
+
readonly artifact: string
|
|
859
|
+
readonly cause: unknown
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
class RulesetLoadError extends Error {}
|
|
710
863
|
```
|
|
711
864
|
|
|
712
865
|
### Presets
|
package/dist/core/index.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { LoadResolvedRulesetOptions, LoadedRuleset, OpenApiLintArtifactWriteError, OpenApiLintThresholdError, ResolvedRulesetCandidate, RulesetLoadError, RulesetResolver, RulesetResolverContext, RulesetResolverInput, createOpenApiLintRuntime, defaultRulesetResolvers, enforceThreshold, lintOpenApi, loadResolvedRuleset, loadRuleset,
|
|
1
|
+
import { a as createOpenApiLintRuntime, c as ResolvedRulesetCandidate, d as RulesetResolverContext, f as RulesetResolverInput, g as lintOpenApi, h as loadRuleset, i as OpenApiLintArtifactWriteError, l as RulesetLoadError, m as loadResolvedRuleset, n as enforceThreshold, o as LoadResolvedRulesetOptions, p as defaultRulesetResolvers, r as shouldFail, s as LoadedRuleset, t as OpenApiLintThresholdError, u as RulesetResolver } from "../index--_yjTKg8.mjs";
|
|
2
|
+
export { LoadResolvedRulesetOptions, LoadedRuleset, OpenApiLintArtifactWriteError, OpenApiLintThresholdError, ResolvedRulesetCandidate, RulesetLoadError, RulesetResolver, RulesetResolverContext, RulesetResolverInput, createOpenApiLintRuntime, defaultRulesetResolvers, enforceThreshold, lintOpenApi, loadResolvedRuleset, loadRuleset, shouldFail };
|
package/dist/core/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as enforceThreshold, d as RulesetLoadError, f as defaultRulesetResolvers, g as lintOpenApi, i as OpenApiLintThresholdError, m as loadRuleset, n as createOpenApiLintRuntime, o as shouldFail, p as loadResolvedRuleset,
|
|
2
|
-
export { OpenApiLintArtifactWriteError, OpenApiLintThresholdError, RulesetLoadError, createOpenApiLintRuntime, defaultRulesetResolvers, enforceThreshold, lintOpenApi, loadResolvedRuleset, loadRuleset,
|
|
1
|
+
import { a as enforceThreshold, d as RulesetLoadError, f as defaultRulesetResolvers, g as lintOpenApi, i as OpenApiLintThresholdError, m as loadRuleset, n as createOpenApiLintRuntime, o as shouldFail, p as loadResolvedRuleset, t as OpenApiLintArtifactWriteError } from "../core-BIi33eA1.mjs";
|
|
2
|
+
export { OpenApiLintArtifactWriteError, OpenApiLintThresholdError, RulesetLoadError, createOpenApiLintRuntime, defaultRulesetResolvers, enforceThreshold, lintOpenApi, loadResolvedRuleset, loadRuleset, shouldFail };
|
|
@@ -55,6 +55,8 @@ const normalizeFindings = (diagnostics, spec) => {
|
|
|
55
55
|
ok: summary.error === 0,
|
|
56
56
|
generatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
57
57
|
source: "manual",
|
|
58
|
+
failOn: "error",
|
|
59
|
+
durationMs: null,
|
|
58
60
|
summary,
|
|
59
61
|
findings
|
|
60
62
|
};
|
|
@@ -1198,7 +1200,8 @@ const createOpenApiLintRuntime = (options = {}) => {
|
|
|
1198
1200
|
else if (loadedRuleset.source?.path) reporter.ruleset(`OpenAPI lint loaded ruleset ${loadedRuleset.source.path}.`);
|
|
1199
1201
|
const result = await lintOpenApi(spec, loadedRuleset.ruleset);
|
|
1200
1202
|
result.source = source;
|
|
1201
|
-
result.
|
|
1203
|
+
result.failOn = options.failOn ?? "error";
|
|
1204
|
+
result.ok = !shouldFail(result, result.failOn);
|
|
1202
1205
|
await writeOutputSinks(result, spec, options, artifactWriteFailureMode);
|
|
1203
1206
|
runtime.latest = result;
|
|
1204
1207
|
reporter.complete("OpenAPI lint completed.");
|
|
@@ -1206,6 +1209,7 @@ const createOpenApiLintRuntime = (options = {}) => {
|
|
|
1206
1209
|
runtime.status = "passed";
|
|
1207
1210
|
runtime.lastSuccess = result;
|
|
1208
1211
|
finalizeRuntimeRun(runtime, startedAt);
|
|
1212
|
+
result.durationMs = runtime.durationMs;
|
|
1209
1213
|
return result;
|
|
1210
1214
|
} catch (error) {
|
|
1211
1215
|
runtime.status = "failed";
|
|
@@ -1264,9 +1268,18 @@ const writeOutputSinks = async (result, spec, options, artifactWriteFailureMode)
|
|
|
1264
1268
|
throw error;
|
|
1265
1269
|
}
|
|
1266
1270
|
};
|
|
1271
|
+
const relativiseArtifacts = (artifacts) => {
|
|
1272
|
+
const cwd = process.cwd();
|
|
1273
|
+
const result = {};
|
|
1274
|
+
for (const [key, value] of Object.entries(artifacts)) if (typeof value === "string" && path.isAbsolute(value)) {
|
|
1275
|
+
const rel = path.relative(cwd, value);
|
|
1276
|
+
result[key] = rel.startsWith(".") ? rel : `./${rel}`;
|
|
1277
|
+
} else result[key] = value;
|
|
1278
|
+
return result;
|
|
1279
|
+
};
|
|
1267
1280
|
const mergeArtifacts = (current, next) => ({
|
|
1268
1281
|
...current,
|
|
1269
|
-
...next
|
|
1282
|
+
...relativiseArtifacts(next)
|
|
1270
1283
|
});
|
|
1271
1284
|
const resolveStartupMode = (options = {}) => {
|
|
1272
1285
|
if (options.startup?.mode) return options.startup.mode;
|
|
@@ -85,6 +85,8 @@ type LintRunResult = {
|
|
|
85
85
|
ok: boolean;
|
|
86
86
|
generatedAt: string;
|
|
87
87
|
source: LintRunSource;
|
|
88
|
+
failOn: SeverityThreshold;
|
|
89
|
+
durationMs: number | null;
|
|
88
90
|
summary: {
|
|
89
91
|
error: number;
|
|
90
92
|
warn: number;
|
|
@@ -157,7 +159,6 @@ declare class OpenApiLintArtifactWriteError extends Error {
|
|
|
157
159
|
readonly cause: unknown;
|
|
158
160
|
constructor(artifact: string, cause: unknown);
|
|
159
161
|
}
|
|
160
|
-
declare const resolveStartupMode: (options?: SpectralPluginOptions) => StartupLintMode;
|
|
161
162
|
//#endregion
|
|
162
163
|
//#region src/core/thresholds.d.ts
|
|
163
164
|
declare class OpenApiLintThresholdError extends Error {
|
|
@@ -168,4 +169,4 @@ declare class OpenApiLintThresholdError extends Error {
|
|
|
168
169
|
declare const shouldFail: (result: LintRunResult, threshold: SeverityThreshold) => boolean;
|
|
169
170
|
declare const enforceThreshold: (result: LintRunResult, threshold: SeverityThreshold) => void;
|
|
170
171
|
//#endregion
|
|
171
|
-
export {
|
|
172
|
+
export { SpectralLogger as A, OpenApiLintRuntime as C, OpenApiLintSinkContext as D, OpenApiLintSink as E, StartupLintMode as M, PresetName as O, OpenApiLintArtifacts as S, OpenApiLintRuntimeStatus as T, ArtifactWriteFailureMode as _, createOpenApiLintRuntime as a, LintRunSource as b, ResolvedRulesetCandidate as c, RulesetResolverContext as d, RulesetResolverInput as f, lintOpenApi as g, loadRuleset as h, OpenApiLintArtifactWriteError as i, SpectralPluginOptions as j, SeverityThreshold as k, RulesetLoadError as l, loadResolvedRuleset as m, enforceThreshold as n, LoadResolvedRulesetOptions as o, defaultRulesetResolvers as p, shouldFail as r, LoadedRuleset as s, OpenApiLintThresholdError as t, RulesetResolver as u, LintFinding as v, OpenApiLintRuntimeFailure as w, LintSeverity as x, LintRunResult as y };
|
package/dist/index.d.mts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { A as
|
|
1
|
+
import { A as SpectralLogger, C as OpenApiLintRuntime, D as OpenApiLintSinkContext, E as OpenApiLintSink, M as StartupLintMode, O as PresetName, S as OpenApiLintArtifacts, T as OpenApiLintRuntimeStatus, _ as ArtifactWriteFailureMode, a as createOpenApiLintRuntime, b as LintRunSource, c as ResolvedRulesetCandidate, d as RulesetResolverContext, f as RulesetResolverInput, g as lintOpenApi, h as loadRuleset, i as OpenApiLintArtifactWriteError, j as SpectralPluginOptions, k as SeverityThreshold, l as RulesetLoadError, m as loadResolvedRuleset, n as enforceThreshold, o as LoadResolvedRulesetOptions, p as defaultRulesetResolvers, r as shouldFail, s as LoadedRuleset, t as OpenApiLintThresholdError, u as RulesetResolver, v as LintFinding, w as OpenApiLintRuntimeFailure, x as LintSeverity, y as LintRunResult } from "./index--_yjTKg8.mjs";
|
|
2
2
|
import { RulesetDefinition } from "@stoplight/spectral-core";
|
|
3
3
|
import { Elysia } from "elysia";
|
|
4
4
|
|
|
@@ -72,4 +72,4 @@ declare const strict: RulesetDefinition;
|
|
|
72
72
|
//#region src/presets/index.d.ts
|
|
73
73
|
declare const presets: Record<PresetName, RulesetDefinition>;
|
|
74
74
|
//#endregion
|
|
75
|
-
export { ArtifactWriteFailureMode, LintFinding, LintRunResult, LintRunSource, LintSeverity, LoadResolvedRulesetOptions, LoadedRuleset, OpenApiLintArtifactWriteError, OpenApiLintArtifacts, OpenApiLintRuntime, OpenApiLintRuntimeFailure, OpenApiLintRuntimeStatus, OpenApiLintSink, OpenApiLintSinkContext, OpenApiLintThresholdError, PresetName, ResolvedRulesetCandidate, RulesetLoadError, RulesetResolver, RulesetResolverContext, RulesetResolverInput, SeverityThreshold, SpectralLogger, SpectralPluginOptions, StartupLintMode, createOpenApiLintRuntime, defaultRulesetResolvers, enforceThreshold, lintOpenApi, loadResolvedRuleset, loadRuleset, presets, recommended,
|
|
75
|
+
export { ArtifactWriteFailureMode, LintFinding, LintRunResult, LintRunSource, LintSeverity, LoadResolvedRulesetOptions, LoadedRuleset, OpenApiLintArtifactWriteError, OpenApiLintArtifacts, OpenApiLintRuntime, OpenApiLintRuntimeFailure, OpenApiLintRuntimeStatus, OpenApiLintSink, OpenApiLintSinkContext, OpenApiLintThresholdError, PresetName, ResolvedRulesetCandidate, RulesetLoadError, RulesetResolver, RulesetResolverContext, RulesetResolverInput, SeverityThreshold, SpectralLogger, SpectralPluginOptions, StartupLintMode, createOpenApiLintRuntime, defaultRulesetResolvers, enforceThreshold, lintOpenApi, loadResolvedRuleset, loadRuleset, presets, recommended, server, shouldFail, spectralPlugin, strict };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { a as enforceThreshold, c as strict, d as RulesetLoadError, f as defaultRulesetResolvers, g as lintOpenApi, h as recommended, i as OpenApiLintThresholdError, l as server, m as loadRuleset, n as createOpenApiLintRuntime, o as shouldFail, p as loadResolvedRuleset, r as resolveStartupMode, s as presets, t as OpenApiLintArtifactWriteError, u as resolveReporter } from "./core-
|
|
1
|
+
import { a as enforceThreshold, c as strict, d as RulesetLoadError, f as defaultRulesetResolvers, g as lintOpenApi, h as recommended, i as OpenApiLintThresholdError, l as server, m as loadRuleset, n as createOpenApiLintRuntime, o as shouldFail, p as loadResolvedRuleset, r as resolveStartupMode, s as presets, t as OpenApiLintArtifactWriteError, u as resolveReporter } from "./core-BIi33eA1.mjs";
|
|
2
2
|
import { Elysia } from "elysia";
|
|
3
3
|
//#region src/plugin.ts
|
|
4
4
|
const spectralPlugin = (options = {}) => {
|
|
@@ -82,4 +82,4 @@ const spectralPlugin = (options = {}) => {
|
|
|
82
82
|
return plugin;
|
|
83
83
|
};
|
|
84
84
|
//#endregion
|
|
85
|
-
export { OpenApiLintArtifactWriteError, OpenApiLintThresholdError, RulesetLoadError, createOpenApiLintRuntime, defaultRulesetResolvers, enforceThreshold, lintOpenApi, loadResolvedRuleset, loadRuleset, presets, recommended,
|
|
85
|
+
export { OpenApiLintArtifactWriteError, OpenApiLintThresholdError, RulesetLoadError, createOpenApiLintRuntime, defaultRulesetResolvers, enforceThreshold, lintOpenApi, loadResolvedRuleset, loadRuleset, presets, recommended, server, shouldFail, spectralPlugin, strict };
|