I am trying to make a standard configuration package that will load all my configuration for an API server (more so a set of them) that can be called into multiple apps inside a monorepo built using Turborepo. With my current code I am getting an error of “Property ‘get’ does not exist on type”. I am unsure why.
config/config.ts
import convict from 'convict';
import dotenv from 'dotenv';
import path from 'path';
import { DeepReadOnly } from '@repo/types';
export const apiConfigSchema = {
DEBUG: {
default: '',
doc: 'Debug settings',
format: String,
env: 'DEBUG'
},
DATABASE_URL: {
default: '',
doc: 'Database URL',
format: String,
env: 'DATABASE_URL',
sensitive: true
},
LOG_LEVEL: {
default: 'info',
doc: 'Logger level',
format: String,
env: 'LOG_LEVEL'
},
PORT: {
default: 3000,
doc: 'Port',
format: Number,
env: 'PORT'
},
JWT_SECRET: {
default: '',
doc: 'JWT secret',
format: String,
env: 'JWT_SECRET',
sensitive: true
},
// Add more configuration here
};
dotenv.config({
path: path.resolve(__dirname, '..', '..', '..', '.env')
});
const config = convict(apiConfigSchema);
export type aipSchema = DeepReadOnly<typeof config extends convict.Config<infer T> ? T : never>;
export type ConfigKey = keyof aipSchema;
export default config;
index.ts in the configuration package
export * from './config/config';
The DeepReadOnly type from above
export type DeepReadOnly<T> = T extends Function
? T
: T extends ReadonlyArray<infer R>
? ReadonlyArray<DeepReadOnly<R>>
: T extends Map<infer K, infer V>
? ReadonlyMap<DeepReadOnly<K>, DeepReadOnly<V>>
: T extends object
? { readonly [P in keyof T]: DeepReadOnly<T[P]> }
: T;
My attempt at using the configuration package
import config from "@repo/configuration";
export function generateAccessToken(user: User) {
return jwt.sign({ userId: user.id }, config.get('JWT_SECRET'), {
expiresIn: '5m',
});
}