Browse Source

Update content negotiation headers

Simplify data for language messages.
master
TheoryOfNekomata 9 months ago
parent
commit
48c0eb40df
24 changed files with 294 additions and 215 deletions
  1. +26
    -0
      docs/bruno/Create Resource.bru
  2. +11
    -0
      docs/bruno/Delete Resource.bru
  3. +23
    -0
      docs/bruno/Emplace Resource.bru
  4. +11
    -0
      docs/bruno/Get Resource Collection Metadata.bru
  5. +11
    -0
      docs/bruno/Get Resource Collection.bru
  6. +11
    -0
      docs/bruno/Get Resource Metadata.bru
  7. +11
    -0
      docs/bruno/Get Resource.bru
  8. +22
    -0
      docs/bruno/Patch Resource.bru
  9. +13
    -0
      docs/bruno/bruno.json
  10. +0
    -5
      examples/basic/server.ts
  11. +13
    -7
      src/app.ts
  12. +4
    -7
      src/backend/core.ts
  13. +18
    -15
      src/backend/server.ts
  14. +15
    -10
      src/client/index.ts
  15. +0
    -1
      src/common/charsets/index.ts
  16. +0
    -5
      src/common/charsets/utf-8.ts
  17. +57
    -0
      src/common/index.ts
  18. +45
    -39
      src/common/language.ts
  19. +0
    -109
      src/common/languages/en/index.ts
  20. +0
    -1
      src/common/languages/index.ts
  21. +0
    -5
      src/common/media-types/application/json.ts
  22. +0
    -2
      src/common/media-types/index.ts
  23. +0
    -4
      src/index.ts
  24. +3
    -5
      test/e2e/default.test.ts

+ 26
- 0
docs/bruno/Create Resource.bru View File

@@ -0,0 +1,26 @@
meta {
name: Create Resource
type: http
seq: 5
}

post {
url: http://localhost:3000/api/users
body: json
auth: none
}

headers {
Content-Type: application/json
}

body:json {
{
"firstName": "John",
"middleName": "Smith",
"lastName": "Doe",
"birthday": "1986-04-20",
"bio": "This is my profile!"
}
}

+ 11
- 0
docs/bruno/Delete Resource.bru View File

@@ -0,0 +1,11 @@
meta {
name: Delete Resource
type: http
seq: 8
}

delete {
url: http://localhost:3000/api/users/2
body: none
auth: none
}

+ 23
- 0
docs/bruno/Emplace Resource.bru View File

@@ -0,0 +1,23 @@
meta {
name: Emplace Resource
type: http
seq: 6
}

put {
url: http://localhost:3000/api/users/2
body: json
auth: none
}

body:json {
{
"firstName": "John",
"middleName": "Smith",
"lastName": "Doe",
"birthday": "1986-04-20",
"bio": "This is my profile!",
"id": 2
}
}

+ 11
- 0
docs/bruno/Get Resource Collection Metadata.bru View File

@@ -0,0 +1,11 @@
meta {
name: Get Resource Collection Metadata
type: http
seq: 1
}

head {
url: http://localhost:3000/api/users
body: none
auth: none
}

+ 11
- 0
docs/bruno/Get Resource Collection.bru View File

@@ -0,0 +1,11 @@
meta {
name: Get Resource Collection
type: http
seq: 3
}

get {
url: http://localhost:3000/api/users
body: none
auth: none
}

+ 11
- 0
docs/bruno/Get Resource Metadata.bru View File

@@ -0,0 +1,11 @@
meta {
name: Get Resource Metadata
type: http
seq: 2
}

head {
url: http://localhost:3000/api/users/1
body: none
auth: none
}

+ 11
- 0
docs/bruno/Get Resource.bru View File

@@ -0,0 +1,11 @@
meta {
name: Get Resource
type: http
seq: 4
}

get {
url: http://localhost:3000/api/users/1
body: none
auth: none
}

+ 22
- 0
docs/bruno/Patch Resource.bru View File

@@ -0,0 +1,22 @@
meta {
name: Patch Resource
type: http
seq: 7
}

patch {
url: http://localhost:3000/api/users/1
body: json
auth: none
}

headers {
Content-Type: application/json
}

body:json {
{
"bio": "This is my updated bio!"
}
}

+ 13
- 0
docs/bruno/bruno.json View File

@@ -0,0 +1,13 @@
{
"version": "1",
"name": "Yasumi",
"type": "collection",
"ignore": [
"node_modules",
".git"
],
"presets": {
"requestType": "http",
"requestUrl": "http://localhost:3000"
}
}

