@erenthedeveloper0/zen-openapi 0.1.0-alpha.1 → 0.1.0-alpha.2

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.
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAwB,MAAM,EAAE,MAAM,6BAA6B,CAAA;AAE/E,OAAO,EAAmB,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAIxF;;;;;;;;GAQG;AAEH,MAAM,WAAW,oBAAqB,SAAQ,cAAc;IAC1D,wEAAwE;IACxE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAA;IAC1C,iEAAiE;IACjE,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAA;IACxC;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IACrC,8EAA8E;IAC9E,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAA;CACpF;AASD,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,oBAAoB,EAAE,EAAE,CA6DzD,CAAA"}
1
+ {"version":3,"file":"plugin.d.ts","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAwB,MAAM,EAAY,MAAM,6BAA6B,CAAA;AAEzF,OAAO,EAAmB,KAAK,cAAc,EAAE,KAAK,aAAa,EAAE,MAAM,eAAe,CAAA;AAIxF;;;;;;;;GAQG;AAEH,MAAM,WAAW,oBAAqB,SAAQ,cAAc;IAC1D,wEAAwE;IACxE,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAA;IAC1C,iEAAiE;IACjE,QAAQ,CAAC,EAAE,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,SAAS,CAAA;IACxC;;;;;;OAMG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,SAAS,CAAA;IACrC,8EAA8E;IAC9E,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,aAAa,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,GAAG,SAAS,CAAA;CACpF;AASD,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,oBAAoB,EAAE,EAAE,CAkEzD,CAAA"}
package/dist/plugin.js CHANGED
@@ -1,4 +1,4 @@
1
- import { BootError, definePlugin } from '@erenthedeveloper0/zen-core';
1
+ import { BootError, definePlugin, unsafeHtml } from '@erenthedeveloper0/zen-core';
2
2
  import { openapiDocument } from "./document.js";
3
3
  import { renderReference } from "./ui.js";
