Skip to content

Commit

Permalink
save progress
Browse files Browse the repository at this point in the history
  • Loading branch information
Zamralik committed May 28, 2024
1 parent a5bd747 commit c41f44a
Show file tree
Hide file tree
Showing 75 changed files with 1,457 additions and 444 deletions.
26 changes: 22 additions & 4 deletions packages/architectura/src/core/server/rich-client-request.mts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { Socket } from "node:net";
import type { HTTPMethodEnum } from "../definition/enum/http-method.enum.mjs";
import { type IncomingHttpHeaders, IncomingMessage } from "node:http";
import { type ParsedUrlQuery, parse as parseQuery } from "node:querystring";
import { type JSONObjectType, JSONUtility, type JSONValueType } from "@vitruvius-labs/toolbox";
import { type JSONObjectType, type JSONValueType, jsonDeserialize } from "@vitruvius-labs/toolbox";
import { assertRecord } from "@vitruvius-labs/ts-predicate/type-assertion";
import { isArray } from "@vitruvius-labs/ts-predicate/type-guard";
import { ContentTypeEnum } from "./definition/enum/content-type.enum.mjs";
Expand Down Expand Up @@ -105,11 +105,11 @@ class RichClientRequest extends IncomingMessage
{
this.contentType = CONTENT_TYPE_HEADER;

if (this.contentType.startsWith("multipart/form-data; boundary="))
if (CONTENT_TYPE_HEADER.startsWith("multipart/form-data; boundary="))
{
this.contentType = ContentTypeEnum.FORM_DATA;

const BOUNDARY_IDENTIFIER: string = this.contentType.replace("multipart/form-data; boundary=", "");
const BOUNDARY_IDENTIFIER: string = CONTENT_TYPE_HEADER.replace("multipart/form-data; boundary=", "");

if (BOUNDARY_IDENTIFIER.length === 0)
{
Expand Down Expand Up @@ -465,12 +465,30 @@ class RichClientRequest extends IncomingMessage
public async getBodyAsJSON(): Promise<JSONObjectType>
{
const BODY_AS_STRING: string = await this.getBodyAsString();
const PARSED_BODY: JSONValueType = JSONUtility.Deserialize(BODY_AS_STRING);
const PARSED_BODY: JSONValueType = jsonDeserialize(BODY_AS_STRING);

assertRecord(PARSED_BODY);

return PARSED_BODY;
}

/* @TODO: Add support for multipart body */
/**
* @throws if the request doesn't have a multipart body.
*/
/*
public async getBodyAsMultipart(): Promise<unknown>
{
if (this.boundary === undefined)
{
throw new Error("This request does not have a multipart body.");
}
const BODY_AS_STRING: string = await this.getBodyAsString();
return MultipartUtility.Parse(BODY_AS_STRING.split(this.boundary));
}
*/
}

export { RichClientRequest };
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { pipeline } from "node:stream/promises";
import { ServerResponse as HTTPServerResponse } from "node:http";
import { createBrotliCompress, createDeflate, createGzip } from "node:zlib";
import { isNumber, isRecord, isString } from "@vitruvius-labs/ts-predicate/type-guard";
import { JSONUtility } from "@vitruvius-labs/toolbox";
import { jsonSerialize } from "@vitruvius-labs/toolbox";
import { HTTPStatusCodeEnum } from "./definition/enum/http-status-code.enum.mjs";
import { ContentTypeEnum } from "./definition/enum/content-type.enum.mjs";
import { CookieSameSiteEnum } from "./definition/enum/cookie-same-site.enum.mjs";
Expand Down Expand Up @@ -432,7 +432,7 @@ class RichServerResponse extends HTTPServerResponse<RichClientRequest>
return;
}

this.content = JSONUtility.Serialize(parameters.payload);
this.content = jsonSerialize(parameters.payload);
}

