376 lines
10 KiB
TypeScript
376 lines
10 KiB
TypeScript
import * as process from "process";
|
|
import * as convict from "convict";
|
|
import * as Metamigo from "common";
|
|
import { defState } from "@digiresilience/montar";
|
|
|
|
export const configSchema = {
|
|
db: {
|
|
connection: {
|
|
doc: "The postgres connection url.",
|
|
format: "uri",
|
|
default: "postgresql://metamigo:metamigo@127.0.0.1:5435/metamigo_dev",
|
|
env: "DATABASE_URL",
|
|
sensitive: true,
|
|
},
|
|
name: {
|
|
doc: "The name of the postgres database",
|
|
format: String,
|
|
default: "metamigo_dev",
|
|
env: "DATABASE_NAME",
|
|
},
|
|
owner: {
|
|
doc: "The username of the postgres database owner",
|
|
format: String,
|
|
default: "metamigo",
|
|
env: "DATABASE_OWNER",
|
|
},
|
|
},
|
|
worker: {
|
|
connection: {
|
|
doc: "The postgres connection url for the worker database.",
|
|
format: "uri",
|
|
default: "postgresql://metamigo:metamigo@127.0.0.1:5435/metamigo_dev",
|
|
env: "WORKER_DATABASE_URL",
|
|
},
|
|
concurrency: {
|
|
doc: "The number of jobs to run concurrently",
|
|
default: 1,
|
|
format: "positiveInt",
|
|
env: "WORKER_CONCURRENT_JOBS",
|
|
},
|
|
pollInterval: {
|
|
doc: "How long to wait between polling for jobs in milliseconds (for jobs scheduled in the future/retries)",
|
|
default: 2000,
|
|
format: "positiveInt",
|
|
env: "WORKER_POLL_INTERVAL_MS",
|
|
},
|
|
},
|
|
postgraphile: {
|
|
auth: {
|
|
doc: "The postgres role that postgraphile logs in with",
|
|
format: String,
|
|
default: "metamigo_graphile_auth",
|
|
env: "DATABASE_AUTHENTICATOR",
|
|
},
|
|
appRootConnection: {
|
|
doc: "The postgres root/superuser connection url for development mode so PG can watch the schema changes, this is strangely named in the postgraphile API 'ownerConnectionString'",
|
|
format: String,
|
|
default: "postgresql://postgres:metamigo@127.0.0.1:5435/metamigo_dev",
|
|
env: "APP_ROOT_DATABASE_URL",
|
|
},
|
|
authConnection: {
|
|
doc: "The postgres connection URL for postgraphile, must not be superuser and must have limited privs.",
|
|
format: String,
|
|
default:
|
|
"postgresql://metamigo_graphile_auth:metamigo@127.0.0.1:5435/metamigo_dev",
|
|
env: "DATABASE_AUTH_URL",
|
|
},
|
|
visitor: {
|
|
doc: "The postgres role that postgraphile switches to",
|
|
format: String,
|
|
default: "app_postgraphile",
|
|
env: "DATABASE_VISITOR",
|
|
},
|
|
schema: {
|
|
doc: "The schema postgraphile should expose with graphql",
|
|
format: String,
|
|
default: "app_public",
|
|
},
|
|
enableGraphiql: {
|
|
doc: "Whether to enable the graphiql web interface or not",
|
|
format: "Boolean",
|
|
default: false,
|
|
env: "ENABLE_GRAPHIQL",
|
|
},
|
|
},
|
|
|
|
dev: {
|
|
shadowConnection: {
|
|
doc: "The shadow databse connection url used by postgraphile-migrate. Not needed in production.",
|
|
format: "uri",
|
|
default: "postgresql://metamigo:metamigo@127.0.0.1:5435/metamigo_shadow",
|
|
env: "SHADOW_DATABASE_URL",
|
|
sensitive: true,
|
|
},
|
|
rootConnection: {
|
|
doc: "The postgres root/superuser connection url for testing only, database must NOT be the app database. Not needed in production.",
|
|
format: "uri",
|
|
default: "postgresql://postgres:metamigo@127.0.0.1:5435/template1",
|
|
env: "ROOT_DATABASE_URL",
|
|
sensitive: true,
|
|
},
|
|
},
|
|
frontend: {
|
|
url: {
|
|
doc: "The url the frontend can be accessed at",
|
|
format: "url",
|
|
default: "http://localhost:3000",
|
|
env: "FRONTEND_URL",
|
|
},
|
|
apiUrl: {
|
|
doc: "The url the api backend can be accessed at from the frontend server",
|
|
format: "url",
|
|
default: "http://localhost:3001",
|
|
env: "API_URL",
|
|
},
|
|
},
|
|
nextAuth: {
|
|
secret: {
|
|
doc: "A random string used to hash tokens, sign cookies and generate crytographic keys. Shared with the api backend.",
|
|
format: String,
|
|
default: undefined,
|
|
env: "NEXTAUTH_SECRET",
|
|
sensitive: true,
|
|
},
|
|
audience: {
|
|
doc: "We will add this string as the `aud` claim to our JWT token, if empty or not present defaults to `frontend.url`",
|
|
format: String,
|
|
default: "",
|
|
env: "NEXTAUTH_AUDIENCE",
|
|
},
|
|
signingKeyB64: {
|
|
doc: "A base64 encoded JWK.Key used for JWT signing",
|
|
format: String,
|
|
default: undefined,
|
|
env: "NEXTAUTH_SIGNING_KEY_B64",
|
|
sensitive: true,
|
|
},
|
|
encryptionKeyB64: {
|
|
doc: "A base64 encoded JWK.Key used for JWT encryption",
|
|
format: String,
|
|
default: undefined,
|
|
env: "NEXTAUTH_ENCRYPTION_KEY_B64",
|
|
sensitive: true,
|
|
},
|
|
signingKey: {
|
|
doc: "",
|
|
format: String,
|
|
default: undefined,
|
|
sensitive: true,
|
|
skipGenerate: true,
|
|
},
|
|
encryptionKey: {
|
|
doc: "",
|
|
format: String,
|
|
default: undefined,
|
|
sensitive: true,
|
|
skipGenerate: true,
|
|
},
|
|
google: {
|
|
id: {
|
|
doc: "reference https://next-auth.js.org/providers/google",
|
|
format: String,
|
|
default: undefined,
|
|
env: "GOOGLE_ID",
|
|
sensitive: true,
|
|
},
|
|
secret: {
|
|
doc: "reference https://next-auth.js.org/providers/google",
|
|
format: String,
|
|
default: undefined,
|
|
env: "GOOGLE_SECRET",
|
|
sensitive: true,
|
|
},
|
|
},
|
|
github: {
|
|
id: {
|
|
doc: "reference https://next-auth.js.org/providers/github",
|
|
format: String,
|
|
default: undefined,
|
|
env: "GITHUB_ID",
|
|
sensitive: true,
|
|
},
|
|
secret: {
|
|
doc: "reference https://next-auth.js.org/providers/github",
|
|
format: String,
|
|
default: undefined,
|
|
env: "GITHUB_SECRET",
|
|
sensitive: true,
|
|
},
|
|
},
|
|
gitlab: {
|
|
id: {
|
|
doc: "reference https://next-auth.js.org/providers/gitlab",
|
|
format: String,
|
|
default: undefined,
|
|
env: "GITLAB_ID",
|
|
sensitive: true,
|
|
},
|
|
secret: {
|
|
doc: "reference https://next-auth.js.org/providers/gitlab",
|
|
format: String,
|
|
default: undefined,
|
|
env: "GITLAB_SECRET",
|
|
sensitive: true,
|
|
},
|
|
},
|
|
cognito: {
|
|
id: {
|
|
doc: "reference https://next-auth.js.org/providers/cognito",
|
|
format: String,
|
|
default: undefined,
|
|
env: "COGNITO_ID",
|
|
sensitive: true,
|
|
},
|
|
secret: {
|
|
doc: "reference https://next-auth.js.org/providers/cognito",
|
|
format: String,
|
|
default: undefined,
|
|
env: "COGNITO_SECRET",
|
|
sensitive: true,
|
|
},
|
|
domain: {
|
|
doc: "reference https://next-auth.js.org/providers/cognito",
|
|
format: String,
|
|
default: undefined,
|
|
env: "COGNITO_DOMAIN",
|
|
sensitive: true,
|
|
},
|
|
},
|
|
},
|
|
cfaccess: {
|
|
audience: {
|
|
doc: "the cloudflare access audience id",
|
|
format: String,
|
|
default: undefined,
|
|
env: "CFACCESS_AUDIENCE",
|
|
},
|
|
|
|
domain: {
|
|
doc: "the cloudflare access domain, something like `YOURAPP.cloudflareaccess.com`",
|
|
format: String,
|
|
default: undefined,
|
|
env: "CFACCESS_DOMAIN",
|
|
},
|
|
},
|
|
signald: {
|
|
enabled: {
|
|
doc: "Whether to enable the signald signal backend",
|
|
format: "Boolean",
|
|
default: false,
|
|
env: "SIGNALD_ENABLED",
|
|
},
|
|
socket: {
|
|
doc: "the unix domain socket signald is listening on",
|
|
format: String,
|
|
default: `${process.cwd()}/signald/signald.sock`,
|
|
env: "SIGNALD_SOCKET",
|
|
},
|
|
},
|
|
};
|
|
|
|
// define the interfaces for the concrete config objects
|
|
export interface IDBConfig {
|
|
connection: string;
|
|
name: string;
|
|
owner: string;
|
|
}
|
|
|
|
export interface IWorkerConfig {
|
|
connection: string;
|
|
concurrency: number;
|
|
pollInterval: number;
|
|
}
|
|
|
|
export interface IPostgraphileConfig {
|
|
auth: string;
|
|
visitor: string;
|
|
appRootConnection: string;
|
|
authConnection: string;
|
|
schema: string;
|
|
enableGraphiql: boolean;
|
|
}
|
|
|
|
export interface IDevConfig {
|
|
shadowConnection: string;
|
|
rootConnection: string;
|
|
}
|
|
|
|
export interface IFrontendConfig {
|
|
url: string;
|
|
apiUrl: string;
|
|
}
|
|
|
|
export interface INextAuthConfig {
|
|
secret: string;
|
|
audience: string;
|
|
signingKey: string;
|
|
encryptionKey: string;
|
|
signingKeyB64: string;
|
|
encryptionKeyB64: string;
|
|
google?: { id: string; secret: string };
|
|
github?: { id: string; secret: string };
|
|
gitlab?: { id: string; secret: string };
|
|
cognito?: { id: string; secret: string; domain: string };
|
|
}
|
|
|
|
export interface ICFAccessConfig {
|
|
audience: string;
|
|
domain: string;
|
|
}
|
|
|
|
export interface ISignaldConifg {
|
|
enabled: boolean;
|
|
socket: string;
|
|
}
|
|
|
|
// Extend the metamigo base type to add your app's custom config along side the out
|
|
// of the box Metamigo config
|
|
export interface IAppConfig extends Metamigo.IMetamigoConfig {
|
|
db: IDBConfig;
|
|
worker: IWorkerConfig;
|
|
postgraphile: IPostgraphileConfig;
|
|
dev: IDevConfig;
|
|
frontend: IFrontendConfig;
|
|
nextAuth: INextAuthConfig;
|
|
cfaccess: ICFAccessConfig;
|
|
signald: ISignaldConifg;
|
|
}
|
|
|
|
export type IAppConvict = Metamigo.ExtendedConvict<IAppConfig>;
|
|
|
|
// Merge the Metamigo base schema with your app's schmea
|
|
// @ts-ignore
|
|
export const schema: convict.Schema<IAppConfig> = {
|
|
...Metamigo.configBaseSchema,
|
|
...configSchema,
|
|
};
|
|
|
|
export const loadConfig = async (): Promise<IAppConfig> => {
|
|
const config = await Metamigo.loadConfiguration(schema);
|
|
|
|
if (!config.frontend.url || config.frontend.url === "")
|
|
throw new Error(
|
|
"configuration value frontend.url is missing. Add to config or set NEXTAUTH_URL env var"
|
|
);
|
|
|
|
// nextauth expects the url to be provided with this environment variable, so we will munge it in place here
|
|
process.env.NEXTAUTH_URL = config.frontend.url;
|
|
|
|
if (config.nextAuth.signingKeyB64)
|
|
config.nextAuth.signingKey = Buffer.from(
|
|
config.nextAuth.signingKeyB64,
|
|
"base64"
|
|
).toString("utf-8");
|
|
|
|
if (config.nextAuth.encryptionKeyB64)
|
|
config.nextAuth.encryptionKey = Buffer.from(
|
|
config.nextAuth.encryptionKeyB64,
|
|
"base64"
|
|
).toString("utf-8");
|
|
|
|
if (!config.nextAuth.audience || config.nextAuth.audience === "")
|
|
config.nextAuth.audience = config.frontend.url;
|
|
|
|
return config as any;
|
|
};
|
|
|
|
export const loadConfigRaw = async (): Promise<IAppConvict> => {
|
|
return Metamigo.loadConfigurationRaw(schema);
|
|
};
|
|
|
|
const config = defState("config", {
|
|
start: loadConfig,
|
|
});
|
|
|
|
export default config;
|