mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-07-25 22:38:56 +08:00
refactor(infra): directory structure (#4615)
This commit is contained in:
@@ -0,0 +1,27 @@
|
||||
import { describe, expect, test } from 'vitest';
|
||||
|
||||
import { isValidIPAddress } from '../is-valid-ip-address.js';
|
||||
|
||||
describe('isValidIpAddress', () => {
|
||||
test('should return true for valid IP address', () => {
|
||||
['115.42.150.37', '192.168.0.1', '110.234.52.124', 'localhost'].forEach(
|
||||
ip => {
|
||||
expect(isValidIPAddress(ip)).toBe(true);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test('should return false for invalid IP address', () => {
|
||||
[
|
||||
'210.110',
|
||||
'255',
|
||||
'y.y.y.y',
|
||||
'255.0.0.y',
|
||||
'666.10.10.20',
|
||||
'4444.11.11.11',
|
||||
'33.3333.33.3',
|
||||
].forEach(ip => {
|
||||
expect(isValidIPAddress(ip)).toBe(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import type { z } from 'zod';
|
||||
|
||||
export type Action<
|
||||
InputSchema extends z.ZodObject<any, any, any, any>,
|
||||
Args extends readonly any[],
|
||||
> = {
|
||||
id: string;
|
||||
name: string;
|
||||
description: string;
|
||||
inputSchema: InputSchema;
|
||||
action: (input: z.input<InputSchema>, ...args: Args) => void;
|
||||
};
|
||||
Vendored
+131
@@ -0,0 +1,131 @@
|
||||
// This file should has not side effect
|
||||
import type { Workspace } from '@blocksuite/store';
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
appInfo: {
|
||||
electron: boolean;
|
||||
schema: string;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
//#region runtime variables
|
||||
export const isBrowser = typeof window !== 'undefined';
|
||||
export const isServer = !isBrowser && typeof navigator === 'undefined';
|
||||
export const isDesktop = isBrowser && !!window.appInfo?.electron;
|
||||
//#endregion
|
||||
export const DEFAULT_WORKSPACE_NAME = 'Demo Workspace';
|
||||
export const UNTITLED_WORKSPACE_NAME = 'Untitled';
|
||||
|
||||
export const DEFAULT_SORT_KEY = 'updatedDate';
|
||||
export const MessageCode = {
|
||||
loginError: 0,
|
||||
noPermission: 1,
|
||||
loadListFailed: 2,
|
||||
getDetailFailed: 3,
|
||||
createWorkspaceFailed: 4,
|
||||
getMembersFailed: 5,
|
||||
updateWorkspaceFailed: 6,
|
||||
deleteWorkspaceFailed: 7,
|
||||
inviteMemberFailed: 8,
|
||||
removeMemberFailed: 9,
|
||||
acceptInvitingFailed: 10,
|
||||
getBlobFailed: 11,
|
||||
leaveWorkspaceFailed: 12,
|
||||
downloadWorkspaceFailed: 13,
|
||||
refreshTokenError: 14,
|
||||
blobTooLarge: 15,
|
||||
} as const;
|
||||
|
||||
export const Messages = {
|
||||
[MessageCode.loginError]: {
|
||||
message: 'Login failed',
|
||||
},
|
||||
[MessageCode.noPermission]: {
|
||||
message: 'No permission',
|
||||
},
|
||||
[MessageCode.loadListFailed]: {
|
||||
message: 'Load list failed',
|
||||
},
|
||||
[MessageCode.getDetailFailed]: {
|
||||
message: 'Get detail failed',
|
||||
},
|
||||
[MessageCode.createWorkspaceFailed]: {
|
||||
message: 'Create workspace failed',
|
||||
},
|
||||
[MessageCode.getMembersFailed]: {
|
||||
message: 'Get members failed',
|
||||
},
|
||||
[MessageCode.updateWorkspaceFailed]: {
|
||||
message: 'Update workspace failed',
|
||||
},
|
||||
[MessageCode.deleteWorkspaceFailed]: {
|
||||
message: 'Delete workspace failed',
|
||||
},
|
||||
[MessageCode.inviteMemberFailed]: {
|
||||
message: 'Invite member failed',
|
||||
},
|
||||
[MessageCode.removeMemberFailed]: {
|
||||
message: 'Remove member failed',
|
||||
},
|
||||
[MessageCode.acceptInvitingFailed]: {
|
||||
message: 'Accept inviting failed',
|
||||
},
|
||||
[MessageCode.getBlobFailed]: {
|
||||
message: 'Get blob failed',
|
||||
},
|
||||
[MessageCode.leaveWorkspaceFailed]: {
|
||||
message: 'Leave workspace failed',
|
||||
},
|
||||
[MessageCode.downloadWorkspaceFailed]: {
|
||||
message: 'Download workspace failed',
|
||||
},
|
||||
[MessageCode.refreshTokenError]: {
|
||||
message: 'Refresh token failed',
|
||||
},
|
||||
[MessageCode.blobTooLarge]: {
|
||||
message: 'Blob too large',
|
||||
},
|
||||
} as const satisfies {
|
||||
[key in (typeof MessageCode)[keyof typeof MessageCode]]: {
|
||||
message: string;
|
||||
};
|
||||
};
|
||||
|
||||
export class PageNotFoundError extends TypeError {
|
||||
readonly workspace: Workspace;
|
||||
readonly pageId: string;
|
||||
|
||||
constructor(workspace: Workspace, pageId: string) {
|
||||
super();
|
||||
this.workspace = workspace;
|
||||
this.pageId = pageId;
|
||||
}
|
||||
}
|
||||
|
||||
export class WorkspaceNotFoundError extends TypeError {
|
||||
readonly workspaceId: string;
|
||||
|
||||
constructor(workspaceId: string) {
|
||||
super();
|
||||
this.workspaceId = workspaceId;
|
||||
}
|
||||
}
|
||||
|
||||
export class QueryParamError extends TypeError {
|
||||
readonly targetKey: string;
|
||||
readonly query: unknown;
|
||||
|
||||
constructor(targetKey: string, query: unknown) {
|
||||
super();
|
||||
this.targetKey = targetKey;
|
||||
this.query = query;
|
||||
}
|
||||
}
|
||||
|
||||
export class Unreachable extends Error {
|
||||
constructor(message?: string) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
Vendored
+69
@@ -0,0 +1,69 @@
|
||||
import type { Workspace } from '@blocksuite/store';
|
||||
import { z } from 'zod';
|
||||
|
||||
export const literalValueSchema: z.ZodType<LiteralValue, z.ZodTypeDef> =
|
||||
z.union([
|
||||
z.number(),
|
||||
z.string(),
|
||||
z.boolean(),
|
||||
z.array(z.lazy(() => literalValueSchema)),
|
||||
z.record(z.lazy(() => literalValueSchema)),
|
||||
]);
|
||||
|
||||
export type LiteralValue =
|
||||
| number
|
||||
| string
|
||||
| boolean
|
||||
| { [K: string]: LiteralValue }
|
||||
| Array<LiteralValue>;
|
||||
|
||||
export const refSchema: z.ZodType<Ref, z.ZodTypeDef> = z.object({
|
||||
type: z.literal('ref'),
|
||||
name: z.never(),
|
||||
});
|
||||
|
||||
export type Ref = {
|
||||
type: 'ref';
|
||||
name: keyof VariableMap;
|
||||
};
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-empty-interface
|
||||
export interface VariableMap {}
|
||||
|
||||
export const literalSchema = z.object({
|
||||
type: z.literal('literal'),
|
||||
value: literalValueSchema,
|
||||
});
|
||||
|
||||
export type Literal = z.input<typeof literalSchema>;
|
||||
|
||||
export const filterSchema = z.object({
|
||||
type: z.literal('filter'),
|
||||
left: refSchema,
|
||||
funcName: z.string(),
|
||||
args: z.array(literalSchema),
|
||||
});
|
||||
|
||||
export type Filter = z.input<typeof filterSchema>;
|
||||
|
||||
export const collectionSchema = z.object({
|
||||
id: z.string(),
|
||||
workspaceId: z.string(),
|
||||
name: z.string(),
|
||||
pinned: z.boolean().optional(),
|
||||
filterList: z.array(filterSchema),
|
||||
allowList: z.array(z.string()).optional(),
|
||||
excludeList: z.array(z.string()).optional(),
|
||||
});
|
||||
|
||||
export type Collection = z.input<typeof collectionSchema>;
|
||||
|
||||
export const tagSchema = z.object({
|
||||
id: z.string(),
|
||||
value: z.string(),
|
||||
color: z.string(),
|
||||
parentId: z.string().optional(),
|
||||
});
|
||||
export type Tag = z.input<typeof tagSchema>;
|
||||
|
||||
export type PropertiesMeta = Workspace['meta']['properties'];
|
||||
Vendored
+161
@@ -0,0 +1,161 @@
|
||||
/// <reference types="@blocksuite/global" />
|
||||
import { assertEquals } from '@blocksuite/global/utils';
|
||||
import { z } from 'zod';
|
||||
|
||||
import { isDesktop, isServer } from './constant.js';
|
||||
import { UaHelper } from './ua-helper.js';
|
||||
|
||||
export const blockSuiteFeatureFlags = z.object({
|
||||
enable_set_remote_flag: z.boolean(),
|
||||
enable_block_hub: z.boolean(),
|
||||
|
||||
enable_toggle_block: z.boolean(),
|
||||
enable_bookmark_operation: z.boolean(),
|
||||
enable_note_index: z.boolean(),
|
||||
});
|
||||
|
||||
export const runtimeFlagsSchema = z.object({
|
||||
enablePlugin: z.boolean(),
|
||||
enableTestProperties: z.boolean(),
|
||||
enableBroadcastChannelProvider: z.boolean(),
|
||||
enableDebugPage: z.boolean(),
|
||||
changelogUrl: z.string(),
|
||||
// see: tools/workers
|
||||
imageProxyUrl: z.string(),
|
||||
enablePreloading: z.boolean(),
|
||||
enableNewSettingModal: z.boolean(),
|
||||
enableNewSettingUnstableApi: z.boolean(),
|
||||
enableSQLiteProvider: z.boolean(),
|
||||
enableNotificationCenter: z.boolean(),
|
||||
enableCloud: z.boolean(),
|
||||
enableCaptcha: z.boolean(),
|
||||
enableEnhanceShareMode: z.boolean(),
|
||||
// this is for the electron app
|
||||
serverUrlPrefix: z.string(),
|
||||
enableMoveDatabase: z.boolean(),
|
||||
editorFlags: blockSuiteFeatureFlags,
|
||||
appVersion: z.string(),
|
||||
editorVersion: z.string(),
|
||||
});
|
||||
|
||||
export type BlockSuiteFeatureFlags = z.infer<typeof blockSuiteFeatureFlags>;
|
||||
|
||||
export type RuntimeConfig = z.infer<typeof runtimeFlagsSchema>;
|
||||
|
||||
export const platformSchema = z.enum([
|
||||
'aix',
|
||||
'android',
|
||||
'darwin',
|
||||
'freebsd',
|
||||
'haiku',
|
||||
'linux',
|
||||
'openbsd',
|
||||
'sunos',
|
||||
'win32',
|
||||
'cygwin',
|
||||
'netbsd',
|
||||
]);
|
||||
|
||||
export type Platform = z.infer<typeof platformSchema>;
|
||||
|
||||
type BrowserBase = {
|
||||
/**
|
||||
* @example https://app.affine.pro
|
||||
* @example http://localhost:3000
|
||||
*/
|
||||
origin: string;
|
||||
isDesktop: boolean;
|
||||
isBrowser: true;
|
||||
isServer: false;
|
||||
isDebug: boolean;
|
||||
|
||||
// browser special properties
|
||||
isLinux: boolean;
|
||||
isMacOs: boolean;
|
||||
isIOS: boolean;
|
||||
isSafari: boolean;
|
||||
isWindows: boolean;
|
||||
isFireFox: boolean;
|
||||
isMobile: boolean;
|
||||
isChrome: boolean;
|
||||
};
|
||||
|
||||
type NonChromeBrowser = BrowserBase & {
|
||||
isChrome: false;
|
||||
};
|
||||
|
||||
type ChromeBrowser = BrowserBase & {
|
||||
isSafari: false;
|
||||
isFireFox: false;
|
||||
isChrome: true;
|
||||
chromeVersion: number;
|
||||
};
|
||||
|
||||
type Browser = NonChromeBrowser | ChromeBrowser;
|
||||
|
||||
type Server = {
|
||||
isDesktop: false;
|
||||
isBrowser: false;
|
||||
isServer: true;
|
||||
isDebug: boolean;
|
||||
};
|
||||
|
||||
interface Desktop extends ChromeBrowser {
|
||||
isDesktop: true;
|
||||
isBrowser: true;
|
||||
isServer: false;
|
||||
isDebug: boolean;
|
||||
}
|
||||
|
||||
export type Environment = Browser | Server | Desktop;
|
||||
|
||||
export function setupGlobal() {
|
||||
if (globalThis.$AFFINE_SETUP) {
|
||||
return;
|
||||
}
|
||||
runtimeFlagsSchema.parse(runtimeConfig);
|
||||
|
||||
let environment: Environment;
|
||||
const isDebug = process.env.NODE_ENV === 'development';
|
||||
if (isServer) {
|
||||
environment = {
|
||||
isDesktop: false,
|
||||
isBrowser: false,
|
||||
isServer: true,
|
||||
isDebug,
|
||||
} satisfies Server;
|
||||
} else {
|
||||
const uaHelper = new UaHelper(navigator);
|
||||
|
||||
environment = {
|
||||
origin: window.location.origin,
|
||||
isDesktop,
|
||||
isBrowser: true,
|
||||
isServer: false,
|
||||
isDebug,
|
||||
isLinux: uaHelper.isLinux,
|
||||
isMacOs: uaHelper.isMacOs,
|
||||
isSafari: uaHelper.isSafari,
|
||||
isWindows: uaHelper.isWindows,
|
||||
isFireFox: uaHelper.isFireFox,
|
||||
isMobile: uaHelper.isMobile,
|
||||
isChrome: uaHelper.isChrome,
|
||||
isIOS: uaHelper.isIOS,
|
||||
} as Browser;
|
||||
// Chrome on iOS is still Safari
|
||||
if (environment.isChrome && !environment.isIOS) {
|
||||
assertEquals(environment.isSafari, false);
|
||||
assertEquals(environment.isFireFox, false);
|
||||
environment = {
|
||||
...environment,
|
||||
isSafari: false,
|
||||
isFireFox: false,
|
||||
isChrome: true,
|
||||
chromeVersion: uaHelper.getChromeVersion(),
|
||||
} satisfies ChromeBrowser;
|
||||
}
|
||||
}
|
||||
globalThis.environment = environment;
|
||||
|
||||
globalThis.$AFFINE_SETUP = true;
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
export function isValidIPAddress(address: string) {
|
||||
if (address === 'localhost') {
|
||||
return true;
|
||||
}
|
||||
return /^(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(
|
||||
address
|
||||
);
|
||||
}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
export type PageInfo = {
|
||||
isEdgeless: boolean;
|
||||
title: string;
|
||||
id: string;
|
||||
};
|
||||
|
||||
export type GetPageInfoById = (id: string) => PageInfo | undefined;
|
||||
Vendored
+78
@@ -0,0 +1,78 @@
|
||||
import { assertExists } from '@blocksuite/global/utils';
|
||||
|
||||
export class UaHelper {
|
||||
private uaMap;
|
||||
public isLinux = false;
|
||||
public isMacOs = false;
|
||||
public isSafari = false;
|
||||
public isWindows = false;
|
||||
public isFireFox = false;
|
||||
public isMobile = false;
|
||||
public isChrome = false;
|
||||
public isIOS = false;
|
||||
|
||||
getChromeVersion = (): number => {
|
||||
const raw = this.navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./);
|
||||
assertExists(raw);
|
||||
return parseInt(raw[2], 10);
|
||||
};
|
||||
|
||||
constructor(private readonly navigator: Navigator) {
|
||||
this.uaMap = getUa(navigator);
|
||||
this.initUaFlags();
|
||||
}
|
||||
|
||||
public checkUseragent(isUseragent: keyof ReturnType<typeof getUa>) {
|
||||
return Boolean(this.uaMap[isUseragent]);
|
||||
}
|
||||
|
||||
private initUaFlags() {
|
||||
this.isLinux = this.checkUseragent('linux');
|
||||
this.isMacOs = this.checkUseragent('mac');
|
||||
this.isSafari = this.checkUseragent('safari');
|
||||
this.isWindows = this.checkUseragent('win');
|
||||
this.isFireFox = this.checkUseragent('firefox');
|
||||
this.isMobile = this.checkUseragent('mobile');
|
||||
this.isChrome = this.checkUseragent('chrome');
|
||||
this.isIOS = this.checkUseragent('ios');
|
||||
}
|
||||
}
|
||||
|
||||
const getUa = (navigator: Navigator) => {
|
||||
const ua = navigator.userAgent;
|
||||
const uas = ua.toLowerCase();
|
||||
const mobile = /iPhone|iPad|iPod|Android/i.test(ua);
|
||||
const android =
|
||||
(mobile && (uas.indexOf('android') > -1 || uas.indexOf('linux') > -1)) ||
|
||||
uas.indexOf('adr') > -1;
|
||||
const ios = mobile && !android && /Mac OS/i.test(ua);
|
||||
const mac = !mobile && /Mac OS/i.test(ua);
|
||||
const iphone = ios && uas.indexOf('iphone') > -1;
|
||||
const ipad = ios && !iphone;
|
||||
const wx = /MicroMessenger/i.test(ua);
|
||||
const chrome = /CriOS/i.test(ua) || /Chrome/i.test(ua);
|
||||
const tiktok = mobile && /aweme/i.test(ua);
|
||||
const weibo = mobile && /Weibo/i.test(ua);
|
||||
const safari =
|
||||
ios && !chrome && !wx && !weibo && !tiktok && /Safari|Macintosh/i.test(ua);
|
||||
const firefox = /Firefox/.test(ua);
|
||||
const win = /windows|win32|win64|wow32|wow64/.test(uas);
|
||||
const linux = /linux/.test(uas);
|
||||
return {
|
||||
ua,
|
||||
mobile,
|
||||
android,
|
||||
ios,
|
||||
mac,
|
||||
wx,
|
||||
chrome,
|
||||
iphone,
|
||||
ipad,
|
||||
safari,
|
||||
tiktok,
|
||||
weibo,
|
||||
win,
|
||||
linux,
|
||||
firefox,
|
||||
};
|
||||
};
|
||||
Vendored
+208
@@ -0,0 +1,208 @@
|
||||
import type { EditorContainer } from '@blocksuite/editor';
|
||||
import type { Page } from '@blocksuite/store';
|
||||
import type {
|
||||
ActiveDocProvider,
|
||||
PassiveDocProvider,
|
||||
Workspace as BlockSuiteWorkspace,
|
||||
} from '@blocksuite/store';
|
||||
import type { PropsWithChildren, ReactNode } from 'react';
|
||||
import type { DataSourceAdapter } from 'y-provider';
|
||||
|
||||
import type { Collection } from './filter.js';
|
||||
|
||||
export enum WorkspaceSubPath {
|
||||
ALL = 'all',
|
||||
SETTING = 'setting',
|
||||
TRASH = 'trash',
|
||||
SHARED = 'shared',
|
||||
}
|
||||
|
||||
export interface AffineDownloadProvider extends PassiveDocProvider {
|
||||
flavour: 'affine-download';
|
||||
}
|
||||
|
||||
/**
|
||||
* Download the first binary from local IndexedDB
|
||||
*/
|
||||
export interface BroadCastChannelProvider extends PassiveDocProvider {
|
||||
flavour: 'broadcast-channel';
|
||||
}
|
||||
|
||||
/**
|
||||
* Long polling provider with local IndexedDB
|
||||
*/
|
||||
export interface LocalIndexedDBBackgroundProvider
|
||||
extends DataSourceAdapter,
|
||||
PassiveDocProvider {
|
||||
flavour: 'local-indexeddb-background';
|
||||
}
|
||||
|
||||
export interface LocalIndexedDBDownloadProvider extends ActiveDocProvider {
|
||||
flavour: 'local-indexeddb';
|
||||
}
|
||||
|
||||
export interface SQLiteProvider extends PassiveDocProvider, DataSourceAdapter {
|
||||
flavour: 'sqlite';
|
||||
}
|
||||
|
||||
export interface SQLiteDBDownloadProvider extends ActiveDocProvider {
|
||||
flavour: 'sqlite-download';
|
||||
}
|
||||
|
||||
export interface AffineSocketIOProvider
|
||||
extends PassiveDocProvider,
|
||||
DataSourceAdapter {
|
||||
flavour: 'affine-socket-io';
|
||||
}
|
||||
|
||||
type BaseWorkspace = {
|
||||
flavour: string;
|
||||
id: string;
|
||||
blockSuiteWorkspace: BlockSuiteWorkspace;
|
||||
};
|
||||
|
||||
export interface AffineCloudWorkspace extends BaseWorkspace {
|
||||
flavour: WorkspaceFlavour.AFFINE_CLOUD;
|
||||
id: string;
|
||||
blockSuiteWorkspace: BlockSuiteWorkspace;
|
||||
}
|
||||
|
||||
export interface LocalWorkspace extends BaseWorkspace {
|
||||
flavour: WorkspaceFlavour.LOCAL;
|
||||
id: string;
|
||||
blockSuiteWorkspace: BlockSuiteWorkspace;
|
||||
}
|
||||
|
||||
export interface AffinePublicWorkspace extends BaseWorkspace {
|
||||
flavour: WorkspaceFlavour.AFFINE_PUBLIC;
|
||||
id: string;
|
||||
blockSuiteWorkspace: BlockSuiteWorkspace;
|
||||
}
|
||||
|
||||
export type AffineOfficialWorkspace =
|
||||
| AffineCloudWorkspace
|
||||
| LocalWorkspace
|
||||
| AffinePublicWorkspace;
|
||||
|
||||
export enum ReleaseType {
|
||||
// if workspace is not released yet, we will not show it in the workspace list
|
||||
UNRELEASED = 'unreleased',
|
||||
STABLE = 'stable',
|
||||
}
|
||||
|
||||
export enum LoadPriority {
|
||||
HIGH = 1,
|
||||
MEDIUM = 2,
|
||||
LOW = 3,
|
||||
}
|
||||
|
||||
export enum WorkspaceFlavour {
|
||||
/**
|
||||
* New AFFiNE Cloud Workspace using Nest.js Server.
|
||||
*/
|
||||
AFFINE_CLOUD = 'affine-cloud',
|
||||
LOCAL = 'local',
|
||||
AFFINE_PUBLIC = 'affine-public',
|
||||
}
|
||||
|
||||
export const settingPanel = {
|
||||
General: 'general',
|
||||
Collaboration: 'collaboration',
|
||||
Publish: 'publish',
|
||||
Export: 'export',
|
||||
Sync: 'sync',
|
||||
} as const;
|
||||
export const settingPanelValues = [...Object.values(settingPanel)] as const;
|
||||
export type SettingPanel = (typeof settingPanel)[keyof typeof settingPanel];
|
||||
|
||||
// built-in workspaces
|
||||
export interface WorkspaceRegistry {
|
||||
[WorkspaceFlavour.LOCAL]: LocalWorkspace;
|
||||
[WorkspaceFlavour.AFFINE_PUBLIC]: AffinePublicWorkspace;
|
||||
[WorkspaceFlavour.AFFINE_CLOUD]: AffineCloudWorkspace;
|
||||
}
|
||||
|
||||
export interface WorkspaceCRUD<Flavour extends keyof WorkspaceRegistry> {
|
||||
create: (blockSuiteWorkspace: BlockSuiteWorkspace) => Promise<string>;
|
||||
delete: (blockSuiteWorkspace: BlockSuiteWorkspace) => Promise<void>;
|
||||
get: (workspaceId: string) => Promise<WorkspaceRegistry[Flavour] | null>;
|
||||
// not supported yet
|
||||
// update: (workspace: FlavourToWorkspace[Flavour]) => Promise<void>;
|
||||
list: () => Promise<WorkspaceRegistry[Flavour][]>;
|
||||
}
|
||||
|
||||
type UIBaseProps<_Flavour extends keyof WorkspaceRegistry> = {
|
||||
currentWorkspaceId: string;
|
||||
};
|
||||
|
||||
export type WorkspaceHeaderProps<Flavour extends keyof WorkspaceRegistry> =
|
||||
UIBaseProps<Flavour> & {
|
||||
currentEntry:
|
||||
| {
|
||||
subPath: WorkspaceSubPath;
|
||||
}
|
||||
| {
|
||||
pageId: string;
|
||||
};
|
||||
};
|
||||
|
||||
type NewSettingProps<Flavour extends keyof WorkspaceRegistry> =
|
||||
UIBaseProps<Flavour> & {
|
||||
onDeleteLocalWorkspace: () => void;
|
||||
onDeleteCloudWorkspace: () => void;
|
||||
onLeaveWorkspace: () => void;
|
||||
onTransformWorkspace: <
|
||||
From extends keyof WorkspaceRegistry,
|
||||
To extends keyof WorkspaceRegistry,
|
||||
>(
|
||||
from: From,
|
||||
to: To,
|
||||
workspace: WorkspaceRegistry[From]
|
||||
) => void;
|
||||
};
|
||||
|
||||
type PageDetailProps<Flavour extends keyof WorkspaceRegistry> =
|
||||
UIBaseProps<Flavour> & {
|
||||
currentPageId: string;
|
||||
onLoadEditor: (page: Page, editor: EditorContainer) => () => void;
|
||||
};
|
||||
|
||||
type PageListProps<_Flavour extends keyof WorkspaceRegistry> = {
|
||||
blockSuiteWorkspace: BlockSuiteWorkspace;
|
||||
onOpenPage: (pageId: string, newTab?: boolean) => void;
|
||||
collection: Collection;
|
||||
};
|
||||
|
||||
interface FC<P> {
|
||||
(props: P): ReactNode;
|
||||
}
|
||||
|
||||
export interface WorkspaceUISchema<Flavour extends keyof WorkspaceRegistry> {
|
||||
Header: FC<WorkspaceHeaderProps<Flavour>>;
|
||||
PageDetail: FC<PageDetailProps<Flavour>>;
|
||||
PageList: FC<PageListProps<Flavour>>;
|
||||
NewSettingsDetail: FC<NewSettingProps<Flavour>>;
|
||||
Provider: FC<PropsWithChildren>;
|
||||
LoginCard?: FC<object>;
|
||||
}
|
||||
|
||||
export interface AppEvents {
|
||||
// event there is no workspace
|
||||
// usually used to initialize workspace adapter
|
||||
'app:init': () => string[];
|
||||
// event if you have access to workspace adapter
|
||||
'app:access': () => Promise<boolean>;
|
||||
'service:start': () => void;
|
||||
'service:stop': () => void;
|
||||
}
|
||||
|
||||
export interface WorkspaceAdapter<Flavour extends WorkspaceFlavour> {
|
||||
releaseType: ReleaseType;
|
||||
flavour: Flavour;
|
||||
// The Adapter will be loaded according to the priority
|
||||
loadPriority: LoadPriority;
|
||||
Events: Partial<AppEvents>;
|
||||
// Fetch necessary data for the first render
|
||||
CRUD: WorkspaceCRUD<Flavour>;
|
||||
UI: WorkspaceUISchema<Flavour>;
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
/**
|
||||
* @deprecated Remove this file after we migrate to the new cloud.
|
||||
*/
|
||||
import { z } from 'zod';
|
||||
|
||||
export interface User {
|
||||
id: string;
|
||||
name: string;
|
||||
email: string;
|
||||
avatar_url: string;
|
||||
create_at: string;
|
||||
}
|
||||
|
||||
export interface GetUserByEmailParams {
|
||||
email: string;
|
||||
workspace_id: string;
|
||||
}
|
||||
|
||||
export const usageResponseSchema = z.object({
|
||||
blob_usage: z.object({
|
||||
usage: z.number(),
|
||||
max_usage: z.number(),
|
||||
}),
|
||||
});
|
||||
|
||||
export type UsageResponse = z.infer<typeof usageResponseSchema>;
|
||||
|
||||
export interface GetWorkspaceDetailParams {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export enum WorkspaceType {
|
||||
Private = 0,
|
||||
Normal = 1,
|
||||
}
|
||||
|
||||
export enum PermissionType {
|
||||
Read = 0,
|
||||
Write = 1,
|
||||
Admin = 10,
|
||||
Owner = 99,
|
||||
}
|
||||
|
||||
export const userSchema = z.object({
|
||||
id: z.string(),
|
||||
name: z.string(),
|
||||
email: z.string(),
|
||||
avatar_url: z.string(),
|
||||
created_at: z.number(),
|
||||
});
|
||||
|
||||
export const workspaceSchema = z.object({
|
||||
id: z.string(),
|
||||
type: z.nativeEnum(WorkspaceType),
|
||||
public: z.boolean(),
|
||||
permission: z.nativeEnum(PermissionType),
|
||||
});
|
||||
|
||||
export type Workspace = z.infer<typeof workspaceSchema>;
|
||||
|
||||
export const workspaceDetailSchema = z.object({
|
||||
...workspaceSchema.shape,
|
||||
permission: z.undefined(),
|
||||
owner: userSchema,
|
||||
member_count: z.number(),
|
||||
});
|
||||
|
||||
export type WorkspaceDetail = z.infer<typeof workspaceDetailSchema>;
|
||||
|
||||
export interface Permission {
|
||||
id: string;
|
||||
type: PermissionType;
|
||||
workspace_id: string;
|
||||
user_id: string;
|
||||
user_email: string;
|
||||
accepted: boolean;
|
||||
create_at: number;
|
||||
}
|
||||
|
||||
export interface RegisteredUser extends User {
|
||||
type: 'Registered';
|
||||
}
|
||||
|
||||
export interface UnregisteredUser {
|
||||
type: 'Unregistered';
|
||||
email: string;
|
||||
}
|
||||
|
||||
export interface Member extends Permission {
|
||||
user: RegisteredUser | UnregisteredUser;
|
||||
}
|
||||
|
||||
export interface GetWorkspaceMembersParams {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface CreateWorkspaceParams {
|
||||
name: string;
|
||||
}
|
||||
|
||||
export interface UpdateWorkspaceParams {
|
||||
id: string;
|
||||
public: boolean;
|
||||
}
|
||||
|
||||
export interface DeleteWorkspaceParams {
|
||||
id: string;
|
||||
}
|
||||
|
||||
export interface InviteMemberParams {
|
||||
id: string;
|
||||
email: string;
|
||||
}
|
||||
|
||||
export interface RemoveMemberParams {
|
||||
permissionId: number;
|
||||
}
|
||||
|
||||
export interface AcceptInvitingParams {
|
||||
invitingCode: string;
|
||||
}
|
||||
|
||||
export interface LeaveWorkspaceParams {
|
||||
id: number | string;
|
||||
}
|
||||
|
||||
export const createWorkspaceResponseSchema = z.object({
|
||||
id: z.string(),
|
||||
public: z.boolean(),
|
||||
type: z.nativeEnum(WorkspaceType),
|
||||
created_at: z.number(),
|
||||
});
|
||||
Reference in New Issue
Block a user