private processCookieHeader(): void
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import type { ExecutionContext } from "../core/execution-context/execution-conte
class HelloWorldEndpoint extends BaseEndpoint
{
protected readonly method: HTTPMethodEnum = HTTPMethodEnum.GET;
protected readonly route: RegExp = /^.*$/;
protected readonly route: string = ".*";

public override async execute(context: ExecutionContext): Promise<void>
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { TokenType } from "../definition/type/token.type.mjs";
import type { SecretType } from "../definition/type/secret.type.mjs";
import type { JWTClaimsInterface } from "../definition/interface/jwt-claims.interface.mjs";
import { JSONUtility } from "@vitruvius-labs/toolbox";
import { jsonDeserialize } from "@vitruvius-labs/toolbox";
import { Base64URL } from "../utility/base64-url.mjs";
import { validateSecret } from "../utility/validate-secret.mjs";
import { assertToken } from "../predicate/assert-token.mjs";
Expand Down Expand Up @@ -66,7 +66,7 @@ class JWTFactory
throw new Error("Invalid token signature.");
}

const CLAIMS: unknown = JSONUtility.Deserialize(Base64URL.Decode(ENCODED_CLAIMS));
const CLAIMS: unknown = jsonDeserialize(Base64URL.Decode(ENCODED_CLAIMS));

assertClaims(CLAIMS);

