@vode-app/create-hono-server (0.1.0-pre.57)
Installation
@vode-app:registry=npm install @vode-app/create-hono-server@0.1.0-pre.57"@vode-app/create-hono-server": "0.1.0-pre.57"About this package
Introduction
This template scaffolds a ...
Table of Contents
Quick Start
# print the latest version
npm info "@vode-app/create-hono-server" version
# create/update a package from the template in the current directory
npm create --no-install --no-git "@vode-app/hono-server@latest" .
# set metadata in package.json
npm update
Documentation
The following sections explain the configurations and conventions baked into the generated package. Useful when adapting it to fit specific needs.
<DOCUMENTATION>
In the src/main.ts file, an App Host (appHost) is first created, then an App Host Server (appHostServer) is started with the created App Host.
An App Host is just a Hono<E> instance. Do with it what you will.
Generated example in src/main.ts:
import {
// ... ,
buildinfoUrl as serverBuildinfoUrl,
buildinfoTemplateUrl as serverTemplateBuildinfoUrl,
} from './package-urls.js';
// ...
import {
// ... ,
createBuildinfoEndpoint,
createHealthEndpoint,
createOpenapiEndpoints,
// ...
} from '@vode-app/common-server-side/hono';
// ...
let appHost: Hono<AppHostEnv>;
console.log('[main] Creating app host...');
try {
appHost = basePathTrimmed
? new Hono<AppHostEnv>().basePath(`/${basePathTrimmed}/`)
: new Hono<AppHostEnv>()
;
appHost.route('/', createHealthEndpoint({
path: '/health',
description: 'Server health check endpoint.',
}));
appHost.route('/', createBuildinfoEndpoint({
path: '/buildinfo',
description: 'Server buildinfo endpoint.',
buildinfoUrl: serverBuildinfoUrl,
}));
appHost.route('/', createBuildinfoEndpoint({
path: '/buildinfo-template',
description: 'Server template buildinfo endpoint.',
buildinfoUrl: serverTemplateBuildinfoUrl,
}));
const version = readFileSync(serverBuildinfoUrl, 'utf-8');
appHost.route('/', createOpenapiEndpoints(appHost, {
title: 'Example Vode App Server',
version: version,
description: 'OpenAPI documentation for the Example Vode App Server.',
path: 'openapi',
uiPath: 'scalar',
}));
} catch (error) {
console.error('[main] Failed to create app host:', error);
process.exit(1);
}
console.log('[main] App host created.');
// ...
createAppHost()
A convenience function for creating an App Host is provided by the @vode-app/common-server-side/hono package. It abstracts away some of the common setup and configuration, while still allowing for flexibility and customization.
Example usage in src/main.ts:
import {
// ... ,
createAppHost,
type CreateAppHostOptions,
createBuildinfoEndpoint,
createHealthEndpoint,
createLoggingMiddleware,
createRequestLoggerMiddleware,
// ...
} from '@vode-app/common-server-side/hono';
// ...
import { requestId } from 'hono/request-id';
import { compress } from 'hono/compress';
import { secureHeaders } from 'hono/secure-headers';
// ...
let appHost: Hono<AppHostEnv>;
console.log('[main] Creating app host...');
try {
const createAppHostOptions: CreateAppHostOptions<AppHostEnv> = {
middleware: [
createLoggingMiddleware({
logLevel: env.LOG_LEVEL,
logLevelPerScope: logLevelPerScope
? logLevelPerScope
: undefined
,
}),
// DEVEL: Add dependency injection middleware here
requestId(),
createRequestLoggerMiddleware<AppHostEnv>(),
compress(),
secureHeaders(),
// DEVEL: Add middleware here
],
endpointGroups: [
createHealthEndpoint({
path: '/health',
description: 'Server health check endpoint.',
}),
createBuildinfoEndpoint({
path: '/buildinfo',
description: 'Server buildinfo endpoint.',
buildinfoUrl: serverBuildinfoUrl,
}),
createBuildinfoEndpoint({
path: '/buildinfo-template',
description: 'Server template buildinfo endpoint.',
buildinfoUrl: serverTemplateBuildinfoUrl,
}),
// DEVEL: Add endpoint groups here
],
exposeOpenApi: env.EXPOSE_OPENAPI,
};
if (basePathTrimmed) createAppHostOptions.basePath = basePathTrimmed;
if (createAppHostOptions.exposeOpenApi) {
const version = readFileSync(serverBuildinfoUrl, 'utf-8');
createAppHostOptions.openApi = {
title: 'Example Vode App Server',
version: version,
description: 'OpenAPI documentation for the Example Vode App Server.',
path: 'openapi',
uiPath: 'scalar',
};
}
appHost = createAppHost<AppHostEnv>(createAppHostOptions);
} catch (error) {
console.error('[main] Failed to create app host:', error);
process.exit(1);
}
console.log('[main] App host created.');
// ...
createSpaHost()
A convenience function for creating an SPA Host is provided by the @vode-app/common-server-side/hono package. It abstracts away some of the common setup and configuration for hosting a Single Page Application (SPA), while still allowing for flexibility and customization. Under the hood, it creates an App Host and configures it to serve the SPA.
Example usage in src/main.ts:
import {
// ... ,
createSpaHost,
type CreateSpaHostOptions,
type CreateSpaOptions,
// ...
} from '@vode-app/common-server-side/hono';
// ...
import { fileURLToPath } from 'node:url';
// ...
import {
buildinfoUrl as clientBuildinfoUrl,
buildinfoTemplateUrl as clientTemplateBuildinfoUrl,
indexHtmlUrl as clientIndexHtmlUrl,
distUrl as clientDistUrl,
} from '@vode-app/example-client/package-urls';
// ...
let appHost: Hono<AppHostEnv>;
console.log('[main] Creating app host...');
try {
const createSpaOptions: CreateSpaOptions = {
path: 'example/',
buildinfoUrl: clientBuildinfoUrl,
buildinfoTemplateUrl: clientTemplateBuildinfoUrl,
indexHtmlUrl: clientIndexHtmlUrl,
assetsRoot: fileURLToPath(clientDistUrl),
};
if (basePathTrimmed) createSpaOptions.basePath = `/${basePathTrimmed}/`;
const createSpaHostOptions: CreateSpaHostOptions<AppHostEnv> = {
logLevel: {
default: env.LOG_LEVEL,
perScope: logLevelPerScope,
},
dependencyInjectionMiddleware: [
// DEVEL: add dependency injection middleware here
],
middleware: [
// DEVEL: add middleware here
],
serverBuildinfoUrl: serverBuildinfoUrl,
serverTemplateBuildinfoUrl: serverTemplateBuildinfoUrl,
spa: createSpaOptions,
endpointGroups: [
// DEVEL: add endpoint groups here
],
exposeOpenApi: env.EXPOSE_OPENAPI,
};
if (basePathTrimmed) createSpaHostOptions.basePath = basePathTrimmed;
if (createSpaHostOptions.exposeOpenApi) {
createSpaHostOptions.openApi = {
title: 'Web API',
version: '1.0.0',
description: 'API documentation for the server.',
path: 'openapi',
uiPath: 'scalar',
};
}
appHost = createSpaHost<AppHostEnv>(createSpaHostOptions);
} catch (error) {
console.error('[main] Failed to create app host:', error);
process.exit(1);
}
console.log('[main] App host created.');
// ...
DevOps
npm install
npm update
npm run clean
npm run build
npm run tests
npx tsx dist/cli.bundle.js -- example/
git fetch upstream
git fetch origin
git fetch . upstream/main:origin/main
git fetch . origin/main:main
git push origin main
git merge --ff-only main
git push
Change Management
- Create a new branch for the change.
- Make the changes and commit.
- Bump the version in
package.json. - Add an entry for the new version in
CHANGELOG.md. - Pull-request the branch.
- Ensure package artifacts are current.
- Publish.
Registry
.npmrc:
@vode-app:registry=https://git.chimps.quest/api/packages/vode-app/npm/
//git.chimps.quest/api/packages/vode-app/npm/:_authToken=${VODE_APP_REGISTRY_AUTH_TOKEN}
or bunfig.toml:
[install.scopes]
"vode-app" = { url = "https://git.chimps.quest/api/packages/vode-app/npm/", token = "$VODE_APP_REGISTRY_AUTH_TOKEN" }
# git.chimps.quest/api/packages/vode-app/npm/
export VODE_APP_REGISTRY_AUTH_TOKEN=<AUTH_TOKEN>
# or
$env:VODE_APP_REGISTRY_AUTH_TOKEN = "<AUTH_TOKEN>"
npm publish
CI/CD Workflows
Build and Publish
⚠️ .npmrc configuring the package registry and its authentication token is required for the workflow to work.
| Parameter | Type | Description |
|---|---|---|
RUNNER_LABEL |
Variable | The label of the runner to use for the workflow. |
ACCESS_TOKEN |
Secret | The authentication token for the package registry. |
.github/workflows/build-publish.yml:
name: Build and Publish
on:
push:
branches:
- main
jobs:
publish:
runs-on: ${{ vars.RUNNER_LABEL }}
steps:
- uses: actions/checkout@v4
- name: Install
env:
VODE_APP_REGISTRY_AUTH_TOKEN: ${{ secrets.ACCESS_TOKEN }}
run: npm ci
- name: Build
run: npm run build
- name: Test
run: npm run tests
- name: Publish
env:
VODE_APP_REGISTRY_AUTH_TOKEN: ${{ secrets.ACCESS_TOKEN }}
run: |
PKG_NAME=$(node -p "require('./package.json').name")
PKG_VERSION=$(node -p "require('./package.json').version")
NPM_TAG="latest"
if echo "$PKG_VERSION" | grep -q -- '-'; then
NPM_TAG="next"
fi
if npm view "$PKG_NAME@$PKG_VERSION" version >/dev/null 2>&1; then
echo "$PKG_NAME@$PKG_VERSION already published, skipping."
else
npm publish --tag "$NPM_TAG"
fi
Dependencies
Development dependencies
| ID | Version |
|---|---|
| @types/node | latest |
| esbuild | latest |
| tsx | latest |
| typescript | ^6.0.3 |