+ 0
- 5
examples/basic/server.ts View File

@@ -2,8 +2,6 @@ import {
application,
resource,
validation as v,
mediaTypes,
charsets,
} from '../../src';
import {TEXT_SERIALIZER_PAIR} from './serializers';
import {autoIncrement, dataSource} from './data-source';
@@ -52,10 +50,7 @@ const User = resource(v.object(
const app = application({
name: 'piano-service',
})
.mediaType(mediaTypes.applicationJson)
.mediaType(mediaTypes.textJson)
.mediaType(TEXT_SERIALIZER_PAIR)
.charset(charsets.utf8)
.resource(Piano)
.resource(User);



+ 13
- 7
src/app.ts View File

@@ -1,8 +1,14 @@
import * as v from 'valibot';
import * as en from './common/languages/en';
import * as utf8 from './common/charsets/utf-8';
import * as applicationJson from './common/media-types/application/json';
import {Resource, Language, MediaType, Charset, ApplicationParams, ApplicationState} from './common';
import {
Resource,
Language,
MediaType,
Charset,
ApplicationParams,
ApplicationState,
FALLBACK_LANGUAGE,
FALLBACK_CHARSET, FALLBACK_MEDIA_TYPE,
} from './common';
import {BackendBuilder, createBackend, CreateBackendParams} from './backend';
import {ClientBuilder, createClient, CreateClientParams} from './client';

@@ -24,9 +30,9 @@ export const application = (appParams: ApplicationParams): ApplicationBuilder =>
charsets: new Set<Charset>(),
};

appState.languages.add(en);
appState.charsets.add(utf8);
appState.mediaTypes.add(applicationJson);
appState.languages.add(FALLBACK_LANGUAGE);
appState.charsets.add(FALLBACK_CHARSET);
appState.mediaTypes.add(FALLBACK_MEDIA_TYPE);

return {
mediaType(serializerPair: MediaType) {


+ 4
- 7
src/backend/core.ts View File

@@ -1,13 +1,10 @@
import * as v from 'valibot';
import {ApplicationState, Resource} from '../common';
import {ApplicationState, FALLBACK_CHARSET, FALLBACK_LANGUAGE, FALLBACK_MEDIA_TYPE, Resource} from '../common';
import http from 'http';
import {createServer, CreateServerParams} from './server';
import https from 'https';
import {BackendState} from './common';
import {BaseDataSource} from '../common/data-source';
import * as en from '../common/languages/en';
import * as utf8 from '../common/charsets/utf-8';
import * as applicationJson from '../common/media-types/application/json';
import {DataSource} from './data-source';

export interface BackendResource<
@@ -41,9 +38,9 @@ export const createBackend = (params: CreateBackendParams) => {
app: params.app,
dataSource: params.dataSource,
cn: {
language: en,
charset: utf8,
mediaType: applicationJson
language: FALLBACK_LANGUAGE,
charset: FALLBACK_CHARSET,
mediaType: FALLBACK_MEDIA_TYPE,
},
showTotalItemCountOnGetCollection: false,
showTotalItemCountOnCreateItem: false,


+ 18
- 15
src/backend/server.ts View File

@@ -188,7 +188,7 @@ const adjustRequestForContentNegotiation = (req: RequestContext, res: http.Serve
// TODO refactor
const currentLanguage = availableLanguages.find((l) => l.name === languageCandidate);
if (typeof currentLanguage === 'undefined') {
const data = req.backend?.cn.language.bodies.languageNotAcceptable();
const data = req.backend?.cn.language.bodies.languageNotAcceptable;
const responseRaw = req.backend?.cn.mediaType.serialize(data);
const response = typeof responseRaw !== 'undefined' ? req.backend?.cn.charset.encode(responseRaw) : undefined;
res.writeHead(constants.HTTP_STATUS_NOT_ACCEPTABLE, {
@@ -198,14 +198,14 @@ const adjustRequestForContentNegotiation = (req: RequestContext, res: http.Serve
`charset="${req.backend?.cn.charset.name}"`
].join('; '),
});
res.statusMessage = req.backend?.cn.language.statusMessages.languageNotAcceptable() ?? '';
res.statusMessage = req.backend?.cn.language.statusMessages.languageNotAcceptable ?? '';
res.end(response);
return;
}

const currentMediaType = availableMediaTypes.find((l) => l.name === mediaTypeCandidate);
if (typeof currentMediaType === 'undefined') {
const data = req.backend?.cn.language.bodies.mediaTypeNotAcceptable();
const data = req.backend?.cn.language.bodies.mediaTypeNotAcceptable;
const responseRaw = req.backend?.cn.mediaType.serialize(data);
const response = typeof responseRaw !== 'undefined' ? req.backend?.cn.charset.encode(responseRaw) : undefined;
res.writeHead(constants.HTTP_STATUS_NOT_ACCEPTABLE, {
@@ -215,14 +215,14 @@ const adjustRequestForContentNegotiation = (req: RequestContext, res: http.Serve
`charset="${req.backend?.cn.charset.name}"`
].join('; '),
});
res.statusMessage = req.backend?.cn.language.statusMessages.mediaTypeNotAcceptable() ?? '';
res.statusMessage = req.backend?.cn.language.statusMessages.mediaTypeNotAcceptable ?? '';
res.end(response);
return;
}

const responseBodyCharset = availableCharsets.find((l) => l.name === charsetCandidate);
if (typeof responseBodyCharset === 'undefined') {
const data = req.backend!.cn.language.bodies.encodingNotAcceptable();
const data = req.backend!.cn.language.bodies.encodingNotAcceptable;
const responseRaw = req.backend!.cn.mediaType.serialize(data);
const response = typeof responseRaw !== 'undefined' ? req.backend!.cn.charset.encode(responseRaw) : undefined;
res.writeHead(constants.HTTP_STATUS_NOT_ACCEPTABLE, {
@@ -232,7 +232,7 @@ const adjustRequestForContentNegotiation = (req: RequestContext, res: http.Serve
`charset="${req.backend?.cn.charset.name}"`
].join('; '),
});
res.statusMessage = req.backend?.cn.language.statusMessages.encodingNotAcceptable() ?? '';
res.statusMessage = req.backend?.cn.language.statusMessages.encodingNotAcceptable ?? '';
res.end(response);
return;
}
@@ -282,7 +282,7 @@ export const createServer = (backendState: BackendState, serverParams = {} as Cr
const resource = Array.from(req.backend.app.resources).find((r) => r.state!.routeName === resourceRouteName);
if (typeof resource === 'undefined') {
res.statusCode = constants.HTTP_STATUS_NOT_FOUND;
res.statusMessage = req.backend.cn.language.statusMessages.urlNotFound();
res.statusMessage = req.backend.cn.language.statusMessages.urlNotFound;
res.end();
return;
}
@@ -423,8 +423,8 @@ export const createServer = (backendState: BackendState, serverParams = {} as Cr
].join('; ');
}

const statusMessageFn = middlewareState.statusMessage ? req.cn.language.statusMessages[middlewareState.statusMessage] : undefined;
res.statusMessage = statusMessageFn?.(req.resource) ?? '';
const statusMessageKey = middlewareState.statusMessage ? req.cn.language.statusMessages[middlewareState.statusMessage] : undefined;
res.statusMessage = statusMessageKey?.replace(/\$RESOURCE/g, req.resource.state.itemName) ?? '';
res.writeHead(middlewareState.statusCode, headers);
if (typeof encoded !== 'undefined') {
res.end(encoded);
@@ -458,8 +458,8 @@ export const createServer = (backendState: BackendState, serverParams = {} as Cr
`charset=${req.backend.cn.charset.name}`
].join('; ');

const statusMessageFn = finalErr.response.statusMessage ? req.backend.cn.language.statusMessages[finalErr.response.statusMessage] : undefined;
res.statusMessage = statusMessageFn?.(req.resource) ?? '';
const statusMessageKey = finalErr.response.statusMessage ? req.backend.cn.language.statusMessages[finalErr.response.statusMessage] : undefined;
res.statusMessage = statusMessageKey?.replace(/\$RESOURCE/g, req.resource.state.itemName) ?? '';
res.writeHead(finalErr.response.statusCode, headers);
if (typeof encoded !== 'undefined') {
res.end(encoded);
@@ -471,17 +471,20 @@ export const createServer = (backendState: BackendState, serverParams = {} as Cr
}

if (middlewares.length > 0) {
res.statusMessage = req.backend.cn.language.statusMessages.methodNotAllowed();
res.statusMessage = req.backend.cn.language.statusMessages.methodNotAllowed.replace(/\$RESOURCE/g, req.resource.state.itemName) ?? '';
res.writeHead(constants.HTTP_STATUS_METHOD_NOT_ALLOWED, {
Allow: middlewares.map((m) => m[0]).join(', ')
Allow: middlewares.map((m) => m[0]).join(', '),
'Content-Language': req.backend.cn.language.name,
});
res.end();
return;
}

// TODO error handler in line with authentication
res.statusMessage = req.backend.cn.language.statusMessages.urlNotFound();
res.writeHead(constants.HTTP_STATUS_NOT_FOUND);
res.statusMessage = req.backend.cn.language.statusMessages.urlNotFound.replace(/\$RESOURCE/g, req.resource.state.itemName) ?? '';
res.writeHead(constants.HTTP_STATUS_NOT_FOUND, {
'Content-Language': req.backend.cn.language.name,
});
res.end();
return;
});


+ 15
- 10
src/client/index.ts View File

@@ -1,7 +1,12 @@
import * as applicationJson from '../common/media-types/application/json';
import * as utf8 from '../common/charsets/utf-8';
import * as en from '../common/languages/en';
import {ApplicationState, Charset, Language, MediaType} from '../common';
import {
ApplicationState,
Charset,
FALLBACK_CHARSET,
FALLBACK_LANGUAGE,
FALLBACK_MEDIA_TYPE,
Language,
MediaType,
} from '../common';

export interface ClientState {
app: ApplicationState;
@@ -23,25 +28,25 @@ export interface CreateClientParams {
export const createClient = (params: CreateClientParams) => {
const clientState: ClientState = {
app: params.app,
mediaType: applicationJson,
charset: utf8,
language: en
mediaType: FALLBACK_MEDIA_TYPE,
charset: FALLBACK_CHARSET,
language: FALLBACK_LANGUAGE
};

return {
setMediaType(mediaTypeName) {
const mediaType = Array.from(clientState.app.mediaTypes).find((l) => l.name === mediaTypeName);
clientState.mediaType = mediaType ?? applicationJson;
clientState.mediaType = mediaType ?? FALLBACK_MEDIA_TYPE;
return this;
},
setCharset(charsetName) {
const charset = Array.from(clientState.app.charsets).find((l) => l.name === charsetName);
clientState.charset = charset ?? utf8;
clientState.charset = charset ?? FALLBACK_CHARSET;
return this;
},
setLanguage(languageCode) {
const language = Array.from(clientState.app.languages).find((l) => l.name === languageCode);
clientState.language = language ?? en;
clientState.language = language ?? FALLBACK_LANGUAGE;
return this;
}
} satisfies ClientBuilder;


+ 0
- 1
src/common/charsets/index.ts View File

@@ -1 +0,0 @@
export * as utf8 from './utf-8';

+ 0
- 5
src/common/charsets/utf-8.ts View File

@@ -1,5 +0,0 @@
export const encode = (str: string) => Buffer.from(str, 'utf-8');

export const decode = (buf: Buffer) => buf.toString('utf-8');

export const name = 'utf-8';

+ 57
- 0
src/common/index.ts View File

@@ -1,5 +1,62 @@
import {Language} from './language';
import {Charset} from './charset';
import {MediaType} from './media-type';

export * from './app';
export * from './charset';
export * from './media-type';
export * from './resource';
export * from './language';

export const FALLBACK_LANGUAGE = {
name: 'en' as const,
statusMessages: {
unableToSerializeResponse: 'Unable To Serialize Response',
unableToEncodeResponse: 'Unable To Encode Response',
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',
encodingNotAcceptable: 'Encoding Not Acceptable',
mediaTypeNotAcceptable: 'Media Type Not Acceptable',
methodNotAllowed: 'Method Not Allowed',
urlNotFound: 'URL Not Found',
badRequest: 'Bad Request',
ok: 'OK',
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',
invalidResource: 'Invalid $RESOURCE',
resourcePatched: '$RESOURCE Patched',
resourceCreated: '$RESOURCE Created',
resourceReplaced: '$RESOURCE Replaced',
unableToGenerateIdFromResourceDataSource: 'Unable To Generate ID From $RESOURCE Data Source',
unableToEmplaceResource: 'Unable To Emplace $RESOURCE',
resourceIdNotGiven: '$RESOURCE ID Not Given',
unableToCreateResource: 'Unable To Create $RESOURCE',
},
bodies: {
languageNotAcceptable: [],
encodingNotAcceptable: [],
mediaTypeNotAcceptable: []
},
} satisfies Language;

export const FALLBACK_CHARSET = {
encode: (str: string) => Buffer.from(str, 'utf-8'),
decode: (buf: Buffer) => buf.toString('utf-8'),
name: 'utf-8' as const,
} satisfies Charset;

export const FALLBACK_MEDIA_TYPE = {
serialize: (obj: unknown) => JSON.stringify(obj),
deserialize: (str: string) => JSON.parse(str),
name: 'application/json' as const,
} satisfies MediaType;

+ 45
- 39
src/common/language.ts View File

@@ -1,45 +1,51 @@
import {Resource} from './resource';

export type MessageBody = string | string[] | (string | string[])[];

export interface LanguageStatusMessageMap {
unableToInitializeResourceDataSource(resource: Resource): string;
unableToFetchResourceCollection(resource: Resource): string;
unableToFetchResource(resource: Resource): string;
resourceIdNotGiven(resource: Resource): string;
languageNotAcceptable(): string;
encodingNotAcceptable(): string;
mediaTypeNotAcceptable(): string;
methodNotAllowed(): string;
urlNotFound(): string;
badRequest(): string;
ok(): string;
resourceCollectionFetched(resource: Resource): string;
resourceFetched(resource: Resource): string;
resourceNotFound(resource: Resource): string;
deleteNonExistingResource(resource: Resource): string;
unableToCreateResource(resource: Resource): string;
unableToGenerateIdFromResourceDataSource(resource: Resource): string;
unableToEmplaceResource(resource: Resource): string;
unableToSerializeResponse(): string;
unableToEncodeResponse(): string;
unableToDeleteResource(resource: Resource): string;
resourceDeleted(resource: Resource): string;
unableToDeserializeRequest(): string;
patchNonExistingResource(resource: Resource): string;
unableToPatchResource(resource: Resource): string;
invalidResourcePatch(resource: Resource): string;
invalidResource(resource: Resource): string;
resourcePatched(resource: Resource): string;
resourceCreated(resource: Resource): string;
resourceReplaced(resource: Resource): string;
}
export const LANGUAGE_DEFAULT_STATUS_MESSAGE_KEYS = [
'unableToInitializeResourceDataSource',
'unableToFetchResourceCollection',
'unableToFetchResource',
'resourceIdNotGiven',
'languageNotAcceptable',
'encodingNotAcceptable',
'mediaTypeNotAcceptable',
'methodNotAllowed',
'urlNotFound',
'badRequest',
'ok',
'resourceCollectionFetched',
'resourceFetched',
'resourceNotFound',
'deleteNonExistingResource',
'unableToCreateResource',
'unableToGenerateIdFromResourceDataSource',
'unableToEmplaceResource',
'unableToSerializeResponse',
'unableToEncodeResponse',
'unableToDeleteResource',
'resourceDeleted',
'unableToDeserializeRequest',
'patchNonExistingResource',
'unableToPatchResource',
'invalidResourcePatch',
'invalidResource',
'resourcePatched',
'resourceCreated',
'resourceReplaced',
] as const;

export interface LanguageBodyMap {
languageNotAcceptable(): MessageBody;
encodingNotAcceptable(): MessageBody;
mediaTypeNotAcceptable(): MessageBody;
}
export type LanguageDefaultStatusMessageKey = typeof LANGUAGE_DEFAULT_STATUS_MESSAGE_KEYS[number];

export interface LanguageStatusMessageMap extends Record<LanguageDefaultStatusMessageKey, string> {}

export const LANGUAGE_DEFAULT_BODY_KEYS = [
'languageNotAcceptable',
'encodingNotAcceptable',
'mediaTypeNotAcceptable',
] as const;

export type LanguageDefaultBodyKey = typeof LANGUAGE_DEFAULT_BODY_KEYS[number];

export interface LanguageBodyMap extends Record<LanguageDefaultBodyKey, MessageBody> {}

export interface Language {
name: string,


+ 0
- 109
src/common/languages/en/index.ts View File

@@ -1,109 +0,0 @@
import {Resource} from '../../resource';
import {Language} from '../../language';

export const statusMessages = {
unableToSerializeResponse(): string {
return 'Unable To Serialize Response';
},
unableToEncodeResponse(): string {
return 'Unable To Encode Response';
},
unableToInitializeResourceDataSource(resource: Resource): string {
return `Unable To Initialize ${resource.state.itemName} Data Source`;
},
unableToFetchResourceCollection(resource: Resource): string {
return `Unable To Fetch ${resource.state.itemName} Collection`;
},
unableToFetchResource(resource: Resource): string {
return `Unable To Fetch ${resource.state.itemName}`;
},
unableToDeleteResource(resource: Resource): string {
return `Unable To Delete ${resource.state.itemName}`;
},
languageNotAcceptable(): string {
return 'Language Not Acceptable';
},
encodingNotAcceptable(): string {
return 'Encoding Not Acceptable';
},
mediaTypeNotAcceptable(): string {
return 'Media Type Not Acceptable';
},
methodNotAllowed(): string {
return 'Method Not Allowed';
},
urlNotFound(): string {
return 'URL Not Found';
},
badRequest(): string {
return 'Bad Request';
},
ok(): string {
return 'OK';
},
resourceCollectionFetched(resource: Resource): string {
return `${resource.state.itemName} Collection Fetched`;
},
resourceFetched(resource: Resource): string {
return `${resource.state.itemName} Fetched`;
},
resourceNotFound(resource: Resource): string {
return `${resource.state.itemName} Not Found`;
},
deleteNonExistingResource(resource: Resource): string {
return `Delete Non-Existing ${resource.state.itemName}`;
},
resourceDeleted(resource: Resource): string {
return `${resource.state.itemName} Deleted`;
},
unableToDeserializeRequest(): string {
return 'Unable To Deserialize Request';
},
patchNonExistingResource(resource: Resource): string {
return `Patch Non-Existing ${resource.state.itemName}`;
},
unableToPatchResource(resource: Resource): string {
return `Unable To Patch ${resource.state.itemName}`;
},
invalidResourcePatch(resource: Resource): string {
return `Invalid ${resource.state.itemName} Patch`;
},
invalidResource(resource: Resource): string {
return `Invalid ${resource.state.itemName}`;
},
resourcePatched(resource: Resource): string {
return `${resource.state.itemName} Patched`;
},
resourceCreated(resource: Resource): string {
return `${resource.state.itemName} Created`;
},
resourceReplaced(resource: Resource): string {
return `${resource.state.itemName} Replaced`;
},
unableToGenerateIdFromResourceDataSource(resource: Resource): string {
return `Unable To Generate ID From ${resource.state.itemName} Data Source`;
},
unableToEmplaceResource(resource: Resource): string {
return `Unable To Emplace ${resource.state.itemName}`;
},
resourceIdNotGiven(resource: Resource): string {
return `${resource.state.itemName} ID Not Given`;
},
unableToCreateResource(resource: Resource): string {
return `Unable To Create ${resource.state.itemName}`;
}
} satisfies Language['statusMessages'];

export const bodies = {
languageNotAcceptable() {
return [];
},
encodingNotAcceptable() {
return [];
},
mediaTypeNotAcceptable() {
return []
}
} satisfies Language['bodies'];

export const name = 'en' as const;

+ 0
- 1
src/common/languages/index.ts View File

@@ -1 +0,0 @@
export * as en from './en';

+ 0
- 5
src/common/media-types/application/json.ts View File

@@ -1,5 +0,0 @@
export const serialize = (obj: unknown) => JSON.stringify(obj);

export const deserialize = (str: string) => JSON.parse(str);

export const name = 'application/json';

+ 0
- 2
src/common/media-types/index.ts View File

@@ -1,2 +0,0 @@
export * as applicationJson from './application/json';
export * as textJson from './application/json';

+ 0
- 4
src/index.ts View File

@@ -3,8 +3,4 @@ export * as validation from './common/validation';

export * as dataSources from './backend/data-sources';

export * as mediaTypes from './common/media-types';
export * as charsets from './common/charsets';
export * as languages from './common/languages';

export * from './app';

+ 3
- 5
test/e2e/default.test.ts View File

@@ -23,12 +23,12 @@ import {request, Server} from 'http';
import {constants} from 'http2';
import {DataSource} from '../../src/backend/data-source';
import { dataSources } from '../../src/backend';
import { application, resource, validation as v, Resource, charsets, mediaTypes } from '../../src';
import { application, resource, validation as v, Resource } from '../../src';

const PORT = 3000;
const HOST = 'localhost';
const ACCEPT_CHARSET = charsets.utf8.name;
const ACCEPT = mediaTypes.applicationJson.name;
const ACCEPT_CHARSET = 'utf-8';
const ACCEPT = 'application/json';

const autoIncrement = async (dataSource: DataSource) => {
const data = await dataSource.getMultiple() as Record<string, string>[];
@@ -87,8 +87,6 @@ describe('yasumi', () => {
const app = application({
name: 'piano-service',
})
.mediaType(mediaTypes.applicationJson)
.charset(charsets.utf8)
.resource(Piano);

const backend = app


Loading…
Cancel
Save