Expand Down
4 changes: 2 additions & 2 deletions packages/architectura/src/service/jwt/data-object/jwt.mts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { SecretType } from "../definition/type/secret.type.mjs";
import type { JWTHeaderInterface } from "../definition/interface/jwt-header.interface.mjs";
import type { JWTClaimsInterface } from "../definition/interface/jwt-claims.interface.mjs";
import { JSONUtility } from "@vitruvius-labs/toolbox";
import { jsonSerialize } from "@vitruvius-labs/toolbox";
import { Base64URL } from "../utility/base64-url.mjs";
import { validateAlgorithm } from "../utility/validate-algorithm.mjs";
import { validateSecret } from "../utility/validate-secret.mjs";
Expand Down Expand Up @@ -75,7 +75,7 @@ class JWT
{
validateClaims(this.claims);
const HEADER: string = Base64URL.Encode(JSON.stringify(this.header));
const CLAIMS: string = Base64URL.Encode(JSONUtility.Serialize(this.claims));
const CLAIMS: string = Base64URL.Encode(jsonSerialize(this.claims));

const SIGNATURE: string = computeSignature({
algorithm: this.header.alg,
Expand Down
28 changes: 10 additions & 18 deletions packages/architectura/src/service/logger/logger.proxy.mts
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,8 @@ class LoggerProxy
LoggerProxy.Process(message, LogLevelEnum.EMERGENCY, tag);
}

private static Process(message: unknown, level: LogLevelEnum, tag: string | undefined): void
// @ts-expect-error: Returns void to not interrupt the flow
private static async Process(message: unknown, level: LogLevelEnum, tag: string | undefined): void
{
const UUID: string | undefined = ExecutionContextRegistry.GetUnsafeExecutionContext()?.getUUID();

Expand All @@ -118,28 +119,19 @@ class LoggerProxy
tag: tag,
};

let promise: Promise<void> | void = undefined;

if (isString(message))
try
{
promise = LoggerProxy.Logger.handleMessage(message, CONTEXT);
if (isString(message))
{
await LoggerProxy.Logger.handleMessage(message, CONTEXT);
}

return;
await LoggerProxy.Logger.handleError(toError(message), CONTEXT);
}

promise = LoggerProxy.Logger.handleError(toError(message), CONTEXT);

if (!(promise instanceof Promise))
catch (error: unknown)
{
return;
await Server.HandleError(error).catch((): void => { /* Do nothing */ });
}

promise.catch(
(reason: Error): void =>
{
Server.HandleError(reason).catch((): void => { /* Do nothing */ });
}
);
}
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from "./session.model.mjs";
export * from "./session.mjs";
export * from "./session.factory.mjs";
export * from "./session.registry.mjs";
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { SessionDelegateInterface } from "../definition/interface/session-delegate.interface.mjs";
import { Session } from "./session.model.mjs";
import { Session } from "./session.mjs";

/**
* Session Factory
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Session } from "./session.model.mjs";
import type { Session } from "./session.mjs";

/**
* Session registry
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { ExecutionContext } from "../../../core/execution-context/execution
import type { SessionDelegateInterface } from "../definition/interface/session-delegate.interface.mjs";
import { BasePreHook } from "../../../core/hook/base.pre-hook.mjs";
import { Server } from "../../../core/server/server.mjs";
import { Session } from "../entity/session.model.mjs";
import { Session } from "../entity/session.mjs";
import { SessionRegistry } from "../entity/session.registry.mjs";
import { SessionConstantEnum } from "../definition/enum/session-constant.enum.mjs";
import { MillisecondEnum } from "../../../definition/enum/millisecond.enum.mjs";
Expand Down
17 changes: 10 additions & 7 deletions packages/architectura/src/utility/singleton.mts
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ abstract class Singleton
* @sealed
*
* @remarks
* This method returns a boolean if the instance of a singleton class exists.
* This method returns a boolean if the instance of a singleton class exists in the internal registry.
* It takes a constructor as parameter for consistency with GetInstance and FindInstance.
*
* @example
* ```typescript
Expand Down Expand Up @@ -85,8 +86,9 @@ abstract class Singleton
* @sealed
*
* @remarks
* This method returns the instance of a singleton class.
* If the class has not been instantiated yet, throws an error.
* This method returns the instance of a singleton class from the internal registry.
* If the class is not found in the internal registry, throws an error.
* It takes a constructor as parameter because of a TypeScript typing limitation.
*
* @example
* ```typescript
Expand All @@ -105,7 +107,7 @@ abstract class Singleton
*
* @param class_constructor - The constructor of the singleton class.
* @returns The instance of the singleton class.
* @throws If the instance doesn't exist.
* @throws If the instance cannot be found.
*/
public static GetInstance<T extends Singleton>(class_constructor: ConstructorOf<T>): T
{
Expand All @@ -131,7 +133,8 @@ abstract class Singleton
*
* @remarks
* This method returns the instance of a singleton class.
* If the class has not been instantiated yet, it returns undefined.
* If no instance is found in the internal registry, it returns undefined.
* It takes a constructor as parameter because of a TypeScript typing limitation.
*
* @param class_constructor - The constructor of the singleton class.
* @returns The instance of the singleton class, or undefined if it doesn't exists.
Expand All @@ -154,8 +157,8 @@ abstract class Singleton
* @sealed
*
* @remarks
* This method clears the instance of a singleton class. It removes the instance from
* the internal map.
* This method remove the instance of a singleton class from the internal registry.
* It takes a constructor as parameter for consistency with GetInstance and FindInstance.
*
* @example
* ```typescript
Expand Down
39 changes: 13 additions & 26 deletions packages/architectura/test/core/endpoint/base.endpoint.spec.mts
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@ import { deepStrictEqual } from "node:assert";
import { describe, it } from "node:test";
import { BaseEndpoint, BaseErrorHook, BasePostHook, BasePreHook, HTTPMethodEnum } from "../../../src/_index.mjs";

describe("BaseEndpoint", (): void =>
{
describe("getPreHooks", (): void =>
{
it("should return the pre hooks", (): void =>
{
describe("BaseEndpoint", (): void => {
describe("getPreHooks", (): void => {
it("should return the pre hooks", (): void => {
class DummyPreHook extends BasePreHook
{
public execute(): void { }
Expand All @@ -30,10 +27,8 @@ describe("BaseEndpoint", (): void =>
});
});

describe("getExcludedGlobalPreHooks", (): void =>
{
it("should return the excluded pre hook constructors", (): void =>
{
describe("getExcludedGlobalPreHooks", (): void => {
it("should return the excluded pre hook constructors", (): void => {
class DummyPreHook extends BasePreHook
{
public execute(): void { }
Expand All @@ -54,10 +49,8 @@ describe("BaseEndpoint", (): void =>
});
});

describe("getPostHooks", (): void =>
{
it("should return the post hooks", (): void =>
{
describe("getPostHooks", (): void => {
it("should return the post hooks", (): void => {
class DummyPostHook extends BasePostHook
{
public execute(): void { }
Expand All @@ -80,10 +73,8 @@ describe("BaseEndpoint", (): void =>
});
});

describe("getExcludedGlobalPostHooks", (): void =>
{
it("should return the excluded post hook constructors", (): void =>
{
describe("getExcludedGlobalPostHooks", (): void => {
it("should return the excluded post hook constructors", (): void => {
class DummyPostHook extends BasePostHook
{
public execute(): void { }
Expand All @@ -104,10 +95,8 @@ describe("BaseEndpoint", (): void =>
});
});

describe("getErrorHooks", (): void =>
{
it("should return the error hooks", (): void =>
{
describe("getErrorHooks", (): void => {
it("should return the error hooks", (): void => {
class DummyErrorHook extends BaseErrorHook
{
public execute(): void { }
Expand All @@ -130,10 +119,8 @@ describe("BaseEndpoint", (): void =>
});
});

describe("getExcludedGlobalErrorHooks", (): void =>
{
it("should return the excluded error hook constructors", (): void =>
{
describe("getExcludedGlobalErrorHooks", (): void => {
it("should return the excluded error hook constructors", (): void => {
class DummyErrorHook extends BaseErrorHook
{
public execute(): void { }
Expand Down
26 changes: 12 additions & 14 deletions packages/architectura/test/core/endpoint/endpoint.registry.spec.mts
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,11 @@ import { BaseEndpoint, type EndpointEntryInterface, type EndpointMatchInterface,

describe("EndpointRegistry", (): void => {
beforeEach((): void => {
// @ts-expect-error: Access to private property for testing purposes.
EndpointRegistry.ENDPOINTS.clear();
Reflect.get(EndpointRegistry, "ENDPOINTS").clear();
});

afterEach((): void => {
// @ts-expect-error: Access to private property for testing purposes.
EndpointRegistry.ENDPOINTS.clear();
Reflect.get(EndpointRegistry, "ENDPOINTS").clear();
});

describe("FindEndpoint", (): void => {
Expand All @@ -25,8 +23,7 @@ describe("EndpointRegistry", (): void => {
const EMPTY_MAP: Map<string, BaseEndpoint> = new Map();

deepStrictEqual(EndpointRegistry.FindEndpoint(HTTPMethodEnum.GET, "/"), MATCHING_ENDPOINT);
// @ts-expect-error - We need to access this private property for test purposes.
deepStrictEqual(EndpointRegistry.ENDPOINTS, EMPTY_MAP);
deepStrictEqual(Reflect.get(EndpointRegistry, "ENDPOINTS"), EMPTY_MAP);
});

it("should return the registered endpoint that matches", (): void => {
Expand All @@ -45,8 +42,7 @@ describe("EndpointRegistry", (): void => {
matchGroups: undefined,
};

// @ts-expect-error - We need to access this private property for test purposes.
EndpointRegistry.ENDPOINTS.set(
Reflect.get(EndpointRegistry, "ENDPOINTS").set(
"dummy-key",
{
method: HTTPMethodEnum.GET,
Expand All @@ -69,8 +65,7 @@ describe("EndpointRegistry", (): void => {

const ENDPOINT: DummyEndpoint = new DummyEndpoint();

// @ts-expect-error - We need to access this private property for test purposes.
EndpointRegistry.ENDPOINTS.set(
Reflect.get(EndpointRegistry, "ENDPOINTS").set(
"dummy-key",
{
method: HTTPMethodEnum.GET,
Expand All @@ -79,8 +74,7 @@ describe("EndpointRegistry", (): void => {
}
);

// @ts-expect-error - We need to access this private property for test purposes.
EndpointRegistry.ENDPOINTS.set(
Reflect.get(EndpointRegistry, "ENDPOINTS").set(
"dummy-key",
{
method: HTTPMethodEnum.POST,
Expand Down Expand Up @@ -120,8 +114,12 @@ describe("EndpointRegistry", (): void => {
]);

EndpointRegistry.AddEndpoint(ENDPOINT);
// @ts-expect-error - We need to access this private property for test purposes.
deepStrictEqual(EndpointRegistry.ENDPOINTS, POPULATED_MAP);
deepStrictEqual(Reflect.get(EndpointRegistry, "ENDPOINTS"), POPULATED_MAP);
});
});

describe("AddEndpointsDirectory", (): void => {
it.todo("should explore a folder recursively and add endpoints to the registry", async (): Promise<void> => {});
it.todo("should ignore abstract endpoints", async (): Promise<void> => {});
});
});
Loading

0 comments on commit c41f44a

Please sign in to comment.