@owlmeans/entrypoint 0.1.18-rc.9 → 0.1.18
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 +254 -70
- package/agent-meta/manifest.json +3 -3
- package/agent-meta/skills/entrypoint/SKILL.md +77 -130
- package/build/consts.d.ts +0 -5
- package/build/consts.d.ts.map +1 -1
- package/build/consts.js +0 -5
- package/build/consts.js.map +1 -1
- package/build/entrypoint.d.ts.map +1 -1
- package/build/entrypoint.js +18 -6
- package/build/entrypoint.js.map +1 -1
- package/build/filter/types.d.ts +16 -0
- package/build/filter/types.d.ts.map +1 -0
- package/build/filter/types.js +2 -0
- package/build/filter/types.js.map +1 -0
- package/build/filter.d.ts +3 -7
- package/build/filter.d.ts.map +1 -1
- package/build/filter.js +22 -18
- package/build/filter.js.map +1 -1
- package/build/helper.d.ts.map +1 -1
- package/build/index.d.ts +5 -3
- package/build/index.d.ts.map +1 -1
- package/build/index.js +4 -3
- package/build/index.js.map +1 -1
- package/build/materialize.d.ts +7 -0
- package/build/materialize.d.ts.map +1 -0
- package/build/materialize.js +34 -0
- package/build/materialize.js.map +1 -0
- package/build/protocol.d.ts +44 -0
- package/build/protocol.d.ts.map +1 -0
- package/build/protocol.js +124 -0
- package/build/protocol.js.map +1 -0
- package/build/types.d.ts +169 -5
- package/build/types.d.ts.map +1 -1
- package/build/types.local.d.ts +27 -0
- package/build/types.local.d.ts.map +1 -0
- package/build/types.local.js +2 -0
- package/build/types.local.js.map +1 -0
- package/build/utils/entrypoint.d.ts.map +1 -1
- package/build/utils.d.ts +6 -0
- package/build/utils.d.ts.map +1 -0
- package/build/utils.js +6 -0
- package/build/utils.js.map +1 -0
- package/package.json +6 -6
- package/src/consts.ts +0 -5
- package/src/entrypoint.ts +18 -8
- package/src/filter/types.ts +16 -0
- package/src/filter.ts +24 -17
- package/src/index.ts +5 -3
- package/src/materialize.ts +43 -0
- package/src/protocol.ts +191 -0
- package/src/types.local.ts +24 -0
- package/src/types.ts +200 -5
- package/src/utils.ts +5 -0
package/src/protocol.ts
ADDED
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import type { EntrypointReference } from '@owlmeans/context'
|
|
2
|
+
import type { JSONSchemaType, AnySchemaObject } from 'ajv'
|
|
3
|
+
import type { RouteModel } from '@owlmeans/route'
|
|
4
|
+
import type { AnyShapeSource } from './types.local.js'
|
|
5
|
+
import type { EntrypointContract, EntrypointGate, EntrypointOptions, EntrypointProtocol, EntrypointProtocolDeclaration, EntrypointSchema, EntrypointTree, OpenRequest, OpenValue, RegisteredEntrypoint, RequestFromSources, RequestShape, RequestSources, RuntimeResponseSchemas, ShapeSource, Typed } from './types.js'
|
|
6
|
+
|
|
7
|
+
export const schema = <T>(value: JSONSchemaType<T>): EntrypointSchema<T> =>
|
|
8
|
+
value as EntrypointSchema<T>
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Supplies type information where a response has no runtime schema, or attaches a type to an
|
|
12
|
+
* otherwise untyped schema literal at the declaration boundary.
|
|
13
|
+
*/
|
|
14
|
+
export function typed<T>(): Typed<T>
|
|
15
|
+
export function typed<T>(schema: JSONSchemaType<T>): Typed<T>
|
|
16
|
+
export function typed<T>(schema?: JSONSchemaType<T>): Typed<T> {
|
|
17
|
+
return schema == null
|
|
18
|
+
? { kind: 'entrypoint-type' }
|
|
19
|
+
: { kind: 'entrypoint-type', schema }
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const schemaOf = (source: AnyShapeSource | undefined): AnySchemaObject | undefined => {
|
|
23
|
+
if (source == null) return undefined
|
|
24
|
+
const schema = 'kind' in source && source.kind === 'entrypoint-type'
|
|
25
|
+
? source.schema
|
|
26
|
+
: source
|
|
27
|
+
|
|
28
|
+
return schema == null ? undefined : structuredClone(schema)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
const responseSchemasOf = (source: AnyShapeSource | undefined): RuntimeResponseSchemas | undefined => {
|
|
32
|
+
const schema = schemaOf(source)
|
|
33
|
+
return schema == null ? undefined : { default: schema }
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Declare an exact request and response. The primary overload means a body request; use
|
|
38
|
+
* `contract.request` for independently-shaped request sections.
|
|
39
|
+
*/
|
|
40
|
+
export function contract(): EntrypointContract<{}, undefined>
|
|
41
|
+
export function contract<Response>(response: ShapeSource<Response>): EntrypointContract<{}, Response>
|
|
42
|
+
export function contract<Body extends OpenValue, Response>(
|
|
43
|
+
body: ShapeSource<Body>, response: ShapeSource<Response>
|
|
44
|
+
): EntrypointContract<{ body: Body }, Response>
|
|
45
|
+
export function contract(
|
|
46
|
+
first?: AnyShapeSource, second?: AnyShapeSource
|
|
47
|
+
): EntrypointContract<RequestShape, OpenValue> {
|
|
48
|
+
const body = second == null ? undefined : first
|
|
49
|
+
const response = second ?? first
|
|
50
|
+
|
|
51
|
+
return {
|
|
52
|
+
kind: 'entrypoint-contract',
|
|
53
|
+
requestSchemas: { body: schemaOf(body) },
|
|
54
|
+
responseSchemas: responseSchemasOf(response),
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export namespace contract {
|
|
59
|
+
export function request<Sources extends RequestSources, Response>(
|
|
60
|
+
request: Sources,
|
|
61
|
+
response: ShapeSource<Response>
|
|
62
|
+
): EntrypointContract<RequestFromSources<Sources>, Response> {
|
|
63
|
+
return {
|
|
64
|
+
kind: 'entrypoint-contract',
|
|
65
|
+
requestSchemas: {
|
|
66
|
+
body: schemaOf(request.body),
|
|
67
|
+
params: schemaOf(request.params),
|
|
68
|
+
query: schemaOf(request.query),
|
|
69
|
+
headers: schemaOf(request.headers),
|
|
70
|
+
},
|
|
71
|
+
responseSchemas: responseSchemasOf(response),
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
const guardsOf = (guards: EntrypointOptions['guards']): readonly string[] => guards == null
|
|
77
|
+
? []
|
|
78
|
+
: typeof guards === 'string' ? [guards] : [...guards]
|
|
79
|
+
|
|
80
|
+
const gateOf = (gate: EntrypointOptions['gate']): EntrypointProtocol['gate'] => gate == null
|
|
81
|
+
? undefined
|
|
82
|
+
: {
|
|
83
|
+
alias: gate.alias,
|
|
84
|
+
params: gate.params == null ? [] : typeof gate.params === 'string' ? [gate.params] : [...gate.params],
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
/** Create an immutable protocol declaration from a route and its contract. */
|
|
88
|
+
export const protocol = <Request extends RequestShape, Response>(
|
|
89
|
+
route: RouteModel,
|
|
90
|
+
entrypointContract: EntrypointContract<Request, Response>,
|
|
91
|
+
options?: EntrypointOptions
|
|
92
|
+
): EntrypointProtocol<Request, Response> => Object.freeze({
|
|
93
|
+
kind: 'entrypoint-protocol' as const,
|
|
94
|
+
alias: route.route.alias,
|
|
95
|
+
route: Object.freeze({ route: Object.freeze({ ...route.route }) }),
|
|
96
|
+
contract: entrypointContract,
|
|
97
|
+
sticky: options?.sticky ?? false,
|
|
98
|
+
guards: Object.freeze(guardsOf(options?.guards)),
|
|
99
|
+
gate: gateOf(options?.gate),
|
|
100
|
+
})
|
|
101
|
+
|
|
102
|
+
export const openProtocol = (
|
|
103
|
+
route: RouteModel,
|
|
104
|
+
options?: EntrypointOptions
|
|
105
|
+
): EntrypointProtocol<OpenRequest, OpenValue> => Object.freeze({
|
|
106
|
+
kind: 'entrypoint-protocol' as const,
|
|
107
|
+
alias: route.route.alias,
|
|
108
|
+
route: Object.freeze({ route: Object.freeze({ ...route.route }) }),
|
|
109
|
+
sticky: options?.sticky ?? false,
|
|
110
|
+
guards: Object.freeze(guardsOf(options?.guards)),
|
|
111
|
+
gate: gateOf(options?.gate),
|
|
112
|
+
})
|
|
113
|
+
|
|
114
|
+
export const entrypointRef = <Request extends RequestShape = OpenRequest, Response = OpenValue>(
|
|
115
|
+
alias: string
|
|
116
|
+
): EntrypointReference<RegisteredEntrypoint<Request, Response>> => ({ alias })
|
|
117
|
+
|
|
118
|
+
export const aliasOf = (reference: EntrypointReference | string): string =>
|
|
119
|
+
typeof reference === 'string' ? reference : reference.alias
|
|
120
|
+
|
|
121
|
+
export const isEntrypointProtocol = (value: object): value is EntrypointProtocolDeclaration =>
|
|
122
|
+
'kind' in value && value.kind === 'entrypoint-protocol'
|
|
123
|
+
|
|
124
|
+
/** Flatten an exported protocol tree for a layer-specific materializer. */
|
|
125
|
+
export const protocols = (tree: EntrypointTree): EntrypointProtocolDeclaration[] => {
|
|
126
|
+
const result: EntrypointProtocolDeclaration[] = []
|
|
127
|
+
|
|
128
|
+
const visit = (node: EntrypointTree): void => {
|
|
129
|
+
Object.values(node).forEach((entry) => {
|
|
130
|
+
if (isEntrypointProtocol(entry)) {
|
|
131
|
+
result.push(entry)
|
|
132
|
+
} else {
|
|
133
|
+
visit(entry)
|
|
134
|
+
}
|
|
135
|
+
})
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
visit(tree)
|
|
139
|
+
return result
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Rebuild an immutable protocol tree while transforming its declarations.
|
|
144
|
+
*
|
|
145
|
+
* Protocol consumers keep addressing declarations by their exported tree path; a cross-cutting
|
|
146
|
+
* concern such as a coguard therefore never needs to flatten the tree and recover declarations
|
|
147
|
+
* by alias.
|
|
148
|
+
*/
|
|
149
|
+
export const mapProtocols = <Tree extends EntrypointTree>(
|
|
150
|
+
tree: Tree,
|
|
151
|
+
mapper: (protocol: EntrypointProtocolDeclaration) => EntrypointProtocolDeclaration,
|
|
152
|
+
): Tree => Object.freeze(Object.fromEntries(
|
|
153
|
+
Object.entries(tree).map(([key, entry]) => [
|
|
154
|
+
key,
|
|
155
|
+
isEntrypointProtocol(entry) ? mapper(entry) : mapProtocols(entry, mapper),
|
|
156
|
+
])
|
|
157
|
+
)) as Tree
|
|
158
|
+
|
|
159
|
+
/** Resolve the gates a protocol inherits through its route parents without materializing it. */
|
|
160
|
+
export const gatesOf = (
|
|
161
|
+
protocol: EntrypointProtocolDeclaration,
|
|
162
|
+
tree: EntrypointTree,
|
|
163
|
+
): readonly EntrypointGate[] => {
|
|
164
|
+
const byAlias = new Map(protocols(tree).map(candidate => [candidate.alias, candidate]))
|
|
165
|
+
const result: EntrypointGate[] = []
|
|
166
|
+
const visited = new Set<string>()
|
|
167
|
+
let current: EntrypointProtocolDeclaration | undefined = protocol
|
|
168
|
+
|
|
169
|
+
while (current != null && !visited.has(current.alias)) {
|
|
170
|
+
visited.add(current.alias)
|
|
171
|
+
if (current.gate != null && !result.some(gate => gate.alias === current!.gate!.alias)) {
|
|
172
|
+
result.push(current.gate)
|
|
173
|
+
}
|
|
174
|
+
current = current.route.route.parent == null
|
|
175
|
+
? undefined
|
|
176
|
+
: byAlias.get(current.route.route.parent)
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
return result
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/** Clone an immutable protocol while preserving its request/response pair. */
|
|
183
|
+
export const decorateEntrypoint = <Protocol extends EntrypointProtocolDeclaration>(
|
|
184
|
+
protocol: Protocol,
|
|
185
|
+
options: EntrypointOptions
|
|
186
|
+
): Protocol => Object.freeze({
|
|
187
|
+
...protocol,
|
|
188
|
+
sticky: options.sticky ?? protocol.sticky,
|
|
189
|
+
guards: options.guards == null ? protocol.guards : guardsOf(options.guards),
|
|
190
|
+
gate: options.gate == null ? protocol.gate : gateOf(options.gate),
|
|
191
|
+
})
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import type { JSONSchemaType, AnySchemaObject } from 'ajv'
|
|
2
|
+
import type { EntrypointSchema, OpenValue, RequestShape, Typed } from './types.js'
|
|
3
|
+
|
|
4
|
+
export interface TypeToken {
|
|
5
|
+
readonly kind: 'entrypoint-type'
|
|
6
|
+
readonly schema?: AnySchemaObject
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export declare const entrypointSchemaType: unique symbol
|
|
10
|
+
|
|
11
|
+
export type AnyShapeSource = AnySchemaObject | TypeToken
|
|
12
|
+
|
|
13
|
+
export type SourceValue<Source> =
|
|
14
|
+
Source extends Typed<infer Value> ? Value
|
|
15
|
+
: Source extends EntrypointSchema<infer Value> ? Value
|
|
16
|
+
: Source extends JSONSchemaType<infer Value>
|
|
17
|
+
? Value extends OpenValue ? Value : OpenValue
|
|
18
|
+
: OpenValue
|
|
19
|
+
|
|
20
|
+
export type UrlRequest<Request extends RequestShape> =
|
|
21
|
+
(Request extends { params: infer Params } ? { params: Params }
|
|
22
|
+
: Request extends { params?: infer Params } ? { params?: Params } : {})
|
|
23
|
+
& (Request extends { query: infer Query } ? { query: Query }
|
|
24
|
+
: Request extends { query?: infer Query } ? { query?: Query } : {})
|
package/src/types.ts
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
|
-
import type { ResolvedServiceRoute, RouteAddress, RouteModel,
|
|
2
|
-
import type { InitializedService, LazyService, BasicEntrypoint } from '@owlmeans/context'
|
|
3
|
-
import type { AnySchemaObject } from 'ajv'
|
|
1
|
+
import type { ResolvedServiceRoute, RouteAddress, RouteModel, RouteProtocol } from '@owlmeans/route'
|
|
2
|
+
import type { InitializedService, LazyService, BasicEntrypoint, EntrypointReference } from '@owlmeans/context'
|
|
3
|
+
import type { AnySchemaObject, JSONSchemaType } from 'ajv'
|
|
4
4
|
import type { EntrypointOutcome } from './consts.js'
|
|
5
5
|
import type { Auth } from '@owlmeans/auth'
|
|
6
6
|
|
|
7
|
+
import type { AnyShapeSource, entrypointSchemaType, SourceValue, TypeToken, UrlRequest } from './types.local.js'
|
|
8
|
+
|
|
7
9
|
/**
|
|
8
10
|
* A URL unit: an immutable route declaration plus what guards, gates and schemas it answers under.
|
|
9
11
|
*
|
|
@@ -144,10 +146,203 @@ export interface Filter {
|
|
|
144
146
|
* How a call to an entrypoint is actually carried.
|
|
145
147
|
*
|
|
146
148
|
* The transport is chosen by the route's protocol, so a consumer always writes `ep.call(...)` and
|
|
147
|
-
* never learns
|
|
149
|
+
* never learns which built-in or package-owned carrier handled it. An
|
|
148
150
|
* application binds a protocol by registering a transport service under `transportAlias(protocol)`.
|
|
149
151
|
*/
|
|
150
152
|
export interface EntrypointTransport extends InitializedService {
|
|
151
|
-
readonly protocol:
|
|
153
|
+
readonly protocol: RouteProtocol
|
|
152
154
|
handle: EntrypointHandler
|
|
153
155
|
}
|
|
156
|
+
|
|
157
|
+
/** A deliberately broad value used only by declarations without an I/O contract. */
|
|
158
|
+
export type OpenValue = object | string | number | boolean | bigint | null | undefined
|
|
159
|
+
|
|
160
|
+
/** The four independent request sections an entrypoint may declare. */
|
|
161
|
+
export interface RequestShape {
|
|
162
|
+
body?: OpenValue
|
|
163
|
+
params?: object
|
|
164
|
+
query?: object
|
|
165
|
+
headers?: object
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export interface RuntimeRequestSchemas {
|
|
169
|
+
body?: AnySchemaObject
|
|
170
|
+
params?: AnySchemaObject
|
|
171
|
+
query?: AnySchemaObject
|
|
172
|
+
headers?: AnySchemaObject
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
export interface RuntimeResponseSchemas {
|
|
176
|
+
default?: AnySchemaObject
|
|
177
|
+
byStatus?: Readonly<Record<number, AnySchemaObject>>
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** The runtime schemas and compile-time request/response pair attached to one protocol. */
|
|
181
|
+
export interface EntrypointContract<Request extends RequestShape, Response> {
|
|
182
|
+
readonly kind: 'entrypoint-contract'
|
|
183
|
+
readonly requestSchemas: RuntimeRequestSchemas
|
|
184
|
+
readonly responseSchemas?: RuntimeResponseSchemas
|
|
185
|
+
readonly requestType?: Request
|
|
186
|
+
readonly responseType?: Response
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/** Runtime fields common to every protocol, regardless of its compile-time request/reply pair. */
|
|
190
|
+
export interface EntrypointProtocolDeclaration {
|
|
191
|
+
readonly kind: 'entrypoint-protocol'
|
|
192
|
+
readonly alias: string
|
|
193
|
+
readonly route: RouteModel
|
|
194
|
+
readonly contract?: Pick<EntrypointContract<RequestShape, OpenValue>,
|
|
195
|
+
'kind' | 'requestSchemas' | 'responseSchemas'>
|
|
196
|
+
readonly sticky: boolean
|
|
197
|
+
readonly guards: readonly string[]
|
|
198
|
+
readonly gate?: {
|
|
199
|
+
readonly alias: string
|
|
200
|
+
readonly params: readonly string[]
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
/** A context-bound entrypoint made from an immutable protocol declaration. */
|
|
205
|
+
export interface MaterializedEntrypoint<Protocol extends EntrypointProtocolDeclaration> extends CommonEntrypoint { readonly protocol: Protocol }
|
|
206
|
+
|
|
207
|
+
/** The request accepted by a declaration that intentionally supplies no contract. */
|
|
208
|
+
export interface OpenRequest {
|
|
209
|
+
body?: object
|
|
210
|
+
params?: object
|
|
211
|
+
query?: object
|
|
212
|
+
headers?: object
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
/** Addressing and transport controls are never part of an entrypoint's payload contract. */
|
|
216
|
+
export interface CallOptions {
|
|
217
|
+
auth?: Auth
|
|
218
|
+
host?: string
|
|
219
|
+
base?: string | boolean
|
|
220
|
+
unsecure?: boolean
|
|
221
|
+
timeout?: number
|
|
222
|
+
signal?: AbortSignal
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/** A type-only contract source, optionally paired with an AJV schema. */
|
|
226
|
+
export interface Typed<T> extends TypeToken { readonly value?: T }
|
|
227
|
+
|
|
228
|
+
// Kept as a type: `JSONSchemaType` is a conditional type; an interface cannot extend it.
|
|
229
|
+
/**
|
|
230
|
+
* A JSON schema carrying the model type it validates. Use `schema<Model>(...)` once beside the
|
|
231
|
+
* model; every protocol that consumes it then infers the model without another generic.
|
|
232
|
+
*/
|
|
233
|
+
export type EntrypointSchema<T> = JSONSchemaType<T> & {
|
|
234
|
+
readonly [entrypointSchemaType]: T
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/** A schema or an explicit type-only source for one request/response value. */
|
|
238
|
+
export type ShapeSource<T> = EntrypointSchema<T> | JSONSchemaType<T> | Typed<T>
|
|
239
|
+
|
|
240
|
+
export interface RequestSources {
|
|
241
|
+
body?: AnyShapeSource
|
|
242
|
+
params?: AnyShapeSource
|
|
243
|
+
query?: AnyShapeSource
|
|
244
|
+
headers?: AnyShapeSource
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
/** An access gate declared by a protocol, including inherited parent declarations. */
|
|
248
|
+
export interface EntrypointGate {
|
|
249
|
+
readonly alias: string
|
|
250
|
+
readonly params: readonly string[]
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export type RequestFromSources<Sources extends RequestSources> =
|
|
254
|
+
(Sources extends { body: infer Source } ? { body: SourceValue<Source> } : {})
|
|
255
|
+
& (Sources extends { params: infer Source } ? { params: SourceValue<Source> } : {})
|
|
256
|
+
& (Sources extends { query: infer Source } ? { query: SourceValue<Source> } : {})
|
|
257
|
+
& (Sources extends { headers: infer Source } ? { headers: SourceValue<Source> } : {})
|
|
258
|
+
|
|
259
|
+
export interface EntrypointOptions {
|
|
260
|
+
sticky?: boolean
|
|
261
|
+
guards?: string | readonly string[]
|
|
262
|
+
gate?: {
|
|
263
|
+
alias: string
|
|
264
|
+
params?: string | readonly string[]
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export interface EntrypointResult<Response> {
|
|
269
|
+
value: Response
|
|
270
|
+
outcome: EntrypointOutcome
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
export type CallArguments<Request extends RequestShape> = {} extends Request
|
|
274
|
+
? [request?: Request & CallOptions]
|
|
275
|
+
: [request: Request & CallOptions]
|
|
276
|
+
|
|
277
|
+
export type UrlArguments<Request extends RequestShape> = {} extends UrlRequest<Request>
|
|
278
|
+
? [request?: UrlRequest<Request> & CallOptions]
|
|
279
|
+
: [request: UrlRequest<Request> & CallOptions]
|
|
280
|
+
|
|
281
|
+
export interface EntrypointRequestMeta {
|
|
282
|
+
alias: string
|
|
283
|
+
auth?: Auth
|
|
284
|
+
entity?: ResolvedEntity
|
|
285
|
+
path: string
|
|
286
|
+
canceled?: boolean
|
|
287
|
+
cancel?: () => void
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
// Kept as a type: it intersects the `Request` type parameter, which an interface cannot extend.
|
|
291
|
+
/**
|
|
292
|
+
* A protocol request at an implementation boundary.
|
|
293
|
+
*
|
|
294
|
+
* Transport metadata and empty request sections remain available to handlers; a declared section
|
|
295
|
+
* then refines that base shape to its protocol contract.
|
|
296
|
+
*/
|
|
297
|
+
export type HandlerRequest<Request extends RequestShape> = AbstractRequest & Request & EntrypointRequestMeta
|
|
298
|
+
|
|
299
|
+
/**
|
|
300
|
+
* An immutable shared declaration. Its inherited reference type is what gives a context lookup
|
|
301
|
+
* the exact registered entrypoint type without a consumer-supplied generic.
|
|
302
|
+
*/
|
|
303
|
+
export interface EntrypointProtocol<
|
|
304
|
+
Request extends RequestShape = RequestShape,
|
|
305
|
+
Response = OpenValue,
|
|
306
|
+
> extends EntrypointProtocolDeclaration, EntrypointReference<RegisteredEntrypoint<Request, Response>> {
|
|
307
|
+
readonly contract?: EntrypointContract<Request, Response>
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
/** The context-bound counterpart of an immutable protocol declaration. */
|
|
311
|
+
export interface RegisteredEntrypoint<Request extends RequestShape, Response> extends BasicEntrypoint {
|
|
312
|
+
readonly protocol: EntrypointProtocol<Request, Response>
|
|
313
|
+
call: (...args: CallArguments<Request>) => Promise<Response>
|
|
314
|
+
invoke: (...args: CallArguments<Request>) => Promise<EntrypointResult<Response>>
|
|
315
|
+
url: (...args: UrlArguments<Request>) => Promise<string>
|
|
316
|
+
validate: (...args: CallArguments<Request>) => Promise<boolean>
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
export type RequestOf<Protocol extends EntrypointProtocolDeclaration> = Protocol extends EntrypointProtocol<infer Request, infer _Response>
|
|
320
|
+
? Request
|
|
321
|
+
: OpenRequest
|
|
322
|
+
|
|
323
|
+
export type ResponseOf<Protocol extends EntrypointProtocolDeclaration> = Protocol extends EntrypointProtocol<infer _Request, infer Response>
|
|
324
|
+
? Response
|
|
325
|
+
: OpenValue
|
|
326
|
+
|
|
327
|
+
export type BodyOf<Protocol extends EntrypointProtocolDeclaration> = RequestOf<Protocol> extends { body: infer Body }
|
|
328
|
+
? Body
|
|
329
|
+
: OpenValue
|
|
330
|
+
|
|
331
|
+
export type ParamsOf<Protocol extends EntrypointProtocolDeclaration> = RequestOf<Protocol> extends { params: infer Params }
|
|
332
|
+
? Params
|
|
333
|
+
: object
|
|
334
|
+
|
|
335
|
+
export type QueryOf<Protocol extends EntrypointProtocolDeclaration> = RequestOf<Protocol> extends { query: infer Query }
|
|
336
|
+
? Query
|
|
337
|
+
: object
|
|
338
|
+
|
|
339
|
+
export type HeadersOf<Protocol extends EntrypointProtocolDeclaration> = RequestOf<Protocol> extends { headers: infer Headers }
|
|
340
|
+
? Headers
|
|
341
|
+
: object
|
|
342
|
+
|
|
343
|
+
// Kept as a type: `RequestOf` is a conditional type; an interface cannot extend it.
|
|
344
|
+
export type CallRequestOf<Protocol extends EntrypointProtocolDeclaration> = RequestOf<Protocol> & CallOptions
|
|
345
|
+
|
|
346
|
+
export interface EntrypointTree {
|
|
347
|
+
readonly [key: string]: EntrypointProtocolDeclaration | EntrypointTree
|
|
348
|
+
}
|