Skip to content

Commit

Permalink
Merge pull request #366 from kurierjs/feature/typescript-5
Browse files Browse the repository at this point in the history
Upgrades codebase to TypeScript 5.2
  • Loading branch information
joelalejandro authored Oct 21, 2023
2 parents a8ae282 + 6d1bb5b commit 7f5e8b9
Show file tree
Hide file tree
Showing 12 changed files with 1,095 additions and 983 deletions.
1,996 changes: 1,040 additions & 956 deletions package-lock.json

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@
},
"devDependencies": {
"@types/express": "^4.17.13",
"@types/jest": "^29.0.1",
"@types/jest": "^29.5.6",
"@types/jsonwebtoken": "^8.5.9",
"@types/koa": "^2.13.5",
"@types/pluralize": "^0.0.29",
Expand All @@ -60,7 +60,7 @@
"eslint": "^8.23.0",
"eslint-config-prettier": "^8.5.0",
"eslint-plugin-prettier": "^4.2.1",
"jest": "^29.0.3",
"jest": "^29.7.0",
"jest-junit": "^14.0.1",
"prettier": "^2.7.1",
"sqlite3": "^5.0.11",
Expand All @@ -69,9 +69,9 @@
"supertest-koa-agent": "^0.3.2",
"supertest-prefix": "^1.0.2",
"trace-unhandled": "^2.0.1",
"ts-jest": "^29.0.0",
"ts-jest": "^29.1.1",
"ts-node-dev": "^2.0.0",
"typescript": "^4.9.4",
"typescript": "^5.2.2",
"vercel-node-server": "^2.2.1"
}
}
8 changes: 6 additions & 2 deletions src/attribute-types/attribute-type.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
import { ApplicationAttributeInstantiatedTypeClass, ApplicationAttributeTypeOptions } from "../types";
import {
ApplicationAttributeInstantiatedTypeClass,
ApplicationAttributeTypeFactory,
ApplicationAttributeTypeOptions,
} from "../types";
import { capitalize } from "../utils/string";

