package.json
{
"name": "nodejs-server",
"version": "0.0.0",
"license": "MPL-2.0",
"private": true,
"main": "dist/index.js",
"scripts": {
"config:ci": "APP_CONFIG_SECRETS_KEY=`cat ci.asc` yarn app-config",
"trust": "yarn config:ci secret trust",
"dev": "ts-node-dev --files ./src/index.ts",
"start": "node ./dist/index.js",
"build": "tsc -b",
"clean": "rm -rf dist *.tsbuildinfo"
},
"dependencies": {
"@app-config/main": "2",
"fastify": "3"
},
"devDependencies": {
"@lcdev/tsconfig": "0.2",
"ts-node-dev": "1",
"typescript": "4"
}
}
.app-config.schema.yml
type: object
additionalProperties: false
required:
- database
- port
properties:
port:
$ref: "#/definitions/Port"
database:
type: object
additionalProperties: false
required:
- username
- password # encrypted
- port
- database
properties:
username:
type: string
password:
type: string
secret: true
port:
$ref: "#/definitions/Port"
database:
type: string
definitions:
Port:
type: integer
minimum: 0
maximum: 65535
.app-config.meta.yml
generate:
- file: ./src/@types/lcdev__app-config/index.d.ts
teamMembers:
- userId: Daniel Zarinski <daniel@lc.dev>
publicKey: "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: OpenPGP.js v4.10.8\r\nComment: https://openpgpjs.org\r\n\r\nxjMEX7M4jxYJKwYBBAHaRw8BAQdAzCgPEIFywKDr+oOaEbVJE2jqh50vMfxA\r\nPz/D2kgdxM/NH0RhbmllbCBaYXJpbnNraSA8ZGFuaWVsQGxjLmRldj7CjwQQ\r\nFgoAIAUCX7M4jwYLCQcIAwIEFQgKAgQWAgEAAhkBAhsDAh4BACEJEGobs8AV\r\nvWE2FiEEO8f1YfyxR2A6r6SkahuzwBW9YTb8vAEA7KjqMh8lGGVun44r/ieg\r\ndqJtC42bsCcUntcitrgw7MABAMh6lYWS/rkuKBuaFjlOMhBHEDgdsvbTSTUX\r\nHIw+MicCzjgEX7M4jxIKKwYBBAGXVQEFAQEHQCUA3eQvF3CZ9I9ALaIF692V\r\n3s7+VVlbEjVVXfcLDmYWAwEIB8J4BBgWCAAJBQJfsziPAhsMACEJEGobs8AV\r\nvWE2FiEEO8f1YfyxR2A6r6SkahuzwBW9YTZ66gD/X+d8+hjNfHcW5xwHJ2FO\r\nnSI3BINdYnziIuYl4QIDbjcA/3pwrFytlUIxW+aM3MGMkSJ8A5pRCtf47YWH\r\n0dU6Z8cL\r\n=p59L\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n"
- userId: CI <no-reply@lc.dev>
publicKey: "-----BEGIN PGP PUBLIC KEY BLOCK-----\r\nVersion: OpenPGP.js v4.10.8\r\nComment: https://openpgpjs.org\r\n\r\nxjMEX7Xh9xYJKwYBBAHaRw8BAQdAD/oo/0/78VH8LHFejCyxmX7qpUdikC2Y\r\n9ERIOmAKcpLNFENJIDxuby1yZXBseUBsYy5kZXY+wo8EEBYKACAFAl+14fcG\r\nCwkHCAMCBBUICgIEFgIBAAIZAQIbAwIeAQAhCRBR9TO6eWTjuxYhBPgJGasb\r\ntsarWkPZ4lH1M7p5ZOO7tKUA/1S6tzzWYD87LwUIx/r+fbNC2pbwJYBVdUWr\r\n1RfyggtqAP4601DXUnfDHC/7Prb5n9RZ9A1cTY05GgWPEz0HQwOUA844BF+1\r\n4fcSCisGAQQBl1UBBQEBB0A4mG3enF+oJEtmUP3jqX4S4Ykq+B8j+lI9JtNg\r\nSQ0mFgMBCAfCeAQYFggACQUCX7Xh9wIbDAAhCRBR9TO6eWTjuxYhBPgJGasb\r\ntsarWkPZ4lH1M7p5ZOO7OjkA/jE737imk9gtfxOnDXbsOkPW2mCBRUttFcXQ\r\nC/KGO6OxAQCJAYZHdQsWead3XN8tdjehyz9lmab5GcOF4N/WZJnPCw==\r\n=lmdF\r\n-----END PGP PUBLIC KEY BLOCK-----\r\n"
encryptionKeys:
- revision: 1
key: "-----BEGIN PGP MESSAGE-----\r\nVersion: OpenPGP.js v4.10.8\r\nComment: https://openpgpjs.org\r\n\r\n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\r\nyEKZCQ8GTw==\r\n=tUp5\r\n-----END PGP MESSAGE-----\r\n"
.app-config.yml
# Try it out! Run with APP_CONFIG_ENV=production
port: 8000
database:
username: { $substitute: "${USER:-username}" }
port: 3306
database:
$env:
default: dev
production: production
password:
$env:
default: enc:1:wy4ECQMIsX1S2qXZKrXgN2dRmZBrWbmbsBdtMmZ3FwsmpCnCq5+RfN3UxNSZ20jX0j4B9dBnlPsKhYJM0/iPiSH3aT2y/Vvawbhe3KdaOK3tTzgV8Jl27fSvxI+FwCTGkM4cY0s74kleP7gq6Dchtw===Jftl # test
production: enc:1:wy4ECQMIXJen9k4zRaXgl50+lqtJx9XXE+VASto5O0BMJv4DotrdxQNheXBW451B0kEBl9gkhN87rTYyjUAnisg58ECoR9PEUOldxjua4jE4T1PvpIUVGii3er7Cd+alJIC3M2+ffRX0UGuizP8zc/crXw===Y+3h # test123
index.ts
import fastify from 'fastify';
import { config, loadConfig } from '@app-config/main';
const server = fastify();
server.get('/', async () => {
return { message: 'Hello world!' };
});
server.get('/config', async () => {
return config;
});
async function main() {
await loadConfig();
await server.listen(config.port);
console.log(`Listening on :${config.port}`);
}
main().catch((error) => {
console.error(error);
setTimeout(() => process.exit(1), 0);
});
Generated Type File
// AUTO GENERATED CODE
// Run app-config with 'generate' command to regenerate this file
import '@app-config/main';
export interface Index {
database: Database;
port: number;
}
export interface Database {
database: string;
password: string;
port: number;
username: string;
}
// augment the default export from app-config
declare module '@app-config/main' {
export interface ExportedConfig extends Index {}
}