|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480 |
- import {IncomingHttpHeaders, IncomingMessage, OutgoingHttpHeaders, request, RequestOptions} from 'http';
- import {Method, DataSource} from '@modal-sh/yasumi/backend';
- import {FALLBACK_LANGUAGE, Language} from '@modal-sh/yasumi';
-
- interface ClientParams {
- method: Method;
- path: string;
- headers?: IncomingHttpHeaders;
- body?: unknown;
- }
-
- type ResponseBody = Buffer | string | object;
-
- export interface TestClient {
- (params: ClientParams): Promise<[IncomingMessage, ResponseBody?]>;
- acceptMediaType(mediaType: string): this;
- acceptLanguage(language: string): this;
- acceptCharset(charset: string): this;
- contentType(mediaType: string): this;
- contentCharset(charset: string): this;
- }
-
- export const createTestClient = (options: Omit<RequestOptions, 'method' | 'path'>): TestClient => {
- const additionalHeaders: OutgoingHttpHeaders = {};
- const client = (params: ClientParams) => new Promise<[IncomingMessage, ResponseBody?]>((resolve, reject) => {
- const {
- ...etcAdditionalHeaders
- } = additionalHeaders;
-
- // odd that request() uses OutgoingHttpHeaders instead of IncomingHttpHeaders...
- const headers: OutgoingHttpHeaders = {
- ...(options.headers ?? {}),
- ...etcAdditionalHeaders,
- ...(params.headers ?? {}),
- };
-
- let contentTypeHeader: string | undefined;
- if (typeof params.body !== 'undefined') {
- contentTypeHeader = headers['content-type'] = params.headers?.['content-type'] ?? 'application/json';
- }
-
- const req = request({
- ...options,
- method: params.method,
- path: params.path,
- headers,
- });
-
- req.on('response', (res) => {
- // if (req.method.toUpperCase() === 'QUERY') {
- // res.statusMessage = '';
- // res.statusCode = 200;
- // }
-
- res.on('error', (err) => {
- reject(err);
- });
-
- let resBuffer: Buffer | undefined;
- res.on('data', (c) => {
- resBuffer = (
- typeof resBuffer === 'undefined'
- ? Buffer.from(c)
- : Buffer.concat([resBuffer, c])
- );
- });
-
- res.on('close', () => {
- const acceptHeader = Array.isArray(headers['accept']) ? headers['accept'].join('; ') : headers['accept'];
- const contentTypeBase = acceptHeader ?? 'application/octet-stream';
- const [type, subtype] = contentTypeBase.split('/');
- const allSubtypes = subtype.split('+');
- if (typeof resBuffer !== 'undefined') {
- if (allSubtypes.includes('json')) {
- const acceptCharset = (
- Array.isArray(headers['accept-charset'])
- ? headers['accept-charset'].join('; ')
- : headers['accept-charset']
- ) as BufferEncoding | undefined;
- resolve([res, JSON.parse(resBuffer.toString(acceptCharset ?? 'utf-8'))]);
- return;
- }
-
- if (type === 'text') {
- const acceptCharset = (
- Array.isArray(headers['accept-charset'])
- ? headers['accept-charset'].join('; ')
- : headers['accept-charset']
- ) as BufferEncoding | undefined;
- resolve([res, resBuffer.toString(acceptCharset ?? 'utf-8')]);
- return;
- }
-
- resolve([res, resBuffer]);
- return;
- }
-
- resolve([res]);
- });
- });
-
- req.on('error', (err) => {
- reject(err);
- })
-
- if (typeof params.body !== 'undefined') {
- const theContentTypeHeader = Array.isArray(contentTypeHeader) ? contentTypeHeader.join('; ') : contentTypeHeader?.toString();
- const contentTypeAll = theContentTypeHeader ?? 'application/octet-stream';
- const [contentTypeBase, ...contentTypeParams] = contentTypeAll.split(';').map((s) => s.replace(/\s+/g, '').trim());
- const charsetParam = contentTypeParams.find((s) => s.startsWith('charset='));
- const charset = charsetParam?.split('=')?.[1] as BufferEncoding | undefined;
- const [, subtype] = contentTypeBase.split('/');
- const allSubtypes = subtype.split('+');
- req.write(
- allSubtypes.includes('json')
- ? JSON.stringify(params.body)
- : Buffer.from(params.body?.toString() ?? '', contentTypeBase === 'text' ? charset : undefined)
- );
- }
-
- req.end();
- });
-
- client.acceptMediaType = function acceptMediaType(mediaType: string) {
- additionalHeaders['accept'] = mediaType;
- return this;
- };
-
- client.acceptLanguage = function acceptLanguage(language: string) {
- additionalHeaders['accept-language'] = language;
- return this;
- };
-
- client.acceptCharset = function acceptCharset(charset: string) {
- additionalHeaders['accept-charset'] = charset;
- return this;
- };
-
- client.contentType = function contentType(mediaType: string) {
- additionalHeaders['content-type'] = mediaType;
- return this;
- };
-
- client.contentCharset = function contentCharset(charset: string) {
- additionalHeaders['content-type'] = `${additionalHeaders['content-type']}; charset="${charset}"`;
- return this;
- };
-
- return client;
- };
-
- export const dummyGenerationStrategy = () => Promise.resolve();
-
- export class DummyError extends Error {}
-
- export class DummyDataSource implements DataSource {
- private resource?: { dataSource?: unknown };
-
- async create(): Promise<object> {
- return {};
- }
-
- async delete(): Promise<void> {}
-
- async emplace(): Promise<[object, boolean]> {
- return [{}, false];
- }
-
- async getById(): Promise<object> {
- return {};
- }
-
- async newId(): Promise<string> {
- return '';
- }
-
- async getMultiple(): Promise<object[]> {
- return [];
- }
-
- async getSingle(): Promise<object> {
- return {};
- }
-
- async getTotalCount(): Promise<number> {
- return 0;
- }
-
- async initialize(): Promise<void> {}
-
- async patch(): Promise<object> {
- return {};
- }
-
- prepareResource(rr: unknown) {
- this.resource = rr as unknown as { dataSource: DummyDataSource };
- this.resource.dataSource = this;
- }
- }
-
- export const TEST_LANGUAGE: Language = {
- name: FALLBACK_LANGUAGE.name,
- statusMessages: {
- resourceCollectionQueried: '$Resource Collection Queried',
- unableToSerializeResponse: 'Unable To Serialize Response',
- unableToEncodeResponse: 'Unable To Encode Response',
- unableToBindResourceDataSource: 'Unable To Bind $RESOURCE Data Source',
- unableToInitializeResourceDataSource: 'Unable To Initialize $RESOURCE Data Source',
- unableToFetchResourceCollection: 'Unable To Fetch $RESOURCE Collection',
- unableToFetchResource: 'Unable To Fetch $RESOURCE',
- unableToDeleteResource: 'Unable To Delete $RESOURCE',
- languageNotAcceptable: 'Language Not Acceptable',
- characterSetNotAcceptable: 'Character Set Not Acceptable',
- unableToDeserializeResource: 'Unable To Deserialize $RESOURCE',
- unableToDecodeResource: 'Unable To Decode $RESOURCE',
- mediaTypeNotAcceptable: 'Media Type Not Acceptable',
- methodNotAllowed: 'Method Not Allowed',
- urlNotFound: 'URL Not Found',
- badRequest: 'Bad Request',
- ok: 'OK',
- provideOptions: 'Provide Options',
- resourceCollectionFetched: '$RESOURCE Collection Fetched',
- resourceFetched: '$RESOURCE Fetched',
- resourceNotFound: '$RESOURCE Not Found',
- deleteNonExistingResource: 'Delete Non-Existing $RESOURCE',
- resourceDeleted: '$RESOURCE Deleted',
- unableToDeserializeRequest: 'Unable To Deserialize Request',
- patchNonExistingResource: 'Patch Non-Existing $RESOURCE',
- unableToPatchResource: 'Unable To Patch $RESOURCE',
- invalidResourcePatch: 'Invalid $RESOURCE Patch',
- invalidResourcePatchType: 'Invalid $RESOURCE Patch Type',
- invalidResource: 'Invalid $RESOURCE',
- resourcePatched: '$RESOURCE Patched',
- resourceCreated: '$RESOURCE Created',
- resourceReplaced: '$RESOURCE Replaced',
- unableToGenerateIdFromResourceDataSource: 'Unable To Generate ID From $RESOURCE Data Source',
- unableToAssignIdFromResourceDataSource: 'Unable To Assign ID From $RESOURCE Data Source',
- unableToEmplaceResource: 'Unable To Emplace $RESOURCE',
- resourceIdNotGiven: '$RESOURCE ID Not Given',
- unableToCreateResource: 'Unable To Create $RESOURCE',
- notImplemented: 'Not Implemented',
- internalServerError: 'Internal Server Error',
- },
- bodies: {
- badRequest: [
- 'An invalid request has been made.',
- [
- 'Check if the request body has all the required attributes for this endpoint.',
- 'Check if the request body has only the valid attributes for this endpoint.',
- 'Check if the request body matches the schema for the resource associated with this endpoint.',
- 'Check if the request is appropriate for this endpoint.',
- ],
- ],
- languageNotAcceptable: [
- 'The server could not process a response suitable for the client\'s provided language requirement.',
- [
- 'Choose from the available languages on this service.',
- 'Contact the administrator to provide localization for the client\'s given requirements.',
- ],
- ],
- characterSetNotAcceptable: [
- 'The server could not process a response suitable for the client\'s provided character set requirement.',
- [
- 'Choose from the available character sets on this service.',
- 'Contact the administrator to provide localization for the client\'s given requirements.',
- ],
- ],
- mediaTypeNotAcceptable: [
- 'The server could not process a response suitable for the client\'s provided media type requirement.',
- [
- 'Choose from the available media types on this service.',
- 'Contact the administrator to provide localization for the client\'s given requirements.',
- ],
- ],
- deleteNonExistingResource: [
- 'The client has attempted to delete a resource that does not exist.',
- [
- 'Ensure that the resource still exists.',
- 'Ensure that the correct method is provided.',
- ],
- ],
- internalServerError: [
- 'An unknown error has occurred within the service.',
- [
- 'Try the request again at a later time.',
- 'Contact the administrator if the service remains in a degraded or non-functional state.',
- ],
- ],
- invalidResource: [
- 'The request has an invalid structure or is missing some attributes.',
- [
- 'Check if the request body has all the required attributes for this endpoint.',
- 'Check if the request body has only the valid attributes for this endpoint.',
- 'Check if the request body matches the schema for the resource associated with this endpoint.',
- ],
- ],
- invalidResourcePatch: [
- 'The request has an invalid patch data.',
- [
- 'Check if the appropriate patch type is specified on the request data.',
- 'Check if the request body has all the required attributes for this endpoint.',
- 'Check if the request body has only the valid attributes for this endpoint.',
- 'Check if the request body matches the schema for the resource associated with this endpoint.',
- ],
- ],
- invalidResourcePatchType: [
- 'The request has an invalid or unsupported kind of patch data.',
- [
- 'Check if the appropriate patch type is specified on the request data.',
- 'Check if the request body has all the required attributes for this endpoint.',
- 'Check if the request body has only the valid attributes for this endpoint.',
- 'Check if the request body matches the schema for the resource associated with this endpoint.',
- ],
- ],
- methodNotAllowed: [
- 'A request with an invalid or unsupported method has been made.',
- [
- 'Check if the request method is appropriate for this endpoint.',
- 'Check if the client is authorized to perform the method on this endpoint.',
- ]
- ],
- notImplemented: [
- 'The service does not have any implementation for the accessed endpoint.',
- [
- 'Try the request again at a later time.',
- 'Contact the administrator if the service remains in a degraded or non-functional state.',
- ],
- ],
- patchNonExistingResource: [
- 'The client has attempted to patch a resource that does not exist.',
- [
- 'Ensure that the resource still exists.',
- 'Ensure that the correct method is provided.',
- ],
- ],
- resourceIdNotGiven: [
- 'The resource ID is not provided for the accessed endpoint.',
- [
- 'Check if the resource ID is provided and valid in the URL.',
- 'Check if the request method is appropriate for this endpoint.',
- ],
- ],
- unableToAssignIdFromResourceDataSource: [
- 'The resource could not be assigned an ID from the associated data source.',
- [
- 'Try the request again at a later time.',
- 'Contact the administrator regarding missing configuration or unavailability of dependencies.',
- ],
- ],
- unableToBindResourceDataSource: [
- 'The resource could not be associated from the data source.',
- [
- 'Try the request again at a later time.',
- 'Contact the administrator regarding missing configuration or unavailability of dependencies.',
- ],
- ],
- unableToCreateResource: [
- 'An error has occurred on creating the resource.',
- [
- 'Check if the request method is appropriate for this endpoint.',
- 'Check if the request body has all the required attributes for this endpoint.',
- 'Check if the request body has only the valid attributes for this endpoint.',
- 'Check if the request body matches the schema for the resource associated with this endpoint.',
- 'Try the request again at a later time.',
- 'Contact the administrator regarding missing configuration or unavailability of dependencies.',
- ],
- ],
- unableToDecodeResource: [
- 'The resource byte array could not be decoded for the provided character set.',
- [
- 'Choose from the available character sets on this service.',
- 'Contact the administrator to provide localization for the client\'s given requirements.',
- ],
- ],
- unableToDeleteResource: [
- 'An error has occurred on deleting the resource.',
- [
- 'Check if the request method is appropriate for this endpoint.',
- 'Try the request again at a later time.',
- 'Contact the administrator regarding missing configuration or unavailability of dependencies.',
- ],
- ],
- unableToDeserializeRequest: [
- 'The decoded request byte array could not be deserialized for the provided media type.',
- [
- 'Choose from the available media types on this service.',
- 'Contact the administrator to provide localization for the client\'s given requirements.',
- ],
- ],
- unableToDeserializeResource: [
- 'The decoded resource could not be deserialized for the provided media type.',
- [
- 'Choose from the available media types on this service.',
- 'Contact the administrator to provide localization for the client\'s given requirements.',
- ],
- ],
- unableToEmplaceResource: [
- 'An error has occurred on emplacing the resource.',
- [
- 'Check if the request method is appropriate for this endpoint.',
- 'Check if the request body has all the required attributes for this endpoint.',
- 'Check if the request body has only the valid attributes for this endpoint.',
- 'Check if the request body matches the schema for the resource associated with this endpoint.',
- 'Try the request again at a later time.',
- 'Contact the administrator regarding missing configuration or unavailability of dependencies.',
- ],
- ],
- unableToEncodeResponse: [
- 'The response data could not be encoded for the provided character set.',
- [
- 'Choose from the available character sets on this service.',
- 'Contact the administrator to provide localization for the client\'s given requirements.',
- ],
- ],
- unableToFetchResource: [
- 'An error has occurred on fetching the resource.',
- [
- 'Check if the request method is appropriate for this endpoint.',
- 'Try the request again at a later time.',
- 'Contact the administrator regarding missing configuration or unavailability of dependencies.',
- ],
- ],
- unableToFetchResourceCollection: [
- 'An error has occurred on fetching the resource collection.',
- [
- 'Check if the request method is appropriate for this endpoint.',
- 'Try the request again at a later time.',
- 'Contact the administrator regarding missing configuration or unavailability of dependencies.',
- ],
- ],
- unableToGenerateIdFromResourceDataSource: [
- 'The associated data source for the resource could not produce an ID.',
- [
- 'Try the request again at a later time.',
- 'Contact the administrator regarding missing configuration or unavailability of dependencies.',
- ],
- ],
- unableToInitializeResourceDataSource: [
- 'The associated data source for the resource could not be connected for usage.',
- [
- 'Try the request again at a later time.',
- 'Contact the administrator regarding missing configuration or unavailability of dependencies.',
- ],
- ],
- unableToPatchResource: [
- 'An error has occurred on patching the resource.',
- [
- 'Check if the request method is appropriate for this endpoint.',
- 'Check if the request body has all the required attributes for this endpoint.',
- 'Check if the request body has only the valid attributes for this endpoint.',
- 'Check if the request body matches the schema for the resource associated with this endpoint.',
- 'Try the request again at a later time.',
- 'Contact the administrator regarding missing configuration or unavailability of dependencies.',
- ],
- ],
- unableToSerializeResponse: [
- 'The response data could not be serialized for the provided media type.',
- [
- 'Choose from the available media types on this service.',
- 'Contact the administrator to provide localization for the client\'s given requirements.',
- ],
- ],
- urlNotFound: [
- 'An endpoint in the provided URL could not be found.',
- [
- 'Check if the request URL is correct.',
- 'Try the request again at a later time.',
- 'Contact the administrator regarding missing configuration or unavailability of dependencies.',
- ],
- ],
- resourceNotFound: [
- 'The resource in the provided URL could not be found.',
- [
- 'Check if the request URL is correct.',
- 'Try the request again at a later time.',
- 'Contact the administrator regarding missing configuration or unavailability of dependencies.',
- ],
- ],
- },
- };
|