mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-02-18 06:47:02 +08:00
229 lines
6.3 KiB
TypeScript
229 lines
6.3 KiB
TypeScript
/// <reference types="../global.d.ts" />
|
|
|
|
import { createPrivateKey, createPublicKey } from 'node:crypto';
|
|
import { homedir } from 'node:os';
|
|
import { join } from 'node:path';
|
|
|
|
import parse from 'parse-duration';
|
|
|
|
import pkg from '../../package.json' assert { type: 'json' };
|
|
import type { AFFiNEConfig, ServerFlavor } from './def';
|
|
import { applyEnvToConfig } from './env';
|
|
import { getDefaultAFFiNEStorageConfig } from './storage';
|
|
|
|
export const SERVER_FLAVOR = (process.env.SERVER_FLAVOR ??
|
|
'allinone') as ServerFlavor;
|
|
|
|
// Don't use this in production
|
|
export const examplePrivateKey = `-----BEGIN EC PRIVATE KEY-----
|
|
MHcCAQEEIEtyAJLIULkphVhqXqxk4Nr8Ggty3XLwUJWBxzAWCWTMoAoGCCqGSM49
|
|
AwEHoUQDQgAEF3U/0wIeJ3jRKXeFKqQyBKlr9F7xaAUScRrAuSP33rajm3cdfihI
|
|
3JvMxVNsS2lE8PSGQrvDrJZaDo0L+Lq9Gg==
|
|
-----END EC PRIVATE KEY-----`;
|
|
|
|
const jwtKeyPair = (function () {
|
|
const AUTH_PRIVATE_KEY = process.env.AUTH_PRIVATE_KEY ?? examplePrivateKey;
|
|
const privateKey = createPrivateKey({
|
|
key: Buffer.from(AUTH_PRIVATE_KEY),
|
|
format: 'pem',
|
|
type: 'sec1',
|
|
})
|
|
.export({
|
|
format: 'pem',
|
|
type: 'pkcs8',
|
|
})
|
|
.toString('utf8');
|
|
const publicKey = createPublicKey({
|
|
key: Buffer.from(AUTH_PRIVATE_KEY),
|
|
format: 'pem',
|
|
type: 'spki',
|
|
})
|
|
.export({
|
|
format: 'pem',
|
|
type: 'spki',
|
|
})
|
|
.toString('utf8');
|
|
|
|
return {
|
|
publicKey,
|
|
privateKey,
|
|
};
|
|
})();
|
|
|
|
export const getDefaultAFFiNEConfig: () => AFFiNEConfig = () => {
|
|
const defaultConfig = {
|
|
serverId: 'affine-nestjs-server',
|
|
version: pkg.version,
|
|
ENV_MAP: {
|
|
AFFINE_SERVER_PORT: ['port', 'int'],
|
|
AFFINE_SERVER_HOST: 'host',
|
|
AFFINE_SERVER_SUB_PATH: 'path',
|
|
AFFINE_ENV: 'affineEnv',
|
|
DATABASE_URL: 'db.url',
|
|
ENABLE_CAPTCHA: ['auth.captcha.enable', 'boolean'],
|
|
CAPTCHA_TURNSTILE_SECRET: ['auth.captcha.turnstile.secret', 'string'],
|
|
OAUTH_GOOGLE_ENABLED: ['auth.oauthProviders.google.enabled', 'boolean'],
|
|
OAUTH_GOOGLE_CLIENT_ID: 'auth.oauthProviders.google.clientId',
|
|
OAUTH_GOOGLE_CLIENT_SECRET: 'auth.oauthProviders.google.clientSecret',
|
|
OAUTH_GITHUB_ENABLED: ['auth.oauthProviders.github.enabled', 'boolean'],
|
|
OAUTH_GITHUB_CLIENT_ID: 'auth.oauthProviders.github.clientId',
|
|
OAUTH_GITHUB_CLIENT_SECRET: 'auth.oauthProviders.github.clientSecret',
|
|
OAUTH_EMAIL_LOGIN: 'auth.email.login',
|
|
OAUTH_EMAIL_SENDER: 'auth.email.sender',
|
|
OAUTH_EMAIL_SERVER: 'auth.email.server',
|
|
OAUTH_EMAIL_PORT: ['auth.email.port', 'int'],
|
|
OAUTH_EMAIL_PASSWORD: 'auth.email.password',
|
|
THROTTLE_TTL: ['rateLimiter.ttl', 'int'],
|
|
THROTTLE_LIMIT: ['rateLimiter.limit', 'int'],
|
|
REDIS_SERVER_ENABLED: ['redis.enabled', 'boolean'],
|
|
REDIS_SERVER_HOST: 'redis.host',
|
|
REDIS_SERVER_PORT: ['redis.port', 'int'],
|
|
REDIS_SERVER_USER: 'redis.username',
|
|
REDIS_SERVER_PASSWORD: 'redis.password',
|
|
REDIS_SERVER_DATABASE: ['redis.database', 'int'],
|
|
DOC_MERGE_INTERVAL: ['doc.manager.updatePollInterval', 'int'],
|
|
DOC_MERGE_USE_JWST_CODEC: [
|
|
'doc.manager.experimentalMergeWithJwstCodec',
|
|
'boolean',
|
|
],
|
|
ENABLE_LOCAL_EMAIL: ['auth.localEmail', 'boolean'],
|
|
STRIPE_API_KEY: 'payment.stripe.keys.APIKey',
|
|
STRIPE_WEBHOOK_KEY: 'payment.stripe.keys.webhookKey',
|
|
FEATURES_EARLY_ACCESS_PREVIEW: [
|
|
'featureFlags.earlyAccessPreview',
|
|
'boolean',
|
|
],
|
|
} satisfies AFFiNEConfig['ENV_MAP'],
|
|
affineEnv: 'dev',
|
|
get affine() {
|
|
const env = this.affineEnv;
|
|
return {
|
|
canary: env === 'dev',
|
|
beta: env === 'beta',
|
|
stable: env === 'production',
|
|
};
|
|
},
|
|
env: process.env.NODE_ENV ?? 'development',
|
|
get node() {
|
|
const env = this.env;
|
|
return {
|
|
prod: env === 'production',
|
|
dev: env === 'development',
|
|
test: env === 'test',
|
|
};
|
|
},
|
|
get deploy() {
|
|
return !this.node.dev && !this.node.test;
|
|
},
|
|
featureFlags: {
|
|
earlyAccessPreview: false,
|
|
},
|
|
get https() {
|
|
return !this.node.dev;
|
|
},
|
|
host: 'localhost',
|
|
port: 3010,
|
|
path: '',
|
|
db: {
|
|
url: '',
|
|
},
|
|
get origin() {
|
|
return this.node.dev
|
|
? 'http://localhost:8080'
|
|
: `${this.https ? 'https' : 'http'}://${this.host}${
|
|
this.host === 'localhost' ? `:${this.port}` : ''
|
|
}`;
|
|
},
|
|
get baseUrl() {
|
|
return `${this.origin}${this.path}`;
|
|
},
|
|
graphql: {
|
|
buildSchemaOptions: {
|
|
numberScalarMode: 'integer',
|
|
},
|
|
introspection: true,
|
|
playground: true,
|
|
},
|
|
auth: {
|
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
accessTokenExpiresIn: parse('1h')! / 1000,
|
|
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
refreshTokenExpiresIn: parse('7d')! / 1000,
|
|
leeway: 60,
|
|
captcha: {
|
|
enable: false,
|
|
turnstile: {
|
|
secret: '1x0000000000000000000000000000000AA',
|
|
},
|
|
challenge: {
|
|
bits: 20,
|
|
},
|
|
},
|
|
privateKey: jwtKeyPair.privateKey,
|
|
publicKey: jwtKeyPair.publicKey,
|
|
enableSignup: true,
|
|
enableOauth: false,
|
|
get nextAuthSecret() {
|
|
return this.privateKey;
|
|
},
|
|
oauthProviders: {},
|
|
localEmail: false,
|
|
email: {
|
|
server: 'smtp.gmail.com',
|
|
port: 465,
|
|
login: '',
|
|
sender: '',
|
|
password: '',
|
|
},
|
|
},
|
|
storage: getDefaultAFFiNEStorageConfig(),
|
|
objectStorage: {
|
|
r2: {
|
|
enabled: false,
|
|
bucket: '',
|
|
accountId: '',
|
|
accessKeyId: '',
|
|
secretAccessKey: '',
|
|
},
|
|
fs: {
|
|
path: join(homedir(), '.affine-storage'),
|
|
},
|
|
},
|
|
rateLimiter: {
|
|
ttl: 60,
|
|
limit: 60,
|
|
},
|
|
redis: {
|
|
enabled: false,
|
|
host: '127.0.0.1',
|
|
port: 6379,
|
|
username: '',
|
|
password: '',
|
|
database: 0,
|
|
},
|
|
doc: {
|
|
manager: {
|
|
enableUpdateAutoMerging: SERVER_FLAVOR !== 'sync',
|
|
updatePollInterval: 3000,
|
|
experimentalMergeWithJwstCodec: false,
|
|
},
|
|
history: {
|
|
interval: 1000 * 60 * 10 /* 10 mins */,
|
|
},
|
|
},
|
|
payment: {
|
|
stripe: {
|
|
keys: {
|
|
APIKey: '',
|
|
webhookKey: '',
|
|
},
|
|
apiVersion: '2023-10-16',
|
|
},
|
|
},
|
|
} satisfies AFFiNEConfig;
|
|
|
|
applyEnvToConfig(defaultConfig);
|
|
|
|
return defaultConfig;
|
|
};
|