build: affine Node.js server charts (#2895)

This commit is contained in:
LongYinan
2023-06-29 22:02:46 +08:00
committed by GitHub
parent d7fcad2d0d
commit 8021efd81a
43 changed files with 1112 additions and 124 deletions
+9 -18
View File
@@ -106,7 +106,7 @@ export interface AFFiNEConfig {
/**
* which port the server will listen on
*
* @default 3000
* @default 3010
* @env AFFINE_SERVER_PORT
*/
port: number;
@@ -153,23 +153,13 @@ export interface AFFiNEConfig {
/**
* whether use remote object storage
*/
enable: boolean;
/**
* used to store all uploaded builds and analysis reports
*
* the concrete type definition is not given here because different storage providers introduce
* significant differences in configuration
*
* @example
* {
* provider: 'aws',
* region: 'eu-west-1',
* aws_access_key_id: '',
* aws_secret_access_key: '',
* // other aws storage config...
* }
*/
config: Record<string, string>;
r2: {
enabled: boolean;
accountId: string;
bucket: string;
accessKeyId: string;
secretAccessKey: string;
};
/**
* Only used when `enable` is `false`
*/
@@ -224,6 +214,7 @@ export interface AFFiNEConfig {
Record<
ExternalAccount,
{
enabled: boolean;
clientId: string;
clientSecret: string;
/**
+121 -72
View File
@@ -1,5 +1,6 @@
/// <reference types="../global.d.ts" />
import { createPrivateKey, createPublicKey } from 'node:crypto';
import { homedir } from 'node:os';
import { join } from 'node:path';
@@ -7,82 +8,130 @@ import parse from 'parse-duration';
import pkg from '../../package.json' assert { type: 'json' };
import type { AFFiNEConfig } from './def';
import { applyEnvToConfig } from './env';
// Don't use this in production
export const examplePublicKey = `-----BEGIN PUBLIC KEY-----
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEnxM+GhB6eNKPmTP6uH5Gpr+bmQ87
hHGeOiCsay0w/aPwMqzAOKkZGqX+HZ9BNGy/yiXmnscey5b2vOTzxtRvxA==
-----END PUBLIC KEY-----`;
export const examplePrivateKey = `-----BEGIN EC PRIVATE KEY-----
MHcCAQEEIEtyAJLIULkphVhqXqxk4Nr8Ggty3XLwUJWBxzAWCWTMoAoGCCqGSM49
AwEHoUQDQgAEF3U/0wIeJ3jRKXeFKqQyBKlr9F7xaAUScRrAuSP33rajm3cdfihI
3JvMxVNsS2lE8PSGQrvDrJZaDo0L+Lq9Gg==
-----END EC PRIVATE KEY-----`;
// Don't use this in production
export const examplePrivateKey = `-----BEGIN PRIVATE KEY-----
MIGHAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBG0wawIBAQQgWOog5SFXs1Vjh/WP
QCYPQKgf/jsNmWsvD+jYSn6mi3yhRANCAASfEz4aEHp40o+ZM/q4fkamv5uZDzuE
cZ46IKxrLTD9o/AyrMA4qRkapf4dn0E0bL/KJeaexx7Llva85PPG1G/E
-----END 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');
export const getDefaultAFFiNEConfig: () => AFFiNEConfig = () => ({
serverId: 'affine-nestjs-server',
version: pkg.version,
ENV_MAP: {},
env: process.env.NODE_ENV ?? 'development',
get prod() {
return this.env === 'production';
},
get dev() {
return this.env === 'development';
},
get test() {
return this.env === 'test';
},
get deploy() {
return !this.dev && !this.test;
},
https: false,
host: 'localhost',
port: 3010,
path: '',
get origin() {
return this.dev
? 'http://localhost:8080'
: `${this.https ? 'https' : 'http'}://${this.host}${
this.host === 'localhost' ? `:${this.port}` : ''
}`;
},
get baseUrl() {
return `${this.origin}${this.path}`;
},
db: {
url: '',
},
graphql: {
buildSchemaOptions: {
numberScalarMode: 'integer',
return {
publicKey,
privateKey,
};
})();
export const getDefaultAFFiNEConfig: () => AFFiNEConfig = () => {
const defaultConfig = {
serverId: 'affine-nestjs-server',
version: pkg.version,
ENV_MAP: {
AFFINE_SERVER_PORT: 'port',
AFFINE_SERVER_HOST: 'host',
AFFINE_SERVER_SUB_PATH: 'path',
DATABASE_URL: 'db.url',
AUTH_PRIVATE_KEY: 'auth.privateKey',
ENABLE_R2_OBJECT_STORAGE: 'objectStorage.r2.enabled',
R2_OBJECT_STORAGE_ACCOUNT_ID: 'objectStorage.r2.accountId',
R2_OBJECT_STORAGE_ACCESS_KEY_ID: 'objectStorage.r2.accessKeyId',
R2_OBJECT_STORAGE_SECRET_ACCESS_KEY: 'objectStorage.r2.secretAccessKey',
R2_OBJECT_STORAGE_BUCKET: 'objectStorage.r2.bucket',
OAUTH_GOOGLE_CLIENT_ID: 'auth.oauthProviders.google.clientId',
OAUTH_GOOGLE_CLIENT_SECRET: 'auth.oauthProviders.google.clientSecret',
OAUTH_GITHUB_CLIENT_ID: 'auth.oauthProviders.github.clientId',
OAUTH_GITHUB_CLIENT_SECRET: 'auth.oauthProviders.github.clientSecret',
} satisfies AFFiNEConfig['ENV_MAP'],
env: process.env.NODE_ENV ?? 'development',
get prod() {
return this.env === 'production';
},
introspection: true,
playground: true,
debug: 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,
publicKey: examplePublicKey,
privateKey: examplePrivateKey,
enableSignup: true,
enableOauth: false,
nextAuthSecret: '',
oauthProviders: {},
},
objectStorage: {
enable: false,
config: {},
fs: {
path: join(homedir(), '.affine-storage'),
get dev() {
return this.env === 'development';
},
},
});
get test() {
return this.env === 'test';
},
get deploy() {
return !this.dev && !this.test;
},
https: false,
host: 'localhost',
port: 3010,
path: '',
db: {
url: '',
},
get origin() {
return this.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,
debug: 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,
privateKey: jwtKeyPair.privateKey,
publicKey: jwtKeyPair.publicKey,
enableSignup: true,
enableOauth: false,
nextAuthSecret: '',
oauthProviders: {},
},
objectStorage: {
r2: {
enabled: false,
bucket: '',
accountId: '',
accessKeyId: '',
secretAccessKey: '',
},
fs: {
path: join(homedir(), '.affine-storage'),
},
},
} as const;
export { registerEnvs } from './env';
applyEnvToConfig(defaultConfig);
return defaultConfig;
};
+5 -5
View File
@@ -1,17 +1,17 @@
import { set } from 'lodash-es';
import { parseEnvValue } from './def';
import { type AFFiNEConfig, parseEnvValue } from './def';
export function registerEnvs() {
for (const env in globalThis.AFFiNE.ENV_MAP) {
const config = globalThis.AFFiNE.ENV_MAP[env];
export function applyEnvToConfig(rawConfig: AFFiNEConfig) {
for (const env in rawConfig.ENV_MAP) {
const config = rawConfig.ENV_MAP[env];
const [path, value] =
typeof config === 'string'
? [config, process.env[env]]
: [config[0], parseEnvValue(process.env[env], config[1])];
if (typeof value !== 'undefined') {
set(globalThis.AFFiNE, path, process.env[env]);
set(rawConfig, path, value);
}
}
}