4
4
  export const openapiPlugin = definePlugin({
@@ -7,7 +7,7 @@ export const openapiPlugin = definePlugin({
7
7
  setup(app, options) {
8
8
  const jsonPath = options.json === undefined ? '/openapi.json' : options.json;
9
9
  const uiPath = options.ui === undefined ? '/docs' : options.ui;
10
- const served = { result: null, json: '{}', etag: '', html: '' };
10
+ const served = { result: null, json: '{}', etag: '', html: unsafeHtml('') };
11
11
  if (jsonPath !== false) {
12
12
  app.route({
13
13
  method: 'GET',
@@ -40,9 +40,14 @@ export const openapiPlugin = definePlugin({
40
40
  served.result = result;
41
41
  served.json = JSON.stringify(result.document, null, 2);
42
42
  served.etag = weakEtag(served.json);
43
- served.html = uiPath === false
43
+ // `unsafeHtml`, once, at boot: the page inlines the document in a JSON
44
+ // island and a script, which `html` rightly refuses to fill from holes,
45
+ // and `renderReference` escapes both itself (`<` as `<` in the
46
+ // island, every text value through `escapeHtml`). The mark is the
47
+ // statement that it did, made where a reviewer can check it (§19.5).
48
+ served.html = unsafeHtml(uiPath === false
44
49
  ? ''
45
- : renderReference(result.document, { jsonPath: jsonPath === false ? null : jsonPath });
50
+ : renderReference(result.document, { jsonPath: jsonPath === false ? null : jsonPath }));
46
51
  if (options.strict === true && result.diagnostics.length > 0) {
47
52
  throw new BootError(result.diagnostics.map(toBootDiagnostic));
48
53
  }
@@ -1 +1 @@
1
- {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"plugin.js","sourceRoot":"","sources":["../src/plugin.ts"],"names":[],"mappings":"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"}
package/dist/ui.d.ts.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,GAAE;IAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAuB,GAAG,MAAM,CA6B5H"}
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAEjD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe,EAAE,OAAO,GAAE;IAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CAAuB,GAAG,MAAM,CA6B5H"}
package/dist/ui.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { escapeHtml } from '@erenthedeveloper0/zen-core';
1
2
  /**
2
3
  * A self-contained API reference — rfcs/0001 §29.2.
3
4
  *
@@ -41,12 +42,6 @@ export function renderReference(document, options = { jsonPath: null }) {
41
42
  </html>
42
43
  `;
43
44
  }
44
- function escapeHtml(raw) {
45
- return raw.replace(/[&<>"']/g, (char) => HTML_ESCAPES[char] ?? char);
46
- }
47
- const HTML_ESCAPES = {
48
- '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;',
49
- };
50
45
  const STYLE = `
51
46
  :root{--bg:#fff;--fg:#1a1a1a;--muted:#666;--line:#e3e3e3;--code:#f6f6f7;--accent:#3060d0}
52
47
  @media(prefers-color-scheme:dark){:root{--bg:#16171a;--fg:#e8e8ea;--muted:#9a9aa2;--line:#2c2d33;--code:#1e1f24;--accent:#7aa2f7}}
package/dist/ui.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAAC,QAAyB,EAAE,UAAuC,EAAE,QAAQ,EAAE,IAAI,EAAE;IAClH,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC7C,6EAA6E;IAC7E,wEAAwE;IACxE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IACjE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,KAAK,IAAI;QACxC,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,8BAA8B,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAA;IAElF,OAAO;;;;;;SAMA,KAAK;SACL,KAAK;;;;QAIN,KAAK;wBACW,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,QAAQ;;;4CAGxB,OAAO;UACzC,MAAM;;;CAGf,CAAA;AACD,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,OAAO,GAAG,CAAC,OAAO,CAAC,UAAU,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,CAAA;AACtE,CAAC;AAED,MAAM,YAAY,GAAqC;IACrD,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO;CACpE,CAAA;AAED,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+Bb,CAAA;AAED,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6Gd,CAAA"}
1
+ {"version":3,"file":"ui.js","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAA;AAGxD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,eAAe,CAAC,QAAyB,EAAE,UAAuC,EAAE,QAAQ,EAAE,IAAI,EAAE;IAClH,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IAC7C,6EAA6E;IAC7E,wEAAwE;IACxE,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;IACjE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,KAAK,IAAI;QACxC,CAAC,CAAC,EAAE;QACJ,CAAC,CAAC,8BAA8B,UAAU,CAAC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAA;IAElF,OAAO;;;;;;SAMA,KAAK;SACL,KAAK;;;;QAIN,KAAK;wBACW,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,QAAQ;;;4CAGxB,OAAO;UACzC,MAAM;;;CAGf,CAAA;AACD,CAAC;AAED,MAAM,KAAK,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+Bb,CAAA;AAED,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6Gd,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@erenthedeveloper0/zen-openapi",
3
- "version": "0.1.0-alpha.1",
3
+ "version": "0.1.0-alpha.2",
4
4
  "description": "Zen OpenAPI: the application graph as an OAS 3.1 document, $ref deduplication, breaking-change detection and a dependency-free viewer.",
5
5
  "keywords": [
6
6
  "openapi",
@@ -52,7 +52,7 @@
52
52
  "test": "node --test \"test/**/*.test.ts\""
53
53
  },
54
54
  "dependencies": {
55
- "@erenthedeveloper0/zen-core": "0.1.0-alpha.1"
55
+ "@erenthedeveloper0/zen-core": "0.1.0-alpha.2"
56
56
  },
57
57
  "peerDependencies": {
58
58
  "typescript": ">=5.0"
package/src/plugin.ts CHANGED
@@ -1,5 +1,5 @@
1
- import type { AppGraph, Diagnostic, Plugin } from '@erenthedeveloper0/zen-core'
2
- import { BootError, definePlugin } from '@erenthedeveloper0/zen-core'
1
+ import type { AppGraph, Diagnostic, Plugin, SafeHtml } from '@erenthedeveloper0/zen-core'
2
+ import { BootError, definePlugin, unsafeHtml } from '@erenthedeveloper0/zen-core'
3
3
  import { openapiDocument, type OpenApiOptions, type OpenApiResult } from './document.ts'
4
4
  import type { DocDiagnostic } from './schema.ts'
5
5
  import { renderReference } from './ui.ts'
@@ -35,7 +35,7 @@ interface Served {
35
35
  result: OpenApiResult | null
36
36
  json: string
37
37
  etag: string
38
- html: string
38
+ html: SafeHtml
39
39
  }
40
40
 
41
41
  export const openapiPlugin: Plugin<OpenApiPluginOptions, {}> = definePlugin<OpenApiPluginOptions, {}>({
@@ -45,7 +45,7 @@ export const openapiPlugin: Plugin<OpenApiPluginOptions, {}> = definePlugin<Open
45
45
  setup(app, options) {
46
46
  const jsonPath = options.json === undefined ? '/openapi.json' : options.json
47
47
  const uiPath = options.ui === undefined ? '/docs' : options.ui
48
- const served: Served = { result: null, json: '{}', etag: '', html: '' }
48
+ const served: Served = { result: null, json: '{}', etag: '', html: unsafeHtml('') }
49
49
 
50
50
  if (jsonPath !== false) {
51
51
  app.route({
@@ -80,9 +80,14 @@ export const openapiPlugin: Plugin<OpenApiPluginOptions, {}> = definePlugin<Open
80
80
  served.result = result
81
81
  served.json = JSON.stringify(result.document, null, 2)
82
82
  served.etag = weakEtag(served.json)
83
- served.html = uiPath === false
83
+ // `unsafeHtml`, once, at boot: the page inlines the document in a JSON
84
+ // island and a script, which `html` rightly refuses to fill from holes,
85
+ // and `renderReference` escapes both itself (`<` as `<` in the
86
+ // island, every text value through `escapeHtml`). The mark is the
87
+ // statement that it did, made where a reviewer can check it (§19.5).
88
+ served.html = unsafeHtml(uiPath === false
84
89
  ? ''
85
- : renderReference(result.document, { jsonPath: jsonPath === false ? null : jsonPath })
90
+ : renderReference(result.document, { jsonPath: jsonPath === false ? null : jsonPath }))
86
91
 
87
92
  if (options.strict === true && result.diagnostics.length > 0) {
88
93
  throw new BootError(result.diagnostics.map(toBootDiagnostic))
@@ -106,7 +111,7 @@ interface DocsContext {
106
111
  readonly headers: Readonly<Record<string, string | undefined>>
107
112
  empty(status?: 204 | 205 | 304): unknown
108
113
  text(body: string, init?: { media?: string; headers?: Record<string, string> }): unknown
109
- html(body: string): unknown
114
+ html(body: SafeHtml): unknown
110
115
  }
111
116
 
112
117
  function toBootDiagnostic(diagnostic: DocDiagnostic): Diagnostic {
package/src/ui.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import { escapeHtml } from '@erenthedeveloper0/zen-core'
1
2
  import type { OpenApiDocument } from './types.ts'
2
3
 
3
4
  /**
@@ -45,14 +46,6 @@ export function renderReference(document: OpenApiDocument, options: { jsonPath:
45
46
  `
46
47
  }
47
48
 
48
- function escapeHtml(raw: string): string {
49
- return raw.replace(/[&<>"']/g, (char) => HTML_ESCAPES[char] ?? char)
50
- }
51
-
52
- const HTML_ESCAPES: Readonly<Record<string, string>> = {
53
- '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;', "'": '&#39;',
54
- }
55
-
56
49
  const STYLE = `
57
50
  :root{--bg:#fff;--fg:#1a1a1a;--muted:#666;--line:#e3e3e3;--code:#f6f6f7;--accent:#3060d0}
58
51
  @media(prefers-color-scheme:dark){:root{--bg:#16171a;--fg:#e8e8ea;--muted:#9a9aa2;--line:#2c2d33;--code:#1e1f24;--accent:#7aa2f7}}