@substrat-run/vertical-host 0.156.0 → 0.159.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -45,6 +45,14 @@ mountPlatformSurface(app, {
45
45
  export default app;
46
46
  ```
47
47
 
48
+ ## Automatic API reference
49
+
50
+ `mountOperations` also serves `/api/docs` and its self-hosted renderer. Keep serving
51
+ `/openapi.json` from your operation declarations; the page uses the app's current
52
+ session and makes try-it requests on the same origin. No app asset build changes
53
+ are required. Register operations before a catch-all route. Set `docs: false` when
54
+ supplying your own reference, or register that reference before mounting operations.
55
+
48
56
  ## What it owns vs. what you supply
49
57
 
50
58
  - **Generic routes** (`export`, `restore`, `bookmarks`, `rewind`, `snapshot`,
@@ -0,0 +1,5 @@
1
+ /** The reference is platform plumbing; the document and its auth stay with the app. */
2
+ import type { Hono } from 'hono';
3
+ /** Repeated mounts share one reference; an app's existing reference takes precedence. */
4
+ export declare function mountApiDocs(app: Hono<any, any, any>): void;
5
+ //# sourceMappingURL=api-docs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-docs.d.ts","sourceRoot":"","sources":["../src/api-docs.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAwCjC,yFAAyF;AAEzF,wBAAgB,YAAY,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,GAAG,IAAI,CAU3D"}
@@ -0,0 +1,51 @@
1
+ import { servedPathOf } from './mcp-guard.js';
2
+ import { DOCS_RENDERER } from './docs-renderer.generated.js';
3
+ const HTML = `<!doctype html>
4
+ <html lang="en">
5
+ <head>
6
+ <meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1">
7
+ <title>API reference</title>
8
+ <style>body{margin:0}#status{font:16px system-ui;padding:24px}</style>
9
+ </head>
10
+ <body>
11
+ <div id="status" role="status">Loading API reference…</div><div id="app"></div>
12
+ <script src="./docs/renderer.js"></script>
13
+ <script>
14
+ (async () => {
15
+ const status = document.getElementById('status');
16
+ try {
17
+ const response = await fetch('/openapi.json', { credentials: 'same-origin', headers: { Accept: 'application/json' } });
18
+ if (response.status === 401) {
19
+ status.textContent = 'Sign in to the app, then reload this reference. ';
20
+ const link = document.createElement('a'); link.href = '/'; link.textContent = 'Open app'; status.append(link);
21
+ return;
22
+ }
23
+ if (response.status === 403) throw new Error('Your account cannot access this API specification.');
24
+ if (!response.ok) throw new Error('The app has not made its API specification available (' + response.status + ').');
25
+ const content = await response.json().catch(() => {
26
+ throw new Error('The app did not return an OpenAPI specification.');
27
+ });
28
+ if (!content || !content.openapi || !content.paths) throw new Error('The app did not return an OpenAPI specification.');
29
+ if (!window.Scalar) throw new Error('The API reference renderer could not load. Reload to try again.');
30
+ Scalar.createApiReference('#app', { content, hideClientButton: true });
31
+ status.remove();
32
+ } catch (error) {
33
+ status.textContent = error instanceof Error ? error.message : 'Unable to load the API specification.';
34
+ }
35
+ })();
36
+ </script>
37
+ </body></html>`;
38
+ /** Repeated mounts share one reference; an app's existing reference takes precedence. */
39
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
40
+ export function mountApiDocs(app) {
41
+ if (!app.routes.some((route) => route.method === 'GET' && route.path === servedPathOf(app, '/api/docs'))) {
42
+ app.get('/api/docs', (c) => c.html(HTML));
43
+ }
44
+ if (!app.routes.some((route) => route.method === 'GET' && route.path === servedPathOf(app, '/api/docs/renderer.js'))) {
45
+ app.get('/api/docs/renderer.js', (c) => c.body(DOCS_RENDERER, 200, {
46
+ 'Content-Type': 'text/javascript; charset=utf-8',
47
+ 'X-Content-Type-Options': 'nosniff',
48
+ }));
49
+ }
50
+ }
51
+ //# sourceMappingURL=api-docs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api-docs.js","sourceRoot":"","sources":["../src/api-docs.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAE7D,MAAM,IAAI,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;eAkCE,CAAC;AAEhB,yFAAyF;AACzF,8DAA8D;AAC9D,MAAM,UAAU,YAAY,CAAC,GAAwB;IACnD,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC;QACzG,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5C,CAAC;IACD,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,MAAM,KAAK,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,CAAC,GAAG,EAAE,uBAAuB,CAAC,CAAC,EAAE,CAAC;QACrH,GAAG,CAAC,GAAG,CAAC,uBAAuB,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,EAAE,GAAG,EAAE;YACjE,cAAc,EAAE,gCAAgC;YAChD,wBAAwB,EAAE,SAAS;SACpC,CAAC,CAAC,CAAC;IACN,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare const DOCS_RENDERER: string;
2
+ //# sourceMappingURL=docs-renderer.generated.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"docs-renderer.generated.d.ts","sourceRoot":"","sources":["../src/docs-renderer.generated.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,aAAa,EAAE,MAA68+3I,CAAC"}