@toa.io/extensions.exposition 1.0.0-alpha.288 → 1.0.0-alpha.289
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 +11 -0
- package/components/identity.basic/tsconfig.tsbuildinfo +1 -1
- package/components/identity.clients/tsconfig.tsbuildinfo +1 -1
- package/components/identity.credentials/tsconfig.tsbuildinfo +1 -1
- package/components/identity.federation/tsconfig.tsbuildinfo +1 -1
- package/components/identity.grants/tsconfig.tsbuildinfo +1 -1
- package/components/identity.keys/tsconfig.tsbuildinfo +1 -1
- package/components/identity.otp/tsconfig.tsbuildinfo +1 -1
- package/components/identity.passkeys/tsconfig.tsbuildinfo +1 -1
- package/components/identity.roles/tsconfig.tsbuildinfo +1 -1
- package/components/identity.tokens/tsconfig.tsbuildinfo +1 -1
- package/documentation/access.md +3 -2
- package/documentation/discovery.md +8 -8
- package/documentation/help.md +16 -3
- package/documentation/introspection.md +10 -2
- package/documentation/octets.md +20 -0
- package/features/discovery.feature +4 -2
- package/features/discovery.ui.feature +19 -3
- package/features/help.feature +46 -0
- package/features/octets.feature +59 -0
- package/features/steps/Components.ts +4 -2
- package/features/steps/Database.ts +7 -1
- package/features/steps/Gateway.ts +23 -21
- package/features/steps/Parameters.ts +25 -16
- package/features/steps/Realtime.ts +3 -3
- package/package.json +5 -5
- package/source/Directive.ts +0 -11
- package/source/Discovery/trunk.ts +13 -3
- package/source/Factory.ts +3 -86
- package/source/HTTP/Probe.ts +0 -11
- package/source/HTTP/Server.ts +2 -3
- package/source/HTTP/messages.ts +4 -2
- package/source/Introspection.ts +28 -0
- package/source/const.ts +18 -0
- package/source/deployment.ts +2 -2
- package/source/directives/auth/Anonymous.ts +10 -0
- package/source/directives/help/Family.ts +5 -1
- package/source/directives/help/Help.ts +21 -0
- package/source/directives/octets/Directive.ts +7 -0
- package/source/directives/octets/Octets.ts +8 -0
- package/source/directives/octets/Put.ts +10 -0
- package/source/manifest.ts +1 -1
- package/source/root.ts +2 -2
- package/source/service.ts +94 -0
- package/source/shortcuts.ts +14 -0
- package/transpiled/Directive.d.ts +0 -1
- package/transpiled/Directive.js +0 -11
- package/transpiled/Directive.js.map +1 -1
- package/transpiled/Discovery/trunk.d.ts +5 -2
- package/transpiled/Discovery/trunk.js +12 -4
- package/transpiled/Discovery/trunk.js.map +1 -1
- package/transpiled/Factory.js +3 -61
- package/transpiled/Factory.js.map +1 -1
- package/transpiled/HTTP/Probe.d.ts +0 -10
- package/transpiled/HTTP/Probe.js +0 -10
- package/transpiled/HTTP/Probe.js.map +1 -1
- package/transpiled/HTTP/Server.d.ts +0 -1
- package/transpiled/HTTP/Server.js +2 -2
- package/transpiled/HTTP/Server.js.map +1 -1
- package/transpiled/HTTP/messages.js +4 -2
- package/transpiled/HTTP/messages.js.map +1 -1
- package/transpiled/Introspection.d.ts +21 -0
- package/transpiled/Introspection.js +2 -0
- package/transpiled/Introspection.js.map +1 -1
- package/transpiled/const.d.ts +14 -0
- package/transpiled/const.js +14 -0
- package/transpiled/const.js.map +1 -1
- package/transpiled/deployment.js +2 -2
- package/transpiled/deployment.js.map +1 -1
- package/transpiled/directives/auth/Anonymous.d.ts +7 -0
- package/transpiled/directives/auth/Anonymous.js +8 -0
- package/transpiled/directives/auth/Anonymous.js.map +1 -1
- package/transpiled/directives/help/Family.d.ts +1 -1
- package/transpiled/directives/help/Family.js +4 -0
- package/transpiled/directives/help/Family.js.map +1 -1
- package/transpiled/directives/help/Help.d.ts +6 -0
- package/transpiled/directives/help/Help.js +14 -0
- package/transpiled/directives/help/Help.js.map +1 -1
- package/transpiled/directives/octets/Directive.d.ts +6 -0
- package/transpiled/directives/octets/Directive.js.map +1 -1
- package/transpiled/directives/octets/Octets.d.ts +3 -0
- package/transpiled/directives/octets/Octets.js +6 -0
- package/transpiled/directives/octets/Octets.js.map +1 -1
- package/transpiled/directives/octets/Put.d.ts +3 -0
- package/transpiled/directives/octets/Put.js +8 -0
- package/transpiled/directives/octets/Put.js.map +1 -1
- package/transpiled/manifest.js +1 -1
- package/transpiled/root.js +2 -2
- package/transpiled/root.js.map +1 -1
- package/transpiled/service.d.ts +7 -0
- package/transpiled/service.js +74 -0
- package/transpiled/service.js.map +1 -0
- package/transpiled/shortcuts.d.ts +3 -0
- package/transpiled/shortcuts.js +13 -0
- package/transpiled/shortcuts.js.map +1 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/ui/dist/_app/immutable/assets/0.Bl7vLmIK.css +2 -0
- package/ui/dist/_app/immutable/chunks/{CWJaG9mK.js → CDMRPWCx.js} +2 -2
- package/ui/dist/_app/immutable/chunks/DJTKIUs8.js +1 -0
- package/ui/dist/_app/immutable/chunks/{yDQhitF9.js → z-DVUbQC.js} +1 -1
- package/ui/dist/_app/immutable/entry/{app.WZSMBcGf.js → app.5S2Jtv46.js} +2 -2
- package/ui/dist/_app/immutable/entry/start.Bqi6IBmH.js +1 -0
- package/ui/dist/_app/immutable/nodes/{0.Dl2DqINo.js → 0.D4LwNilH.js} +1 -1
- package/ui/dist/_app/immutable/nodes/{1.CSSnGhVD.js → 1.CSRya9So.js} +1 -1
- package/ui/dist/_app/immutable/nodes/{2.DmolQyNG.js → 2.BtiGmR6I.js} +4 -4
- package/ui/dist/_app/version.json +1 -1
- package/ui/dist/index.html +11 -11
- package/components/identity.bans/migrations/0001-system-properties.yaml +0 -14
- package/components/identity.basic/migrations/0001-system-properties.yaml +0 -14
- package/components/identity.clients/migrations/0001-system-properties.yaml +0 -14
- package/components/identity.federation/migrations/0001-system-properties.yaml +0 -14
- package/components/identity.grants/migrations/0001-system-properties.yaml +0 -14
- package/components/identity.keys/migrations/0001-system-properties.yaml +0 -14
- package/components/identity.otp/migrations/0001-system-properties.yaml +0 -14
- package/components/identity.passkeys/migrations/0001-system-properties.yaml +0 -14
- package/components/identity.roles/migrations/0001-system-properties.yaml +0 -14
- package/components/identity.tokens/migrations/0001-system-properties.yaml +0 -14
- package/ui/dist/_app/immutable/assets/0.BcIGtTfw.css +0 -2
- package/ui/dist/_app/immutable/chunks/BgTrzN6u.js +0 -1
- package/ui/dist/_app/immutable/entry/start._LkoC6Lz.js +0 -1
package/source/Factory.ts
CHANGED
|
@@ -1,20 +1,6 @@
|
|
|
1
|
-
import assert from 'node:assert'
|
|
2
1
|
import { createHash } from 'node:crypto'
|
|
3
|
-
import { console, traces, type LevelName, type TracesOptions } from 'openspan'
|
|
4
2
|
import { Tenant } from './Tenant.js'
|
|
5
|
-
import {
|
|
6
|
-
import { Remotes } from './Remotes.js'
|
|
7
|
-
import { Tree } from './RTD/index.js'
|
|
8
|
-
import { EndpointsFactory } from './Endpoint.js'
|
|
9
|
-
import { families, interceptors } from './directives/index.js'
|
|
10
|
-
import { DirectivesFactory } from './Directive.js'
|
|
11
|
-
import { Composition } from './Composition.js'
|
|
12
|
-
import * as root from './root.js'
|
|
13
|
-
import { ATOM_GROUP } from './const.js'
|
|
14
|
-
import { Interception } from './Interception.js'
|
|
15
|
-
import { Dispatcher } from './RPC/index.js'
|
|
16
|
-
import { Server as Model } from './MCP/index.js'
|
|
17
|
-
import * as http from './HTTP/index.js'
|
|
3
|
+
import { CHANNEL } from './const.js'
|
|
18
4
|
import type { Branch } from './Branch.js'
|
|
19
5
|
import type { syntax } from './RTD/index.js'
|
|
20
6
|
import type { Broadcast } from './Gateway.js'
|
|
@@ -46,80 +32,11 @@ export class Factory implements extensions.Factory {
|
|
|
46
32
|
}
|
|
47
33
|
|
|
48
34
|
public async service(): Promise<Connector | null> {
|
|
49
|
-
|
|
50
|
-
process.env.TOA_EXPOSITION_PROPERTIES,
|
|
51
|
-
'TOA_EXPOSITION_PROPERTIES is undefined'
|
|
52
|
-
)
|
|
35
|
+
const { service } = await import('./service.js')
|
|
53
36
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const options = JSON.parse(process.env.TOA_EXPOSITION_PROPERTIES) as http.Options
|
|
57
|
-
const broadcast: Broadcast = await this.host.broadcast(CHANNEL)
|
|
58
|
-
const server = http.Server.create({ ...options })
|
|
59
|
-
const remotes = new Remotes(this.host)
|
|
60
|
-
const node = root.resolve()
|
|
61
|
-
const methods = new EndpointsFactory(remotes)
|
|
62
|
-
const directives = new DirectivesFactory(families, remotes, this.host, options)
|
|
63
|
-
const interception = new Interception(interceptors, options)
|
|
64
|
-
const tree = new Tree(node, methods, directives)
|
|
65
|
-
|
|
66
|
-
const composition = new Composition(this.host)
|
|
67
|
-
const dispatcher = options.rpc === undefined ? null : new Dispatcher(options.rpc)
|
|
68
|
-
const mcp = options.mcp === undefined ? null : new Model(options.mcp, tree)
|
|
69
|
-
const gateway = new Gateway(
|
|
70
|
-
broadcast,
|
|
71
|
-
tree,
|
|
72
|
-
interception,
|
|
73
|
-
directives,
|
|
74
|
-
dispatcher,
|
|
75
|
-
mcp
|
|
76
|
-
)
|
|
77
|
-
|
|
78
|
-
gateway.depends(remotes)
|
|
79
|
-
gateway.depends(composition)
|
|
80
|
-
// what the directives meter through; one atom per process, connected once
|
|
81
|
-
gateway.depends(this.host.atom(ATOM_GROUP))
|
|
82
|
-
|
|
83
|
-
server.attach(gateway.process.bind(gateway))
|
|
84
|
-
server.depends(gateway)
|
|
85
|
-
|
|
86
|
-
return server
|
|
37
|
+
return await service(this.host)
|
|
87
38
|
}
|
|
88
39
|
}
|
|
89
40
|
|
|
90
|
-
const CHANNEL = 'exposition'
|
|
91
|
-
const LOGS_PREFIX = 'TOA_TELEMETRY_LOGS'
|
|
92
|
-
const TRACES_ENV = 'TOA_TELEMETRY_TRACES'
|
|
93
|
-
|
|
94
|
-
function configureLogs(): void {
|
|
95
|
-
const globEnv = process.env[LOGS_PREFIX]
|
|
96
|
-
const level: LevelName = process.env.TOA_DEV === '1' ? 'trace' : 'info'
|
|
97
|
-
const options =
|
|
98
|
-
globEnv === undefined ? { level } : (JSON.parse(globEnv) as { level?: LevelName })
|
|
99
|
-
|
|
100
|
-
console.configure({ level: options.level ?? level })
|
|
101
|
-
|
|
102
|
-
const tracesEnv = process.env[TRACES_ENV]
|
|
103
|
-
|
|
104
|
-
traces(
|
|
105
|
-
tracesEnv === undefined ? development() : (JSON.parse(tracesEnv) as TracesOptions)
|
|
106
|
-
)
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
/**
|
|
110
|
-
* Tracing is off unless it is configured. The console exporter is a local development
|
|
111
|
-
* mechanism, so it is turned on for `toa dev` and for a boot trace the CLI has already
|
|
112
|
-
* asked for (`runtime/boot/src/span.js`), and nowhere else — a deployment that wants
|
|
113
|
-
* traces annotates `telemetry.traces.exporters`.
|
|
114
|
-
*
|
|
115
|
-
* The gateway boots without the telemetry extension, hence the copy of
|
|
116
|
-
* `extensions/telemetry/source/extension.ts`.
|
|
117
|
-
*/
|
|
118
|
-
function development(): TracesOptions {
|
|
119
|
-
const local = process.env.TOA_DEV === '1' || process.env.TOA_BOOT_TRACE === '1'
|
|
120
|
-
|
|
121
|
-
return local ? { exporters: { console: {} } } : {}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
41
|
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
125
42
|
export type Host = extensions.Host
|
package/source/HTTP/Probe.ts
CHANGED
|
@@ -96,15 +96,4 @@ export class Probe {
|
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
98
|
|
|
99
|
-
/**
|
|
100
|
-
* Reserved for this probe. `8001` is the Telemetry readiness probe's, and `toa export` refuses a
|
|
101
|
-
* port claimed twice — `toa mono` and a local run put every service in one process.
|
|
102
|
-
*/
|
|
103
|
-
export const PROBE = 8004
|
|
104
99
|
export const PATH = '/.ready'
|
|
105
|
-
|
|
106
|
-
/**
|
|
107
|
-
* The initial delay of the readiness probe. The server does not sleep for it: whoever
|
|
108
|
-
* probes is the one that waits, and doing it here as well only delayed the process twice.
|
|
109
|
-
*/
|
|
110
|
-
export const DELAY = 3 // seconds
|
package/source/HTTP/Server.ts
CHANGED
|
@@ -10,7 +10,8 @@ import { Connector } from '@toa.io/core'
|
|
|
10
10
|
import { type OutgoingMessage, write } from './messages.js'
|
|
11
11
|
import { ClientError, Exception } from './exceptions.js'
|
|
12
12
|
import { Context } from './Context.js'
|
|
13
|
-
import {
|
|
13
|
+
import { Probe } from './Probe.js'
|
|
14
|
+
import { PORT, PROBE } from '../const.js'
|
|
14
15
|
import type { IncomingMessage, Protocol, ServerResponse } from './types.js'
|
|
15
16
|
import type { Bouncer, MCP, OAuth, RPC } from '../Annotation.js'
|
|
16
17
|
|
|
@@ -331,8 +332,6 @@ function errorAttributes(
|
|
|
331
332
|
return attributes
|
|
332
333
|
}
|
|
333
334
|
|
|
334
|
-
export const PORT = 8000
|
|
335
|
-
|
|
336
335
|
export const DRAIN = 10 // seconds
|
|
337
336
|
|
|
338
337
|
/** Megabytes a single HTTP/2 session may hold, over Node's default of 10. */
|
package/source/HTTP/messages.ts
CHANGED
|
@@ -5,13 +5,15 @@ import * as contentType from 'content-type'
|
|
|
5
5
|
import { console } from 'openspan'
|
|
6
6
|
import { type Format, decoders } from './formats/index.js'
|
|
7
7
|
import { BadRequest, NotAcceptable, UnsupportedMediaType } from './exceptions.js'
|
|
8
|
+
import { environment } from '@toa.io/generic'
|
|
8
9
|
import type { Context } from './Context.js'
|
|
9
10
|
import type { ServerResponse } from './types.js'
|
|
10
11
|
|
|
12
|
+
const context = environment.get('TOA_CONTEXT')
|
|
13
|
+
const env = environment.get('TOA_ENV')
|
|
11
14
|
const server =
|
|
12
15
|
`Exposition/${JSON.parse(readFileSync(new URL('../../package.json', import.meta.url), 'utf8')).version}` +
|
|
13
|
-
((
|
|
14
|
-
(process.env.TOA_ENV === undefined ? '' : `/${process.env.TOA_ENV}`))
|
|
16
|
+
((context === undefined ? '' : ` ${context}`) + (env === undefined ? '' : `/${env}`))
|
|
15
17
|
|
|
16
18
|
/**
|
|
17
19
|
* Applies what the request accumulated in `pipelines.response` — an `io:output` restriction,
|
package/source/Introspection.ts
CHANGED
|
@@ -13,6 +13,13 @@ export interface Introspection {
|
|
|
13
13
|
/** what a person is shown where a client lists this method, which a name is not */
|
|
14
14
|
title?: string
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* whether reaching it takes nothing at all — `auth:anonymous`. Said rather than left
|
|
18
|
+
* unsaid, because it is also what refuses a caller presenting a credential: a client
|
|
19
|
+
* cannot know that from an answer that says nothing.
|
|
20
|
+
*/
|
|
21
|
+
anonymous?: boolean
|
|
22
|
+
|
|
16
23
|
/** whether reaching it takes being someone, whoever — `auth:anyone` and its like */
|
|
17
24
|
authenticated?: boolean
|
|
18
25
|
|
|
@@ -29,11 +36,30 @@ export interface Introspection {
|
|
|
29
36
|
mcp?: boolean
|
|
30
37
|
route?: Record<string, Schema>
|
|
31
38
|
query?: Record<string, Schema>
|
|
39
|
+
|
|
40
|
+
/** what the body is, where it is a file rather than a value — [`octets:put`](octets.md) */
|
|
41
|
+
octets?: Octets
|
|
32
42
|
input?: Schema
|
|
33
43
|
output?: Schema
|
|
34
44
|
errors?: string[]
|
|
35
45
|
}
|
|
36
46
|
|
|
47
|
+
/** What sending a file to a resource takes, which is not something a schema states. */
|
|
48
|
+
export interface Octets {
|
|
49
|
+
/** what may be sent, in the syntax of an `accept` header; anything where unstated */
|
|
50
|
+
accept?: string
|
|
51
|
+
|
|
52
|
+
/** the largest body it takes, as it is written and as a refusal reports it */
|
|
53
|
+
limit: string
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Whether the reply arrives as a stream of parts rather than as one object: a workflow
|
|
57
|
+
* runs on what was stored, and each step answers as it finishes. The first part is the
|
|
58
|
+
* entry itself, which is what a caller that wants nothing else reads and stops.
|
|
59
|
+
*/
|
|
60
|
+
stream?: boolean
|
|
61
|
+
}
|
|
62
|
+
|
|
37
63
|
export type Schema = Awaited<ReturnType<Remote['explain']>>['input']
|
|
38
64
|
|
|
39
65
|
/**
|
|
@@ -64,6 +90,7 @@ export function order(introspection: Introspection): Introspection {
|
|
|
64
90
|
const KEYS = [
|
|
65
91
|
'title',
|
|
66
92
|
'description',
|
|
93
|
+
'anonymous',
|
|
67
94
|
'authenticated',
|
|
68
95
|
'private',
|
|
69
96
|
'protected',
|
|
@@ -71,6 +98,7 @@ const KEYS = [
|
|
|
71
98
|
'mcp',
|
|
72
99
|
'route',
|
|
73
100
|
'query',
|
|
101
|
+
'octets',
|
|
74
102
|
'input',
|
|
75
103
|
'output',
|
|
76
104
|
'errors'
|
package/source/const.ts
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export const BRANCH_TTL = 1_800_000
|
|
2
2
|
|
|
3
|
+
/** The broadcast the gateway and its tenants share. */
|
|
4
|
+
export const CHANNEL = 'exposition'
|
|
5
|
+
|
|
3
6
|
/** The replicas of the gateway decide together, whatever context they serve. */
|
|
4
7
|
export const ATOM_GROUP = 'exposition'
|
|
5
8
|
|
|
@@ -25,3 +28,18 @@ export const MCP = '/.mcp'
|
|
|
25
28
|
* on that path already answers to the same caller, and what it adds is the enumeration.
|
|
26
29
|
*/
|
|
27
30
|
export const DISCOVERY = '/.discovery'
|
|
31
|
+
|
|
32
|
+
/** Where the gateway serves. */
|
|
33
|
+
export const PORT = 8000
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Reserved for the readiness probe. `8001` is the Telemetry readiness probe's, and `toa export`
|
|
37
|
+
* refuses a port claimed twice — `toa mono` and a local run put every service in one process.
|
|
38
|
+
*/
|
|
39
|
+
export const PROBE = 8004
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The initial delay of the readiness probe. The server does not sleep for it: whoever
|
|
43
|
+
* probes is the one that waits, and doing it here as well only delayed the process twice.
|
|
44
|
+
*/
|
|
45
|
+
export const DELAY = 3 // seconds
|
package/source/deployment.ts
CHANGED
|
@@ -3,10 +3,10 @@ import assert from 'node:assert'
|
|
|
3
3
|
import { type Dependency, type Service } from '@toa.io/operations'
|
|
4
4
|
import { type Annotation } from './Annotation.js'
|
|
5
5
|
import * as schemas from './schemas.js'
|
|
6
|
-
import { shortcuts } from './
|
|
6
|
+
import { shortcuts } from './shortcuts.js'
|
|
7
7
|
import { components } from './Composition.js'
|
|
8
8
|
import { parse } from './RTD/syntax/index.js'
|
|
9
|
-
import { DELAY, PORT, PROBE } from './
|
|
9
|
+
import { DELAY, PORT, PROBE } from './const.js'
|
|
10
10
|
|
|
11
11
|
/** Where Toa's release publishes this service's image. An application takes it
|
|
12
12
|
* instead of building one when its context says `registry.services: published`. */
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type Directive, type Context } from './types.js'
|
|
2
|
+
import type { Introspection } from '../../Introspection.js'
|
|
2
3
|
|
|
3
4
|
export class Anonymous implements Directive {
|
|
4
5
|
private readonly allow: boolean
|
|
@@ -23,4 +24,13 @@ export class Anonymous implements Directive {
|
|
|
23
24
|
public admits(_: any, context: Context): boolean {
|
|
24
25
|
return this.authorize(_, context)
|
|
25
26
|
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* That nothing guards it is something said rather than something left unsaid: it is also
|
|
30
|
+
* what refuses a caller presenting a credential, and a client with one has to know which
|
|
31
|
+
* methods not to present it to.
|
|
32
|
+
*/
|
|
33
|
+
public describe(introspection: Introspection): Introspection {
|
|
34
|
+
return this.allow ? { ...introspection, anonymous: true } : introspection
|
|
35
|
+
}
|
|
26
36
|
}
|
|
@@ -47,9 +47,13 @@ export class Family implements DirectiveFamily<Directive> {
|
|
|
47
47
|
directives: Directive[],
|
|
48
48
|
_: Context,
|
|
49
49
|
introspection: Introspection
|
|
50
|
-
): Introspection {
|
|
50
|
+
): Introspection | null {
|
|
51
51
|
const help = Family.method(directives)
|
|
52
52
|
|
|
53
|
+
// what is hidden is hidden from every answer at once, this being the one place they
|
|
54
|
+
// all read; the method itself is reached as it always was
|
|
55
|
+
if (help?.hidden === true) return null
|
|
56
|
+
|
|
53
57
|
const described: Introspection = {
|
|
54
58
|
...introspection,
|
|
55
59
|
...(help?.title === undefined ? {} : { title: help.title }),
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
1
2
|
import { described, type Described } from './described.js'
|
|
2
3
|
|
|
3
4
|
/**
|
|
@@ -14,10 +15,30 @@ export class Help {
|
|
|
14
15
|
public readonly title: string | undefined
|
|
15
16
|
public readonly description: string | undefined
|
|
16
17
|
|
|
18
|
+
/**
|
|
19
|
+
* Whether the method is described at all. `help:method: null` takes it out of every
|
|
20
|
+
* answer — `OPTIONS`, discovery and the tools MCP publishes — and leaves it as callable
|
|
21
|
+
* as it was: a route something else reaches for, and nobody is meant to go looking for.
|
|
22
|
+
*/
|
|
23
|
+
public readonly hidden: boolean
|
|
24
|
+
|
|
17
25
|
public constructor(subject: Subject, value: unknown) {
|
|
26
|
+
assert.ok(
|
|
27
|
+
value !== null || subject === 'method',
|
|
28
|
+
`Directive help:${subject}: only a method is hidden`
|
|
29
|
+
)
|
|
30
|
+
|
|
31
|
+
if (value === null) {
|
|
32
|
+
this.subject = subject
|
|
33
|
+
this.hidden = true
|
|
34
|
+
|
|
35
|
+
return
|
|
36
|
+
}
|
|
37
|
+
|
|
18
38
|
const stated: Described = described(`help:${subject}`, value)
|
|
19
39
|
|
|
20
40
|
this.subject = subject
|
|
41
|
+
this.hidden = false
|
|
21
42
|
this.title = stated.title
|
|
22
43
|
this.description = stated.description
|
|
23
44
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Input } from './types.js'
|
|
2
2
|
import type { Parameter } from '../../RTD/index.js'
|
|
3
|
+
import type { Introspection } from '../../Introspection.js'
|
|
3
4
|
import type * as io from '../../io.js'
|
|
4
5
|
|
|
5
6
|
export abstract class Directive {
|
|
@@ -11,4 +12,10 @@ export abstract class Directive {
|
|
|
11
12
|
input: Input,
|
|
12
13
|
parameters: Parameter[]
|
|
13
14
|
): Promise<io.Output>
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* What a caller has to know to make the request. Only sending a file takes anything a
|
|
18
|
+
* schema does not already say; reading one and deleting one take nothing.
|
|
19
|
+
*/
|
|
20
|
+
public describe?(introspection: Introspection): void
|
|
14
21
|
}
|
|
@@ -9,6 +9,7 @@ import type { Output } from '../../io.js'
|
|
|
9
9
|
import type { Component } from '@toa.io/core'
|
|
10
10
|
import type { Remotes } from '../../Remotes.js'
|
|
11
11
|
import type { Parameter, DirectiveFamily } from '../../RTD/index.js'
|
|
12
|
+
import type { Introspection } from '../../Introspection.js'
|
|
12
13
|
import type { Input } from './types.js'
|
|
13
14
|
|
|
14
15
|
export class Octets implements DirectiveFamily<Directive> {
|
|
@@ -28,6 +29,13 @@ export class Octets implements DirectiveFamily<Directive> {
|
|
|
28
29
|
return new Class(value, this.discovery, remotes)
|
|
29
30
|
}
|
|
30
31
|
|
|
32
|
+
/** What the request takes, which only sending a file says anything about. */
|
|
33
|
+
public explain(directives: Directive[], _: Input, introspection: Introspection): Introspection {
|
|
34
|
+
for (const directive of directives) directive.describe?.(introspection)
|
|
35
|
+
|
|
36
|
+
return introspection
|
|
37
|
+
}
|
|
38
|
+
|
|
31
39
|
public async precall(
|
|
32
40
|
directives: Directive[],
|
|
33
41
|
input: Input,
|
|
@@ -12,6 +12,7 @@ import type { Unit, Location } from './workflows/index.js'
|
|
|
12
12
|
import type { Entry } from '@toa.io/extensions.storages'
|
|
13
13
|
import type { Remotes } from '../../Remotes.js'
|
|
14
14
|
import type { Component } from '@toa.io/core'
|
|
15
|
+
import type { Introspection } from '../../Introspection.js'
|
|
15
16
|
import type { Output } from '../../io.js'
|
|
16
17
|
import type { Input } from './types.js'
|
|
17
18
|
|
|
@@ -63,6 +64,15 @@ export class Put extends Directive {
|
|
|
63
64
|
cors.allow('content-location')
|
|
64
65
|
}
|
|
65
66
|
|
|
67
|
+
/** What sending a file here takes: what may be sent, how much of it, and what comes back. */
|
|
68
|
+
public override describe(introspection: Introspection): void {
|
|
69
|
+
introspection.octets = {
|
|
70
|
+
...(this.accept === undefined ? {} : { accept: this.accept }),
|
|
71
|
+
limit: this.limitString,
|
|
72
|
+
...(this.workflow === undefined ? {} : { stream: true })
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
66
76
|
public async apply(
|
|
67
77
|
storage: string,
|
|
68
78
|
input: Input,
|
package/source/manifest.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import assert from 'node:assert'
|
|
2
2
|
import { parse, type Node, type Method, type Query } from './RTD/syntax/index.js'
|
|
3
|
-
import { shortcuts } from './
|
|
3
|
+
import { shortcuts } from './shortcuts.js'
|
|
4
4
|
import * as schemas from './schemas.js'
|
|
5
5
|
import type { Manifest } from '@toa.io/norm'
|
|
6
6
|
|
package/source/root.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { merge } from '@toa.io/generic'
|
|
1
|
+
import { environment, merge } from '@toa.io/generic'
|
|
2
2
|
import { syntax } from './RTD/index.js'
|
|
3
3
|
|
|
4
4
|
export function resolve(): syntax.Node {
|
|
5
|
-
const value =
|
|
5
|
+
const value = environment.get('TOA_EXPOSITION')
|
|
6
6
|
const root =
|
|
7
7
|
value !== undefined ? (JSON.parse(value) as syntax.Node) : syntax.createNode()
|
|
8
8
|
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import assert from 'node:assert'
|
|
2
|
+
import { console, traces, type LevelName, type TracesOptions } from 'openspan'
|
|
3
|
+
import { Gateway } from './Gateway.js'
|
|
4
|
+
import { Remotes } from './Remotes.js'
|
|
5
|
+
import { Tree } from './RTD/index.js'
|
|
6
|
+
import { EndpointsFactory } from './Endpoint.js'
|
|
7
|
+
import { families, interceptors } from './directives/index.js'
|
|
8
|
+
import { DirectivesFactory } from './Directive.js'
|
|
9
|
+
import { Composition } from './Composition.js'
|
|
10
|
+
import * as root from './root.js'
|
|
11
|
+
import { ATOM_GROUP, CHANNEL } from './const.js'
|
|
12
|
+
import { Interception } from './Interception.js'
|
|
13
|
+
import { Dispatcher } from './RPC/index.js'
|
|
14
|
+
import { Server as Model } from './MCP/index.js'
|
|
15
|
+
import * as http from './HTTP/index.js'
|
|
16
|
+
import { environment } from '@toa.io/generic'
|
|
17
|
+
import type { Broadcast } from './Gateway.js'
|
|
18
|
+
import type { Connector } from '@toa.io/core'
|
|
19
|
+
import type { Host } from './Factory.js'
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* The gateway. A composition loads this extension for its tenants alone, so what the
|
|
23
|
+
* gateway is made of is reached from here and nowhere the factory imports.
|
|
24
|
+
*/
|
|
25
|
+
export async function service(host: Host): Promise<Connector | null> {
|
|
26
|
+
const properties = environment.get('TOA_EXPOSITION_PROPERTIES')
|
|
27
|
+
|
|
28
|
+
assert.ok(properties !== undefined, 'TOA_EXPOSITION_PROPERTIES is undefined')
|
|
29
|
+
|
|
30
|
+
configureLogs()
|
|
31
|
+
|
|
32
|
+
const options = JSON.parse(properties) as http.Options
|
|
33
|
+
const broadcast: Broadcast = await host.broadcast(CHANNEL)
|
|
34
|
+
const server = http.Server.create({ ...options })
|
|
35
|
+
const remotes = new Remotes(host)
|
|
36
|
+
const node = root.resolve()
|
|
37
|
+
const methods = new EndpointsFactory(remotes)
|
|
38
|
+
const directives = new DirectivesFactory(families, remotes, host, options)
|
|
39
|
+
const interception = new Interception(interceptors, options)
|
|
40
|
+
const tree = new Tree(node, methods, directives)
|
|
41
|
+
|
|
42
|
+
const composition = new Composition(host)
|
|
43
|
+
const dispatcher = options.rpc === undefined ? null : new Dispatcher(options.rpc)
|
|
44
|
+
const mcp = options.mcp === undefined ? null : new Model(options.mcp, tree)
|
|
45
|
+
const gateway = new Gateway(broadcast, tree, interception, directives, dispatcher, mcp)
|
|
46
|
+
|
|
47
|
+
gateway.depends(remotes)
|
|
48
|
+
gateway.depends(composition)
|
|
49
|
+
// what the directives meter through; one atom per process, connected once
|
|
50
|
+
gateway.depends(host.atom(ATOM_GROUP))
|
|
51
|
+
|
|
52
|
+
server.attach(gateway.process.bind(gateway))
|
|
53
|
+
server.depends(gateway)
|
|
54
|
+
|
|
55
|
+
return server
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const LOGS_PREFIX = 'TOA_TELEMETRY_LOGS'
|
|
59
|
+
const TRACES_ENV = 'TOA_TELEMETRY_TRACES'
|
|
60
|
+
|
|
61
|
+
function configureLogs(): void {
|
|
62
|
+
const globEnv = environment.get(LOGS_PREFIX)
|
|
63
|
+
const level: LevelName = environment.get('TOA_DEV') === '1' ? 'trace' : 'info'
|
|
64
|
+
const options =
|
|
65
|
+
globEnv === undefined ? { level } : (JSON.parse(globEnv) as { level?: LevelName })
|
|
66
|
+
|
|
67
|
+
console.configure({ level: options.level ?? level })
|
|
68
|
+
|
|
69
|
+
const tracesEnv = environment.get(TRACES_ENV)
|
|
70
|
+
const tracing =
|
|
71
|
+
tracesEnv === undefined ? development() : (JSON.parse(tracesEnv) as TracesOptions)
|
|
72
|
+
|
|
73
|
+
// `openspan` is not Toa's and reads the environment, which no longer holds the context by
|
|
74
|
+
// the time the exporter is made — so the service is named here
|
|
75
|
+
if (tracing.exporters?.otlp !== undefined)
|
|
76
|
+
tracing.exporters.otlp.service ??= environment.get('TOA_CONTEXT')
|
|
77
|
+
|
|
78
|
+
traces(tracing)
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Tracing is off unless it is configured. The console exporter is a local development
|
|
83
|
+
* mechanism, so it is turned on for `toa dev` and for a boot trace the CLI has already
|
|
84
|
+
* asked for (`runtime/boot/src/span.js`), and nowhere else — a deployment that wants
|
|
85
|
+
* traces annotates `telemetry.traces.exporters`.
|
|
86
|
+
*
|
|
87
|
+
* The gateway boots without the telemetry extension, hence the copy of
|
|
88
|
+
* `extensions/telemetry/source/extension.ts`.
|
|
89
|
+
*/
|
|
90
|
+
function development(): TracesOptions {
|
|
91
|
+
const local = environment.get('TOA_DEV') === '1' || environment.get('TOA_BOOT_TRACE') === '1'
|
|
92
|
+
|
|
93
|
+
return local ? { exporters: { console: {} } } : {}
|
|
94
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Shortcuts } from './RTD/syntax/index.js'
|
|
2
|
+
|
|
3
|
+
/** What a directive may be written as, where the family is implied. */
|
|
4
|
+
export const shortcuts: Shortcuts = new Map([
|
|
5
|
+
['anonymous', 'auth:anonymous'],
|
|
6
|
+
['anyone', 'auth:anyone'],
|
|
7
|
+
['id', 'auth:id'],
|
|
8
|
+
['role', 'auth:role'],
|
|
9
|
+
['rule', 'auth:rule'],
|
|
10
|
+
['incept', 'auth:incept'],
|
|
11
|
+
['input', 'io:input'],
|
|
12
|
+
['output', 'io:output'],
|
|
13
|
+
['languages', 'map:languages']
|
|
14
|
+
])
|
package/transpiled/Directive.js
CHANGED
|
@@ -160,15 +160,4 @@ function options(set, stage) {
|
|
|
160
160
|
options.attributes = { directives: Array.from(new Set(set.names)).join(' ') };
|
|
161
161
|
return options;
|
|
162
162
|
}
|
|
163
|
-
export const shortcuts = new Map([
|
|
164
|
-
['anonymous', 'auth:anonymous'],
|
|
165
|
-
['anyone', 'auth:anyone'],
|
|
166
|
-
['id', 'auth:id'],
|
|
167
|
-
['role', 'auth:role'],
|
|
168
|
-
['rule', 'auth:rule'],
|
|
169
|
-
['incept', 'auth:incept'],
|
|
170
|
-
['input', 'io:input'],
|
|
171
|
-
['output', 'io:output'],
|
|
172
|
-
['languages', 'map:languages']
|
|
173
|
-
]);
|
|
174
163
|
//# sourceMappingURL=Directive.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Directive.js","sourceRoot":"","sources":["../source/Directive.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"Directive.js","sourceRoot":"","sources":["../source/Directive.ts"],"names":[],"mappings":"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"}
|
|
@@ -4,7 +4,10 @@ import type { Context, OutgoingMessage } from '../HTTP/index.js';
|
|
|
4
4
|
* and `/` is usually not one of those — a person who typed the address into a browser is
|
|
5
5
|
* looking for something to look at, and the page is the only thing here that is one.
|
|
6
6
|
*
|
|
7
|
-
* A client that
|
|
8
|
-
*
|
|
7
|
+
* A client that asked for something in particular gets what it asked for: only an `accept`
|
|
8
|
+
* that prefers a page, or one that names no preference at all, is sent here. The second is
|
|
9
|
+
* what an unfurler sends — several ask for anything, and a link to an application would
|
|
10
|
+
* otherwise show nothing — and what `curl` sends, which the page serves no worse than the
|
|
11
|
+
* `405` it used to get.
|
|
9
12
|
*/
|
|
10
13
|
export declare function looking(context: Context): OutgoingMessage | null;
|
|
@@ -8,14 +8,22 @@ const HTML = 'text/html';
|
|
|
8
8
|
* and `/` is usually not one of those — a person who typed the address into a browser is
|
|
9
9
|
* looking for something to look at, and the page is the only thing here that is one.
|
|
10
10
|
*
|
|
11
|
-
* A client that
|
|
12
|
-
*
|
|
11
|
+
* A client that asked for something in particular gets what it asked for: only an `accept`
|
|
12
|
+
* that prefers a page, or one that names no preference at all, is sent here. The second is
|
|
13
|
+
* what an unfurler sends — several ask for anything, and a link to an application would
|
|
14
|
+
* otherwise show nothing — and what `curl` sends, which the page serves no worse than the
|
|
15
|
+
* `405` it used to get.
|
|
13
16
|
*/
|
|
14
17
|
export function looking(context) {
|
|
15
18
|
if (context.request.method !== 'GET' || context.procedural)
|
|
16
19
|
return null;
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
const accept = context.request.headers.accept;
|
|
21
|
+
if (accept !== undefined && accept.trim() !== ANYTHING) {
|
|
22
|
+
if (new Negotiator(context.request).mediaType([...types, HTML]) !== HTML)
|
|
23
|
+
return null;
|
|
24
|
+
}
|
|
19
25
|
return { status: 302, headers: new Headers({ location: DISCOVERY + '/' }) };
|
|
20
26
|
}
|
|
27
|
+
/** An `accept` that names nothing, which is the same as naming none. */
|
|
28
|
+
const ANYTHING = '*/*';
|
|
21
29
|
//# sourceMappingURL=trunk.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"trunk.js","sourceRoot":"","sources":["../../source/Discovery/trunk.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,YAAY,CAAA;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAGvC,wEAAwE;AACxE,MAAM,IAAI,GAAG,WAAW,CAAA;AAExB
|
|
1
|
+
{"version":3,"file":"trunk.js","sourceRoot":"","sources":["../../source/Discovery/trunk.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,YAAY,CAAA;AACnC,OAAO,EAAE,KAAK,EAAE,MAAM,0BAA0B,CAAA;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAA;AAGvC,wEAAwE;AACxE,MAAM,IAAI,GAAG,WAAW,CAAA;AAExB;;;;;;;;;;GAUG;AACH,MAAM,UAAU,OAAO,CAAC,OAAgB;IACtC,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,KAAK,IAAI,OAAO,CAAC,UAAU;QAAE,OAAO,IAAI,CAAA;IAEvE,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAA;IAE7C,IAAI,MAAM,KAAK,SAAS,IAAI,MAAM,CAAC,IAAI,EAAE,KAAK,QAAQ,EAAE,CAAC;QACvD,IAAI,IAAI,UAAU,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,IAAI;YAAE,OAAO,IAAI,CAAA;IACvF,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,OAAO,EAAE,IAAI,OAAO,CAAC,EAAE,QAAQ,EAAE,SAAS,GAAG,GAAG,EAAE,CAAC,EAAE,CAAA;AAC7E,CAAC;AAED,wEAAwE;AACxE,MAAM,QAAQ,GAAG,KAAK,CAAA"}
|