Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion packages/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@
],
"dependencies": {
"@readme/api-core": "file:../core",
"@readme/oas-to-har": "^23.0.14",
"@readme/openapi-parser": "^2.4.0",
"chalk": "^5.3.0",
"commander": "^11.1.0",
Expand Down
20 changes: 13 additions & 7 deletions packages/api/src/lib/suggestedOperations.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { AuthForHAR } from '@readme/oas-to-har/lib/types';
import type Oas from 'oas';
import type Operation from 'oas/operation';

import oasToHar from '@readme/oas-to-har';
import APICore from '@readme/api-core';
import client from 'httpsnippet-client-api';
import { Webhook } from 'oas/operation';

Expand Down Expand Up @@ -55,8 +55,19 @@ export function getSuggestedOperation(oas: Oas) {
* Generate an example code snippet for a given (suggested) operation. We'll show this to users
* post-codegeneration so they can see how to use the SDK we created for them.
*
* We're intentionally using `httpsnippet-client-api` and not `@readme/oas-to-snippet` here,
* which would handle HAR and snippet generation, because don't need the entire `oas-to-snippet`
* and `@readme/httpsnippet` libraries for what we're doing here.
*
* All we want to do is generate a very simple code example for `api` snippets and as we're
* controlling which kinds of endpoints we're generating these for the HAR dataset we're working
* with is a mostly fully known object.
*
*/
export async function buildCodeSnippetForOperation(oas: Oas, operation: Operation, opts: { identifier: string }) {
const core = new APICore();
core.setSpec(oas);

// If this endpoint has authentication on it then we should try to flesh out some placeholder
// values in the `.auth()` SDK method for them so they can see how to use auth.
let auth: AuthForHAR = {};
Expand All @@ -80,12 +91,7 @@ export async function buildCodeSnippetForOperation(oas: Oas, operation: Operatio
auth = oas.getAuth(auth) as AuthForHAR;
}

// We're pulling in `@reamde/oas-to-har` and `httpsnippet-client-api` here instead of using
// `@readme/oas-to-snippet`, which would handle both, because we don't need the entire
// `oas-to-snippet` for what we're doing here. All we want to do is generate a very simple code
// example for `api` snippets and because we're controlling which kinds of endpoints we're
// generating this for the HAR dataset we're working with here is mostly a fully known object.
const har = oasToHar(oas, operation, undefined, auth)?.log?.entries?.[0]?.request;
const har = core.getHARForRequest(operation, {}, auth)?.log?.entries?.[0]?.request;
if (!har) {
return false;
}
Expand Down
13 changes: 11 additions & 2 deletions packages/core/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import type { ConfigOptions } from './types.js';
import type { AuthForHAR, DataForHAR } from '@readme/oas-to-har/lib/types';
import type { Har } from 'har-format';
import type Operation from 'oas/operation';
import type { HttpMethods, OASDocument } from 'oas/rmoas.types';
Expand Down Expand Up @@ -66,6 +67,15 @@ export default class APICore {
return this.fetchOperation<HTTPStatus>(operation, body, metadata);
}

/**
* Retrieve a HAR for a given HTTP request.
*
* @internal
*/
getHARForRequest(operation: Operation, data: DataForHAR, auth: AuthForHAR) {
return oasToHar(this.spec, operation, data, auth);
}

async fetchOperation<HTTPStatus extends number = number>(
operation: Operation,
body?: unknown,
Expand All @@ -84,8 +94,7 @@ export default class APICore {
}
}

// @ts-expect-error `this.auth` typing is off. FIXME
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oh hell yeah

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

turns out the problem was that i wasn't casting some numbers as a string with String()

const har = oasToHar(this.spec, operation, data, prepareAuth(this.auth, operation));
const har = this.getHARForRequest(operation, data, prepareAuth(this.auth, operation));

let timeoutSignal: NodeJS.Timeout;
const init: RequestInit = {};
Expand Down
19 changes: 6 additions & 13 deletions packages/core/src/lib/prepareAuth.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
/* eslint-disable no-underscore-dangle */
import type { AuthForHAR } from '@readme/oas-to-har/lib/types';
import type Operation from 'oas/operation';
import type { KeyedSecuritySchemeObject } from 'oas/rmoas.types';

Expand All @@ -7,15 +8,7 @@ export default function prepareAuth(authKey: (number | string)[], operation: Ope
return {};
}

const preparedAuth: Record<
string,
| string
| number
| {
pass: string | number;
user: string | number;
}
> = {};
const preparedAuth: AuthForHAR = {};

const security = operation.getSecurity();
if (security.length === 0) {
Expand Down Expand Up @@ -61,8 +54,8 @@ export default function prepareAuth(authKey: (number | string)[], operation: Ope

const scheme = schemes.shift() as KeyedSecuritySchemeObject;
preparedAuth[scheme._key] = {
user: authKey[0],
pass: authKey.length === 2 ? authKey[1] : '',
user: String(authKey[0]),
pass: authKey.length === 2 ? String(authKey[1]) : '',
};

return preparedAuth;
Expand All @@ -82,8 +75,8 @@ export default function prepareAuth(authKey: (number | string)[], operation: Ope
case 'http':
if (scheme.scheme === 'basic') {
preparedAuth[scheme._key] = {
user: authKey[0],
pass: authKey.length === 2 ? authKey[1] : '',
user: String(authKey[0]),
pass: authKey.length === 2 ? String(authKey[1]) : '',
};
} else if (scheme.scheme === 'bearer') {
preparedAuth[scheme._key] = authKey[0];
Expand Down