Skip to content

Commit

Permalink
chore: add codemod for custom http headers (#369)
Browse files Browse the repository at this point in the history
  • Loading branch information
smeijer authored Sep 6, 2024
1 parent 0e515bd commit 3172d78
Show file tree
Hide file tree
Showing 5 changed files with 153 additions and 0 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,7 @@
"sort-package-json": "^2.10.0",
"tiny-glob": "^0.2.9",
"ts-jest": "^29.2.0",
"ts-morph": "^23.0.0",
"tslib": "^2.6.2",
"tsx": "^4.19.0",
"turbo": "^2.1.0",
Expand Down
4 changes: 4 additions & 0 deletions packages/project-client/scripts/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { rimraf } from 'rimraf';
import { sortPackageJson } from 'sort-package-json';

import rootPkgJson from '../../../package.json';
import { applyCodeMods } from './mod';

const debug = Debug('build');

Expand Down Expand Up @@ -120,6 +121,9 @@ async function build(specfile = 'https://public.magicbell.com/specs/openapi.v2.j
await move('output/typescript/documentation', './docs');
await rimraf('output');

// code mods
await applyCodeMods();

// patch package.json
let pkgJson = JSON.parse(await fs.readFile('./package.json', { encoding: 'utf-8' }));
pkgJson.scripts.codegen = 'tsx scripts/build.ts';
Expand Down
80 changes: 80 additions & 0 deletions packages/project-client/scripts/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import { fileURLToPath } from 'node:url';

import fs from 'fs';
import path from 'path';
import { Project } from 'ts-morph';

const __dirname = path.dirname(fileURLToPath(import.meta.url));

function addHttpClientHeaderHandler(project: Project) {
const file = project.getSourceFileOrThrow('./src/http/client.ts');
const httpClient = file.getClassOrThrow('HttpClient');
const constructor = httpClient.getConstructors()[0];

const importPath = './handlers/mb-header-handler';

const existingImport = file.getImportDeclaration((dec) => {
return dec.getModuleSpecifierValue() === importPath;
});

if (!existingImport) {
file.addImportDeclaration({
moduleSpecifier: importPath,
namedImports: [{ name: 'HeaderHandler' }],
});
}

const newHandlerLine = 'this.requestHandlerChain.addHandler(new HeaderHandler());';

const alreadyHasHandler = constructor.getStatements().some((statement) => {
return statement.getText() === newHandlerLine;
});

if (!alreadyHasHandler) {
constructor.insertStatements(0, newHandlerLine);
}
}

function addHeaderHandlerFile(project: Project) {
const sourceFilePath = path.join(__dirname, 'mods', 'mb-header-handler.ts');
const targetFilePath = './src/http/handlers/mb-header-handler.ts';

const contents = fs.readFileSync(sourceFilePath, { encoding: 'utf-8' });
const file = project.createSourceFile(targetFilePath, contents, { overwrite: true });

// fix import paths
file.getImportDeclarations().forEach((dec) => {
const moduleSpecifierValue = dec.getModuleSpecifierValue();

const newModuleSpecifierValue = path.relative(
path.dirname(targetFilePath),
path.resolve(path.dirname(sourceFilePath), moduleSpecifierValue),
);

dec.setModuleSpecifier(newModuleSpecifierValue);
});
}

function addHeadersToSdkConfig(project: Project) {
const file = project.getSourceFileOrThrow('./src/http/types.ts');
const sdkConfig = file.getInterfaceOrThrow('SdkConfig');

if (!sdkConfig.getProperty('headers')) {
sdkConfig.addProperty({
name: 'headers',
type: 'Record<string, string>',
hasQuestionToken: true,
});
}
}

export async function applyCodeMods() {
const project = new Project({
tsConfigFilePath: path.join(__dirname, '..', 'tsconfig.build.json'),
});

addHeaderHandlerFile(project);
addHttpClientHeaderHandler(project);
addHeadersToSdkConfig(project);
await project.save();
}
35 changes: 35 additions & 0 deletions packages/project-client/scripts/mods/mb-header-handler.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { SerializationStyle } from '../../src/http/serialization/base-serializer';
import { Request } from '../../src/http/transport/request';
import { HttpResponse, RequestHandler } from '../../src/http/types';

export class HeaderHandler implements RequestHandler {
next?: RequestHandler;

async handle<T>(request: Request<T>): Promise<HttpResponse<T>> {
if (!this.next) {
throw new Error(`No next handler set in ${HeaderHandler.name}`);
}

const requestWithHeaders = this.addHeaders(request);
return this.next?.handle(requestWithHeaders);
}

private addHeaders<T>(request: Request<T>): Request<T> {
const { headers } = request.config as any;
if (typeof headers !== 'object') {
return request;
}

for (const [key, value] of Object.entries(headers)) {
request.addHeaderParam(key, {
key: key,
value: value,
explode: false,
encode: false,
style: SerializationStyle.SIMPLE,
});
}

return request;
}
}
33 changes: 33 additions & 0 deletions yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -3976,6 +3976,16 @@
resolved "https://registry.yarnpkg.com/@tootallnate/quickjs-emscripten/-/quickjs-emscripten-0.23.0.tgz#db4ecfd499a9765ab24002c3b696d02e6d32a12c"
integrity sha512-C5Mc6rdnsaJDjO3UpGW/CQTHtCKaYlScZTly4JIu97Jxo/odCiH0ITnDXSJPTOrEKk/ycSZ0AOgTmkDtkOsvIA==

"@ts-morph/common@~0.24.0":
version "0.24.0"
resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.24.0.tgz#9125b3d5ef9e2633cd6a54296b420b89366599c1"
integrity sha512-c1xMmNHWpNselmpIqursHeOHHBTIsJLbB+NuovbTTRCNiTLEr/U9dbJ8qy0jd/O2x5pc3seWuOUN5R2IoOTp8A==
dependencies:
fast-glob "^3.3.2"
minimatch "^9.0.4"
mkdirp "^3.0.1"
path-browserify "^1.0.1"

"@tsconfig/create-react-app@^2.0.5":
version "2.0.5"
resolved "https://registry.yarnpkg.com/@tsconfig/create-react-app/-/create-react-app-2.0.5.tgz#1265ae3b1cbc5fb30f9ba477e7925eb3fc2f2678"
Expand Down Expand Up @@ -6388,6 +6398,11 @@ co@^4.6.0:
resolved "https://registry.yarnpkg.com/co/-/co-4.6.0.tgz#6ea6bdf3d853ae54ccb8e47bfa0bf3f9031fb184"
integrity sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==

code-block-writer@^13.0.1:
version "13.0.2"
resolved "https://registry.yarnpkg.com/code-block-writer/-/code-block-writer-13.0.2.tgz#e1c6c3dbe5d38b4ac76fb62c4d4b2fc4bf04c9c1"
integrity sha512-XfXzAGiStXSmCIwrkdfvc7FS5Dtj8yelCtyOf2p2skCAfvLd6zu0rGzuS9NSCO3bq1JKpFZ7tbKdKlcd5occQA==

code-red@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/code-red/-/code-red-1.0.4.tgz#59ba5c9d1d320a4ef795bc10a28bd42bfebe3e35"
Expand Down Expand Up @@ -11320,6 +11335,11 @@ mkdirp@^1.0.4:
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==

mkdirp@^3.0.1:
version "3.0.1"
resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50"
integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==

mri@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/mri/-/mri-1.2.0.tgz#6721480fec2a11a4889861115a48b6cbe7cc8f0b"
Expand Down Expand Up @@ -11992,6 +12012,11 @@ pascal-case@^4.0.0:
dependencies:
no-case "^4.0.0"

path-browserify@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd"
integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==

path-exists@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3"
Expand Down Expand Up @@ -14435,6 +14460,14 @@ ts-lit-plugin@^2.0.2:
lit-analyzer "^2.0.1"
web-component-analyzer "^2.0.0"

ts-morph@^23.0.0:
version "23.0.0"
resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-23.0.0.tgz#601d74edd1d24247e312b9fa5d147bdc659bff15"
integrity sha512-FcvFx7a9E8TUe6T3ShihXJLiJOiqyafzFKUO4aqIHDUCIvADdGNShcbc2W5PMr3LerXRv7mafvFZ9lRENxJmug==
dependencies:
"@ts-morph/common" "~0.24.0"
code-block-writer "^13.0.1"

ts-pattern@^5.0.1:
version "5.3.1"
resolved "https://registry.yarnpkg.com/ts-pattern/-/ts-pattern-5.3.1.tgz#ec098665841b1e6a7f7cb2c01bb270b79a2e2858"
Expand Down

0 comments on commit 3172d78

Please sign in to comment.