Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: smol refactors #1149

Merged
merged 5 commits into from
Jan 17, 2025
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
2 changes: 1 addition & 1 deletion src/commands/changelogs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Args, Flags } from '@oclif/core';

import BaseCommand from '../lib/baseCommand.js';
import { githubFlag, keyFlag } from '../lib/flags.js';
import syncDocsPath from '../lib/syncDocsPath.js';
import syncDocsPath from '../lib/syncDocsPath.legacy.js';

export default class ChangelogsCommand extends BaseCommand<typeof ChangelogsCommand> {
// we need this as a const for syncDocsPath
Expand Down
14 changes: 5 additions & 9 deletions src/lib/baseCommand.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import chalk from 'chalk';
import debugPkg from 'debug';

import { isGHA, isTest } from './isCI.js';
import { handleAPIv2Res, readmeAPIv2Fetch, type FilePathDetails } from './readmeAPIFetch.js';
import { handleAPIv2Res, readmeAPIv2Fetch } from './readmeAPIFetch.js';

type Flags<T extends typeof OclifCommand> = Interfaces.InferredFlags<(typeof BaseCommand)['baseFlags'] & T['flags']>;
type Args<T extends typeof OclifCommand> = Interfaces.InferredArgs<T['args']>;
Expand Down Expand Up @@ -116,19 +116,15 @@ export default abstract class BaseCommand<T extends typeof OclifCommand> extends
/**
* Wrapper around `handleAPIv2Res` that binds the context of the class to the function.
*/
public async handleAPIRes(res: Response) {
return handleAPIv2Res.call(this, res);
public async handleAPIRes(...args: Parameters<typeof handleAPIv2Res>) {
return handleAPIv2Res.call(this, ...args);
}

/**
* Wrapper around `readmeAPIv2Fetch` that binds the context of the class to the function.
*/
public async readmeAPIFetch(
pathname: string,
options: RequestInit = { headers: new Headers() },
fileOpts: FilePathDetails = { filePath: '', fileType: false },
) {
return readmeAPIv2Fetch.call(this, pathname, options, fileOpts);
public async readmeAPIFetch(...args: Parameters<typeof readmeAPIv2Fetch>) {
return readmeAPIv2Fetch.call(this, ...args);
}

async runCreateGHAHook(opts: CreateGHAHookOptsInClass) {
Expand Down
30 changes: 23 additions & 7 deletions src/lib/readmeAPIFetch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ const SUCCESS_NO_CONTENT = 204;
* This contains a few pieces of information about a file so
* we can properly construct a source URL for it.
*/
export interface FilePathDetails {
interface FilePathDetails {
/** The URL or local file path */
filePath: string;
/** This is derived from the `oas-normalize` `type` property. */
Expand Down Expand Up @@ -348,10 +348,30 @@ export async function handleAPIv1Res(res: Response, rejectOnJsonError = true) {
*
* If we receive non-JSON responses, we consider them errors and throw them.
*/
export async function handleAPIv2Res<T extends Command>(this: T, res: Response) {
export async function handleAPIv2Res<T extends Command>(
this: T,
res: Response,
/**
* If we're making a request where we don't care about the body (e.g. a HEAD or DELETE request),
* we can skip parsing the JSON body using this flag.
*/
skipJsonParsing = false,
) {
const contentType = res.headers.get('content-type') || '';
const extension = mime.extension(contentType) || contentType.includes('json') ? 'json' : false;
if (extension === 'json') {
if (res.status === SUCCESS_NO_CONTENT) {
// to prevent a memory leak, we should still consume the response body? even though we don't use it?
// https://x.com/cramforce/status/1762142087930433999
const body = await res.text();
this.debug(`received status code ${res.status} from ${res.url} with no content: ${body}`);
return {};
} else if (skipJsonParsing) {
// to prevent a memory leak, we should still consume the response body? even though we don't use it?
// https://x.com/cramforce/status/1762142087930433999
const body = await res.text();
this.debug(`received status code ${res.status} from ${res.url} and not parsing JSON b/c of flag: ${body}`);
return {};
} else if (extension === 'json') {
// TODO: type this better
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const body = (await res.json()) as any;
Expand All @@ -361,10 +381,6 @@ export async function handleAPIv2Res<T extends Command>(this: T, res: Response)
}
return body;
}
if (res.status === SUCCESS_NO_CONTENT) {
this.debug(`received status code ${res.status} from ${res.url} with no content`);
return {};
}

// If we receive a non-JSON response, it's likely an error.
// Let's debug the raw response body and throw it.
Expand Down
2 changes: 2 additions & 0 deletions src/lib/syncDocsPath.ts → src/lib/syncDocsPath.legacy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,8 @@ function sortFiles(filePaths: string[]): ReadDocMetadata[] {
* Takes a path (either to a directory of files or to a single file)
* and syncs those (either via POST or PUT) to ReadMe.
* @returns A promise-wrapped string with the results
*
* @deprecated This is for APIv1 only. Use `syncDocsPath.ts` instead, if possible.
*/
export default async function syncDocsPath(
this: ChangelogsCommand,
Expand Down
Loading