@toa.io/extensions.exposition 1.0.0-alpha.286 → 1.0.0-alpha.288

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.
Files changed (219) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/components/identity.basic/tsconfig.tsbuildinfo +1 -1
  3. package/components/identity.clients/tsconfig.tsbuildinfo +1 -1
  4. package/components/identity.credentials/tsconfig.tsbuildinfo +1 -1
  5. package/components/identity.federation/tsconfig.tsbuildinfo +1 -1
  6. package/components/identity.grants/tsconfig.tsbuildinfo +1 -1
  7. package/components/identity.keys/tsconfig.tsbuildinfo +1 -1
  8. package/components/identity.otp/tsconfig.tsbuildinfo +1 -1
  9. package/components/identity.passkeys/manifest.toa.yaml +2 -1
  10. package/components/identity.passkeys/source/errors.test.ts +34 -0
  11. package/components/identity.passkeys/source/webauthn.test.ts +26 -0
  12. package/components/identity.passkeys/tsconfig.tsbuildinfo +1 -1
  13. package/components/identity.passkeys/types/toa.d.ts +1 -1
  14. package/components/identity.tokens/tsconfig.tsbuildinfo +1 -1
  15. package/documentation/access.md +22 -4
  16. package/documentation/discovery.md +81 -0
  17. package/documentation/help.md +109 -0
  18. package/documentation/introspection.md +34 -9
  19. package/documentation/mcp.md +13 -16
  20. package/features/cors.feature +31 -1
  21. package/features/dev.feature +2 -0
  22. package/features/discovery.feature +211 -0
  23. package/features/discovery.ui.feature +197 -0
  24. package/features/help.feature +466 -0
  25. package/features/introspection.feature +94 -8
  26. package/features/map.feature +1 -0
  27. package/features/mcp.feature +74 -12
  28. package/features/methods.feature +2 -1
  29. package/features/oauth.grants.feature +3 -1
  30. package/features/octets.download.feature +1 -0
  31. package/features/octets.meta.feature +1 -0
  32. package/features/site/_app/immutable/asset.js +1 -0
  33. package/features/site/favicon.ico +0 -0
  34. package/features/site/index.html +10 -0
  35. package/features/steps/Parameters.ts +12 -0
  36. package/package.json +6 -4
  37. package/readme.md +3 -0
  38. package/source/Directive.ts +4 -0
  39. package/source/Discovery/Explorer.ts +34 -0
  40. package/source/Discovery/Site.test.ts +147 -0
  41. package/source/Discovery/Site.ts +202 -0
  42. package/source/Discovery/index.ts +3 -0
  43. package/source/Discovery/tree.test.ts +175 -0
  44. package/source/Discovery/tree.ts +77 -0
  45. package/source/Discovery/trunk.ts +23 -0
  46. package/source/Endpoint.ts +4 -0
  47. package/source/Gateway.ts +34 -4
  48. package/source/HTTP/Context.ts +7 -0
  49. package/source/Introspection.ts +33 -10
  50. package/source/MCP/schema.ts +16 -5
  51. package/source/MCP/tools.ts +14 -32
  52. package/source/Mapping.ts +5 -0
  53. package/source/Query.ts +17 -2
  54. package/source/RTD/Directives.ts +10 -0
  55. package/source/RTD/Endpoint.ts +8 -1
  56. package/source/RTD/Node.ts +20 -6
  57. package/source/RTD/Tree.ts +19 -9
  58. package/source/RTD/factory.ts +37 -1
  59. package/source/RTD/segment.ts +21 -0
  60. package/source/const.ts +8 -0
  61. package/source/directives/auth/Anonymous.test.ts +31 -5
  62. package/source/directives/auth/Anonymous.ts +5 -3
  63. package/source/directives/auth/Anyone.ts +6 -0
  64. package/source/directives/auth/Assert.ts +5 -0
  65. package/source/directives/auth/Delegate.ts +5 -2
  66. package/source/directives/auth/Federation.ts +11 -0
  67. package/source/directives/auth/Id.ts +15 -0
  68. package/source/directives/auth/Input.ts +5 -0
  69. package/source/directives/auth/Role.ts +17 -0
  70. package/source/directives/cors/CORS.test.ts +75 -0
  71. package/source/directives/cors/CORS.ts +10 -3
  72. package/source/directives/help/Family.ts +118 -0
  73. package/source/directives/help/Help.test.ts +227 -0
  74. package/source/directives/help/Help.ts +26 -0
  75. package/source/directives/help/Parameters.ts +47 -0
  76. package/source/directives/help/described.ts +57 -0
  77. package/source/directives/help/index.ts +45 -0
  78. package/source/directives/index.ts +8 -1
  79. package/source/directives/map/Headers.ts +6 -6
  80. package/source/directives/mcp/MCP.ts +12 -21
  81. package/source/directives/mcp/Tool.test.ts +22 -68
  82. package/source/directives/mcp/Tool.ts +14 -41
  83. package/transpiled/Directive.d.ts +1 -0
  84. package/transpiled/Directive.js +3 -0
  85. package/transpiled/Directive.js.map +1 -1
  86. package/transpiled/Discovery/Explorer.d.ts +11 -0
  87. package/transpiled/Discovery/Explorer.js +29 -0
  88. package/transpiled/Discovery/Explorer.js.map +1 -0
  89. package/transpiled/Discovery/Site.d.ts +43 -0
  90. package/transpiled/Discovery/Site.js +171 -0
  91. package/transpiled/Discovery/Site.js.map +1 -0
  92. package/transpiled/Discovery/index.d.ts +3 -0
  93. package/transpiled/Discovery/index.js +4 -0
  94. package/transpiled/Discovery/index.js.map +1 -0
  95. package/transpiled/Discovery/tree.d.ts +26 -0
  96. package/transpiled/Discovery/tree.js +50 -0
  97. package/transpiled/Discovery/tree.js.map +1 -0
  98. package/transpiled/Discovery/trunk.d.ts +10 -0
  99. package/transpiled/Discovery/trunk.js +21 -0
  100. package/transpiled/Discovery/trunk.js.map +1 -0
  101. package/transpiled/Endpoint.d.ts +2 -1
  102. package/transpiled/Endpoint.js +3 -0
  103. package/transpiled/Endpoint.js.map +1 -1
  104. package/transpiled/Gateway.d.ts +4 -0
  105. package/transpiled/Gateway.js +29 -4
  106. package/transpiled/Gateway.js.map +1 -1
  107. package/transpiled/HTTP/Context.d.ts +6 -0
  108. package/transpiled/HTTP/Context.js +6 -0
  109. package/transpiled/HTTP/Context.js.map +1 -1
  110. package/transpiled/Introspection.d.ts +18 -7
  111. package/transpiled/Introspection.js +16 -1
  112. package/transpiled/Introspection.js.map +1 -1
  113. package/transpiled/MCP/schema.d.ts +2 -2
  114. package/transpiled/MCP/schema.js +11 -5
  115. package/transpiled/MCP/schema.js.map +1 -1
  116. package/transpiled/MCP/tools.d.ts +1 -1
  117. package/transpiled/MCP/tools.js +12 -28
  118. package/transpiled/MCP/tools.js.map +1 -1
  119. package/transpiled/Mapping.d.ts +2 -0
  120. package/transpiled/Mapping.js +4 -0
  121. package/transpiled/Mapping.js.map +1 -1
  122. package/transpiled/Query.d.ts +12 -0
  123. package/transpiled/Query.js +16 -2
  124. package/transpiled/Query.js.map +1 -1
  125. package/transpiled/RTD/Directives.d.ts +8 -0
  126. package/transpiled/RTD/Endpoint.d.ts +7 -1
  127. package/transpiled/RTD/Node.d.ts +11 -2
  128. package/transpiled/RTD/Node.js +12 -2
  129. package/transpiled/RTD/Node.js.map +1 -1
  130. package/transpiled/RTD/Tree.js +15 -8
  131. package/transpiled/RTD/Tree.js.map +1 -1
  132. package/transpiled/RTD/factory.js +27 -1
  133. package/transpiled/RTD/factory.js.map +1 -1
  134. package/transpiled/RTD/segment.d.ts +7 -0
  135. package/transpiled/RTD/segment.js +17 -0
  136. package/transpiled/RTD/segment.js.map +1 -1
  137. package/transpiled/const.d.ts +7 -0
  138. package/transpiled/const.js +7 -0
  139. package/transpiled/const.js.map +1 -1
  140. package/transpiled/directives/auth/Anonymous.d.ts +4 -2
  141. package/transpiled/directives/auth/Anonymous.js +5 -3
  142. package/transpiled/directives/auth/Anonymous.js.map +1 -1
  143. package/transpiled/directives/auth/Anyone.d.ts +3 -0
  144. package/transpiled/directives/auth/Anyone.js +4 -0
  145. package/transpiled/directives/auth/Anyone.js.map +1 -1
  146. package/transpiled/directives/auth/Assert.d.ts +2 -0
  147. package/transpiled/directives/auth/Assert.js +4 -0
  148. package/transpiled/directives/auth/Assert.js.map +1 -1
  149. package/transpiled/directives/auth/Delegate.d.ts +4 -1
  150. package/transpiled/directives/auth/Delegate.js +5 -2
  151. package/transpiled/directives/auth/Delegate.js.map +1 -1
  152. package/transpiled/directives/auth/Federation.d.ts +5 -0
  153. package/transpiled/directives/auth/Federation.js +8 -0
  154. package/transpiled/directives/auth/Federation.js.map +1 -1
  155. package/transpiled/directives/auth/Id.d.ts +9 -0
  156. package/transpiled/directives/auth/Id.js +12 -0
  157. package/transpiled/directives/auth/Id.js.map +1 -1
  158. package/transpiled/directives/auth/Input.d.ts +2 -0
  159. package/transpiled/directives/auth/Input.js +4 -0
  160. package/transpiled/directives/auth/Input.js.map +1 -1
  161. package/transpiled/directives/auth/Role.d.ts +7 -0
  162. package/transpiled/directives/auth/Role.js +11 -0
  163. package/transpiled/directives/auth/Role.js.map +1 -1
  164. package/transpiled/directives/cors/CORS.js +9 -2
  165. package/transpiled/directives/cors/CORS.js.map +1 -1
  166. package/transpiled/directives/help/Family.d.ts +28 -0
  167. package/transpiled/directives/help/Family.js +79 -0
  168. package/transpiled/directives/help/Family.js.map +1 -0
  169. package/transpiled/directives/help/Help.d.ts +16 -0
  170. package/transpiled/directives/help/Help.js +22 -0
  171. package/transpiled/directives/help/Help.js.map +1 -0
  172. package/transpiled/directives/help/Parameters.d.ts +18 -0
  173. package/transpiled/directives/help/Parameters.js +34 -0
  174. package/transpiled/directives/help/Parameters.js.map +1 -0
  175. package/transpiled/directives/help/described.d.ts +16 -0
  176. package/transpiled/directives/help/described.js +23 -0
  177. package/transpiled/directives/help/described.js.map +1 -0
  178. package/transpiled/directives/help/index.d.ts +22 -0
  179. package/transpiled/directives/help/index.js +34 -0
  180. package/transpiled/directives/help/index.js.map +1 -0
  181. package/transpiled/directives/index.d.ts +4 -0
  182. package/transpiled/directives/index.js +8 -1
  183. package/transpiled/directives/index.js.map +1 -1
  184. package/transpiled/directives/map/Headers.d.ts +5 -0
  185. package/transpiled/directives/map/Headers.js +7 -5
  186. package/transpiled/directives/map/Headers.js.map +1 -1
  187. package/transpiled/directives/mcp/MCP.d.ts +8 -5
  188. package/transpiled/directives/mcp/MCP.js +9 -13
  189. package/transpiled/directives/mcp/MCP.js.map +1 -1
  190. package/transpiled/directives/mcp/Tool.d.ts +6 -12
  191. package/transpiled/directives/mcp/Tool.js +10 -23
  192. package/transpiled/directives/mcp/Tool.js.map +1 -1
  193. package/tsconfig.tsbuildinfo +1 -1
  194. package/ui/dist/_app/env.js +1 -0
  195. package/ui/dist/_app/immutable/assets/0.BcIGtTfw.css +2 -0
  196. package/ui/dist/_app/immutable/assets/2.BC0-Jhqu.css +1 -0
  197. package/ui/dist/_app/immutable/assets/inter-cyrillic-ext-wght-normal.BOeWTOD4.woff2 +0 -0
  198. package/ui/dist/_app/immutable/assets/inter-cyrillic-wght-normal.DqGufNeO.woff2 +0 -0
  199. package/ui/dist/_app/immutable/assets/inter-greek-ext-wght-normal.DlzME5K_.woff2 +0 -0
  200. package/ui/dist/_app/immutable/assets/inter-greek-wght-normal.CkhJZR-_.woff2 +0 -0
  201. package/ui/dist/_app/immutable/assets/inter-latin-ext-wght-normal.DO1Apj_S.woff2 +0 -0
  202. package/ui/dist/_app/immutable/assets/inter-latin-wght-normal.Dx4kXJAl.woff2 +0 -0
  203. package/ui/dist/_app/immutable/assets/inter-vietnamese-wght-normal.CBcvBZtf.woff2 +0 -0
  204. package/ui/dist/_app/immutable/chunks/BgTrzN6u.js +1 -0
  205. package/ui/dist/_app/immutable/chunks/Bjy-W4x2.js +81 -0
  206. package/ui/dist/_app/immutable/chunks/CWJaG9mK.js +6 -0
  207. package/ui/dist/_app/immutable/chunks/DjIYL2zC.js +3 -0
  208. package/ui/dist/_app/immutable/chunks/xihTtKlq.js +1 -0
  209. package/ui/dist/_app/immutable/chunks/yDQhitF9.js +1 -0
  210. package/ui/dist/_app/immutable/entry/app.WZSMBcGf.js +2 -0
  211. package/ui/dist/_app/immutable/entry/start._LkoC6Lz.js +1 -0
  212. package/ui/dist/_app/immutable/nodes/0.Dl2DqINo.js +1 -0
  213. package/ui/dist/_app/immutable/nodes/1.CSSnGhVD.js +1 -0
  214. package/ui/dist/_app/immutable/nodes/2.DmolQyNG.js +14 -0
  215. package/ui/dist/_app/version.json +1 -0
  216. package/ui/dist/apple-touch-icon.png +0 -0
  217. package/ui/dist/favicon-96x96.png +0 -0
  218. package/ui/dist/favicon.ico +0 -0
  219. package/ui/dist/index.html +66 -0
