@publier/openapi 0.1.19 → 0.2.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/dist/index.d.mts CHANGED
@@ -216,7 +216,7 @@ interface AsyncApiSourceOptions {
216
216
  */
217
217
  export declare function asyncapiSource(options: AsyncApiSourceOptions): ContentSource;
218
218
  type SampleLang = 'curl' | 'javascript' | 'python' | 'go' | 'java' | 'csharp';
219
- export declare function generateCodeSample(method: HttpMethod, path: string, operation: OpenApiOperation, lang: SampleLang, baseUrl: string): string;
219
+ export declare function generateCodeSample(method: HttpMethod, path: string, operation: OpenApiOperation, lang: SampleLang, baseUrl: string, spec?: OpenApiSpec): string;
220
220
  interface APIReferenceProps {
221
221
  method: HttpMethod;
222
222
  path: string;
@@ -244,6 +244,8 @@ interface CodeSamplesProps {
244
244
  method: HttpMethod;
245
245
  path: string;
246
246
  operation: OpenApiOperation;
247
+ /** The parsed specification; its security schemes put credentials into the samples. */
248
+ spec?: OpenApiSpec;
247
249
  baseUrl?: string;
248
250
  }
249
251
  interface RequestExampleProps {
@@ -321,8 +323,8 @@ interface ExtractEndpointsOptions {
321
323
  }
322
324
  export declare function extractEndpoints(spec: OpenApiSpec, options?: ExtractEndpointsOptions): EndpointEntry[];
323
325
  export declare function generateExampleFromSchema(schema: OpenApiSchema): unknown;
324
- export declare function getMediaTypeExample(content: Record<string, OpenApiMediaType>, mediaType?: string): string | undefined;
325
326
  export declare function formatJson(value: unknown): string;
327
+ export declare function getMediaTypeExample(content: Record<string, OpenApiMediaType>, mediaType?: string): string | undefined;
326
328
  interface GenerateFilesOptions {
327
329
  /** The parsed OpenAPI spec. */
328
330
  spec: OpenApiSpec;
package/dist/index.mjs CHANGED
@@ -1 +1 @@
1
- import{asyncapiSourceBuild as e,openapiDecodePlaceholders as t,openapiExtractEndpoints as n,openapiGetMediaTypeExample as r,openapiGetSnippetClient as i,openapiHarFromOperation as a,openapiNavigationBuild as o,openapiSourceBuild as s}from"@publier/native";import{HTTPSnippet as c}from"@readme/httpsnippet";import l from"openapi-sampler";function u(t){let{spec:n,baseUrl:r=``}=t,{pages:i,tree:a}=JSON.parse(e(JSON.stringify(n),r)),o=new Map(i.map(e=>[e.slug.join(`/`),e]));return{async getPage(e){return o.get(e.join(`/`))},async getPages(){return i},async getPageTree(){return a},async generateParams(){return i.map(e=>({slug:e.slug}))}}}function d(e,n,r,o,s){let l=i(o);if(!l)return``;let[u,d]=l,f=JSON.parse(a(e,n,JSON.stringify(r),s)),p=new c(f).convert(u,d),m=``;if(Array.isArray(p)){let e=p.find(e=>typeof e==`string`);typeof e==`string`&&(m=e)}else typeof p==`string`&&(m=p);return t(m)}const f=[`get`,`post`,`put`,`delete`,`patch`,`head`,`options`];function p(e,t={}){let{mergePathParameters:r=!1,includeWebhooks:i=!0}=t;return JSON.parse(n(JSON.stringify(e),r,i))}function m(e){return l.sample(e)}function h(e,t=`application/json`){let n=r(JSON.stringify(e),t);if(n===`__schema__`){let n=Object.keys(e)[0],r=e[t]??(n?e[n]:void 0);return r?.schema?g(m(r.schema)):void 0}return n??void 0}function g(e){return JSON.stringify(e,null,2)}function _(e,t={}){let{groupBy:n=`tag`,slugPrefix:r,excludeDeprecated:i=!1,includeWebhooks:a=!0}=t;return JSON.parse(o(JSON.stringify(e),n,r??null,i,a))}function v(e){let{spec:t,baseUrl:n=``}=e,{pages:r,tree:i}=JSON.parse(s(JSON.stringify(t),n)),a=new Map(r.map(e=>[e.slug.join(`/`),e]));return{async getPage(e){return a.get(e.join(`/`))},async getPages(){return r},async getPageTree(){return i},async generateParams(){return r.map(e=>({slug:e.slug}))}}}export{f as HTTP_METHODS,u as asyncapiSource,_ as buildNavigation,p as extractEndpoints,g as formatJson,d as generateCodeSample,m as generateExampleFromSchema,h as getMediaTypeExample,v as openapiSource};
1
+ import{asyncapiSourceBuild as e,openapiExtractEndpoints as t,openapiNavigationBuild as n,openapiSourceBuild as r}from"@publier/native";import{HTTPSnippet as i}from"@readme/httpsnippet";import a from"@readme/oas-to-har";import o from"oas";import s from"openapi-sampler";function c(t){let{spec:n,baseUrl:r=``}=t,{pages:i,tree:a}=JSON.parse(e(JSON.stringify(n),r)),o=new Map(i.map(e=>[e.slug.join(`/`),e]));return{async getPage(e){return o.get(e.join(`/`))},async getPages(){return i},async getPageTree(){return a},async generateParams(){return i.map(e=>({slug:e.slug}))}}}function l(e){return s.sample(e)}function u(e,t=`application/json`){let n=e[t]??Object.values(e)[0];if(!n)return;if(n.example!==void 0)return n.example;let r=Object.values(n.examples??{}).find(e=>e.value!==void 0);return r?r.value:n.schema?l(n.schema):void 0}function d(e){return JSON.stringify(e,null,2)}function f(e,t=`application/json`){let n=u(e,t);return n===void 0?void 0:d(n)}const p={curl:[`shell`,`curl`],javascript:[`javascript`,`fetch`],python:[`python`,`requests`],go:[`go`,`native`],java:[`java`,`nethttp`],csharp:[`csharp`,`httpclient`]};function m(e,t){let n=e.getDefinition().components?.securitySchemes??{},r={};for(let e of Object.keys(t[0]??{})){let t=n[e];t?.type===`http`&&t.scheme?.toLowerCase()===`basic`?r[e]={user:`<username>`,pass:`<password>`}:t?.type===`apiKey`?r[e]=`<api-key>`:t&&(r[e]=`<token>`)}return r}function h(e,t,n,r,i){let s={openapi:`3.0.0`,info:{title:`API`,version:`1`},...i,servers:[{url:r}],paths:{...i?.paths,[t]:{...i?.paths?.[t],[e]:n}}},c=new o(s),l=c.operation(t,e),d={path:{},query:{},header:{},cookie:{}};for(let[,e]of t.matchAll(/\{([^}]+)\}/g))e&&(d.path[e]=`{${e}}`);for(let e of l.getParameters()){let t=d[e.in];t&&e.in!==`path`&&(t[e.name]=`<value>`)}if(l.hasRequestBody()){let e=l.schema.requestBody,t=l.getContentType(),n=u(e?.content??{},t);l.isFormUrlEncoded()||l.isMultipart()?d.formData=n??{}:n!==void 0&&(d.body=n)}return a(c,l,d,m(c,l.getSecurity())).log.entries[0].request}function g(e){return e.replace(/%(?:25)?(3C|3E|7B|7D)/gi,(e,t)=>String.fromCharCode(Number.parseInt(t,16)))}function _(e,t){let[n,r]=p[t],a=new i(e).convert(n,r),o=Array.isArray(a)?a.find(e=>typeof e==`string`):a;return g(typeof o==`string`?o:``)}function v(e,t,n,r,i,a){return p[r]?_(h(e,t,n,i,a),r):``}const y=[`get`,`post`,`put`,`delete`,`patch`,`head`,`options`];function b(e,n={}){let{mergePathParameters:r=!1,includeWebhooks:i=!0}=n;return JSON.parse(t(JSON.stringify(e),r,i))}function x(e,t={}){let{groupBy:r=`tag`,slugPrefix:i,excludeDeprecated:a=!1,includeWebhooks:o=!0}=t;return JSON.parse(n(JSON.stringify(e),r,i??null,a,o))}function S(e){let{spec:t,baseUrl:n=``}=e,{pages:i,tree:a}=JSON.parse(r(JSON.stringify(t),n)),o=new Map(i.map(e=>[e.slug.join(`/`),e]));return{async getPage(e){return o.get(e.join(`/`))},async getPages(){return i},async getPageTree(){return a},async generateParams(){return i.map(e=>({slug:e.slug}))}}}export{y as HTTP_METHODS,c as asyncapiSource,x as buildNavigation,b as extractEndpoints,d as formatJson,v as generateCodeSample,l as generateExampleFromSchema,f as getMediaTypeExample,S as openapiSource};
package/dist/parser.d.mts CHANGED
@@ -1,3 +1,15 @@
1
+ /**
2
+ * OpenAPI ingestion on @scalar/openapi-parser: load (file, URL or text; JSON or
3
+ * YAML; external `$ref`s), Swagger 2 → 3.0 upgrade, validation, dereference.
4
+ *
5
+ * The Rust renderers read a fully inlined document as JSON, so the result is
6
+ * made JSON-safe: a `$ref` that points back into the node being expanded is
7
+ * left as `{ "$ref": "#/…" }` (the shape the renderers already treat as
8
+ * "stop here"), instead of a cyclic object graph.
9
+ *
10
+ * 3.0 documents stay 3.0 on purpose: the 3.0 → 3.1 upgrade rewrites `nullable`
11
+ * into `type: [..., "null"]`, which the schema renderers cannot read.
12
+ */
1
13
  interface OpenApiSpec {
2
14
  openapi: string;
3
15
  info: OpenApiInfo;
@@ -129,5 +141,11 @@ interface OpenApiCodeSample {
129
141
  label?: string;
130
142
  source: string;
131
143
  }
132
- export declare function parseOpenApiSpec(input: string): OpenApiSpec;
144
+ /**
145
+ * @param input File path, URL, or the JSON/YAML text of a spec, or a parsed
146
+ * spec object. Relative external `$ref`s resolve against a path or URL input.
147
+ * @throws with the parser's validation messages when the document is not a
148
+ * valid OpenAPI/Swagger document.
149
+ */
150
+ export declare function parseOpenApiSpec(input: string | object): Promise<OpenApiSpec>;
133
151
  export {};
package/dist/parser.mjs CHANGED
@@ -1 +1 @@
1
- import{openapiParseOpenapiSpec as e}from"@publier/native";import{parse as t}from"yaml";function n(n){let r;try{JSON.parse(n),r=n}catch{r=JSON.stringify(t(n))}return JSON.parse(e(r))}export{n as parseOpenApiSpec};
1
+ import{bundle as e}from"@scalar/json-magic/bundle";import{fetchUrls as t,parseJson as n,parseYaml as r}from"@scalar/json-magic/bundle/plugins/browser";import{readFiles as i}from"@scalar/json-magic/bundle/plugins/node";import{dereference as a,validate as o}from"@scalar/openapi-parser";import{upgradeFromTwoToThree as s}from"@scalar/openapi-upgrader/2.0-to-3.0";function c(e,t,n){if(typeof e!=`object`||!e)return e;let r=t.get(e);if(r!==void 0){if(n.has(r))return{$ref:r};n.add(r)}let i=Array.isArray(e)?e.map(e=>c(e,t,n)):Object.fromEntries(Object.entries(e).map(([e,r])=>[e,c(r,t,n)]));return r!==void 0&&n.delete(r),i}async function l(l){let u=await e(l,{plugins:[i(),t(),r(),n()],treeShake:!1}),d=typeof u.swagger==`string`?s(u):u,f=await o(d);if(!f.valid){let e=f.errors.map(e=>e.message).join(`; `);throw Error(`Invalid OpenAPI spec: ${e}`)}let p=/* @__PURE__ */ new Map,{schema:m,errors:h}=a(d,{onDereference:({schema:e,ref:t})=>{p.set(e,t)}});if(h?.length)throw Error(`Invalid OpenAPI spec: ${h.map(e=>e.message).join(`; `)}`);return c(m,p,/* @__PURE__ */ new Set)}export{l as parseOpenApiSpec};
package/dist/server.mjs CHANGED
@@ -1 +1 @@
1
- import{readFileSync as e}from"node:fs";import{openapiExtractEndpoints as t,openapiMergeSpecs as n,openapiNavigationBuild as r,openapiParseOpenapiSpec as i}from"@publier/native";import{parse as a}from"yaml";const o=[`get`,`post`,`put`,`delete`,`patch`,`head`,`options`];function s(e,n={}){let{mergePathParameters:r=!1,includeWebhooks:i=!0}=n;return JSON.parse(t(JSON.stringify(e),r,i))}function c(e,t={}){let{groupBy:n=`tag`,slugPrefix:i,excludeDeprecated:a=!1,includeWebhooks:o=!0}=t;return JSON.parse(r(JSON.stringify(e),n,i??null,a,o))}function l(e){let t;try{JSON.parse(e),t=e}catch{t=JSON.stringify(a(e))}return JSON.parse(i(t))}function u(t){let r=null;async function i(){if(r&&!t.disableCache)return r;let i=[];for(let n of t.input)if(typeof n==`string`){let t;if(n.startsWith(`http:`)||n.startsWith(`https:`)){let e=await fetch(n);if(!e.ok)throw Error(`Failed to fetch OpenAPI spec from "${n}": ${e.status} ${e.statusText}`);t=await e.text()}else t=e(n,`utf-8`);i.push(l(t))}else i.push(n);if(i.length===0)throw Error(`No OpenAPI specs provided`);return i.length===1?(r=i[0],r):(r=JSON.parse(n(JSON.stringify(i))),r)}return{getSpec:i,async getOperation(e){let t=await i();for(let[n,r]of Object.entries(t.paths))for(let t of o){let i=r[t];if(i?.operationId===e)return{method:t,path:n,operation:i}}},async getOperationByPath(e,t){let n=(await i()).paths[e]?.[t];return n?{method:t,path:e,operation:n}:void 0},async getOperationsByTag(e){return s(await i(),{mergePathParameters:!0}).filter(t=>t.operation.tags?.includes(e)).map(({method:e,path:t,operation:n})=>({method:e,path:t,operation:n}))},async getEndpoints(){return s(await i(),{mergePathParameters:!0})},async getNavigation(e){return c(await i(),e)}}}export{u as createOpenAPI};
1
+ import{openapiExtractEndpoints as e,openapiMergeSpecs as t,openapiNavigationBuild as n}from"@publier/native";import{bundle as r}from"@scalar/json-magic/bundle";import{fetchUrls as i,parseJson as a,parseYaml as o}from"@scalar/json-magic/bundle/plugins/browser";import{readFiles as s}from"@scalar/json-magic/bundle/plugins/node";import{dereference as c,validate as l}from"@scalar/openapi-parser";import{upgradeFromTwoToThree as u}from"@scalar/openapi-upgrader/2.0-to-3.0";const d=[`get`,`post`,`put`,`delete`,`patch`,`head`,`options`];function f(t,n={}){let{mergePathParameters:r=!1,includeWebhooks:i=!0}=n;return JSON.parse(e(JSON.stringify(t),r,i))}function p(e,t={}){let{groupBy:r=`tag`,slugPrefix:i,excludeDeprecated:a=!1,includeWebhooks:o=!0}=t;return JSON.parse(n(JSON.stringify(e),r,i??null,a,o))}function m(e,t,n){if(typeof e!=`object`||!e)return e;let r=t.get(e);if(r!==void 0){if(n.has(r))return{$ref:r};n.add(r)}let i=Array.isArray(e)?e.map(e=>m(e,t,n)):Object.fromEntries(Object.entries(e).map(([e,r])=>[e,m(r,t,n)]));return r!==void 0&&n.delete(r),i}async function h(e){let t=await r(e,{plugins:[s(),i(),o(),a()],treeShake:!1}),n=typeof t.swagger==`string`?u(t):t,d=await l(n);if(!d.valid){let e=d.errors.map(e=>e.message).join(`; `);throw Error(`Invalid OpenAPI spec: ${e}`)}let f=/* @__PURE__ */ new Map,{schema:p,errors:h}=c(n,{onDereference:({schema:e,ref:t})=>{f.set(e,t)}});if(h?.length)throw Error(`Invalid OpenAPI spec: ${h.map(e=>e.message).join(`; `)}`);return m(p,f,/* @__PURE__ */ new Set)}function g(e){let n=null;async function r(){if(n&&!e.disableCache)return n;let r=[];for(let t of e.input)typeof t==`string`?r.push(await h(t)):r.push(t);if(r.length===0)throw Error(`No OpenAPI specs provided`);return r.length===1?(n=r[0],n):(n=JSON.parse(t(JSON.stringify(r))),n)}return{getSpec:r,async getOperation(e){let t=await r();for(let[n,r]of Object.entries(t.paths))for(let t of d){let i=r[t];if(i?.operationId===e)return{method:t,path:n,operation:i}}},async getOperationByPath(e,t){let n=(await r()).paths[e]?.[t];return n?{method:t,path:e,operation:n}:void 0},async getOperationsByTag(e){return f(await r(),{mergePathParameters:!0}).filter(t=>t.operation.tags?.includes(e)).map(({method:e,path:t,operation:n})=>({method:e,path:t,operation:n}))},async getEndpoints(){return f(await r(),{mergePathParameters:!0})},async getNavigation(e){return p(await r(),e)}}}export{g as createOpenAPI};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@publier/openapi",
3
- "version": "0.1.19",
3
+ "version": "0.2.0",
4
4
  "license": "UNLICENSED",
5
5
  "type": "module",
6
6
  "files": [
@@ -45,8 +45,13 @@
45
45
  "access": "public"
46
46
  },
47
47
  "dependencies": {
48
- "@publier/native": "0.19.0",
48
+ "@publier/native": "0.20.0",
49
49
  "@readme/httpsnippet": "^11.4.1",
50
+ "@readme/oas-to-har": "^39.0.1",
51
+ "@scalar/json-magic": "^0.19.1",
52
+ "@scalar/openapi-parser": "^0.29.22",
53
+ "@scalar/openapi-upgrader": "^0.4.9",
54
+ "oas": "^39.0.1",
50
55
  "openapi-sampler": "^1.7.10",
51
56
  "yaml": "^2.9.1"
52
57
  },
@@ -16,6 +16,6 @@ const L = JSON.parse(openapiRenderApiReferenceShell());
16
16
  <APIPage method={method} path={path} operation={operation} />
17
17
  <Fragment set:html={L.mainCloseAsideOpen} />
18
18
  <RequestExample method={method} path={path} operation={operation} baseUrl={baseUrl} />
19
- <CodeSamples method={method} path={path} operation={operation} baseUrl={baseUrl} />
19
+ <CodeSamples method={method} path={path} operation={operation} spec={spec} baseUrl={baseUrl} />
20
20
  <ResponseExample responses={operation.responses} instanceId={instanceId} />
21
21
  <Fragment set:html={L.close} />
@@ -4,8 +4,8 @@ import { buildCodeSamples } from '../code-sample-generators.ts';
4
4
  import type { CodeSamplesProps } from './props.ts';
5
5
  type Props = CodeSamplesProps;
6
6
 
7
- const { method, path, operation, baseUrl = 'https://api.example.com' } = Astro.props;
8
- const samples = buildCodeSamples(method, path, operation, baseUrl);
7
+ const { method, path, operation, spec, baseUrl = 'https://api.example.com' } = Astro.props;
8
+ const samples = buildCodeSamples(method, path, operation, baseUrl, spec);
9
9
  const html = openapiRenderCodeSamples(method, path, JSON.stringify(samples));
10
10
  ---
11
11
 
@@ -43,6 +43,8 @@ export interface CodeSamplesProps {
43
43
  method: HttpMethod;
44
44
  path: string;
45
45
  operation: OpenApiOperation;
46
+
47
+ spec?: OpenApiSpec;
46
48
  baseUrl?: string;
47
49
  }
48
50