@ringpublishing/hat-server
v1.0.0
Published
Head App Template - server
Downloads
1
Readme
Description
This is a server for Head App Template.
Development
To install and work on hat-server locally:
Clone the repository and
npm i
To watch for changes and continually rebuild the package:
npm run dev
When developing hat-server
by using hat-boilderplate
, you should use npm link
On hat-server
repository:
npm link
On hat-boilderplate
repository:
npm link "hat-server"
Running Tests
npm run test
Know issues
- When using
npm run test-watch
some tests may fail because server is not stopped properly and throws an error. Please usenpm run test
instead.
Usages
Basic usage:
import {BootServer, BootServerConfig} from "hat-server";
const bootServer = new BootServer({} as BootServerConfig);
bootServer.start();
Additional/override headers:
Those headers will override default headers of
BootServer
but, won't override Next headers, to override them use Next.js features.
import {BootServer, BootServerConfig} from "hat-server";
const bootServer = new BootServer({
onRequest: (req, res) => {
res.setHeader('X-XSS-Protection', '1; mode=block');
},
} as BootServerConfig);
bootServer.start();
Additional data in controller params:
import { ApolloQueryResult } from "@apollo/client";
import { BootServer, BootServerConfig } from "hat-server";
const bar = 'test'
const bootServer = new BootServer({
additionalDataInControllerParams: (gqlResponse: ApolloQueryResult<DefaultHatSite>) => {
return {
myCustomKey: 'myCustomValue',
customFnc: (toReturn) => {
if (toReturn === 'foo') {
return gqlResponse.data.site.headers;
}
return bar;
},
}
},
} as BootServerConfig);
bootServer.start();
In app/page.tsx
:
//...
export default async function Page(props) {
console.log(props.searchParams.controllerParams.customData.myCustomKey); // return 'myCustomValue'
console.log(props.searchParams.controllerParams.customData.customFnc('foo')); // return { location: null }
console.log(props.searchParams.controllerParams.customData.customFnc('bar')); // return 'test'
//...
Add/reduce requests to Website API for specific requests
import {BootServer, BootServerConfig} from "hat-server";
import http from "http";
const bootServer = new BootServer({
shouldMakeRequestToWebsiteAPIOnThisRequest: (req: http.IncomingMessage, defaultPathCheckValue) => {
if (req.path) {
const shouldMakeRequestForCustomPath = !req.path.includes('custom/path/without/request');
return defaultPathCheckValue && shouldMakeRequestForCustomPath;
}
return defaultPathCheckValue;
},
} as BootServerConfig);
bootServer.start();
To checking we recommend
String.includes
orString.indexOf
because of performance, we advise against usingString.match
or any Regexp.
Extending GraphQl query with type
This example will extend Story
type with:
kind {
name
}
You also have to provide correct types for typescript.
import {BootServer, BootServerConfig} from "hat-server";
import http from "http";
import {
Author,
BootServer,
BootServerConfig,
CustomAction,
DefaultHatSite, Scalars,
Site,
SiteData,
SiteNode,
Source, Story as DefaultStory, Topic
} from "hat-server";
import {ApolloQueryResult} from "@apollo/client";
export interface CustomHatSite extends DefaultHatSite {
site: CustomSite
}
export interface CustomSite extends Site {
data: CustomSiteData
}
export interface CustomSiteData extends SiteData {
content: CustomSiteContent
}
export type CustomSiteContent =
| Author
| CustomAction
| SiteNode
| Source
| Story
| Topic
export interface Story extends DefaultStory {
kind: Kind
}
export interface Kind {
name: Scalars['String']
}
const bootServer = new BootServer({
prepareCustomGraphQLQueryToWebsiteAPI: (url, variantId, defaultGraphqlQuery) => {
return bootServer.getQuery(url, variantId, `
data {
content {
__typename
...on Story {
id,
title,
kind {
name
}
}
...on SiteNode {
id,
slug
}
...on Topic {
id,
name
}
...on Source{
id,
name
}
...on Author{
id,
name
}
...on CustomAction{
id,
action
}
}
}`)
},
additionalDataInControllerParams: (gqlResponse: ApolloQueryResult<CustomHatSite>) => {
if (gqlResponse.data?.site.data.content.__typename === 'Story') {
console.log(gqlResponse.data.site.data.content.kind) // return { name: 'Article' }
}
},
} as BootServerConfig);
bootServer.start();
Remember to check if the given query does not return errors for example via
additionalDataInControllerParams
In case when you want to reduce returned values for example without Story
, then you have to prepare mapper for missing properties for other components which can be using them.
For more use cases, see a file: __tests__/BootServer.spec.ts
.