export default function AttributeType<StoredDataType = string, JsonDataType = StoredDataType>(
name: string,
options: ApplicationAttributeTypeOptions<StoredDataType, JsonDataType>,
) {
const { jsonType, serialize, deserialize } = options;
let attributeClass;
let attributeClass: ApplicationAttributeTypeFactory;

if (jsonType === Object) {
attributeClass = class ThisAttributeTypeDefinition implements ApplicationAttributeInstantiatedTypeClass {
Expand Down
6 changes: 3 additions & 3 deletions src/middlewares/json-api-express.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,12 @@ export default function jsonApiExpress(
return next();
}

req["href"] = `${req.protocol}://${req.get("host")}${req.originalUrl}`;
req["urlData"] = urlData(appInstance, req.path);
req.href = `${req.protocol}://${req.get("host")}${req.originalUrl}`;
req.urlData = urlData(appInstance, req.path);

await runHookFunctions(appInstance, "beforeRequestHandling", hookParameters);

if (req.method === "PATCH" && req["urlData"].resource === "bulk") {
if (req.method === "PATCH" && req.urlData.resource === "bulk") {
res.send(await handleBulkEndpoint(appInstance, req.body.operations));
return next();
}
Expand Down
4 changes: 2 additions & 2 deletions src/middlewares/json-api-koa.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,11 +58,11 @@ export default function jsonApiKoa(
return next();
}

ctx.request["urlData"] = urlData(appInstance, ctx.path);
ctx.request.urlData = urlData(appInstance, ctx.path);

await runHookFunctions(appInstance, "beforeRequestHandling", hookParameters);

if (ctx.method === "PATCH" && ctx.request["urlData"].resource === "bulk") {
if (ctx.method === "PATCH" && ctx.request.urlData.resource === "bulk") {
ctx.body = await handleBulkEndpoint(appInstance, ctx.request.body.operations);
return next();
}
Expand Down
8 changes: 4 additions & 4 deletions src/middlewares/json-api-vercel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,14 +68,14 @@ export default function jsonApiVercel(

// This `href` property is used later in the parsing process to extract query parameters.
// Protocol is there just to make a valid URL. It has no behavioural signifance.
req["href"] = `https://${req.headers.host}${req.url!}`;
req.href = `https://${req.headers.host}${req.url!}`;

const urlObject = new URL(req["href"]);
req["urlData"] = urlData(appInstance, urlObject.pathname);
const urlObject = new URL(req.href);
req.urlData = urlData(appInstance, urlObject.pathname);

await runHookFunctions(appInstance, "beforeRequestHandling", hookParameters);

if (req.method === "PATCH" && req["urlData"].resource === "bulk") {
if (req.method === "PATCH" && req.urlData.resource === "bulk") {
const bulkResponse = await handleBulkEndpoint(appInstance, req.body.operations as Operation[]);
res.json(bulkResponse);
return;
Expand Down
27 changes: 25 additions & 2 deletions src/types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { IncomingHttpHeaders, IncomingMessage, ServerResponse } from "http";
import { IncomingMessage, ServerResponse } from "http";
import { Knex } from "knex";
import { Request as ExpressRequest } from "express";
import { Request as KoaRequest } from "koa";
Expand All @@ -7,9 +7,28 @@ import ApplicationInstance from "./application-instance";
import Password from "./attribute-types/password";
import Resource from "./resource";
import User from "./resources/user";
import OperationProcessor from "./processors/operation-processor";
import Application from "./application";

declare module "express" {
interface Request {
href: string;
urlData: UrlData;
}
}

declare module "koa" {
interface Request {
urlData: UrlData;
}
}

export type UrlData = {
id: string;
resource: string;
relationship: string;
isRelationships: boolean;
};

export enum HttpStatusCode {
OK = 200,
Created = 201,
Expand Down Expand Up @@ -234,6 +253,10 @@ export type VercelRequest<BodyType = JsonApiDocument> = IncomingMessage & {
query: Record<string, string | string[]>;
cookies: Record<string, string>;
body: BodyType;

// Custom extensions made by Kurier.
href: string;
urlData: UrlData;
};

export type VercelResponse = ServerResponse & {
Expand Down
4 changes: 2 additions & 2 deletions src/utils/flatten.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// Thanks 30 seconds of code...
// https://github.com/30-seconds/30-seconds-of-code#flatten

export default function flatten(arr: any[], depth = 1) {
return arr.reduce((a: any[], v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []);
export default function flatten(arr: unknown[], depth = 1) {
return arr.reduce((a: unknown[], v) => a.concat(depth > 1 && Array.isArray(v) ? flatten(v, depth - 1) : v), []);
}
2 changes: 1 addition & 1 deletion src/utils/hooks.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { ApplicationHooks, ApplicationInstanceInterface } from "../types";
export const runHookFunctions = async (
appInstance: ApplicationInstanceInterface,
hookType: keyof ApplicationHooks,
parameters: Record<string, any> = {},
parameters: Record<string, unknown> = {},
) => {
for (const hook of appInstance.app.hooks[hookType]) {
try {
Expand Down
11 changes: 6 additions & 5 deletions src/utils/http-utils.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as escapeStringRegexp from "escape-string-regexp";
import { ApplicationInstanceInterface, JsonApiBulkResponse, VendorRequest } from "../types";
import { ApplicationInstanceInterface, JsonApiBulkResponse, UrlData, VendorRequest } from "../types";
import JsonApiError from "../errors/error";
import JsonApiErrors from "../errors/json-api-errors";
import User from "../resources/user";
Expand Down Expand Up @@ -28,15 +28,16 @@ async function authenticate(appInstance: ApplicationInstanceInterface, request:
appInstance.user = currentUser;
}

function urlData(appInstance: ApplicationInstanceInterface, path: string) {
function urlData(appInstance: ApplicationInstanceInterface, path: string): UrlData {
const urlRegexp = new RegExp(
`^(\/+)?((?<namespace>${escapeStringRegexp(
appInstance.app.namespace,
)})(\/+|$))?(?<resource>[^\\s\/?]+)?(\/+)?((?<id>[^\\s\/?]+)?(\/+)?(?<relationships>relationships)?(\/+)?)?` +
"(?<relationship>[^\\s/?]+)?(/+)?$",
);

const { resource, id, relationships, relationship } = (path.match(urlRegexp) || {})["groups"] || ({} as any);
const { resource, id, relationships, relationship } =
(path.match(urlRegexp) || ({} as UrlData))["groups"] || ({} as UrlData);

return {
id,
Expand Down Expand Up @@ -74,7 +75,7 @@ async function handleJsonApiEndpoint(
}

function convertHttpRequestToOperation(req: VendorRequest): Operation {
const { id, resource, relationship } = req["urlData"];
const { id, resource, relationship } = req.urlData;
const type = camelize(singularize(resource));

const opMap = {
Expand All @@ -87,7 +88,7 @@ function convertHttpRequestToOperation(req: VendorRequest): Operation {

return {
op: opMap[req.method as string],
params: parse(req["href"]),
params: parse(req.href),
ref: { id, type, relationship },
data: (req.body || {}).data,
} as Operation;
Expand Down
2 changes: 1 addition & 1 deletion src/utils/object.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
const isEmptyObject = (obj: any) => obj && Object.keys(obj).length === 0;
const isEmptyObject = (obj: object | undefined) => obj && Object.keys(obj).length === 0;

export { isEmptyObject };
2 changes: 1 addition & 1 deletion src/utils/promise-hash-map.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const promiseHashMap = async (hash, callback) => {
const promiseHashMap = async (hash: Record<string, unknown>, callback: (key: string | number) => Promise<unknown>) => {
const keys = Object.keys(hash);
const result = {};

Expand Down

0 comments on commit 7f5e8b9

Please sign in to comment.