@@ -29,13 +29,13 @@ export class Headers extends Mapping<Record<string, string>> {
29
29
  this.headers.forEach((header) => cors.allow(header))
30
30
  }
31
31
 
32
+ /**
33
+ * The property is filled from a request header, so it is not the body's to send. Which
34
+ * header, and that there is one at all, is not answered: what an application reads off a
35
+ * request is its own, and a caller has nowhere to put one anyway.
36
+ */
32
37
  public override explain(introspection: Introspection): void {
33
- for (const [property, header] of Object.entries(this.value)) {
34
- const schema = take(introspection, property)
35
-
36
- introspection.headers ??= {}
37
- introspection.headers[property] = { ...schema, header }
38
- }
38
+ for (const property of Object.keys(this.value)) take(introspection, property)
39
39
  }
40
40
 
41
41
  public properties(context: Input): Record<string, string> {
@@ -1,8 +1,8 @@
1
1
  import assert from 'node:assert'
2
2
  import { Tool } from './Tool.js'
3
+ import type { DirectiveFamily } from '../../RTD/index.js'
3
4
  import type { Context } from '../../HTTP/index.js'
4
5
  import type { Introspection } from '../../Introspection.js'
5
- import type { DirectiveFamily } from '../../RTD/index.js'
6
6
 
7
7
  /** The name the family is declared under, and what `MCP` asks a method for. */
8
8
  export const FAMILY = 'mcp'
@@ -11,9 +11,17 @@ export class MCP implements DirectiveFamily<Tool> {
11
11
  public readonly name = FAMILY
12
12
  public readonly mandatory = false
13
13
 
14
- /** What this method is published as, which is what the nearest declaration says. */
15
- public static published(directives: Tool[] | undefined): Tool | null {
16
- return directives?.[0] ?? null
14
+ /** Whether this method is published, which is what the nearest declaration says. */
15
+ public static published(directives: Tool[] | undefined): boolean {
16
+ return directives?.[0]?.published ?? false
17
+ }
18
+
19
+ /**
20
+ * Whether this method is published to a model, which is what the route declares. Whether
21
+ * one is served at all is the annotation's, and a route says nothing of that.
22
+ */
23
+ public explain(directives: Tool[], _: Context, introspection: Introspection): Introspection {
24
+ return MCP.published(directives) ? { ...introspection, mcp: true } : introspection
17
25
  }
18
26
 
19
27
  // eslint-disable-next-line max-params
@@ -22,21 +30,4 @@ export class MCP implements DirectiveFamily<Tool> {
22
30
 
23
31
  return new Tool(value, route)
24
32
  }
25
-
26
- /** What the route states this method is, which is the only thing that states it. */
27
- public explain(
28
- directives: Tool[],
29
- _: Context,
30
- introspection: Introspection
31
- ): Introspection {
32
- const tool = MCP.published(directives)
33
-
34
- if (tool === null) return introspection
35
-
36
- return {
37
- ...introspection,
38
- description: tool.description,
39
- ...(tool.title === undefined ? {} : { title: tool.title })
40
- }
41
- }
42
33
  }
@@ -4,99 +4,53 @@ import { Tool } from './Tool.js'
4
4
  import { MCP } from './MCP.js'
5
5
 
6
6
  describe('mcp:tool', () => {
7
- it('should take what the route states the tool is', () => {
8
- const tool = new Tool('The pots that are hot.', '/pots/hot')
9
-
10
- assert.strictEqual(tool.description, 'The pots that are hot.')
11
- assert.strictEqual(tool.title, undefined)
12
- })
13
-
14
- it('should take a title beside the description', () => {
15
- const tool = new Tool(
16
- { title: 'Hot pots', description: 'The pots that are hot.' },
17
- '/pots'
18
- )
19
-
20
- assert.strictEqual(tool.title, 'Hot pots')
21
- assert.strictEqual(tool.description, 'The pots that are hot.')
22
- })
23
-
24
- it('should not accept a mapping without a description', () => {
25
- assert.throws(() => new Tool({ title: 'Hot pots' }, '/pots'), /cannot be empty/)
26
- })
27
-
28
- it('should not accept an empty title', () => {
29
- assert.throws(
30
- () => new Tool({ title: ' ', description: 'A pot.' }, '/pots'),
31
- /a title cannot be empty/
32
- )
7
+ it('should publish a method', () => {
8
+ assert.strictEqual(new Tool(true, '/pots/hot').published, true)
33
9
  })
34
10
 
35
- it('should not accept what it does not know', () => {
36
- assert.throws(
37
- () => new Tool({ description: 'A pot.', name: 'pots' }, '/pots'),
38
- /unknown 'name'/
39
- )
11
+ it('should withdraw one, because a declaration is inherited', () => {
12
+ assert.strictEqual(new Tool(false, '/pots/hot').published, false)
40
13
  })
41
14
 
42
- it('should not accept an empty description', () => {
43
- assert.throws(() => new Tool(' ', '/pots'), /cannot be empty/)
15
+ it('should not accept what a tool is, which is `help:method`', () => {
16
+ assert.throws(() => new Tool('The pots that are hot.', '/pots'), /`help:method`/)
17
+ assert.throws(() => new Tool({ title: 'Hot pots' }, '/pots'), /`help:method`/)
44
18
  })
45
19
 
46
20
  it('should not accept a value that is not one', () => {
47
- // `true` published a tool that stated nothing, back when an operation stated it instead
48
- assert.throws(() => new Tool(true, '/pots'), /the value is what the tool is/)
49
- assert.throws(() => new Tool(false, '/pots'), /the value is what the tool is/)
50
- assert.throws(() => new Tool(1, '/pots'), /the value is what the tool is/)
51
- assert.throws(() => new Tool(['A pot.'], '/pots'), /the value is what the tool is/)
21
+ assert.throws(() => new Tool(undefined, '/pots'), /whether the method is published/)
22
+ assert.throws(() => new Tool(null, '/pots'), /whether the method is published/)
52
23
  })
53
24
 
54
25
  it('should refuse a route no name can spell', () => {
55
- assert.throws(() => new Tool('A pot.', '/pots/a.b'), /no tool name can spell/)
56
- assert.throws(() => new Tool('A pot.', '/pots/:a.b'), /no tool name can spell/)
57
-
58
- // an underscore is what the convention keeps for itself
59
- assert.throws(() => new Tool('A pot.', '/pots/a_b'), /no tool name can spell/)
26
+ assert.throws(() => new Tool(true, '/pots/v1.0'), /no tool name can spell/)
60
27
  })
61
28
 
62
29
  it('should name the route it refuses', () => {
63
- assert.throws(() => new Tool('A pot.', '/pots/a.b'), /'\/pots\/a\.b'/)
30
+ assert.throws(() => new Tool(true, '/pots/v1.0'), /'\/pots\/v1\.0'/)
31
+ })
32
+
33
+ it('should not ask a route it does not publish to be spellable', () => {
34
+ assert.strictEqual(new Tool(false, '/pots/v1.0').published, false)
64
35
  })
65
36
  })
66
37
 
67
38
  describe('mcp:tool inheritance', () => {
68
- const family = new MCP()
39
+ const mcp = new MCP()
69
40
 
70
41
  it('should take the nearest declaration', () => {
71
- const own = new Tool('Nearest.', '/pots')
72
- const inherited = new Tool('Furthest.', '/pots')
42
+ const nearest = new Tool(false, '/pots')
43
+ const further = new Tool(true, '/pots')
73
44
 
74
- assert.strictEqual(MCP.published([own, inherited])?.description, 'Nearest.')
45
+ assert.strictEqual(MCP.published([nearest, further]), false)
75
46
  })
76
47
 
77
48
  it('should publish nothing where nothing is declared', () => {
78
- assert.strictEqual(MCP.published(undefined), null)
79
- assert.strictEqual(MCP.published([]), null)
80
- })
81
-
82
- it('should describe a method with what the route states', () => {
83
- const described = family.explain(
84
- [new Tool('What the route is.', '/pots')],
85
- null as never,
86
- { description: 'What the operation is.' }
87
- )
88
-
89
- assert.strictEqual(described.description, 'What the route is.')
90
- })
91
-
92
- it('should state nothing where nothing is declared', () => {
93
- assert.strictEqual(family.explain([], null as never, {}).description, undefined)
49
+ assert.strictEqual(MCP.published(undefined), false)
50
+ assert.strictEqual(MCP.published([]), false)
94
51
  })
95
52
 
96
53
  it('should refuse a directive it does not know', () => {
97
- assert.throws(
98
- () => family.create('resource', 'A pot.', null, '/pots'),
99
- /Unknown directive: mcp:resource/
100
- )
54
+ assert.throws(() => mcp.create('tools', true, null, '/pots'), /Unknown directive/)
101
55
  })
102
56
  })
@@ -3,57 +3,30 @@ import { refusal } from '../../RPC/names.js'
3
3
  import { segment } from '../../RTD/segment.js'
4
4
 
5
5
  /**
6
- * What one method is, published to a model. Declaring it is what publishes it, and what it
7
- * says is what it says it is: a tool a model cannot read the purpose of is one it cannot
8
- * choose, so there is no way to publish one that states nothing.
6
+ * Whether one method is published to a model. Declaring it is what publishes it, and it
7
+ * says nothing else — what a tool is, is [`help:method`](../help/Help.ts), which is what
8
+ * describes the method to everything else as well.
9
9
  *
10
- * A `title` is what a person is shown where a client lists what it may call — a name is an
11
- * address and reads as one. A description alone is written as the value; both are written as
12
- * a mapping.
13
- *
14
- * The operation states what it is too, and that is not this. An operation is written without
15
- * knowledge of any route, and a tool is an operation and a route together — the same
16
- * operation mounted twice is two tools, and one sentence is not true of both.
10
+ * `false` withdraws one: the declaration is inherited, as every directive is, and a node
11
+ * publishing what is under it is how a subtree is published at all.
17
12
  */
18
13
  export class Tool {
19
- public readonly description: string
20
- public readonly title: string | undefined
14
+ public readonly published: boolean
21
15
 
22
16
  public constructor(value: unknown, route: string) {
23
- const stated = typeof value === 'string' ? { description: value } : value
24
-
25
- assert.ok(
26
- typeof stated === 'object' && stated !== null && !Array.isArray(stated),
27
- 'Directive mcp:tool: the value is what the tool is, or a `title` and a `description`'
28
- )
29
-
30
- const { description, title, ...rest } = stated as Record<string, unknown>
31
-
32
- assert.ok(
33
- Object.keys(rest).length === 0,
34
- `Directive mcp:tool: unknown ${Object.keys(rest)
35
- .map((key) => `'${key}'`)
36
- .join(', ')}`
37
- )
38
-
39
17
  assert.ok(
40
- typeof description === 'string' && description.trim().length > 0,
41
- 'Directive mcp:tool: a description cannot be empty'
42
- )
43
-
44
- assert.ok(
45
- title === undefined || (typeof title === 'string' && title.trim().length > 0),
46
- 'Directive mcp:tool: a title cannot be empty'
18
+ typeof value === 'boolean',
19
+ 'Directive mcp:tool: the value is whether the method is published; what it is, is `help:method`'
47
20
  )
48
21
 
49
22
  // a tool is called by name, so a route that cannot be named cannot be one — said where
50
23
  // the mistake is, rather than as a tool that is quietly never listed
51
- assert.ok(
52
- refusal(segment(route)) === null,
53
- `Directive mcp:tool: '${route}' holds a segment no tool name can spell`
54
- )
24
+ if (value)
25
+ assert.ok(
26
+ refusal(segment(route)) === null,
27
+ `Directive mcp:tool: '${route}' holds a segment no tool name can spell`
28
+ )
55
29
 
56
- this.description = description
57
- this.title = title as string | undefined
30
+ this.published = value
58
31
  }
59
32
  }
@@ -36,6 +36,7 @@ export declare class DirectivesFactory implements RTD.DirectiveFactory {
36
36
  /** Request-scoped, on the message going back. */
37
37
  depart(context: Context, response: OutgoingMessage): Promise<void>;
38
38
  create(declarations: RTD.syntax.Directive[], route?: string): Directives;
39
+ inheritable(directive: RTD.syntax.Directive): boolean;
39
40
  dispose(): void;
40
41
  /** Mandatory families first, in their own order; everything else keeps its own. */
41
42
  private rank;
@@ -141,6 +141,9 @@ export class DirectivesFactory {
141
141
  this.instances.push(directives);
142
142
  return directives;
143
143
  }
144
+ inheritable(directive) {
145
+ return this.families[directive.family]?.inherited !== false;
146
+ }
144
147
  dispose() {
145
148
  for (const directives of this.instances)
146
149
  directives.dispose();
@@ -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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"}
@@ -0,0 +1,11 @@
1
+ import * as http from '../HTTP/index.js';
2
+ import type { Tree } from '../RTD/index.js';
3
+ /**
4
+ * What an application serves, for every route at once. Each entry is what `OPTIONS` on that
5
+ * path answers, so a key taken from here is a request that can be made.
6
+ */
7
+ export declare class Explorer {
8
+ private readonly tree;
9
+ constructor(tree: Tree);
10
+ process(context: http.Context): Promise<http.OutgoingMessage>;
11
+ }
@@ -0,0 +1,29 @@
1
+ import * as http from '../HTTP/index.js';
2
+ import { BRANCH_TTL } from '../const.js';
3
+ import { describe } from './tree.js';
4
+ /**
5
+ * What an application serves, for every route at once. Each entry is what `OPTIONS` on that
6
+ * path answers, so a key taken from here is a request that can be made.
7
+ */
8
+ export class Explorer {
9
+ tree;
10
+ constructor(tree) {
11
+ this.tree = tree;
12
+ }
13
+ async process(context) {
14
+ if (context.request.method !== 'OPTIONS')
15
+ throw new http.MethodNotAllowed(new Headers({ allow: ALLOW }));
16
+ return {
17
+ body: await describe(this.tree, context),
18
+ headers: new Headers({
19
+ allow: ALLOW,
20
+ // it stands until a branch expires, and it is filtered by who asked
21
+ 'cache-control': `private, max-age=${BRANCH_TTL / 1000}`,
22
+ vary: 'authorization'
23
+ })
24
+ };
25
+ }
26
+ }
27
+ /** The verbs of this path, which are not the verbs of the tree it answers with. */
28
+ const ALLOW = 'GET, HEAD, OPTIONS';
29
+ //# sourceMappingURL=Explorer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Explorer.js","sourceRoot":"","sources":["../../source/Discovery/Explorer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,IAAI,MAAM,kBAAkB,CAAA;AACxC,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,WAAW,CAAA;AAGpC;;;GAGG;AACH,MAAM,OAAO,QAAQ;IACF,IAAI,CAAM;IAE3B,YAAmB,IAAU;QAC3B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;IAClB,CAAC;IAEM,KAAK,CAAC,OAAO,CAAC,OAAqB;QACxC,IAAI,OAAO,CAAC,OAAO,CAAC,MAAM,KAAK,SAAS;YACtC,MAAM,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,OAAO,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,CAAA;QAEhE,OAAO;YACL,IAAI,EAAE,MAAM,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC;YACxC,OAAO,EAAE,IAAI,OAAO,CAAC;gBACnB,KAAK,EAAE,KAAK;gBACZ,oEAAoE;gBACpE,eAAe,EAAE,oBAAoB,UAAU,GAAG,IAAI,EAAE;gBACxD,IAAI,EAAE,eAAe;aACtB,CAAC;SACH,CAAA;IACH,CAAC;CACF;AAED,mFAAmF;AACnF,MAAM,KAAK,GAAG,oBAAoB,CAAA"}
@@ -0,0 +1,43 @@
1
+ import type { Input, Output } from '../io.js';
2
+ import type { Interceptor } from '../Interception.js';
3
+ /**
4
+ * The page that reads the tree: the directory `ui` builds, and nothing else.
5
+ *
6
+ * An interceptor rather than an endpoint, for the reason the OAuth documents are one — it
7
+ * runs before a credential is resolved. A page is public, and one served after `auth` would
8
+ * refuse the client holding a stale token, who is the client most likely to have opened it.
9
+ * It is also what keeps `depart` off these replies: a re-issued credential sets `no-store`,
10
+ * which would take the build hash off every asset that carries one.
11
+ *
12
+ * It claims the whole prefix, so that nothing under it reaches the router — a crawler
13
+ * asking for assets that are not there would otherwise have every one of them counted as a
14
+ * route that has gone missing, and ping discovery about it.
15
+ *
16
+ * `OPTIONS` on the prefix itself is the exception it lets through: the tree is what answers
17
+ * there, and that needs the identity this stage does not have yet.
18
+ */
19
+ export declare class Site implements Interceptor {
20
+ readonly name = "discovery";
21
+ /** What a test points at a fixture; the build otherwise. */
22
+ private readonly override;
23
+ private root;
24
+ constructor(root?: string);
25
+ /**
26
+ * Resolved here rather than at construction because this is a module singleton, built
27
+ * when the module loads and before anything has said where the page is. Said once, too,
28
+ * because a page that is not built is otherwise a `503` per request and nothing else.
29
+ */
30
+ mount(): void;
31
+ intercept(input: Input): Output;
32
+ /**
33
+ * The file a request lands on, or `null` when nothing does. A path that exists is served
34
+ * as it is; anything else that could be a route falls back to the page, because the
35
+ * client router — not this server — knows what routes there are.
36
+ */
37
+ private resolve;
38
+ /**
39
+ * Always with a `content-type` of its own: a stream without one is framed as
40
+ * `multipart/*` and the page arrives as an envelope of JSON-encoded buffers.
41
+ */
42
+ private send;
43
+ }
@@ -0,0 +1,171 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import { Readable } from 'node:stream';
4
+ import { console } from 'openspan';
5
+ import * as http from '../HTTP/index.js';
6
+ import { DISCOVERY } from '../const.js';
7
+ /**
8
+ * The page that reads the tree: the directory `ui` builds, and nothing else.
9
+ *
10
+ * An interceptor rather than an endpoint, for the reason the OAuth documents are one — it
11
+ * runs before a credential is resolved. A page is public, and one served after `auth` would
12
+ * refuse the client holding a stale token, who is the client most likely to have opened it.
13
+ * It is also what keeps `depart` off these replies: a re-issued credential sets `no-store`,
14
+ * which would take the build hash off every asset that carries one.
15
+ *
16
+ * It claims the whole prefix, so that nothing under it reaches the router — a crawler
17
+ * asking for assets that are not there would otherwise have every one of them counted as a
18
+ * route that has gone missing, and ping discovery about it.
19
+ *
20
+ * `OPTIONS` on the prefix itself is the exception it lets through: the tree is what answers
21
+ * there, and that needs the identity this stage does not have yet.
22
+ */
23
+ export class Site {
24
+ name = 'discovery';
25
+ /** What a test points at a fixture; the build otherwise. */
26
+ override;
27
+ root;
28
+ constructor(root) {
29
+ this.override = root;
30
+ this.root = root ?? site();
31
+ }
32
+ /**
33
+ * Resolved here rather than at construction because this is a module singleton, built
34
+ * when the module loads and before anything has said where the page is. Said once, too,
35
+ * because a page that is not built is otherwise a `503` per request and nothing else.
36
+ */
37
+ mount() {
38
+ this.root = this.override ?? site();
39
+ if (!isFile(path.join(this.root, 'index.html')))
40
+ console.warn('Discovery UI is not built', { root: this.root });
41
+ }
42
+ intercept(input) {
43
+ const { pathname } = input.url;
44
+ if (pathname !== DISCOVERY && !pathname.startsWith(DISCOVERY + '/'))
45
+ return null;
46
+ // the prefix itself, as opposed to something under it
47
+ const bare = pathname === DISCOVERY || pathname === DISCOVERY + '/';
48
+ const method = input.request.method;
49
+ if (method !== 'GET' && method !== 'HEAD') {
50
+ // the tree answers here, and it needs the identity this stage does not have yet
51
+ if (bare && method === 'OPTIONS')
52
+ return null;
53
+ throw new http.MethodNotAllowed(new Headers({ allow: bare ? 'GET, HEAD, OPTIONS' : 'GET, HEAD' }));
54
+ }
55
+ // the page is a directory, and every asset it names is relative to it
56
+ if (pathname === DISCOVERY)
57
+ return {
58
+ status: 302,
59
+ headers: new Headers({ location: DISCOVERY + '/' + input.url.search })
60
+ };
61
+ const file = this.resolve(pathname);
62
+ if (file === null)
63
+ throw new http.NotFound();
64
+ return this.send(file, method);
65
+ }
66
+ /**
67
+ * The file a request lands on, or `null` when nothing does. A path that exists is served
68
+ * as it is; anything else that could be a route falls back to the page, because the
69
+ * client router — not this server — knows what routes there are.
70
+ */
71
+ resolve(pathname) {
72
+ /*
73
+ * Decoded after the prefix is off, so that an encoded separator cannot smuggle a
74
+ * segment past the test that put us here. A dot segment never arrives — `..` and
75
+ * `%2e%2e` alike are collapsed while the URL is parsed — but `%2f` survives that and
76
+ * decodes to a separator here, which is what the guard below is for.
77
+ */
78
+ const relative = decode(pathname.slice(DISCOVERY.length));
79
+ if (relative === null || relative.includes('\0'))
80
+ return null;
81
+ const file = path.join(this.root, relative);
82
+ if (file !== this.root && !file.startsWith(this.root + path.sep))
83
+ return null;
84
+ if (isFile(file))
85
+ return file;
86
+ /*
87
+ * A missing asset is missing, but a route can look like one. What this server would
88
+ * have served is what it knows how to serve, so anything else is a route and falls
89
+ * back to the page — as does anything ending in a slash, which is no name for a file.
90
+ */
91
+ const asset = !relative.endsWith('/') && path.extname(relative) in TYPES;
92
+ return asset ? null : path.join(this.root, 'index.html');
93
+ }
94
+ /**
95
+ * Always with a `content-type` of its own: a stream without one is framed as
96
+ * `multipart/*` and the page arrives as an envelope of JSON-encoded buffers.
97
+ */
98
+ send(file, method) {
99
+ const stats = fs.statSync(file, { throwIfNoEntry: false });
100
+ if (stats === undefined)
101
+ return {
102
+ status: 503,
103
+ headers: new Headers({ 'content-type': 'text/plain; charset=utf-8' }),
104
+ body: Readable.from([Buffer.from(NOT_BUILT)])
105
+ };
106
+ const headers = new Headers({
107
+ 'content-type': TYPES[path.extname(file)] ?? 'application/octet-stream',
108
+ 'content-length': String(stats.size),
109
+ 'cache-control': caching(path.relative(this.root, file))
110
+ });
111
+ // a HEAD reply carries no body but reports the length a GET would have returned; the
112
+ // HTTP/2 layer does not drop one written to it, so none is opened
113
+ if (method === 'HEAD')
114
+ return { status: 200, headers };
115
+ return { status: 200, headers, body: fs.createReadStream(file) };
116
+ }
117
+ }
118
+ const NOT_BUILT = 'The discovery UI is not built. Run `npm run build:ui`.\n';
119
+ function decode(pathname) {
120
+ try {
121
+ return decodeURIComponent(pathname);
122
+ }
123
+ catch {
124
+ return null;
125
+ }
126
+ }
127
+ function isFile(file) {
128
+ return fs.statSync(file, { throwIfNoEntry: false })?.isFile() === true;
129
+ }
130
+ /**
131
+ * Where `npm run build:ui` puts the page. Two levels up because this module is a directory
132
+ * deeper than `source` itself, and `transpiled` mirrors that — so it resolves the same from
133
+ * either. The variable is the features', which run against a fixture rather than a build.
134
+ */
135
+ function site() {
136
+ return (process.env.__TESTING_EXPOSITION_DISCOVERY_ROOT ??
137
+ path.resolve(import.meta.dirname, '..', '..', 'ui', 'dist'));
138
+ }
139
+ /** Assets under this prefix carry their build hash in the name. */
140
+ const IMMUTABLE = path.join('_app', 'immutable');
141
+ const FOREVER = 'public, max-age=31536000, immutable';
142
+ /** The icons: named without a hash, so they are re-read, but rarely. */
143
+ const ICONS = new Set(['favicon.ico', 'favicon-96x96.png', 'apple-touch-icon.png']);
144
+ const DAY = 'public, max-age=86400';
145
+ /**
146
+ * How long what is served may be held. The page is never cached — it names the assets, and
147
+ * their names carry the build. An icon is named for what it is rather than for its content,
148
+ * so it is asked about again, but not on every page load.
149
+ */
150
+ function caching(relative) {
151
+ if (relative.startsWith(IMMUTABLE))
152
+ return FOREVER;
153
+ return ICONS.has(relative) ? DAY : 'no-cache';
154
+ }
155
+ const TYPES = {
156
+ '.css': 'text/css; charset=utf-8',
157
+ '.html': 'text/html; charset=utf-8',
158
+ '.ico': 'image/x-icon',
159
+ '.jpg': 'image/jpeg',
160
+ '.js': 'text/javascript; charset=utf-8',
161
+ '.json': 'application/json; charset=utf-8',
162
+ '.map': 'application/json; charset=utf-8',
163
+ '.png': 'image/png',
164
+ '.svg': 'image/svg+xml',
165
+ '.txt': 'text/plain; charset=utf-8',
166
+ '.webmanifest': 'application/manifest+json',
167
+ '.webp': 'image/webp',
168
+ '.woff': 'font/woff',
169
+ '.woff2': 'font/woff2'
170
+ };
171
+ //# sourceMappingURL=Site.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Site.js","sourceRoot":"","sources":["../../source/Discovery/Site.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export { Explorer } from './Explorer.js';
2
+ export { Site } from './Site.js';
3
+ export { looking } from './trunk.js';
@@ -0,0 +1,4 @@
1
+ export { Explorer } from './Explorer.js';
2
+ export { Site } from './Site.js';
3
+ export { looking } from './trunk.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../source/Discovery/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAA;AACxC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EAAE,OAAO,EAAE,MAAM,YAAY,CAAA"}
@@ -0,0 +1,26 @@
1
+ import { type Described } from '../directives/help/index.js';
2
+ import type * as http from '../HTTP/index.js';
3
+ import type { Tree } from '../RTD/index.js';
4
+ /**
5
+ * Every route in the tree this caller may reach, keyed by the template it answers at, and
6
+ * each described exactly as `OPTIONS` on that path describes it — so a key can be taken
7
+ * from the answer and sent back as a request.
8
+ *
9
+ * A route a name cannot spell is here, unlike at `/.rpc` and `/.mcp`: HTTP addresses a
10
+ * route by its path, so leaving one out would make this disagree with the router. A
11
+ * resource no method of which this caller may reach is not here at all — `OPTIONS` answers
12
+ * `403` to one, and an empty entry would still say it exists.
13
+ *
14
+ * Sorted, because a branch is merged whenever its tenant answers and two replicas would
15
+ * otherwise order the same tree differently. Verbs keep the order they were declared in,
16
+ * which is the order `OPTIONS` answers them in.
17
+ */
18
+ export declare function describe(tree: Tree, request: http.Context): Promise<Discovered>;
19
+ /** What the tree answers. An object, so that what is said of the whole of it has somewhere to go. */
20
+ export interface Discovered {
21
+ routes: Record<string, Resource>;
22
+ }
23
+ /** What one resource is, and what it serves; a verb is upper case, and nothing else here is. */
24
+ export interface Resource extends Described {
25
+ [verb: string]: unknown;
26
+ }