feat(server): implement doc service (#9961)

close CLOUD-94
This commit is contained in:
fengmk2
2025-02-08 03:37:41 +00:00
parent 5ae5fd88f1
commit 5d62c5e85c
37 changed files with 914 additions and 20 deletions

View File

@@ -2,7 +2,7 @@ import type { LeafPaths } from '../utils/types';
import { AppStartupConfig } from './types';
export type EnvConfigType = 'string' | 'int' | 'float' | 'boolean';
export type ServerFlavor = 'allinone' | 'graphql' | 'sync' | 'renderer';
export type ServerFlavor = 'allinone' | 'graphql' | 'sync' | 'renderer' | 'doc';
export type AFFINE_ENV = 'dev' | 'beta' | 'production';
export type NODE_ENV = 'development' | 'test' | 'production' | 'script';
@@ -41,9 +41,9 @@ export type AFFiNEConfig = PreDefinedAFFiNEConfig &
AppPluginsConfig;
declare global {
// eslint-disable-next-line @typescript-eslint/no-namespace
// oxlint-disable-next-line @typescript-eslint/no-namespace
namespace globalThis {
// eslint-disable-next-line no-var
// oxlint-disable-next-line no-var
var AFFiNE: AFFiNEConfig;
}
}

View File

@@ -30,6 +30,7 @@ function getPredefinedAFFiNEConfig(): PreDefinedAFFiNEConfig {
'graphql',
'sync',
'renderer',
'doc',
]);
const deploymentType = readEnv<DeploymentType>(
'DEPLOYMENT_TYPE',
@@ -66,6 +67,7 @@ function getPredefinedAFFiNEConfig(): PreDefinedAFFiNEConfig {
graphql: flavor === 'graphql' || flavor === 'allinone',
sync: flavor === 'sync' || flavor === 'allinone',
renderer: flavor === 'renderer' || flavor === 'allinone',
doc: flavor === 'doc' || flavor === 'allinone',
},
affine,
node,

View File

@@ -101,6 +101,15 @@ export class UserFriendlyError extends Error {
this.requestId = ClsServiceManager.getClsService()?.getId();
}
static fromUserFriendlyErrorJSON(body: UserFriendlyError) {
return new UserFriendlyError(
body.type as UserFriendlyErrorBaseType,
body.name.toLowerCase() as keyof typeof USER_FRIENDLY_ERRORS,
body.message,
body.data
);
}
toJSON() {
return {
status: this.status,

View File

@@ -50,8 +50,18 @@ test.beforeEach(async t => {
test('should be able to sign and verify', t => {
const data = 'hello world';
const signature = t.context.crypto.sign(data);
t.true(t.context.crypto.verify(data, signature));
t.false(t.context.crypto.verify(data, 'fake-signature'));
t.true(t.context.crypto.verify(signature));
t.false(t.context.crypto.verify('fake-signature'));
t.false(t.context.crypto.verify(`${data},fake-signature`));
});
test('should same data should get different signature', t => {
const data = 'hello world';
const signature = t.context.crypto.sign(data);
const signature2 = t.context.crypto.sign(data);
t.not(signature2, signature);
t.true(t.context.crypto.verify(signature));
t.true(t.context.crypto.verify(signature2));
});
test('should be able to encrypt and decrypt', t => {

View File

@@ -46,10 +46,14 @@ export class CryptoHelper {
const sign = createSign('rsa-sha256');
sign.update(data, 'utf-8');
sign.end();
return sign.sign(this.keyPair.privateKey, 'base64');
return `${data},${sign.sign(this.keyPair.privateKey, 'base64')}`;
}
verify(data: string, signature: string) {
verify(signatureWithData: string) {
const [data, signature] = signatureWithData.split(',');
if (!signature) {
return false;
}
const verify = createVerify('rsa-sha256');
verify.update(data, 'utf-8');
verify.end();