@croutonian/with-openapi 0.4.0 → 0.5.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/dist/index.d.ts +46 -10
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -660,15 +660,47 @@ type MatchedOperation<Document, Route extends string, Method extends string> = {
|
|
|
660
660
|
*/
|
|
661
661
|
type MatchedFor<Document> = { [Route in RoutesOf<Document>]: { [Method in MethodsOf<Document, Route>]: MatchedOperation<Document, Route, Method> }[MethodsOf<Document, Route>] }[RoutesOf<Document>];
|
|
662
662
|
/**
|
|
663
|
-
*
|
|
663
|
+
* Whether `Key` is set to `'pass'` — or might be.
|
|
664
664
|
*
|
|
665
|
-
*
|
|
666
|
-
*
|
|
667
|
-
*
|
|
668
|
-
*
|
|
669
|
-
* Degrading to today's shape is what keeps this change additive.
|
|
665
|
+
* Everything here fails *safe*: the unmatched branch is only dropped when the
|
|
666
|
+
* config provably cannot produce one. A widened config satisfies
|
|
667
|
+
* `'pass' extends string`, so it keeps the branch rather than promising a
|
|
668
|
+
* `matched: true` the runtime may not deliver.
|
|
670
669
|
*/
|
|
671
|
-
type
|
|
670
|
+
type MayPass<Config, Key extends string> = Key extends keyof Config ? 'pass' extends Config[Key] ? true : false : false;
|
|
671
|
+
/**
|
|
672
|
+
* Whether a `skip` predicate might fire.
|
|
673
|
+
*
|
|
674
|
+
* Asks whether `skip` could *possibly* be a function, not whether it
|
|
675
|
+
* definitely is. `skip: condition ? fn : undefined` has type
|
|
676
|
+
* `Fn | undefined`, and a check of the second kind reads that as "no skip"
|
|
677
|
+
* and drops the branch — while at runtime the predicate fires whenever the
|
|
678
|
+
* condition holds, handing a handler an unmatched contribution the compiler
|
|
679
|
+
* said could not exist.
|
|
680
|
+
*/
|
|
681
|
+
type HasSkip<Config> = 'skip' extends keyof Config ? [Config['skip']] extends [undefined] ? false : true : false;
|
|
682
|
+
/**
|
|
683
|
+
* Whether this config can produce an unmatched contribution at all.
|
|
684
|
+
*
|
|
685
|
+
* Mirrors the three runtime branches that call `unmatched()`: a `skip` that
|
|
686
|
+
* fired, `onUnknownRoute: 'pass'` with no route match, `onUnknownMethod:
|
|
687
|
+
* 'pass'` with no operation. On the defaults none of them can, because both
|
|
688
|
+
* options default to `'reject'` and answer the request themselves.
|
|
689
|
+
*/
|
|
690
|
+
type CanBeUnmatched<Config> = MayPass<Config, 'onUnknownRoute'> extends true ? true : MayPass<Config, 'onUnknownMethod'> extends true ? true : HasSkip<Config> extends true ? true : false;
|
|
691
|
+
/**
|
|
692
|
+
* What lands at `ctx.openapi` for a given document and config.
|
|
693
|
+
*
|
|
694
|
+
* Two reductions, in order. Handed a document that arrived without its
|
|
695
|
+
* literal type — annotated `: OpenAPIObject`, say — `RoutesOf` is `never`,
|
|
696
|
+
* and this degrades to the unspecialized {@link OpenApiContribution}; without
|
|
697
|
+
* that, the union would have no `matched: true` branch at all and every
|
|
698
|
+
* existing consumer would break. Otherwise the unmatched branch is dropped
|
|
699
|
+
* unless the config can actually produce one, so a downstream middleware or
|
|
700
|
+
* handler can read `route`, `operationId` and `params` without a guard for a
|
|
701
|
+
* case that cannot happen.
|
|
702
|
+
*/
|
|
703
|
+
type ContributionFor<Document, Config = WithOpenApiConfig> = [RoutesOf<Document>] extends [never] ? OpenApiContribution : CanBeUnmatched<Config> extends true ? MatchedFor<Document> | OpenApiUnmatched : MatchedFor<Document>;
|
|
672
704
|
//#endregion
|
|
673
705
|
//#region src/with-openapi.d.ts
|
|
674
706
|
/**
|
|
@@ -681,15 +713,19 @@ type ContributionFor<Document> = [RoutesOf<Document>] extends [never] ? OpenApiC
|
|
|
681
713
|
* handler-taking forms fall through to the general signatures below it, where
|
|
682
714
|
* `ctx.openapi` keeps its unspecialized shape.
|
|
683
715
|
*
|
|
716
|
+
* The whole config is captured, not just the document: `onUnknownRoute`,
|
|
717
|
+
* `onUnknownMethod` and `skip` are what decide whether an unmatched
|
|
718
|
+
* contribution is reachable, and on the defaults it is not — so a downstream
|
|
719
|
+
* middleware or handler gets `matched: true` already narrowed, with no guard
|
|
720
|
+
* for a case the config rules out.
|
|
721
|
+
*
|
|
684
722
|
* The runtime is untouched: this re-describes what `defineMiddleware` already
|
|
685
723
|
* returns. That makes the description an assertion we own — if `ParamsFor`
|
|
686
724
|
* ever disagrees with what the middleware actually deserializes, the types
|
|
687
725
|
* are what lie, and nothing here would catch it.
|
|
688
726
|
*/
|
|
689
727
|
interface TypedByDocument {
|
|
690
|
-
<const
|
|
691
|
-
document: Document;
|
|
692
|
-
}): SingleKeyEntry<'openapi', Record<never, never>, ContributionFor<Document>>;
|
|
728
|
+
<const Config extends WithOpenApiConfig>(config: Config): SingleKeyEntry<'openapi', Record<never, never>, ContributionFor<Config['document'], Config>>;
|
|
693
729
|
}
|
|
694
730
|
/**
|
|
695
731
|
* Middleware that holds an API to its own description.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@croutonian/with-openapi",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "OpenAPI middleware for @supabase/middleware. Matches each request against an OpenAPI 3.1 document, optionally rejects the ones it does not describe, contributes the matched operation and validated params to ctx, and optionally serves a Scalar API reference.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"openapi",
|