Merge pull request #935 from toeverything/feat/client-app
feat: tauri desktop client app
This commit is contained in:
@@ -43,6 +43,7 @@ export const EditorHeader = () => {
|
||||
>
|
||||
{title && (
|
||||
<StyledTitle
|
||||
data-tauri-drag-region
|
||||
onMouseEnter={() => {
|
||||
if (isTrash) return;
|
||||
|
||||
|
||||
@@ -56,7 +56,11 @@ export const Header = ({
|
||||
setShowWarning(false);
|
||||
}}
|
||||
/>
|
||||
<StyledHeader hasWarning={showWarning} data-testid="editor-header-items">
|
||||
<StyledHeader
|
||||
hasWarning={showWarning}
|
||||
data-testid="editor-header-items"
|
||||
data-tauri-drag-region
|
||||
>
|
||||
{children}
|
||||
<StyledHeaderRightSide>
|
||||
{rightItems.map(itemName => {
|
||||
|
||||
@@ -79,7 +79,7 @@ const AppDefender = ({ children }: PropsWithChildren) => {
|
||||
const { synced } = useAppState();
|
||||
|
||||
useEffect(() => {
|
||||
if (router.asPath === '/') {
|
||||
if (['/index.html', '/'].includes(router.asPath)) {
|
||||
router.replace('/workspace');
|
||||
}
|
||||
}, [router]);
|
||||
|
||||
@@ -32,7 +32,9 @@ export const AppStateProvider = ({
|
||||
if (dataCenter.workspaces.length === 0) {
|
||||
await createDefaultWorkspace(dataCenter);
|
||||
}
|
||||
setUser((await dataCenter.getUserInfo()) || null);
|
||||
setUser(
|
||||
(await dataCenter.getUserInfo(dataCenter.providers[0]?.id)) || null
|
||||
);
|
||||
setAppState({
|
||||
dataCenter,
|
||||
workspaceList: dataCenter.workspaces,
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
"dependencies": {
|
||||
"@blocksuite/blocks": "0.4.0-20230210031655-264744e",
|
||||
"@blocksuite/store": "0.4.0-20230210031655-264744e",
|
||||
"@tauri-apps/api": "^1.2.0",
|
||||
"debug": "^4.3.4",
|
||||
"encoding": "^0.1.13",
|
||||
"firebase": "^9.15.0",
|
||||
|
||||
@@ -46,7 +46,16 @@ export class DataCenter {
|
||||
};
|
||||
};
|
||||
// TODO: switch different provider
|
||||
await dc.registerProvider(new LocalProvider(getInitParams()));
|
||||
if (
|
||||
typeof window !== 'undefined' &&
|
||||
window.CLIENT_APP &&
|
||||
typeof window.__TAURI_IPC__ === 'function'
|
||||
) {
|
||||
const { TauriIPCProvider } = await import('./provider/tauri-ipc');
|
||||
await dc.registerProvider(new TauriIPCProvider(getInitParams()));
|
||||
} else {
|
||||
await dc.registerProvider(new LocalProvider(getInitParams()));
|
||||
}
|
||||
await dc.registerProvider(new AffineProvider(getInitParams()));
|
||||
|
||||
for (const provider of dc.providerMap.values()) {
|
||||
|
||||
8
packages/data-center/src/global-types.ts
Normal file
8
packages/data-center/src/global-types.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
declare global {
|
||||
interface Window {
|
||||
CLIENT_APP?: boolean;
|
||||
__editoVersion?: string;
|
||||
}
|
||||
}
|
||||
|
||||
export {};
|
||||
@@ -27,7 +27,7 @@ export enum WorkspaceType {
|
||||
export enum PermissionType {
|
||||
Read = 0,
|
||||
Write = 1,
|
||||
Admin = 2,
|
||||
Admin = 10,
|
||||
Owner = 99,
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import { PutBlob, GetBlob } from '../ipc/types/blob';
|
||||
import {
|
||||
YDocumentUpdate,
|
||||
GetDocumentParameter,
|
||||
GetDocumentResponse,
|
||||
} from '../ipc/types/document';
|
||||
import { CreateUser, GetUserParameters, User } from '../ipc/types/user';
|
||||
import {
|
||||
CreateWorkspace,
|
||||
CreateWorkspaceResult,
|
||||
GetWorkspaces,
|
||||
GetWorkspacesResult,
|
||||
GetWorkspace,
|
||||
GetWorkspaceResult,
|
||||
} from '../ipc/types/workspace';
|
||||
|
||||
export const updateYDocument = async (parameters: YDocumentUpdate) =>
|
||||
await true;
|
||||
|
||||
export const getYDocument = async (
|
||||
parameters: GetDocumentParameter
|
||||
): Promise<GetDocumentResponse> =>
|
||||
await {
|
||||
updates: [],
|
||||
};
|
||||
|
||||
export const createWorkspace = async (
|
||||
parameters: CreateWorkspace
|
||||
): Promise<CreateWorkspaceResult> => await { id: 'xxx', name: 'xxx' };
|
||||
|
||||
export const getWorkspaces = async (
|
||||
parameters: GetWorkspaces
|
||||
): Promise<GetWorkspacesResult> =>
|
||||
await {
|
||||
workspaces: [],
|
||||
};
|
||||
|
||||
export const getWorkspace = async (
|
||||
parameters: GetWorkspace
|
||||
): Promise<GetWorkspaceResult> =>
|
||||
await {
|
||||
workspace: {
|
||||
created_at: 0,
|
||||
id: '',
|
||||
member_count: 1,
|
||||
public: true,
|
||||
type: 0,
|
||||
},
|
||||
};
|
||||
|
||||
export const putBlob = async (parameters: PutBlob): Promise<string> =>
|
||||
await 'path/xxx';
|
||||
|
||||
export const getBlob = async (parameters: GetBlob): Promise<number[]> =>
|
||||
await [];
|
||||
|
||||
/**
|
||||
* This will create a private workspace too.
|
||||
* @returns
|
||||
*/
|
||||
export const createUser = async (parameters: CreateUser): Promise<User> =>
|
||||
await {
|
||||
created_at: 0,
|
||||
id: '1',
|
||||
email: 'xxx@xxx.xxx',
|
||||
name: 'xxx',
|
||||
};
|
||||
|
||||
export const getUser = async (parameters: GetUserParameters): Promise<User> =>
|
||||
await {
|
||||
created_at: 0,
|
||||
id: '1',
|
||||
email: 'xxx@xxx.xxx',
|
||||
name: 'xxx',
|
||||
};
|
||||
@@ -0,0 +1,54 @@
|
||||
import { test, expect } from '@playwright/test';
|
||||
import { WorkspaceUnitCollection } from '../../../workspace-unit-collection.js';
|
||||
import { TauriIPCProvider } from '../index.js';
|
||||
import { MessageCenter } from '../../../message/index.js';
|
||||
import * as ipcMethods from './mock-apis.js';
|
||||
|
||||
import 'fake-indexeddb/auto';
|
||||
|
||||
test.describe.serial('tauri-ipc provider', async () => {
|
||||
const workspaceMetaCollection = new WorkspaceUnitCollection();
|
||||
const provider = new TauriIPCProvider({
|
||||
workspaces: workspaceMetaCollection.createScope(),
|
||||
messageCenter: new MessageCenter(),
|
||||
});
|
||||
provider.init(ipcMethods);
|
||||
|
||||
const workspaceName = 'workspace-test';
|
||||
let workspaceId: string | undefined;
|
||||
|
||||
test('create workspace', async () => {
|
||||
const workspaceUnit = await provider.createWorkspace({
|
||||
name: workspaceName,
|
||||
});
|
||||
workspaceId = workspaceUnit?.id;
|
||||
|
||||
expect(workspaceMetaCollection.workspaces.length).toEqual(1);
|
||||
expect(workspaceMetaCollection.workspaces[0].name).toEqual(workspaceName);
|
||||
});
|
||||
|
||||
test('workspace list', async () => {
|
||||
const workspacesMetaCollection1 = new WorkspaceUnitCollection();
|
||||
const provider1 = new TauriIPCProvider({
|
||||
workspaces: workspacesMetaCollection1.createScope(),
|
||||
messageCenter: new MessageCenter(),
|
||||
});
|
||||
provider1.init(ipcMethods);
|
||||
|
||||
await provider1.getUserInfo();
|
||||
await provider1.loadWorkspaces();
|
||||
expect(workspacesMetaCollection1.workspaces.length).toEqual(0);
|
||||
await provider1.createWorkspace({
|
||||
name: workspaceName,
|
||||
});
|
||||
expect(workspacesMetaCollection1.workspaces[0].name).toEqual(workspaceName);
|
||||
expect(workspacesMetaCollection1.workspaces[0].id).toEqual(workspaceId);
|
||||
});
|
||||
|
||||
test('update workspace', async () => {
|
||||
await provider.updateWorkspaceMeta(workspaceId!, {
|
||||
name: '1111',
|
||||
});
|
||||
expect(workspaceMetaCollection.workspaces[0].name).toEqual('1111');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,70 @@
|
||||
import { BlobSyncState } from '@blocksuite/store';
|
||||
import * as ipcMethods from '../ipc/methods.js';
|
||||
import { Signal } from '@blocksuite/store';
|
||||
import type {
|
||||
BlobProvider,
|
||||
BlobSyncStateChangeEvent,
|
||||
BlobId,
|
||||
BlobURL,
|
||||
} from '@blocksuite/store/dist/persistence/blob/types.js';
|
||||
|
||||
export class IPCBlobProvider implements BlobProvider {
|
||||
#ipc = ipcMethods;
|
||||
|
||||
#workspace: string;
|
||||
|
||||
readonly signals = {
|
||||
onBlobSyncStateChange: new Signal<BlobSyncStateChangeEvent>(),
|
||||
};
|
||||
|
||||
private constructor(workspace: string) {
|
||||
this.#workspace = workspace;
|
||||
}
|
||||
|
||||
static async init(workspace: string): Promise<IPCBlobProvider> {
|
||||
const provider = new IPCBlobProvider(workspace);
|
||||
return provider;
|
||||
}
|
||||
|
||||
get uploading() {
|
||||
return false;
|
||||
}
|
||||
|
||||
get blobs() {
|
||||
// TODO: implement blob list in Octobase
|
||||
return Promise.resolve([]) as Promise<string[]>;
|
||||
}
|
||||
|
||||
async get(id: BlobId): Promise<BlobURL | null> {
|
||||
const blobArray = await this.#ipc.getBlob({
|
||||
id,
|
||||
});
|
||||
// Make a Blob from the bytes
|
||||
const blob = new Blob([new Uint8Array(blobArray)], { type: 'image/bmp' });
|
||||
this.signals.onBlobSyncStateChange.emit({
|
||||
id,
|
||||
state: BlobSyncState.Success,
|
||||
});
|
||||
return window.URL.createObjectURL(blob);
|
||||
}
|
||||
|
||||
async set(blob: Blob): Promise<BlobId> {
|
||||
// TODO: skip if already has
|
||||
const blobID = await this.#ipc.putBlob({
|
||||
blob: Array.from(new Uint8Array(await blob.arrayBuffer())),
|
||||
});
|
||||
this.signals.onBlobSyncStateChange.emit({
|
||||
id: blobID,
|
||||
state: BlobSyncState.Success,
|
||||
});
|
||||
return blobID;
|
||||
}
|
||||
|
||||
async delete(id: BlobId): Promise<void> {
|
||||
// TODO: implement blob delete in Octobase
|
||||
}
|
||||
|
||||
async clear(): Promise<void> {
|
||||
// TODO: implement blob clear in Octobase, use workspace id #workspace
|
||||
}
|
||||
}
|
||||
194
packages/data-center/src/provider/tauri-ipc/index.ts
Normal file
194
packages/data-center/src/provider/tauri-ipc/index.ts
Normal file
@@ -0,0 +1,194 @@
|
||||
import * as Y from 'yjs';
|
||||
import assert from 'assert';
|
||||
|
||||
import { LocalProvider } from '../local/index.js';
|
||||
import type { IPCMethodsType } from './ipc/methods.js';
|
||||
import {
|
||||
CreateWorkspaceInfoParams,
|
||||
ProviderConstructorParams,
|
||||
} from '../base.js';
|
||||
import { Workspace as BlocksuiteWorkspace } from '@blocksuite/store';
|
||||
import { IPCBlobProvider } from './blocksuite-provider/blob.js';
|
||||
import type { WorkspaceUnit } from 'src/workspace-unit.js';
|
||||
import { createWorkspaceUnit, loadWorkspaceUnit } from '../local/utils.js';
|
||||
import { WorkspaceWithPermission } from './ipc/types/workspace.js';
|
||||
import { applyUpdate } from '../../utils/index.js';
|
||||
import { User } from 'src/types/index.js';
|
||||
|
||||
/**
|
||||
* init - createUser - create first workspace and ydoc - loadWorkspace - return the first workspace - wrapWorkspace - #initDocFromIPC - applyUpdate - on('update') - updateYDocument
|
||||
*
|
||||
* (init - createUser - error) loadWorkspace - return the first workspace - wrapWorkspace - #initDocFromIPC - applyUpdate - on('update') - updateYDocument
|
||||
*/
|
||||
export class TauriIPCProvider extends LocalProvider {
|
||||
public id = 'tauri-ipc';
|
||||
static defaultUserEmail = 'xxx@xx.xx';
|
||||
/**
|
||||
* // TODO: We only have one user in this version of app client. But may support switch user later.
|
||||
*/
|
||||
#userID?: string;
|
||||
#ipc: IPCMethodsType | undefined;
|
||||
|
||||
constructor(params: ProviderConstructorParams) {
|
||||
super(params);
|
||||
}
|
||||
|
||||
async init(ipc?: IPCMethodsType) {
|
||||
if (ipc) {
|
||||
this.#ipc = ipc;
|
||||
} else {
|
||||
this.#ipc = await import('./ipc/methods.js');
|
||||
}
|
||||
try {
|
||||
const user = await this.#ipc?.getUser({
|
||||
email: TauriIPCProvider.defaultUserEmail,
|
||||
});
|
||||
this.#userID = user.id;
|
||||
} catch (error) {
|
||||
// maybe user not existed, we create a default user if we don't have one.
|
||||
try {
|
||||
const user = await this.#ipc?.createUser({
|
||||
email: TauriIPCProvider.defaultUserEmail,
|
||||
name: 'xxx',
|
||||
password: 'xxx',
|
||||
avatar_url: '',
|
||||
});
|
||||
this.#userID = user.id;
|
||||
} catch (error) {
|
||||
// maybe user existed, which can be omited
|
||||
console.error(error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* get auth user info
|
||||
* @returns
|
||||
*/
|
||||
public async getUserInfo(): Promise<User | undefined> {
|
||||
const user = await this.#ipc?.getUser({
|
||||
email: TauriIPCProvider.defaultUserEmail,
|
||||
});
|
||||
if (user?.name !== undefined) {
|
||||
return {
|
||||
...user,
|
||||
avatar: user?.avatar_url || '',
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
async #initDocFromIPC(
|
||||
workspaceID: string,
|
||||
blocksuiteWorkspace: BlocksuiteWorkspace
|
||||
) {
|
||||
this._logger(`Loading ${workspaceID}...`);
|
||||
const result = await this.#ipc?.getYDocument({ id: workspaceID });
|
||||
if (result) {
|
||||
const updates = result.updates.map(
|
||||
binaryUpdate => new Uint8Array(binaryUpdate)
|
||||
);
|
||||
|
||||
const mergedUpdate = Y.mergeUpdates(updates);
|
||||
await applyUpdate(blocksuiteWorkspace, mergedUpdate);
|
||||
this._logger(`Loaded: ${workspaceID}`);
|
||||
}
|
||||
}
|
||||
|
||||
async #connectDocToIPC(
|
||||
workspaceID: string,
|
||||
blocksuiteWorkspace: BlocksuiteWorkspace
|
||||
) {
|
||||
this._logger(`Connecting yDoc for ${workspaceID}...`);
|
||||
blocksuiteWorkspace.doc.on('update', async (update: Uint8Array) => {
|
||||
try {
|
||||
const binary = Y.encodeStateAsUpdate(blocksuiteWorkspace.doc);
|
||||
const success = await this.#ipc?.updateYDocument({
|
||||
update: Array.from(binary),
|
||||
id: workspaceID,
|
||||
});
|
||||
if (!success) {
|
||||
throw new Error(`YDoc update failed, id: ${workspaceID}`);
|
||||
}
|
||||
} catch (error) {
|
||||
// TODO: write error log to disk, and add button to open them in settings panel
|
||||
console.error("#yDocument.on('update'", error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async clear() {
|
||||
await super.clear();
|
||||
}
|
||||
|
||||
override async warpWorkspace(blocksuiteWorkspace: BlocksuiteWorkspace) {
|
||||
const { room } = blocksuiteWorkspace;
|
||||
assert(room);
|
||||
|
||||
(await blocksuiteWorkspace.blobs)?.setProvider(
|
||||
await IPCBlobProvider.init(room)
|
||||
);
|
||||
await this.#initDocFromIPC(room, blocksuiteWorkspace);
|
||||
await this.#connectDocToIPC(room, blocksuiteWorkspace);
|
||||
|
||||
return blocksuiteWorkspace;
|
||||
}
|
||||
|
||||
public override async createWorkspace(
|
||||
meta: CreateWorkspaceInfoParams
|
||||
): Promise<WorkspaceUnit | undefined> {
|
||||
this._logger('Creating client app workspace');
|
||||
assert(this.#ipc);
|
||||
assert(this.#userID);
|
||||
const { id } = await this.#ipc.createWorkspace({
|
||||
name: meta.name,
|
||||
// TODO: get userID here
|
||||
user_id: this.#userID,
|
||||
});
|
||||
|
||||
const workspaceUnit = await createWorkspaceUnit({
|
||||
name: meta.name,
|
||||
id,
|
||||
published: false,
|
||||
avatar: '',
|
||||
owner: undefined,
|
||||
syncMode: 'core',
|
||||
memberCount: 1,
|
||||
provider: this.id,
|
||||
});
|
||||
this._workspaces.add(workspaceUnit);
|
||||
const doc = workspaceUnit?.blocksuiteWorkspace?.doc;
|
||||
if (doc) {
|
||||
const update = Y.encodeStateAsUpdate(doc);
|
||||
const success = await this.#ipc?.updateYDocument({
|
||||
update: Array.from(update),
|
||||
id,
|
||||
});
|
||||
if (!success) {
|
||||
throw new Error(`YDoc update failed, id: ${id}`);
|
||||
}
|
||||
}
|
||||
return workspaceUnit;
|
||||
}
|
||||
|
||||
override async loadWorkspaces(): Promise<WorkspaceUnit[]> {
|
||||
assert(this.#ipc);
|
||||
assert(this.#userID);
|
||||
const { workspaces } = await this.#ipc.getWorkspaces({
|
||||
user_id: this.#userID,
|
||||
});
|
||||
const workspaceUnits = await Promise.all(
|
||||
workspaces.map((meta: WorkspaceWithPermission) => {
|
||||
return loadWorkspaceUnit({
|
||||
...meta,
|
||||
memberCount: 1,
|
||||
// TODO: load name here
|
||||
name: '',
|
||||
provider: this.id,
|
||||
syncMode: 'all',
|
||||
});
|
||||
})
|
||||
);
|
||||
this._workspaces.add(workspaceUnits);
|
||||
return workspaceUnits;
|
||||
}
|
||||
}
|
||||
78
packages/data-center/src/provider/tauri-ipc/ipc/methods.ts
Normal file
78
packages/data-center/src/provider/tauri-ipc/ipc/methods.ts
Normal file
@@ -0,0 +1,78 @@
|
||||
import { invoke } from '@tauri-apps/api';
|
||||
import {
|
||||
GetDocumentParameter,
|
||||
GetDocumentResponse,
|
||||
YDocumentUpdate,
|
||||
} from './types/document';
|
||||
import {
|
||||
CreateWorkspace,
|
||||
CreateWorkspaceResult,
|
||||
GetWorkspace,
|
||||
GetWorkspaceResult,
|
||||
GetWorkspaces,
|
||||
GetWorkspacesResult,
|
||||
User,
|
||||
} from './types/workspace';
|
||||
import { GetBlob, PutBlob } from './types/blob';
|
||||
import { CreateUser, GetUserParameters } from './types/user';
|
||||
|
||||
export interface IPCMethodsType {
|
||||
updateYDocument: typeof updateYDocument;
|
||||
getYDocument: typeof getYDocument;
|
||||
createWorkspace: typeof createWorkspace;
|
||||
getWorkspaces: typeof getWorkspaces;
|
||||
getWorkspace: typeof getWorkspace;
|
||||
putBlob: typeof putBlob;
|
||||
getBlob: typeof getBlob;
|
||||
createUser: typeof createUser;
|
||||
getUser: typeof getUser;
|
||||
}
|
||||
|
||||
export const updateYDocument = async (parameters: YDocumentUpdate) =>
|
||||
await invoke<boolean>('update_y_document', {
|
||||
parameters,
|
||||
});
|
||||
|
||||
export const getYDocument = async (parameters: GetDocumentParameter) =>
|
||||
await invoke<GetDocumentResponse>('get_doc', {
|
||||
parameters,
|
||||
});
|
||||
|
||||
export const createWorkspace = async (parameters: CreateWorkspace) =>
|
||||
await invoke<CreateWorkspaceResult>('create_workspace', {
|
||||
parameters,
|
||||
});
|
||||
|
||||
export const getWorkspaces = async (parameters: GetWorkspaces) =>
|
||||
await invoke<GetWorkspacesResult>('get_workspaces', {
|
||||
parameters,
|
||||
});
|
||||
|
||||
export const getWorkspace = async (parameters: GetWorkspace) =>
|
||||
await invoke<GetWorkspaceResult>('get_workspace', {
|
||||
parameters,
|
||||
});
|
||||
|
||||
export const putBlob = async (parameters: PutBlob) =>
|
||||
await invoke<string>('put_blob', {
|
||||
parameters,
|
||||
});
|
||||
|
||||
export const getBlob = async (parameters: GetBlob) =>
|
||||
await invoke<number[]>('get_blob', {
|
||||
parameters,
|
||||
});
|
||||
|
||||
/**
|
||||
* This will create a private workspace too.
|
||||
* @returns
|
||||
*/
|
||||
export const createUser = async (parameters: CreateUser) =>
|
||||
await invoke<User>('create_user', {
|
||||
parameters,
|
||||
});
|
||||
|
||||
export const getUser = async (parameters: GetUserParameters) =>
|
||||
await invoke<User>('get_user', {
|
||||
parameters,
|
||||
});
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "IBlobParameters",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["Put"],
|
||||
"properties": {
|
||||
"Put": {
|
||||
"$ref": "#/definitions/PutBlob"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["Get"],
|
||||
"properties": {
|
||||
"Get": {
|
||||
"$ref": "#/definitions/GetBlob"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
],
|
||||
"definitions": {
|
||||
"GetBlob": {
|
||||
"type": "object",
|
||||
"required": ["id"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"workspace_id": {
|
||||
"type": ["string", "null"]
|
||||
}
|
||||
}
|
||||
},
|
||||
"PutBlob": {
|
||||
"type": "object",
|
||||
"required": ["blob"],
|
||||
"properties": {
|
||||
"blob": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "uint8",
|
||||
"minimum": 0.0
|
||||
}
|
||||
},
|
||||
"workspace_id": {
|
||||
"type": ["string", "null"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/**
|
||||
* This file was automatically generated by json-schema-to-typescript.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
||||
* and run json-schema-to-typescript to regenerate this file.
|
||||
*/
|
||||
|
||||
export type IBlobParameters =
|
||||
| {
|
||||
Put: PutBlob;
|
||||
}
|
||||
| {
|
||||
Get: GetBlob;
|
||||
};
|
||||
|
||||
export interface PutBlob {
|
||||
blob: number[];
|
||||
workspace_id?: string | null;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
export interface GetBlob {
|
||||
id: string;
|
||||
workspace_id?: string | null;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "IDocumentParameters",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["YDocumentUpdate"],
|
||||
"properties": {
|
||||
"YDocumentUpdate": {
|
||||
"$ref": "#/definitions/YDocumentUpdate"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["CreateDocumentParameter"],
|
||||
"properties": {
|
||||
"CreateDocumentParameter": {
|
||||
"$ref": "#/definitions/CreateDocumentParameter"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["GetDocumentParameter"],
|
||||
"properties": {
|
||||
"GetDocumentParameter": {
|
||||
"$ref": "#/definitions/GetDocumentParameter"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["GetDocumentResponse"],
|
||||
"properties": {
|
||||
"GetDocumentResponse": {
|
||||
"$ref": "#/definitions/GetDocumentResponse"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
],
|
||||
"definitions": {
|
||||
"CreateDocumentParameter": {
|
||||
"type": "object",
|
||||
"required": ["workspace_id", "workspace_name"],
|
||||
"properties": {
|
||||
"workspace_id": {
|
||||
"type": "string"
|
||||
},
|
||||
"workspace_name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"GetDocumentParameter": {
|
||||
"type": "object",
|
||||
"required": ["id"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"GetDocumentResponse": {
|
||||
"type": "object",
|
||||
"required": ["updates"],
|
||||
"properties": {
|
||||
"updates": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "uint8",
|
||||
"minimum": 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"YDocumentUpdate": {
|
||||
"type": "object",
|
||||
"required": ["id", "update"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"update": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "integer",
|
||||
"format": "uint8",
|
||||
"minimum": 0.0
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/**
|
||||
* This file was automatically generated by json-schema-to-typescript.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
||||
* and run json-schema-to-typescript to regenerate this file.
|
||||
*/
|
||||
|
||||
export type IDocumentParameters =
|
||||
| {
|
||||
YDocumentUpdate: YDocumentUpdate;
|
||||
}
|
||||
| {
|
||||
CreateDocumentParameter: CreateDocumentParameter;
|
||||
}
|
||||
| {
|
||||
GetDocumentParameter: GetDocumentParameter;
|
||||
}
|
||||
| {
|
||||
GetDocumentResponse: GetDocumentResponse;
|
||||
};
|
||||
|
||||
export interface YDocumentUpdate {
|
||||
id: string;
|
||||
update: number[];
|
||||
[k: string]: unknown;
|
||||
}
|
||||
export interface CreateDocumentParameter {
|
||||
workspace_id: string;
|
||||
workspace_name: string;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
export interface GetDocumentParameter {
|
||||
id: string;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
export interface GetDocumentResponse {
|
||||
updates: number[][];
|
||||
[k: string]: unknown;
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "IUserParameters",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["CreateUser"],
|
||||
"properties": {
|
||||
"CreateUser": {
|
||||
"$ref": "#/definitions/CreateUser"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["User"],
|
||||
"properties": {
|
||||
"User": {
|
||||
"$ref": "#/definitions/User"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["GetUserParameters"],
|
||||
"properties": {
|
||||
"GetUserParameters": {
|
||||
"$ref": "#/definitions/GetUserParameters"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
],
|
||||
"definitions": {
|
||||
"CreateUser": {
|
||||
"type": "object",
|
||||
"required": ["email", "name", "password"],
|
||||
"properties": {
|
||||
"avatar_url": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
},
|
||||
"password": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"GetUserParameters": {
|
||||
"type": "object",
|
||||
"required": ["email"],
|
||||
"properties": {
|
||||
"email": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"User": {
|
||||
"type": "object",
|
||||
"required": ["created_at", "email", "id", "name"],
|
||||
"properties": {
|
||||
"avatar_url": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"created_at": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/**
|
||||
* This file was automatically generated by json-schema-to-typescript.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
||||
* and run json-schema-to-typescript to regenerate this file.
|
||||
*/
|
||||
|
||||
export type IUserParameters =
|
||||
| {
|
||||
CreateUser: CreateUser;
|
||||
}
|
||||
| {
|
||||
User: User;
|
||||
}
|
||||
| {
|
||||
GetUserParameters: GetUserParameters;
|
||||
};
|
||||
|
||||
export interface CreateUser {
|
||||
avatar_url?: string | null;
|
||||
email: string;
|
||||
name: string;
|
||||
password: string;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
export interface User {
|
||||
avatar_url?: string | null;
|
||||
created_at: number;
|
||||
email: string;
|
||||
id: string;
|
||||
name: string;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
export interface GetUserParameters {
|
||||
email: string;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
@@ -0,0 +1,240 @@
|
||||
{
|
||||
"$schema": "http://json-schema.org/draft-07/schema#",
|
||||
"title": "IWorkspaceParameters",
|
||||
"oneOf": [
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["CreateWorkspace"],
|
||||
"properties": {
|
||||
"CreateWorkspace": {
|
||||
"$ref": "#/definitions/CreateWorkspace"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["GetWorkspace"],
|
||||
"properties": {
|
||||
"GetWorkspace": {
|
||||
"$ref": "#/definitions/GetWorkspace"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["GetWorkspaces"],
|
||||
"properties": {
|
||||
"GetWorkspaces": {
|
||||
"$ref": "#/definitions/GetWorkspaces"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["GetWorkspaceResult"],
|
||||
"properties": {
|
||||
"GetWorkspaceResult": {
|
||||
"$ref": "#/definitions/GetWorkspaceResult"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["GetWorkspacesResult"],
|
||||
"properties": {
|
||||
"GetWorkspacesResult": {
|
||||
"$ref": "#/definitions/GetWorkspacesResult"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["UpdateWorkspace"],
|
||||
"properties": {
|
||||
"UpdateWorkspace": {
|
||||
"$ref": "#/definitions/UpdateWorkspace"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
},
|
||||
{
|
||||
"type": "object",
|
||||
"required": ["CreateWorkspaceResult"],
|
||||
"properties": {
|
||||
"CreateWorkspaceResult": {
|
||||
"$ref": "#/definitions/CreateWorkspaceResult"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
],
|
||||
"definitions": {
|
||||
"CreateWorkspace": {
|
||||
"type": "object",
|
||||
"required": ["name", "user_id"],
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "only set name, avatar is update in datacenter to yDoc directly",
|
||||
"type": "string"
|
||||
},
|
||||
"user_id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"CreateWorkspaceResult": {
|
||||
"type": "object",
|
||||
"required": ["id", "name"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"GetWorkspace": {
|
||||
"type": "object",
|
||||
"required": ["id"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"GetWorkspaceResult": {
|
||||
"type": "object",
|
||||
"required": ["workspace"],
|
||||
"properties": {
|
||||
"workspace": {
|
||||
"$ref": "#/definitions/WorkspaceDetail"
|
||||
}
|
||||
}
|
||||
},
|
||||
"GetWorkspaces": {
|
||||
"type": "object",
|
||||
"required": ["user_id"],
|
||||
"properties": {
|
||||
"user_id": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"GetWorkspacesResult": {
|
||||
"type": "object",
|
||||
"required": ["workspaces"],
|
||||
"properties": {
|
||||
"workspaces": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/WorkspaceWithPermission"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"PermissionType": {
|
||||
"type": "integer",
|
||||
"enum": [0, 1, 10, 99]
|
||||
},
|
||||
"UpdateWorkspace": {
|
||||
"type": "object",
|
||||
"required": ["id", "public"],
|
||||
"properties": {
|
||||
"id": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"public": {
|
||||
"type": "boolean"
|
||||
}
|
||||
}
|
||||
},
|
||||
"User": {
|
||||
"type": "object",
|
||||
"required": ["created_at", "email", "id", "name"],
|
||||
"properties": {
|
||||
"avatar_url": {
|
||||
"type": ["string", "null"]
|
||||
},
|
||||
"created_at": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"email": {
|
||||
"type": "string"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"name": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"WorkspaceDetail": {
|
||||
"type": "object",
|
||||
"required": ["created_at", "id", "member_count", "public", "type"],
|
||||
"properties": {
|
||||
"created_at": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"member_count": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"owner": {
|
||||
"anyOf": [
|
||||
{
|
||||
"$ref": "#/definitions/User"
|
||||
},
|
||||
{
|
||||
"type": "null"
|
||||
}
|
||||
]
|
||||
},
|
||||
"public": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"$ref": "#/definitions/WorkspaceType"
|
||||
}
|
||||
}
|
||||
},
|
||||
"WorkspaceType": {
|
||||
"type": "integer",
|
||||
"enum": [0, 1]
|
||||
},
|
||||
"WorkspaceWithPermission": {
|
||||
"type": "object",
|
||||
"required": ["created_at", "id", "permission", "public", "type"],
|
||||
"properties": {
|
||||
"created_at": {
|
||||
"type": "integer",
|
||||
"format": "int64"
|
||||
},
|
||||
"id": {
|
||||
"type": "string"
|
||||
},
|
||||
"permission": {
|
||||
"$ref": "#/definitions/PermissionType"
|
||||
},
|
||||
"public": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"type": {
|
||||
"$ref": "#/definitions/WorkspaceType"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* This file was automatically generated by json-schema-to-typescript.
|
||||
* DO NOT MODIFY IT BY HAND. Instead, modify the source JSONSchema file,
|
||||
* and run json-schema-to-typescript to regenerate this file.
|
||||
*/
|
||||
|
||||
export type IWorkspaceParameters =
|
||||
| {
|
||||
CreateWorkspace: CreateWorkspace;
|
||||
}
|
||||
| {
|
||||
GetWorkspace: GetWorkspace;
|
||||
}
|
||||
| {
|
||||
GetWorkspaces: GetWorkspaces;
|
||||
}
|
||||
| {
|
||||
GetWorkspaceResult: GetWorkspaceResult;
|
||||
}
|
||||
| {
|
||||
GetWorkspacesResult: GetWorkspacesResult;
|
||||
}
|
||||
| {
|
||||
UpdateWorkspace: UpdateWorkspace;
|
||||
}
|
||||
| {
|
||||
CreateWorkspaceResult: CreateWorkspaceResult;
|
||||
};
|
||||
export type WorkspaceType = 0 | 1;
|
||||
export type PermissionType = 0 | 1 | 10 | 99;
|
||||
|
||||
export interface CreateWorkspace {
|
||||
/**
|
||||
* only set name, avatar is update in datacenter to yDoc directly
|
||||
*/
|
||||
name: string;
|
||||
user_id: string;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
export interface GetWorkspace {
|
||||
id: string;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
export interface GetWorkspaces {
|
||||
user_id: string;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
export interface GetWorkspaceResult {
|
||||
workspace: WorkspaceDetail;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
export interface WorkspaceDetail {
|
||||
created_at: number;
|
||||
id: string;
|
||||
member_count: number;
|
||||
owner?: User | null;
|
||||
public: boolean;
|
||||
type: WorkspaceType;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
export interface User {
|
||||
avatar_url?: string | null;
|
||||
created_at: number;
|
||||
email: string;
|
||||
id: string;
|
||||
name: string;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
export interface GetWorkspacesResult {
|
||||
workspaces: WorkspaceWithPermission[];
|
||||
[k: string]: unknown;
|
||||
}
|
||||
export interface WorkspaceWithPermission {
|
||||
created_at: number;
|
||||
id: string;
|
||||
permission: PermissionType;
|
||||
public: boolean;
|
||||
type: WorkspaceType;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
export interface UpdateWorkspace {
|
||||
id: number;
|
||||
public: boolean;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
export interface CreateWorkspaceResult {
|
||||
id: string;
|
||||
name: string;
|
||||
[k: string]: unknown;
|
||||
}
|
||||
@@ -11,6 +11,13 @@ import { getLogger } from '../logger';
|
||||
// provider: string;
|
||||
// };
|
||||
|
||||
declare global {
|
||||
interface Window {
|
||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||
__TAURI_IPC__: Function;
|
||||
}
|
||||
}
|
||||
|
||||
export type User = {
|
||||
name: string;
|
||||
id: string;
|
||||
|
||||
Reference in New Issue
Block a user