@@ -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!" | |||
} | |||
} |
@@ -0,0 +1,11 @@ | |||
meta { | |||
name: Delete Resource | |||
type: http | |||
seq: 8 | |||
} | |||
delete { | |||
url: http://localhost:3000/api/users/2 | |||
body: none | |||
auth: none | |||
} |
@@ -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 | |||
} | |||
} |
@@ -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 | |||
} |
@@ -0,0 +1,11 @@ | |||
meta { | |||
name: Get Resource Collection | |||
type: http | |||
seq: 3 | |||
} | |||
get { | |||
url: http://localhost:3000/api/users | |||
body: none | |||
auth: none | |||
} |
@@ -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 | |||
} |
@@ -0,0 +1,11 @@ | |||
meta { | |||
name: Get Resource | |||
type: http | |||
seq: 4 | |||
} | |||
get { | |||
url: http://localhost:3000/api/users/1 | |||
body: none | |||
auth: none | |||
} |
@@ -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!" | |||
} | |||
} |
@@ -0,0 +1,13 @@ | |||
{ | |||
"version": "1", | |||
"name": "Yasumi", | |||
"type": "collection", | |||
"ignore": [ | |||
"node_modules", | |||
".git" | |||
], | |||
"presets": { | |||
"requestType": "http", | |||
"requestUrl": "http://localhost:3000" | |||
} | |||
} |
@@ -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); | |||
@@ -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) { | |||
@@ -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, | |||
@@ -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; | |||
}); | |||
@@ -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; | |||
@@ -1 +0,0 @@ | |||
export * as utf8 from './utf-8'; |
@@ -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'; |
@@ -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; |
@@ -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, | |||
@@ -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; |
@@ -1 +0,0 @@ | |||
export * as en from './en'; |
@@ -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'; |
@@ -1,2 +0,0 @@ | |||
export * as applicationJson from './application/json'; | |||
export * as textJson from './application/json'; |
@@ -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'; |
@@ -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 | |||