refactor: jwt internal version migration
This commit is contained in:
@@ -12,7 +12,7 @@
|
|||||||
"file-selector": "^0.6.0",
|
"file-selector": "^0.6.0",
|
||||||
"flexsearch": "^0.7.21",
|
"flexsearch": "^0.7.21",
|
||||||
"lib0": "^0.2.52",
|
"lib0": "^0.2.52",
|
||||||
"lru-cache": "^7.13.2",
|
"lru-cache": "^7.14.0",
|
||||||
"ts-debounce": "^4.0.0"
|
"ts-debounce": "^4.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -1,3 +1,10 @@
|
|||||||
|
import {
|
||||||
|
BlockFlavorKeys,
|
||||||
|
BlockFlavors,
|
||||||
|
BlockTypeKeys,
|
||||||
|
BlockTypes,
|
||||||
|
} from '../types';
|
||||||
|
import { getLogger } from '../utils';
|
||||||
import {
|
import {
|
||||||
BlockInstance,
|
BlockInstance,
|
||||||
BlockListener,
|
BlockListener,
|
||||||
@@ -6,14 +13,7 @@ import {
|
|||||||
ContentTypes,
|
ContentTypes,
|
||||||
HistoryManager,
|
HistoryManager,
|
||||||
MapOperation,
|
MapOperation,
|
||||||
} from '../adapter';
|
} from '../yjs/types';
|
||||||
import {
|
|
||||||
BlockFlavorKeys,
|
|
||||||
BlockFlavors,
|
|
||||||
BlockTypeKeys,
|
|
||||||
BlockTypes,
|
|
||||||
} from '../types';
|
|
||||||
import { getLogger } from '../utils';
|
|
||||||
|
|
||||||
declare const JWT_DEV: boolean;
|
declare const JWT_DEV: boolean;
|
||||||
const logger = getLogger('BlockDB:block');
|
const logger = getLogger('BlockDB:block');
|
||||||
@@ -29,10 +29,10 @@ export class AbstractBlock<
|
|||||||
private readonly _id: string;
|
private readonly _id: string;
|
||||||
private readonly _block: BlockInstance<C>;
|
private readonly _block: BlockInstance<C>;
|
||||||
private readonly _history: HistoryManager;
|
private readonly _history: HistoryManager;
|
||||||
private readonly _root?: AbstractBlock<B, C>;
|
private readonly _root: AbstractBlock<B, C> | undefined;
|
||||||
private readonly _parentListener: Map<string, BlockListener>;
|
private readonly _parentListener: Map<string, BlockListener>;
|
||||||
|
|
||||||
private _parent?: AbstractBlock<B, C>;
|
private _parent: AbstractBlock<B, C> | undefined;
|
||||||
private _changeParent?: () => void;
|
private _changeParent?: () => void;
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@@ -48,7 +48,9 @@ export class AbstractBlock<
|
|||||||
this._parentListener = new Map();
|
this._parentListener = new Map();
|
||||||
|
|
||||||
JWT_DEV && logger_debug(`init: exists ${this._id}`);
|
JWT_DEV && logger_debug(`init: exists ${this._id}`);
|
||||||
if (parent) this._refreshParent(parent);
|
if (parent) {
|
||||||
|
this._refreshParent(parent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public get root() {
|
public get root() {
|
||||||
@@ -146,7 +148,7 @@ export class AbstractBlock<
|
|||||||
return new Date(timestamp)
|
return new Date(timestamp)
|
||||||
.toISOString()
|
.toISOString()
|
||||||
.split('T')[0]
|
.split('T')[0]
|
||||||
.replace(/-/g, '');
|
?.replace(/-/g, '');
|
||||||
}
|
}
|
||||||
// eslint-disable-next-line no-empty
|
// eslint-disable-next-line no-empty
|
||||||
} catch (e) {}
|
} catch (e) {}
|
||||||
@@ -259,7 +261,7 @@ export class AbstractBlock<
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Insert sub-Block
|
* Insert children block
|
||||||
* @param block Block instance
|
* @param block Block instance
|
||||||
* @param position Insertion position, if it is empty, it will be inserted at the end. If the block already exists, the position will be moved
|
* @param position Insertion position, if it is empty, it will be inserted at the end. If the block already exists, the position will be moved
|
||||||
* @returns
|
* @returns
|
||||||
@@ -270,9 +272,12 @@ export class AbstractBlock<
|
|||||||
) {
|
) {
|
||||||
JWT_DEV && logger(`insertChildren: start`);
|
JWT_DEV && logger(`insertChildren: start`);
|
||||||
|
|
||||||
if (block.id === this._id) return; // avoid self-reference
|
if (block.id === this._id) {
|
||||||
|
// avoid self-reference
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (
|
if (
|
||||||
this.type !== BlockTypes.block || // binary cannot insert subblocks
|
this.type !== BlockTypes.block || // binary cannot insert children blocks
|
||||||
(block.type !== BlockTypes.block &&
|
(block.type !== BlockTypes.block &&
|
||||||
this.flavor !== BlockFlavors.workspace) // binary can only be inserted into workspace
|
this.flavor !== BlockFlavors.workspace) // binary can only be inserted into workspace
|
||||||
) {
|
) {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import { BlockItem } from '../types';
|
||||||
|
import { getLogger } from '../utils';
|
||||||
import {
|
import {
|
||||||
ArrayOperation,
|
ArrayOperation,
|
||||||
BlockInstance,
|
BlockInstance,
|
||||||
@@ -5,9 +7,7 @@ import {
|
|||||||
ContentTypes,
|
ContentTypes,
|
||||||
InternalPlainObject,
|
InternalPlainObject,
|
||||||
MapOperation,
|
MapOperation,
|
||||||
} from '../adapter';
|
} from '../yjs/types';
|
||||||
import { BlockItem } from '../types';
|
|
||||||
import { getLogger } from '../utils';
|
|
||||||
|
|
||||||
import { AbstractBlock } from './abstract';
|
import { AbstractBlock } from './abstract';
|
||||||
import { BlockCapability } from './capability';
|
import { BlockCapability } from './capability';
|
||||||
@@ -23,8 +23,8 @@ export interface Decoration extends InternalPlainObject {
|
|||||||
type Validator = <T>(value: T | undefined) => boolean | void;
|
type Validator = <T>(value: T | undefined) => boolean | void;
|
||||||
|
|
||||||
export type IndexMetadata = Readonly<{
|
export type IndexMetadata = Readonly<{
|
||||||
content?: string;
|
content: string | undefined;
|
||||||
reference?: string;
|
reference: string | undefined;
|
||||||
tags: string[];
|
tags: string[];
|
||||||
}>;
|
}>;
|
||||||
export type QueryMetadata = Readonly<
|
export type QueryMetadata = Readonly<
|
||||||
@@ -51,7 +51,7 @@ export class BaseBlock<
|
|||||||
B extends BlockInstance<C>,
|
B extends BlockInstance<C>,
|
||||||
C extends ContentOperation
|
C extends ContentOperation
|
||||||
> extends AbstractBlock<B, C> {
|
> extends AbstractBlock<B, C> {
|
||||||
private readonly _exporters?: Exporters;
|
private readonly _exporters: Exporters | undefined;
|
||||||
private readonly _contentExportersGetter: () => Map<
|
private readonly _contentExportersGetter: () => Map<
|
||||||
string,
|
string,
|
||||||
ReadableContentExporter<string, any>
|
ReadableContentExporter<string, any>
|
||||||
@@ -68,7 +68,7 @@ export class BaseBlock<
|
|||||||
ReadableContentExporter<string[], any>
|
ReadableContentExporter<string[], any>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
validators: Map<string, Validator> = new Map();
|
private readonly _validators: Map<string, Validator> = new Map();
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
block: B,
|
block: B,
|
||||||
@@ -157,14 +157,14 @@ export class BaseBlock<
|
|||||||
|
|
||||||
setValidator(key: string, validator?: Validator) {
|
setValidator(key: string, validator?: Validator) {
|
||||||
if (validator) {
|
if (validator) {
|
||||||
this.validators.set(key, validator);
|
this._validators.set(key, validator);
|
||||||
} else {
|
} else {
|
||||||
this.validators.delete(key);
|
this._validators.delete(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private validate(key: string, value: unknown): boolean {
|
private validate(key: string, value: unknown): boolean {
|
||||||
const validate = this.validators.get(key);
|
const validate = this._validators.get(key);
|
||||||
if (validate) {
|
if (validate) {
|
||||||
return validate(value) === false ? false : true;
|
return validate(value) === false ? false : true;
|
||||||
}
|
}
|
||||||
@@ -179,7 +179,7 @@ export class BaseBlock<
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get an instance of the child Block
|
* Get an instance of the child block
|
||||||
* @param blockId block id
|
* @param blockId block id
|
||||||
*/
|
*/
|
||||||
private get_children_instance(blockId?: string): BaseBlock<B, C>[] {
|
private get_children_instance(blockId?: string): BaseBlock<B, C>[] {
|
||||||
@@ -201,9 +201,15 @@ export class BaseBlock<
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const parent_page = this._getParentPage(false);
|
const parent_page = this._getParentPage(false);
|
||||||
if (parent_page) metadata['page'] = parent_page;
|
if (parent_page) {
|
||||||
if (this.group) metadata['group'] = this.group.id;
|
metadata['page'] = parent_page;
|
||||||
if (this.parent) metadata['parent'] = this.parent.id;
|
}
|
||||||
|
if (this.group) {
|
||||||
|
metadata['group'] = this.group.id;
|
||||||
|
}
|
||||||
|
if (this.parent) {
|
||||||
|
metadata['parent'] = this.parent.id;
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
logger(`Failed to export default metadata`, e);
|
logger(`Failed to export default metadata`, e);
|
||||||
}
|
}
|
||||||
@@ -228,7 +234,9 @@ export class BaseBlock<
|
|||||||
for (const [name, exporter] of this._contentExportersGetter()) {
|
for (const [name, exporter] of this._contentExportersGetter()) {
|
||||||
try {
|
try {
|
||||||
const content = exporter(this.getContent());
|
const content = exporter(this.getContent());
|
||||||
if (content) contents.push(content);
|
if (content) {
|
||||||
|
contents.push(content);
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger(`Failed to export content: ${name}`, err);
|
logger(`Failed to export content: ${name}`, err);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,14 +7,14 @@ import produce from 'immer';
|
|||||||
import LRUCache from 'lru-cache';
|
import LRUCache from 'lru-cache';
|
||||||
import sift, { Query } from 'sift';
|
import sift, { Query } from 'sift';
|
||||||
|
|
||||||
|
import { BlockFlavors } from '../types';
|
||||||
|
import { BlockEventBus, getLogger } from '../utils';
|
||||||
import {
|
import {
|
||||||
AsyncDatabaseAdapter,
|
AsyncDatabaseAdapter,
|
||||||
BlockInstance,
|
BlockInstance,
|
||||||
ChangedStates,
|
ChangedStates,
|
||||||
ContentOperation,
|
ContentOperation,
|
||||||
} from '../adapter';
|
} from '../yjs/types';
|
||||||
import { BlockFlavors } from '../types';
|
|
||||||
import { BlockEventBus, getLogger } from '../utils';
|
|
||||||
|
|
||||||
import { BaseBlock, IndexMetadata, QueryMetadata } from './base';
|
import { BaseBlock, IndexMetadata, QueryMetadata } from './base';
|
||||||
|
|
||||||
@@ -315,7 +315,9 @@ export class BlockIndexer<
|
|||||||
private _testMetaKey(key: string) {
|
private _testMetaKey(key: string) {
|
||||||
try {
|
try {
|
||||||
const metadata = this._blockMetadata.values().next().value;
|
const metadata = this._blockMetadata.values().next().value;
|
||||||
if (!metadata || typeof metadata !== 'object') return false;
|
if (!metadata || typeof metadata !== 'object') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
return !!(key in metadata);
|
return !!(key in metadata);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
return false;
|
return false;
|
||||||
@@ -324,8 +326,11 @@ export class BlockIndexer<
|
|||||||
|
|
||||||
private _getSortedMetadata(sort: string, desc?: boolean) {
|
private _getSortedMetadata(sort: string, desc?: boolean) {
|
||||||
const sorter = naturalSort(Array.from(this._blockMetadata.entries()));
|
const sorter = naturalSort(Array.from(this._blockMetadata.entries()));
|
||||||
if (desc) return sorter.desc(([, m]) => m[sort]);
|
if (desc) {
|
||||||
else return sorter.asc(([, m]) => m[sort]);
|
return sorter.desc(([, m]) => m[sort]);
|
||||||
|
} else {
|
||||||
|
return sorter.asc(([, m]) => m[sort]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public query(query: QueryIndexMetadata) {
|
public query(query: QueryIndexMetadata) {
|
||||||
@@ -337,15 +342,23 @@ export class BlockIndexer<
|
|||||||
if ($sort && this._testMetaKey($sort)) {
|
if ($sort && this._testMetaKey($sort)) {
|
||||||
const metadata = this._getSortedMetadata($sort, $desc);
|
const metadata = this._getSortedMetadata($sort, $desc);
|
||||||
metadata.forEach(([key, value]) => {
|
metadata.forEach(([key, value]) => {
|
||||||
if (matches.length > limit) return;
|
if (matches.length > limit) {
|
||||||
if (filter(value)) matches.push(key);
|
return;
|
||||||
|
}
|
||||||
|
if (filter(value)) {
|
||||||
|
matches.push(key);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return matches;
|
return matches;
|
||||||
} else {
|
} else {
|
||||||
this._blockMetadata.forEach((value, key) => {
|
this._blockMetadata.forEach((value, key) => {
|
||||||
if (matches.length > limit) return;
|
if (matches.length > limit) {
|
||||||
if (filter(value)) matches.push(key);
|
return;
|
||||||
|
}
|
||||||
|
if (filter(value)) {
|
||||||
|
matches.push(key);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return matches;
|
return matches;
|
||||||
|
|||||||
@@ -1,26 +1,7 @@
|
|||||||
/* eslint-disable max-lines */
|
/* eslint-disable max-lines */
|
||||||
import { DocumentSearchOptions } from 'flexsearch';
|
import { DocumentSearchOptions } from 'flexsearch';
|
||||||
import LRUCache from 'lru-cache';
|
import LRUCache from 'lru-cache';
|
||||||
import {
|
|
||||||
AsyncDatabaseAdapter,
|
|
||||||
BlockInstance,
|
|
||||||
BlockListener,
|
|
||||||
ChangedStates,
|
|
||||||
Connectivity,
|
|
||||||
ContentOperation,
|
|
||||||
ContentTypes,
|
|
||||||
DataExporter,
|
|
||||||
getDataExporter,
|
|
||||||
HistoryManager,
|
|
||||||
YjsAdapter,
|
|
||||||
YjsContentOperation,
|
|
||||||
YjsInitOptions,
|
|
||||||
} from './adapter';
|
|
||||||
import {
|
|
||||||
getYjsProviders,
|
|
||||||
YjsBlockInstance,
|
|
||||||
YjsProviderOptions,
|
|
||||||
} from './adapter/yjs';
|
|
||||||
import {
|
import {
|
||||||
BaseBlock,
|
BaseBlock,
|
||||||
BlockIndexer,
|
BlockIndexer,
|
||||||
@@ -39,6 +20,26 @@ import {
|
|||||||
UUID,
|
UUID,
|
||||||
} from './types';
|
} from './types';
|
||||||
import { BlockEventBus, genUUID, getLogger } from './utils';
|
import { BlockEventBus, genUUID, getLogger } from './utils';
|
||||||
|
import {
|
||||||
|
getYjsProviders,
|
||||||
|
YjsAdapter,
|
||||||
|
YjsBlockInstance,
|
||||||
|
YjsContentOperation,
|
||||||
|
YjsInitOptions,
|
||||||
|
YjsProviderOptions,
|
||||||
|
} from './yjs';
|
||||||
|
import {
|
||||||
|
AsyncDatabaseAdapter,
|
||||||
|
BlockInstance,
|
||||||
|
BlockListener,
|
||||||
|
ChangedStates,
|
||||||
|
Connectivity,
|
||||||
|
ContentOperation,
|
||||||
|
ContentTypes,
|
||||||
|
DataExporter,
|
||||||
|
getDataExporter,
|
||||||
|
HistoryManager,
|
||||||
|
} from './yjs/types';
|
||||||
|
|
||||||
declare const JWT_DEV: boolean;
|
declare const JWT_DEV: boolean;
|
||||||
|
|
||||||
@@ -157,8 +158,11 @@ export class BlockClient<
|
|||||||
|
|
||||||
public addBlockListener(tag: string, listener: BlockListener) {
|
public addBlockListener(tag: string, listener: BlockListener) {
|
||||||
const bus = this._eventBus.topic<ChangedStates>('updated');
|
const bus = this._eventBus.topic<ChangedStates>('updated');
|
||||||
if (tag !== 'index' || !bus.has(tag)) bus.on(tag, listener);
|
if (tag !== 'index' || !bus.has(tag)) {
|
||||||
else console.error(`block listener ${tag} is reserved or exists`);
|
bus.on(tag, listener);
|
||||||
|
} else {
|
||||||
|
console.error(`block listener ${tag} is reserved or exists`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeBlockListener(tag: string) {
|
public removeBlockListener(tag: string) {
|
||||||
@@ -170,8 +174,11 @@ export class BlockClient<
|
|||||||
listener: BlockListener<Set<string>>
|
listener: BlockListener<Set<string>>
|
||||||
) {
|
) {
|
||||||
const bus = this._eventBus.topic<ChangedStates<Set<string>>>('editing');
|
const bus = this._eventBus.topic<ChangedStates<Set<string>>>('editing');
|
||||||
if (tag !== 'index' || !bus.has(tag)) bus.on(tag, listener);
|
if (tag !== 'index' || !bus.has(tag)) {
|
||||||
else console.error(`editing listener ${tag} is reserved or exists`);
|
bus.on(tag, listener);
|
||||||
|
} else {
|
||||||
|
console.error(`editing listener ${tag} is reserved or exists`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeEditingListener(tag: string) {
|
public removeEditingListener(tag: string) {
|
||||||
@@ -184,15 +191,18 @@ export class BlockClient<
|
|||||||
) {
|
) {
|
||||||
const bus =
|
const bus =
|
||||||
this._eventBus.topic<ChangedStates<Connectivity>>('connectivity');
|
this._eventBus.topic<ChangedStates<Connectivity>>('connectivity');
|
||||||
if (tag !== 'index' || !bus.has(tag)) bus.on(tag, listener);
|
if (tag !== 'index' || !bus.has(tag)) {
|
||||||
else
|
bus.on(tag, listener);
|
||||||
|
} else {
|
||||||
console.error(`connectivity listener ${tag} is reserved or exists`);
|
console.error(`connectivity listener ${tag} is reserved or exists`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public removeConnectivityListener(tag: string) {
|
public removeConnectivityListener(tag: string) {
|
||||||
this._eventBus.topic('connectivity').off(tag);
|
this._eventBus.topic('connectivity').off(tag);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// @ts-ignore
|
||||||
private inspector() {
|
private inspector() {
|
||||||
return {
|
return {
|
||||||
...this._adapter.inspector(),
|
...this._adapter.inspector(),
|
||||||
@@ -220,7 +230,9 @@ export class BlockClient<
|
|||||||
this.addBlockListener('index', async states => {
|
this.addBlockListener('index', async states => {
|
||||||
await Promise.allSettled(
|
await Promise.allSettled(
|
||||||
Array.from(states.entries()).map(([id, state]) => {
|
Array.from(states.entries()).map(([id, state]) => {
|
||||||
if (state === 'delete') this._blockCaches.delete(id);
|
if (state === 'delete') {
|
||||||
|
this._blockCaches.delete(id);
|
||||||
|
}
|
||||||
return this._blockIndexer.refreshIndex(id, state);
|
return this._blockIndexer.refreshIndex(id, state);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
@@ -255,7 +267,7 @@ export class BlockClient<
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* research all
|
* Full text search
|
||||||
* @param part_of_title_or_content Title or content keyword, support Chinese
|
* @param part_of_title_or_content Title or content keyword, support Chinese
|
||||||
* @param part_of_title_or_content.index search range, optional values: title, ttl, content, reference
|
* @param part_of_title_or_content.index search range, optional values: title, ttl, content, reference
|
||||||
* @param part_of_title_or_content.tag tag, string or array of strings, supports multiple tags
|
* @param part_of_title_or_content.tag tag, string or array of strings, supports multiple tags
|
||||||
@@ -295,7 +307,9 @@ export class BlockClient<
|
|||||||
this.search(part_of_title_or_content).flatMap(({ result }) =>
|
this.search(part_of_title_or_content).flatMap(({ result }) =>
|
||||||
result.map(async id => {
|
result.map(async id => {
|
||||||
const page = this._pageMapping.get(id as string);
|
const page = this._pageMapping.get(id as string);
|
||||||
if (page) return page;
|
if (page) {
|
||||||
|
return page;
|
||||||
|
}
|
||||||
const block = await this.get(id as BlockTypeKeys);
|
const block = await this.get(id as BlockTypeKeys);
|
||||||
return this.set_page(block);
|
return this.set_page(block);
|
||||||
})
|
})
|
||||||
@@ -307,9 +321,10 @@ export class BlockClient<
|
|||||||
}
|
}
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
this._blockIndexer.getMetadata(pages).map(async page => ({
|
this._blockIndexer.getMetadata(pages).map(async page => ({
|
||||||
content: this.get_decoded_content(
|
content:
|
||||||
await this._adapter.getBlock(page.id)
|
this.get_decoded_content(
|
||||||
),
|
await this._adapter.getBlock(page.id)
|
||||||
|
) || '',
|
||||||
...page,
|
...page,
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
@@ -327,9 +342,10 @@ export class BlockClient<
|
|||||||
const ids = this.query(query);
|
const ids = this.query(query);
|
||||||
return Promise.all(
|
return Promise.all(
|
||||||
this._blockIndexer.getMetadata(ids).map(async page => ({
|
this._blockIndexer.getMetadata(ids).map(async page => ({
|
||||||
content: this.get_decoded_content(
|
content:
|
||||||
await this._adapter.getBlock(page.id)
|
this.get_decoded_content(
|
||||||
),
|
await this._adapter.getBlock(page.id)
|
||||||
|
) || '',
|
||||||
...page,
|
...page,
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
@@ -378,7 +394,7 @@ export class BlockClient<
|
|||||||
|
|
||||||
private async get_parent(id: string) {
|
private async get_parent(id: string) {
|
||||||
const parents = this._parentMapping.get(id);
|
const parents = this._parentMapping.get(id);
|
||||||
if (parents) {
|
if (parents && parents[0]) {
|
||||||
const parent_block_id = parents[0];
|
const parent_block_id = parents[0];
|
||||||
if (!this._blockCaches.has(parent_block_id)) {
|
if (!this._blockCaches.has(parent_block_id)) {
|
||||||
this._blockCaches.set(
|
this._blockCaches.set(
|
||||||
@@ -405,7 +421,9 @@ export class BlockClient<
|
|||||||
|
|
||||||
private set_page(block: BaseBlock<B, C>) {
|
private set_page(block: BaseBlock<B, C>) {
|
||||||
const page = this._pageMapping.get(block.id);
|
const page = this._pageMapping.get(block.id);
|
||||||
if (page) return page;
|
if (page) {
|
||||||
|
return page;
|
||||||
|
}
|
||||||
const parent_page = block.parent_page;
|
const parent_page = block.parent_page;
|
||||||
if (parent_page) {
|
if (parent_page) {
|
||||||
this._pageMapping.set(block.id, parent_page);
|
this._pageMapping.set(block.id, parent_page);
|
||||||
@@ -472,8 +490,9 @@ export class BlockClient<
|
|||||||
matched += 1;
|
matched += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (matched === conditions.length)
|
if (matched === conditions.length) {
|
||||||
exporters.push([name, exporter] as const);
|
exporters.push([name, exporter] as const);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return exporters;
|
return exporters;
|
||||||
@@ -487,7 +506,9 @@ export class BlockClient<
|
|||||||
);
|
);
|
||||||
if (exporter) {
|
if (exporter) {
|
||||||
const op = block.content.asMap();
|
const op = block.content.asMap();
|
||||||
if (op) return exporter[1](op);
|
if (op) {
|
||||||
|
return exporter[1](op);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
@@ -566,7 +587,9 @@ export class BlockClient<
|
|||||||
this.set_page(abstract_block);
|
this.set_page(abstract_block);
|
||||||
abstract_block.on('parent', 'client_hook', state => {
|
abstract_block.on('parent', 'client_hook', state => {
|
||||||
const [parent] = state.keys();
|
const [parent] = state.keys();
|
||||||
this.set_parent(parent, abstract_block.id);
|
if (parent) {
|
||||||
|
this.set_parent(parent, abstract_block.id);
|
||||||
|
}
|
||||||
this.set_page(abstract_block);
|
this.set_page(abstract_block);
|
||||||
});
|
});
|
||||||
this._blockCaches.set(abstract_block.id, abstract_block);
|
this._blockCaches.set(abstract_block.id, abstract_block);
|
||||||
@@ -650,13 +673,6 @@ export type BlockInitOptions = NonNullable<
|
|||||||
Parameters<typeof BlockClient.init>[1]
|
Parameters<typeof BlockClient.init>[1]
|
||||||
>;
|
>;
|
||||||
|
|
||||||
export type {
|
|
||||||
ArrayOperation,
|
|
||||||
ChangedStates,
|
|
||||||
Connectivity,
|
|
||||||
MapOperation,
|
|
||||||
TextOperation,
|
|
||||||
} from './adapter';
|
|
||||||
export type {
|
export type {
|
||||||
BlockSearchItem,
|
BlockSearchItem,
|
||||||
Decoration as BlockDecoration,
|
Decoration as BlockDecoration,
|
||||||
@@ -665,4 +681,11 @@ export type {
|
|||||||
export { BlockTypes, BucketBackend as BlockBackend } from './types';
|
export { BlockTypes, BucketBackend as BlockBackend } from './types';
|
||||||
export type { BlockTypeKeys } from './types';
|
export type { BlockTypeKeys } from './types';
|
||||||
export { isBlock } from './utils';
|
export { isBlock } from './utils';
|
||||||
|
export type {
|
||||||
|
ArrayOperation,
|
||||||
|
ChangedStates,
|
||||||
|
Connectivity,
|
||||||
|
MapOperation,
|
||||||
|
TextOperation,
|
||||||
|
} from './yjs/types';
|
||||||
export type { QueryIndexMetadata };
|
export type { QueryIndexMetadata };
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { ContentOperation } from '../adapter';
|
import { ContentOperation } from '../yjs/types';
|
||||||
import { RefMetadata } from './metadata';
|
import { RefMetadata } from './metadata';
|
||||||
import { UUID } from './uuid';
|
import { UUID } from './uuid';
|
||||||
// base type of block
|
// base type of block
|
||||||
@@ -60,8 +60,8 @@ export type BlockItem<C extends ContentOperation> = {
|
|||||||
flavor: typeof BlockFlavors[BlockFlavorKeys];
|
flavor: typeof BlockFlavors[BlockFlavorKeys];
|
||||||
children: string[];
|
children: string[];
|
||||||
readonly created: number; // creation time, UTC timestamp
|
readonly created: number; // creation time, UTC timestamp
|
||||||
readonly updated?: number; // update time, UTC timestamp
|
readonly updated?: number | undefined; // update time, UTC timestamp
|
||||||
readonly creator?: string; // creator id
|
readonly creator?: string | undefined; // creator id
|
||||||
content: C; // Essentially what is stored here is either Uint8Array (binary resource) or YDoc (structured resource)
|
content: C; // Essentially what is stored here is either Uint8Array (binary resource) or YDoc (structured resource)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ class BlockScopedEventBus<T> extends BlockEventBus {
|
|||||||
options?: ListenerOptions
|
options?: ListenerOptions
|
||||||
) {
|
) {
|
||||||
if (options?.debounce) {
|
if (options?.debounce) {
|
||||||
const { wait, maxWait } = options.debounce;
|
const { wait, maxWait = 500 } = options.debounce;
|
||||||
const debounced = debounce(listener, wait, { maxWait });
|
const debounced = debounce(listener, wait, { maxWait });
|
||||||
this.on_listener(this._topic, name, e => {
|
this.on_listener(this._topic, name, e => {
|
||||||
debounced((e as CustomEvent)?.detail);
|
debounced((e as CustomEvent)?.detail);
|
||||||
|
|||||||
@@ -39,7 +39,9 @@ export function getLogger(namespace: string) {
|
|||||||
if (JWT_DEV) {
|
if (JWT_DEV) {
|
||||||
const logger = debug(namespace);
|
const logger = debug(namespace);
|
||||||
logger.log = console.log.bind(console);
|
logger.log = console.log.bind(console);
|
||||||
if (JWT_DEV === ('testing' as any)) logger.enabled = true;
|
if (JWT_DEV === ('testing' as any)) {
|
||||||
|
logger.enabled = true;
|
||||||
|
}
|
||||||
return logger;
|
return logger;
|
||||||
} else {
|
} else {
|
||||||
return () => {};
|
return () => {};
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ export class YjsRemoteBinaries {
|
|||||||
} else {
|
} else {
|
||||||
// TODO: Remote Load
|
// TODO: Remote Load
|
||||||
try {
|
try {
|
||||||
const file = await this._remoteStorage?.instance.getBuffData(
|
const file = await this._remoteStorage?.instance?.getBuffData(
|
||||||
name
|
name
|
||||||
);
|
);
|
||||||
console.log(file);
|
console.log(file);
|
||||||
@@ -44,11 +44,11 @@ export class YjsRemoteBinaries {
|
|||||||
this._binaries.set(name, binary);
|
this._binaries.set(name, binary);
|
||||||
if (this._remoteStorage) {
|
if (this._remoteStorage) {
|
||||||
// TODO: Remote Save, if there is an object with the same name remotely, the upload is skipped, because the file name is the hash of the file content
|
// TODO: Remote Save, if there is an object with the same name remotely, the upload is skipped, because the file name is the hash of the file content
|
||||||
const has_file = this._remoteStorage.instance.exist(name);
|
const has_file = this._remoteStorage.instance?.exist(name);
|
||||||
if (!has_file) {
|
if (!has_file) {
|
||||||
const upload_file = new File(binary.toArray(), name);
|
const upload_file = new File(binary.toArray(), name);
|
||||||
await this._remoteStorage.instance
|
await this._remoteStorage.instance
|
||||||
.upload(upload_file)
|
?.upload(upload_file)
|
||||||
.catch(err => {
|
.catch(err => {
|
||||||
throw new Error(`${err} upload error`);
|
throw new Error(`${err} upload error`);
|
||||||
});
|
});
|
||||||
@@ -5,8 +5,8 @@ import {
|
|||||||
transact,
|
transact,
|
||||||
} from 'yjs';
|
} from 'yjs';
|
||||||
|
|
||||||
import { BlockItem, BlockTypes } from '../../types';
|
import { BlockItem, BlockTypes } from '../types';
|
||||||
import { BlockInstance, BlockListener, HistoryManager } from '../index';
|
import { BlockInstance, BlockListener, HistoryManager } from './types';
|
||||||
|
|
||||||
import { YjsHistoryManager } from './history';
|
import { YjsHistoryManager } from './history';
|
||||||
import { ChildrenListenerHandler, ContentListenerHandler } from './listener';
|
import { ChildrenListenerHandler, ContentListenerHandler } from './listener';
|
||||||
@@ -34,7 +34,7 @@ type YjsBlockInstanceProps = {
|
|||||||
export class YjsBlockInstance implements BlockInstance<YjsContentOperation> {
|
export class YjsBlockInstance implements BlockInstance<YjsContentOperation> {
|
||||||
private readonly _id: string;
|
private readonly _id: string;
|
||||||
private readonly _block: YMap<unknown>;
|
private readonly _block: YMap<unknown>;
|
||||||
private readonly _binary?: YArray<ArrayBuffer>;
|
private readonly _binary: YArray<ArrayBuffer> | undefined;
|
||||||
private readonly _children: YArray<string>;
|
private readonly _children: YArray<string>;
|
||||||
private readonly _setBlock: (
|
private readonly _setBlock: (
|
||||||
id: string,
|
id: string,
|
||||||
@@ -48,8 +48,7 @@ export class YjsBlockInstance implements BlockInstance<YjsContentOperation> {
|
|||||||
private readonly _childrenListeners: Map<string, BlockListener>;
|
private readonly _childrenListeners: Map<string, BlockListener>;
|
||||||
private readonly _contentListeners: Map<string, BlockListener>;
|
private readonly _contentListeners: Map<string, BlockListener>;
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
private _childrenMap: Map<string, number>;
|
||||||
_childrenMap: Map<string, number>;
|
|
||||||
|
|
||||||
constructor(props: YjsBlockInstanceProps) {
|
constructor(props: YjsBlockInstanceProps) {
|
||||||
this._id = props.id;
|
this._id = props.id;
|
||||||
@@ -184,7 +183,9 @@ export class YjsBlockInstance implements BlockInstance<YjsContentOperation> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
hasChildren(id: string): boolean {
|
hasChildren(id: string): boolean {
|
||||||
if (this.children.includes(id)) return true;
|
if (this.children.includes(id)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return this.getChildren().some(block => block.hasChildren(id));
|
return this.getChildren().some(block => block.hasChildren(id));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -263,7 +264,9 @@ export class YjsBlockInstance implements BlockInstance<YjsContentOperation> {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (id) failed.push(id);
|
if (id) {
|
||||||
|
failed.push(id);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
this._childrenMap = getMapFromYArray(this._children);
|
this._childrenMap = getMapFromYArray(this._children);
|
||||||
@@ -32,7 +32,7 @@ export class GateKeeper {
|
|||||||
return creator === this._userId || !!this._common.get(block_id);
|
return creator === this._userId || !!this._common.get(block_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkDeleteLists(block_ids: string[]) {
|
checkDeleteLists(block_ids: string[]): [string[], string[]] {
|
||||||
const success = [];
|
const success = [];
|
||||||
const fail = [];
|
const fail = [];
|
||||||
for (const block_id of block_ids) {
|
for (const block_id of block_ids) {
|
||||||
@@ -1,10 +1,11 @@
|
|||||||
import { Map as YMap, UndoManager } from 'yjs';
|
import { Map as YMap, UndoManager } from 'yjs';
|
||||||
|
|
||||||
import { HistoryCallback, HistoryManager } from '../../adapter';
|
import { HistoryCallback, HistoryManager } from './types';
|
||||||
|
|
||||||
type StackItem = UndoManager['undoStack'][0];
|
type StackItem = UndoManager['undoStack'][0];
|
||||||
|
|
||||||
export class YjsHistoryManager implements HistoryManager {
|
export class YjsHistoryManager implements HistoryManager {
|
||||||
|
// @ts-ignore
|
||||||
private readonly _blocks: YMap<any>;
|
private readonly _blocks: YMap<any>;
|
||||||
private readonly _historyManager: UndoManager;
|
private readonly _historyManager: UndoManager;
|
||||||
private readonly _pushListeners: Map<string, HistoryCallback<any>>;
|
private readonly _pushListeners: Map<string, HistoryCallback<any>>;
|
||||||
@@ -56,7 +57,7 @@ export class YjsHistoryManager implements HistoryManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
break(): void {
|
break(): void {
|
||||||
// this.#history_manager.
|
// this._historyManager.
|
||||||
}
|
}
|
||||||
|
|
||||||
undo<T = unknown>(): Map<string, T> | undefined {
|
undo<T = unknown>(): Map<string, T> | undefined {
|
||||||
@@ -18,15 +18,15 @@ import {
|
|||||||
transact,
|
transact,
|
||||||
} from 'yjs';
|
} from 'yjs';
|
||||||
|
|
||||||
|
import { BlockItem, BlockTypes } from '../types';
|
||||||
|
import { getLogger, sha3, sleep } from '../utils';
|
||||||
import {
|
import {
|
||||||
AsyncDatabaseAdapter,
|
AsyncDatabaseAdapter,
|
||||||
BlockListener,
|
BlockListener,
|
||||||
ChangedStateKeys,
|
ChangedStateKeys,
|
||||||
Connectivity,
|
Connectivity,
|
||||||
HistoryManager,
|
HistoryManager,
|
||||||
} from '../../adapter';
|
} from './types';
|
||||||
import { BlockItem, BlockTypes } from '../../types';
|
|
||||||
import { getLogger, sha3, sleep } from '../../utils';
|
|
||||||
|
|
||||||
import { YjsRemoteBinaries } from './binary';
|
import { YjsRemoteBinaries } from './binary';
|
||||||
import { YjsBlockInstance } from './block';
|
import { YjsBlockInstance } from './block';
|
||||||
@@ -40,6 +40,7 @@ import {
|
|||||||
import { YjsProvider } from './provider';
|
import { YjsProvider } from './provider';
|
||||||
|
|
||||||
declare const JWT_DEV: boolean;
|
declare const JWT_DEV: boolean;
|
||||||
|
// @ts-ignore
|
||||||
const logger = getLogger('BlockDB:yjs');
|
const logger = getLogger('BlockDB:yjs');
|
||||||
|
|
||||||
type ConnectivityListener = (
|
type ConnectivityListener = (
|
||||||
@@ -54,7 +55,7 @@ type YjsProviders = {
|
|||||||
gatekeeper: GateKeeper;
|
gatekeeper: GateKeeper;
|
||||||
connListener: { listeners?: ConnectivityListener };
|
connListener: { listeners?: ConnectivityListener };
|
||||||
userId: string;
|
userId: string;
|
||||||
remoteToken?: string; // remote storage token
|
remoteToken: string | undefined; // remote storage token
|
||||||
};
|
};
|
||||||
|
|
||||||
const _yjsDatabaseInstance = new Map<string, YjsProviders>();
|
const _yjsDatabaseInstance = new Map<string, YjsProviders>();
|
||||||
@@ -70,8 +71,8 @@ async function _initYjsDatabase(
|
|||||||
workspace: string,
|
workspace: string,
|
||||||
options: {
|
options: {
|
||||||
userId: string;
|
userId: string;
|
||||||
token?: string;
|
token?: string | undefined;
|
||||||
provider?: Record<string, YjsProvider>;
|
provider?: Record<string, YjsProvider> | undefined;
|
||||||
}
|
}
|
||||||
): Promise<YjsProviders> {
|
): Promise<YjsProviders> {
|
||||||
if (_asyncInitLoading.has(workspace)) {
|
if (_asyncInitLoading.has(workspace)) {
|
||||||
@@ -243,9 +244,10 @@ export class YjsAdapter implements AsyncDatabaseAdapter<YjsContentOperation> {
|
|||||||
typeof updated === 'number' &&
|
typeof updated === 'number' &&
|
||||||
updated + 1000 * 10 > Date.now()
|
updated + 1000 * 10 > Date.now()
|
||||||
) {
|
) {
|
||||||
if (!editing_mapping[editing])
|
if (!editing_mapping[editing]) {
|
||||||
editing_mapping[editing] = [];
|
editing_mapping[editing] = [];
|
||||||
editing_mapping[editing].push(userId);
|
}
|
||||||
|
editing_mapping[editing]?.push(userId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
listener(
|
listener(
|
||||||
@@ -338,7 +340,7 @@ export class YjsAdapter implements AsyncDatabaseAdapter<YjsContentOperation> {
|
|||||||
],
|
],
|
||||||
});
|
});
|
||||||
const [file] = (await fromEvent(handles)) as File[];
|
const [file] = (await fromEvent(handles)) as File[];
|
||||||
const binary = await file.arrayBuffer();
|
const binary = await file?.arrayBuffer();
|
||||||
// await this._provider.idb.clearData();
|
// await this._provider.idb.clearData();
|
||||||
const doc = new Doc({ autoLoad: true, shouldLoad: true });
|
const doc = new Doc({ autoLoad: true, shouldLoad: true });
|
||||||
let updated = 0;
|
let updated = 0;
|
||||||
@@ -348,7 +350,9 @@ export class YjsAdapter implements AsyncDatabaseAdapter<YjsContentOperation> {
|
|||||||
updated += 1;
|
updated += 1;
|
||||||
});
|
});
|
||||||
setInterval(() => {
|
setInterval(() => {
|
||||||
if (updated > 0) updated -= 1;
|
if (updated > 0) {
|
||||||
|
updated -= 1;
|
||||||
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
|
|
||||||
const update_check = new Promise<void>(resolve => {
|
const update_check = new Promise<void>(resolve => {
|
||||||
@@ -362,8 +366,10 @@ export class YjsAdapter implements AsyncDatabaseAdapter<YjsContentOperation> {
|
|||||||
});
|
});
|
||||||
// await new IndexedDBProvider(this._provider.idb.name, doc)
|
// await new IndexedDBProvider(this._provider.idb.name, doc)
|
||||||
// .whenSynced;
|
// .whenSynced;
|
||||||
applyUpdate(doc, new Uint8Array(binary));
|
if (binary) {
|
||||||
await update_check;
|
applyUpdate(doc, new Uint8Array(binary));
|
||||||
|
await update_check;
|
||||||
|
}
|
||||||
console.log('load success');
|
console.log('load success');
|
||||||
},
|
},
|
||||||
parse: () => this._doc.toJSON(),
|
parse: () => this._doc.toJSON(),
|
||||||
@@ -409,8 +415,8 @@ export class YjsAdapter implements AsyncDatabaseAdapter<YjsContentOperation> {
|
|||||||
|
|
||||||
async createBlock(
|
async createBlock(
|
||||||
options: Pick<BlockItem<YjsContentOperation>, 'type' | 'flavor'> & {
|
options: Pick<BlockItem<YjsContentOperation>, 'type' | 'flavor'> & {
|
||||||
uuid?: string;
|
uuid: string | undefined;
|
||||||
binary?: ArrayBufferLike;
|
binary: ArrayBufferLike | undefined;
|
||||||
}
|
}
|
||||||
): Promise<YjsBlockInstance> {
|
): Promise<YjsBlockInstance> {
|
||||||
const uuid = options.uuid || `affine${nanoid(16)}`;
|
const uuid = options.uuid || `affine${nanoid(16)}`;
|
||||||
@@ -481,7 +487,9 @@ export class YjsAdapter implements AsyncDatabaseAdapter<YjsContentOperation> {
|
|||||||
|
|
||||||
async getBlock(id: string): Promise<YjsBlockInstance | undefined> {
|
async getBlock(id: string): Promise<YjsBlockInstance | undefined> {
|
||||||
const block_instance = this.get_block_sync(id);
|
const block_instance = this.get_block_sync(id);
|
||||||
if (block_instance) return block_instance;
|
if (block_instance) {
|
||||||
|
return block_instance;
|
||||||
|
}
|
||||||
const block = this._blocks.get(id);
|
const block = this._blocks.get(id);
|
||||||
if (block && block.get('type') === BlockTypes.binary) {
|
if (block && block.get('type') === BlockTypes.binary) {
|
||||||
const binary = await this._binaries.get(
|
const binary = await this._binaries.get(
|
||||||
@@ -540,7 +548,9 @@ export class YjsAdapter implements AsyncDatabaseAdapter<YjsContentOperation> {
|
|||||||
let uploaded: Promise<void> | undefined;
|
let uploaded: Promise<void> | undefined;
|
||||||
if (!block.size) {
|
if (!block.size) {
|
||||||
const content = item.content[INTO_INNER]();
|
const content = item.content[INTO_INNER]();
|
||||||
if (!content) return reject();
|
if (!content) {
|
||||||
|
return reject();
|
||||||
|
}
|
||||||
|
|
||||||
const children = new YArray();
|
const children = new YArray();
|
||||||
children.push(item.children);
|
children.push(item.children);
|
||||||
@@ -1,7 +1,8 @@
|
|||||||
import { produce } from 'immer';
|
import { produce } from 'immer';
|
||||||
import { debounce } from 'ts-debounce';
|
import { debounce } from 'ts-debounce';
|
||||||
import { YEvent } from 'yjs';
|
import { YEvent } from 'yjs';
|
||||||
import { BlockListener, ChangedStateKeys } from '../index';
|
|
||||||
|
import { BlockListener, ChangedStateKeys } from './types';
|
||||||
|
|
||||||
let listener_suspend = false;
|
let listener_suspend = false;
|
||||||
|
|
||||||
@@ -6,6 +6,7 @@ import {
|
|||||||
Text as YText,
|
Text as YText,
|
||||||
} from 'yjs';
|
} from 'yjs';
|
||||||
|
|
||||||
|
import { ChildrenListenerHandler, ContentListenerHandler } from './listener';
|
||||||
import {
|
import {
|
||||||
ArrayOperation,
|
ArrayOperation,
|
||||||
BaseTypes,
|
BaseTypes,
|
||||||
@@ -16,21 +17,29 @@ import {
|
|||||||
Operable,
|
Operable,
|
||||||
TextOperation,
|
TextOperation,
|
||||||
TextToken,
|
TextToken,
|
||||||
} from '../index';
|
} from './types';
|
||||||
import { ChildrenListenerHandler, ContentListenerHandler } from './listener';
|
|
||||||
|
|
||||||
const INTO_INNER = Symbol('INTO_INNER');
|
const INTO_INNER = Symbol('INTO_INNER');
|
||||||
|
|
||||||
export const DO_NOT_USE_THIS_OR_YOU_WILL_BE_FIRED_SYMBOL_INTO_INNER: typeof INTO_INNER =
|
export const DO_NOT_USE_THIS_OR_YOU_WILL_BE_FIRED_SYMBOL_INTO_INNER: typeof INTO_INNER =
|
||||||
INTO_INNER;
|
INTO_INNER;
|
||||||
|
|
||||||
function auto_get(root: ContentOperation, key: string): unknown | undefined {
|
function auto_get(
|
||||||
|
root: ContentOperation,
|
||||||
|
key: string | undefined
|
||||||
|
): unknown | undefined {
|
||||||
const array = root.asArray();
|
const array = root.asArray();
|
||||||
if (array && !Number.isNaN(Number(key))) return array.get(Number(key));
|
if (array && !Number.isNaN(Number(key))) {
|
||||||
|
return array.get(Number(key));
|
||||||
|
}
|
||||||
const map = root.asMap();
|
const map = root.asMap();
|
||||||
if (map) return map.get(key);
|
if (map && key) {
|
||||||
|
return map.get(key);
|
||||||
|
}
|
||||||
const text = root.asText();
|
const text = root.asText();
|
||||||
if (text) return text.toString();
|
if (text) {
|
||||||
|
return text.toString();
|
||||||
|
}
|
||||||
console.error('auto_get unknown root', root, key);
|
console.error('auto_get unknown root', root, key);
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
@@ -150,7 +159,9 @@ export class YjsContentOperation implements ContentOperation {
|
|||||||
if (root instanceof YjsContentOperation) {
|
if (root instanceof YjsContentOperation) {
|
||||||
if (path.length === 1) {
|
if (path.length === 1) {
|
||||||
const [key] = path;
|
const [key] = path;
|
||||||
if (key) return auto_set(root, key, data);
|
if (key) {
|
||||||
|
return auto_set(root, key, data);
|
||||||
|
}
|
||||||
console.error('autoSet unknown path', root, path, data);
|
console.error('autoSet unknown path', root, path, data);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -191,6 +202,7 @@ export class YjsContentOperation implements ContentOperation {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/naming-convention
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
||||||
|
// @ts-ignore
|
||||||
private toJSON() {
|
private toJSON() {
|
||||||
return this._content.toJSON();
|
return this._content.toJSON();
|
||||||
}
|
}
|
||||||
@@ -283,7 +295,9 @@ class YjsArrayOperation<T extends ContentTypes>
|
|||||||
|
|
||||||
get(index: number): Operable<T> | undefined {
|
get(index: number): Operable<T> | undefined {
|
||||||
const content = this._arrayContent.get(index);
|
const content = this._arrayContent.get(index);
|
||||||
if (content) return this.to_operable(content);
|
if (content) {
|
||||||
|
return this.to_operable(content);
|
||||||
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -368,7 +382,9 @@ class YjsMapOperation<T extends ContentTypes>
|
|||||||
set(key: string, value: Operable<T>): void {
|
set(key: string, value: Operable<T>): void {
|
||||||
if (value instanceof YjsContentOperation) {
|
if (value instanceof YjsContentOperation) {
|
||||||
const content = value[INTO_INNER]();
|
const content = value[INTO_INNER]();
|
||||||
if (content) this._mapContent.set(key, content as unknown as T);
|
if (content) {
|
||||||
|
this._mapContent.set(key, content as unknown as T);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
this._mapContent.set(key, value as T);
|
this._mapContent.set(key, value as T);
|
||||||
}
|
}
|
||||||
@@ -376,7 +392,9 @@ class YjsMapOperation<T extends ContentTypes>
|
|||||||
|
|
||||||
get(key: string): Operable<T> | undefined {
|
get(key: string): Operable<T> | undefined {
|
||||||
const content = this._mapContent.get(key);
|
const content = this._mapContent.get(key);
|
||||||
if (content) return this.to_operable(content);
|
if (content) {
|
||||||
|
return this.to_operable(content);
|
||||||
|
}
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -7,13 +7,13 @@ import {
|
|||||||
WebsocketProvider,
|
WebsocketProvider,
|
||||||
} from '@toeverything/datasource/jwt-rpc';
|
} from '@toeverything/datasource/jwt-rpc';
|
||||||
|
|
||||||
import { Connectivity } from '../../adapter';
|
import { BucketBackend } from '../types';
|
||||||
import { BucketBackend } from '../../types';
|
import { Connectivity } from './types';
|
||||||
|
|
||||||
type YjsDefaultInstances = {
|
type YjsDefaultInstances = {
|
||||||
awareness: Awareness;
|
awareness: Awareness;
|
||||||
doc: Doc;
|
doc: Doc;
|
||||||
token?: string;
|
token?: string | undefined;
|
||||||
workspace: string;
|
workspace: string;
|
||||||
emitState: (connectivity: Connectivity) => void;
|
emitState: (connectivity: Connectivity) => void;
|
||||||
};
|
};
|
||||||
@@ -139,8 +139,8 @@ interface AsyncDatabaseAdapter<C extends ContentOperation> {
|
|||||||
reload(): void;
|
reload(): void;
|
||||||
createBlock(
|
createBlock(
|
||||||
options: Pick<BlockItem<C>, 'type' | 'flavor'> & {
|
options: Pick<BlockItem<C>, 'type' | 'flavor'> & {
|
||||||
binary?: ArrayBuffer;
|
binary: ArrayBuffer | undefined;
|
||||||
uuid?: string;
|
uuid: string | undefined;
|
||||||
}
|
}
|
||||||
): Promise<BlockInstance<C>>;
|
): Promise<BlockInstance<C>>;
|
||||||
getBlock(id: string): Promise<BlockInstance<C> | undefined>;
|
getBlock(id: string): Promise<BlockInstance<C> | undefined>;
|
||||||
@@ -184,8 +184,6 @@ export const getDataExporter = () => {
|
|||||||
return { importData, exportData, hasExporter, installExporter };
|
return { importData, exportData, hasExporter, installExporter };
|
||||||
};
|
};
|
||||||
|
|
||||||
export { YjsAdapter } from './yjs';
|
|
||||||
export type { YjsContentOperation, YjsInitOptions } from './yjs';
|
|
||||||
export type {
|
export type {
|
||||||
AsyncDatabaseAdapter,
|
AsyncDatabaseAdapter,
|
||||||
BlockPosition,
|
BlockPosition,
|
||||||
57
pnpm-lock.yaml
generated
57
pnpm-lock.yaml
generated
@@ -184,7 +184,7 @@ importers:
|
|||||||
yjs: ^13.5.41
|
yjs: ^13.5.41
|
||||||
dependencies:
|
dependencies:
|
||||||
authing-js-sdk: 4.23.35
|
authing-js-sdk: 4.23.35
|
||||||
firebase-admin: 11.0.1_@firebase+app-types@0.7.0
|
firebase-admin: 11.0.1
|
||||||
lib0: 0.2.52
|
lib0: 0.2.52
|
||||||
lru-cache: 7.13.2
|
lru-cache: 7.13.2
|
||||||
nanoid: 4.0.0
|
nanoid: 4.0.0
|
||||||
@@ -566,6 +566,9 @@ importers:
|
|||||||
dependencies:
|
dependencies:
|
||||||
ffc-js-client-side-sdk: 1.1.5
|
ffc-js-client-side-sdk: 1.1.5
|
||||||
|
|
||||||
|
libs/datasource/jwst/pkg:
|
||||||
|
specifiers: {}
|
||||||
|
|
||||||
libs/datasource/jwt:
|
libs/datasource/jwt:
|
||||||
specifiers:
|
specifiers:
|
||||||
'@types/debug': ^4.1.7
|
'@types/debug': ^4.1.7
|
||||||
@@ -583,7 +586,7 @@ importers:
|
|||||||
idb-keyval: ^6.2.0
|
idb-keyval: ^6.2.0
|
||||||
immer: ^9.0.15
|
immer: ^9.0.15
|
||||||
lib0: ^0.2.52
|
lib0: ^0.2.52
|
||||||
lru-cache: ^7.13.2
|
lru-cache: ^7.14.0
|
||||||
nanoid: ^4.0.0
|
nanoid: ^4.0.0
|
||||||
sha3: ^2.1.4
|
sha3: ^2.1.4
|
||||||
sift: ^16.0.0
|
sift: ^16.0.0
|
||||||
@@ -614,7 +617,7 @@ importers:
|
|||||||
file-selector: 0.6.0
|
file-selector: 0.6.0
|
||||||
flexsearch: 0.7.21
|
flexsearch: 0.7.21
|
||||||
lib0: 0.2.52
|
lib0: 0.2.52
|
||||||
lru-cache: 7.13.2
|
lru-cache: 7.14.0
|
||||||
ts-debounce: 4.0.0
|
ts-debounce: 4.0.0
|
||||||
|
|
||||||
libs/datasource/jwt-rpc:
|
libs/datasource/jwt-rpc:
|
||||||
@@ -3180,6 +3183,15 @@ packages:
|
|||||||
- utf-8-validate
|
- utf-8-validate
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@firebase/auth-interop-types/0.1.6_@firebase+util@1.6.3:
|
||||||
|
resolution: {integrity: sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==}
|
||||||
|
peerDependencies:
|
||||||
|
'@firebase/app-types': 0.x
|
||||||
|
'@firebase/util': 1.x
|
||||||
|
dependencies:
|
||||||
|
'@firebase/util': 1.6.3
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@firebase/auth-interop-types/0.1.6_pbfwexsq7uf6mrzcwnikj3g37m:
|
/@firebase/auth-interop-types/0.1.6_pbfwexsq7uf6mrzcwnikj3g37m:
|
||||||
resolution: {integrity: sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==}
|
resolution: {integrity: sha512-etIi92fW3CctsmR9e3sYM3Uqnoq861M0Id9mdOPF6PWIg38BXL5k4upCNBggGUpLIS0H1grMOvy/wn1xymwe2g==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -3188,6 +3200,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@firebase/app-types': 0.7.0
|
'@firebase/app-types': 0.7.0
|
||||||
'@firebase/util': 1.6.3
|
'@firebase/util': 1.6.3
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@firebase/auth-types/0.11.0_pbfwexsq7uf6mrzcwnikj3g37m:
|
/@firebase/auth-types/0.11.0_pbfwexsq7uf6mrzcwnikj3g37m:
|
||||||
resolution: {integrity: sha512-q7Bt6cx+ySj9elQHTsKulwk3+qDezhzRBFC9zlQ1BjgMueUOnGMcvqmU0zuKlQ4RhLSH7MNAdBV2znVaoN3Vxw==}
|
resolution: {integrity: sha512-q7Bt6cx+ySj9elQHTsKulwk3+qDezhzRBFC9zlQ1BjgMueUOnGMcvqmU0zuKlQ4RhLSH7MNAdBV2znVaoN3Vxw==}
|
||||||
@@ -3223,6 +3236,19 @@ packages:
|
|||||||
'@firebase/util': 1.6.3
|
'@firebase/util': 1.6.3
|
||||||
tslib: 2.4.0
|
tslib: 2.4.0
|
||||||
|
|
||||||
|
/@firebase/database-compat/0.2.4:
|
||||||
|
resolution: {integrity: sha512-VtsGixO5mTjNMJn6PwxAJEAR70fj+3blCXIdQKel3q+eYGZAfdqxox1+tzZDnf9NWBJpaOgAHPk3JVDxEo9NFQ==}
|
||||||
|
dependencies:
|
||||||
|
'@firebase/component': 0.5.17
|
||||||
|
'@firebase/database': 0.13.4
|
||||||
|
'@firebase/database-types': 0.9.12
|
||||||
|
'@firebase/logger': 0.3.3
|
||||||
|
'@firebase/util': 1.6.3
|
||||||
|
tslib: 2.4.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@firebase/app-types'
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@firebase/database-compat/0.2.4_@firebase+app-types@0.7.0:
|
/@firebase/database-compat/0.2.4_@firebase+app-types@0.7.0:
|
||||||
resolution: {integrity: sha512-VtsGixO5mTjNMJn6PwxAJEAR70fj+3blCXIdQKel3q+eYGZAfdqxox1+tzZDnf9NWBJpaOgAHPk3JVDxEo9NFQ==}
|
resolution: {integrity: sha512-VtsGixO5mTjNMJn6PwxAJEAR70fj+3blCXIdQKel3q+eYGZAfdqxox1+tzZDnf9NWBJpaOgAHPk3JVDxEo9NFQ==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3234,6 +3260,7 @@ packages:
|
|||||||
tslib: 2.4.0
|
tslib: 2.4.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@firebase/app-types'
|
- '@firebase/app-types'
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@firebase/database-types/0.9.10:
|
/@firebase/database-types/0.9.10:
|
||||||
resolution: {integrity: sha512-2ji6nXRRsY+7hgU6zRhUtK0RmSjVWM71taI7Flgaw+BnopCo/lDF5HSwxp8z7LtiHlvQqeRA3Ozqx5VhlAbiKg==}
|
resolution: {integrity: sha512-2ji6nXRRsY+7hgU6zRhUtK0RmSjVWM71taI7Flgaw+BnopCo/lDF5HSwxp8z7LtiHlvQqeRA3Ozqx5VhlAbiKg==}
|
||||||
@@ -3248,6 +3275,19 @@ packages:
|
|||||||
'@firebase/app-types': 0.7.0
|
'@firebase/app-types': 0.7.0
|
||||||
'@firebase/util': 1.6.3
|
'@firebase/util': 1.6.3
|
||||||
|
|
||||||
|
/@firebase/database/0.13.4:
|
||||||
|
resolution: {integrity: sha512-NW7bOoiaC4sJCj6DY/m9xHoFNa0CK32YPMCh6FiMweLCDQbOZM8Ql/Kn6yyuxCb7K7ypz9eSbRlCWQJsJRQjhg==}
|
||||||
|
dependencies:
|
||||||
|
'@firebase/auth-interop-types': 0.1.6_@firebase+util@1.6.3
|
||||||
|
'@firebase/component': 0.5.17
|
||||||
|
'@firebase/logger': 0.3.3
|
||||||
|
'@firebase/util': 1.6.3
|
||||||
|
faye-websocket: 0.11.4
|
||||||
|
tslib: 2.4.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- '@firebase/app-types'
|
||||||
|
dev: false
|
||||||
|
|
||||||
/@firebase/database/0.13.4_@firebase+app-types@0.7.0:
|
/@firebase/database/0.13.4_@firebase+app-types@0.7.0:
|
||||||
resolution: {integrity: sha512-NW7bOoiaC4sJCj6DY/m9xHoFNa0CK32YPMCh6FiMweLCDQbOZM8Ql/Kn6yyuxCb7K7ypz9eSbRlCWQJsJRQjhg==}
|
resolution: {integrity: sha512-NW7bOoiaC4sJCj6DY/m9xHoFNa0CK32YPMCh6FiMweLCDQbOZM8Ql/Kn6yyuxCb7K7ypz9eSbRlCWQJsJRQjhg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -3259,6 +3299,7 @@ packages:
|
|||||||
tslib: 2.4.0
|
tslib: 2.4.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@firebase/app-types'
|
- '@firebase/app-types'
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@firebase/firestore-compat/0.1.23_53yvy43rwpg2c45kgeszsxtrca:
|
/@firebase/firestore-compat/0.1.23_53yvy43rwpg2c45kgeszsxtrca:
|
||||||
resolution: {integrity: sha512-QfcuyMAavp//fQnjSfCEpnbWi7spIdKaXys1kOLu7395fLr+U6ykmto1HUMCSz8Yus9cEr/03Ujdi2SUl2GUAA==}
|
resolution: {integrity: sha512-QfcuyMAavp//fQnjSfCEpnbWi7spIdKaXys1kOLu7395fLr+U6ykmto1HUMCSz8Yus9cEr/03Ujdi2SUl2GUAA==}
|
||||||
@@ -10332,12 +10373,12 @@ packages:
|
|||||||
semver-regex: 2.0.0
|
semver-regex: 2.0.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/firebase-admin/11.0.1_@firebase+app-types@0.7.0:
|
/firebase-admin/11.0.1:
|
||||||
resolution: {integrity: sha512-rL3wlZbi2Kb/KJgcmj1YHlD4ZhfmhfgRO2YJialxAllm0tj1IQea878hHuBLGmv4DpbW9t9nLvX9kddNR2Y65Q==}
|
resolution: {integrity: sha512-rL3wlZbi2Kb/KJgcmj1YHlD4ZhfmhfgRO2YJialxAllm0tj1IQea878hHuBLGmv4DpbW9t9nLvX9kddNR2Y65Q==}
|
||||||
engines: {node: '>=14'}
|
engines: {node: '>=14'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@fastify/busboy': 1.1.0
|
'@fastify/busboy': 1.1.0
|
||||||
'@firebase/database-compat': 0.2.4_@firebase+app-types@0.7.0
|
'@firebase/database-compat': 0.2.4
|
||||||
'@firebase/database-types': 0.9.10
|
'@firebase/database-types': 0.9.10
|
||||||
'@types/node': 18.0.1
|
'@types/node': 18.0.1
|
||||||
jsonwebtoken: 8.5.1
|
jsonwebtoken: 8.5.1
|
||||||
@@ -13573,6 +13614,12 @@ packages:
|
|||||||
/lru-cache/7.13.2:
|
/lru-cache/7.13.2:
|
||||||
resolution: {integrity: sha512-VJL3nIpA79TodY/ctmZEfhASgqekbT574/c4j3jn4bKXbSCnTTCH/KltZyvL2GlV+tGSMtsWyem8DCX7qKTMBA==}
|
resolution: {integrity: sha512-VJL3nIpA79TodY/ctmZEfhASgqekbT574/c4j3jn4bKXbSCnTTCH/KltZyvL2GlV+tGSMtsWyem8DCX7qKTMBA==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
|
/lru-cache/7.14.0:
|
||||||
|
resolution: {integrity: sha512-EIRtP1GrSJny0dqb50QXRUNBxHJhcpxHC++M5tD7RYbvLLn5KVWKsbyswSSqDuU15UFi3bgTQIY8nhDMeF6aDQ==}
|
||||||
|
engines: {node: '>=12'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/lru-memoizer/2.1.4:
|
/lru-memoizer/2.1.4:
|
||||||
resolution: {integrity: sha512-IXAq50s4qwrOBrXJklY+KhgZF+5y98PDaNo0gi/v2KQBFLyWr+JyFvijZXkGKjQj/h9c0OwoE+JZbwUXce76hQ==}
|
resolution: {integrity: sha512-IXAq50s4qwrOBrXJklY+KhgZF+5y98PDaNo0gi/v2KQBFLyWr+JyFvijZXkGKjQj/h9c0OwoE+JZbwUXce76hQ==}
|
||||||
|
|||||||
Reference in New Issue
Block a user