Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix type errors in devtools package #938

Merged
merged 5 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/devtools-publish.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ on:
branches:
- 'main'
paths:
- packages/devtools/**
- packages/devtools/package.json
jobs:
build-and-deploy:
runs-on: ubuntu-latest
Expand Down
10 changes: 7 additions & 3 deletions packages/devtools/src/devtools/components/Detail.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,13 @@ function TreeGraph({ tree }: { tree: Devtools.TreeNodeInfo }) {
[],
);

return flattenTreeWithDepth(tree).map((node) => (
<TreeNode key={node.id} node={node} />
));
return (
<>
{flattenTreeWithDepth(tree).map((node) => (
<TreeNode key={node.id} node={node} />
))}
</>
);
}

export function TreeDetail({
Expand Down
4 changes: 2 additions & 2 deletions packages/devtools/src/devtools/components/Tree.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import useResizeObserver from 'use-resize-observer';

import { useSelectedNode } from '../contexts/SelectedNode';
import { useSelectedPresence } from '../contexts/SelectedPresence';
import type { Devtools } from 'yorkie-js-sdk';
import type { Devtools, Json } from 'yorkie-js-sdk';

import {
ArrayIcon,
Expand All @@ -47,7 +47,7 @@ export type UserNode = Devtools.Client & {
export type PresenceJsonNode = {
id: string;
key: string;
value: Devtools.Json;
value: Json;
isLastChild: boolean;
type: 'JSON';
};
Expand Down
57 changes: 26 additions & 31 deletions packages/devtools/src/devtools/contexts/YorkieSource.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,18 +24,14 @@ import {
useState,
} from 'react';

import {
DocEventType,
type SDKToPanelMessage,
type TransactionEvent,
} from 'yorkie-js-sdk';
import { DocEventType, Devtools, type SDKToPanelMessage } from 'yorkie-js-sdk';
import { connectPort, sendToSDK } from '../../port';
import { Code, YorkieError } from '@yorkie-js-sdk/src/util/error';

const DocKeyContext = createContext<string>(null);
const YorkieDocContext = createContext(null);
const TransactionEventsContext = createContext<{
events: Array<TransactionEvent>;
const ReplayDocEventsContext = createContext<{
events: Array<Devtools.EventsForDocReplay>;
hidePresenceEvents: boolean;
setHidePresenceEvents: Dispatch<SetStateAction<boolean>>;
}>(null);
Expand All @@ -47,17 +43,16 @@ type Props = {
export function YorkieSourceProvider({ children }: Props) {
const [currentDocKey, setCurrentDocKey] = useState<string>('');
const [doc, setDoc] = useState(null);
const [transactionEvents, setTransactionEvents] = useState<
Array<TransactionEvent>
const [replayDocEvents, setReplayDocEvents] = useState<
Array<Devtools.EventsForDocReplay>
>([]);

// filter out presence events
const [hideTransactionPresenceEvents, setHideTransactionPresenceEvents] =
useState(false);
const [hidePresenceEvents, setHidePresenceEvents] = useState(false);

const resetDocument = () => {
setCurrentDocKey('');
setTransactionEvents([]);
setReplayDocEvents([]);
setDoc(null);
};

Expand All @@ -77,11 +72,11 @@ export function YorkieSourceProvider({ children }: Props) {
case 'doc::sync::full':
// TODO(chacha912): Notify the user that they need to use the latest version of Yorkie-JS-SDK.
if (message.events === undefined) break;
setTransactionEvents(message.events);
setReplayDocEvents(message.events);
break;
case 'doc::sync::partial':
if (message.event === undefined) break;
setTransactionEvents((events) => [...events, message.event]);
setReplayDocEvents((events) => [...events, message.event]);
break;
}
}, []);
Expand All @@ -108,17 +103,17 @@ export function YorkieSourceProvider({ children }: Props) {

return (
<DocKeyContext.Provider value={currentDocKey}>
<TransactionEventsContext.Provider
<ReplayDocEventsContext.Provider
value={{
events: transactionEvents,
hidePresenceEvents: hideTransactionPresenceEvents,
setHidePresenceEvents: setHideTransactionPresenceEvents,
events: replayDocEvents,
hidePresenceEvents,
setHidePresenceEvents,
}}
>
<YorkieDocContext.Provider value={[doc, setDoc]}>
{children}
</YorkieDocContext.Provider>
</TransactionEventsContext.Provider>
</ReplayDocEventsContext.Provider>
</DocKeyContext.Provider>
);
}
Expand All @@ -145,51 +140,51 @@ export function useYorkieDoc() {
return value;
}

export enum TransactionEventType {
export enum ReplayDocEventType {
Document = 'document',
Presence = 'presence',
}

export const getTransactionEventType = (
event: TransactionEvent,
): TransactionEventType => {
export const getReplayDocEventType = (
event: Devtools.EventsForDocReplay,
): ReplayDocEventType => {
for (const docEvent of event) {
if (
docEvent.type === DocEventType.StatusChanged ||
docEvent.type === DocEventType.Snapshot ||
docEvent.type === DocEventType.LocalChange ||
docEvent.type === DocEventType.RemoteChange
) {
return TransactionEventType.Document;
return ReplayDocEventType.Document;
}
}

return TransactionEventType.Presence;
return ReplayDocEventType.Presence;
};

export function useTransactionEvents() {
export function useReplayDocEvents() {
const { events, hidePresenceEvents, setHidePresenceEvents } = useContext(
TransactionEventsContext,
ReplayDocEventsContext,
);

if (events === undefined) {
throw new YorkieError(
Code.ErrContextNotProvided,
'useTransactionEvents should be used within YorkieSourceProvider',
'useReplayDocEvents should be used within YorkieSourceProvider',
);
}

// create an enhanced events with metadata
const enhancedEvents = useMemo(() => {
return events.map((event) => {
const transactionEventType = getTransactionEventType(event);
const replayDocEventType = getReplayDocEventType(event);

return {
event,
transactionEventType,
replayDocEventType: replayDocEventType,
isFiltered:
hidePresenceEvents &&
transactionEventType === TransactionEventType.Presence,
replayDocEventType === ReplayDocEventType.Presence,
};
});
}, [hidePresenceEvents, events]);
Expand Down
6 changes: 3 additions & 3 deletions packages/devtools/src/devtools/panel/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ import { SelectedPresenceProvider } from '../contexts/SelectedPresence';
import {
YorkieSourceProvider,
useCurrentDocKey,
useTransactionEvents,
useReplayDocEvents,
useYorkieDoc,
} from '../contexts/YorkieSource';
import { Document } from '../tabs/Document';
Expand All @@ -34,7 +34,7 @@ import { Separator } from '../components/ResizableSeparator';
const Panel = () => {
const currentDocKey = useCurrentDocKey();
const { originalEvents, presenceFilteredEvents, hidePresenceEvents } =
useTransactionEvents();
useReplayDocEvents();
const [, setDoc] = useYorkieDoc();
const [selectedEventIndexInfo, setSelectedEventIndexInfo] = useState({
index: null,
Expand Down Expand Up @@ -91,7 +91,7 @@ const Panel = () => {
filteredEventIndex++;
}

doc.applyTransactionEvent(originalEvents[eventIndex].event);
doc.applyEventsForDocReplay(originalEvents[eventIndex].event);
eventIndex++;
}

Expand Down
16 changes: 8 additions & 8 deletions packages/devtools/src/devtools/tabs/History.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,18 +15,18 @@
*/

import { useEffect, useState, useRef } from 'react';
import { DocEventType, Change, type TransactionEvent } from 'yorkie-js-sdk';
import { DocEventType, Change, Devtools } from 'yorkie-js-sdk';
import Slider from 'rc-slider';
import { JSONView } from '../components/JsonView';
import { CursorIcon, DocumentIcon } from '../icons';
import {
TransactionEventType,
useTransactionEvents,
ReplayDocEventType,
useReplayDocEvents,
} from '../contexts/YorkieSource';

const SLIDER_MARK_WIDTH = 24;

const getEventInfo = (event: TransactionEvent) => {
const getEventInfo = (event: Devtools.EventsForDocReplay) => {
const info = [];
for (const docEvent of event) {
if (
Expand Down Expand Up @@ -75,7 +75,7 @@ export function History({
presenceFilteredEvents,
hidePresenceEvents,
setHidePresenceEvents,
} = useTransactionEvents();
} = useReplayDocEvents();

const events = hidePresenceEvents ? presenceFilteredEvents : originalEvents;

Expand Down Expand Up @@ -109,13 +109,13 @@ export function History({
const marks = {};
for (const [index, event] of events.entries()) {
const source = event.event[0].source;
const transactionEventType = event.transactionEventType;
const replayDocEventType = event.replayDocEventType;

marks[index] = (
<span
className={`mark-history mark-${source} mark-${transactionEventType}`}
className={`mark-history mark-${source} mark-${replayDocEventType}`}
>
{transactionEventType === TransactionEventType.Presence ? (
{replayDocEventType === ReplayDocEventType.Presence ? (
<CursorIcon />
) : (
<DocumentIcon />
Expand Down
36 changes: 10 additions & 26 deletions packages/sdk/src/devtools/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,29 @@
* limitations under the License.
*/

import {
Document,
Indexable,
TransactionEvent,
} from '@yorkie-js-sdk/src/yorkie';
import { DocEventType } from '@yorkie-js-sdk/src/document/document';
import { Document, Indexable } from '@yorkie-js-sdk/src/yorkie';
import { logger } from '@yorkie-js-sdk/src/util/logger';
import type * as DevTools from './protocol';
import { EventSourceDevPanel, EventSourceSDK } from './protocol';
import { EventsForDocReplay, isEventsForDocReplay } from './types';

type DevtoolsStatus = 'connected' | 'disconnected' | 'synced';
let devtoolsStatus: DevtoolsStatus = 'disconnected';
const unsubsByDocKey = new Map<string, Array<() => void>>();

/**
* `transactionEventsByDocKey` stores all events in the document for replaying
* `replayEventsByDocKey` stores all events in the document for replaying
* (time-traveling feature) in Devtools. Later, external storage such as
* IndexedDB will be used.
*/
const transactionEventsByDocKey = new Map<string, Array<TransactionEvent>>();
const replayEventsByDocKey = new Map<string, Array<EventsForDocReplay>>();
declare global {
interface Window {
transactionEventsByDocKey: Map<string, Array<TransactionEvent>>;
replayEventsByDocKey: Map<string, Array<EventsForDocReplay>>;
}
}
if (typeof window !== 'undefined') {
window.transactionEventsByDocKey = transactionEventsByDocKey;
window.replayEventsByDocKey = replayEventsByDocKey;
}

/**
Expand Down Expand Up @@ -79,25 +75,13 @@ export function setupDevtools<T, P extends Indexable>(
return;
}

transactionEventsByDocKey.set(doc.getKey(), []);
replayEventsByDocKey.set(doc.getKey(), []);
const unsub = doc.subscribe('all', (event) => {
if (
event.some(
(docEvent) =>
docEvent.type !== DocEventType.StatusChanged &&
docEvent.type !== DocEventType.Snapshot &&
docEvent.type !== DocEventType.LocalChange &&
docEvent.type !== DocEventType.RemoteChange &&
docEvent.type !== DocEventType.Initialized &&
docEvent.type !== DocEventType.Watched &&
docEvent.type !== DocEventType.Unwatched &&
docEvent.type !== DocEventType.PresenceChanged,
)
) {
if (!isEventsForDocReplay(event)) {
return;
}

transactionEventsByDocKey.get(doc.getKey())!.push(event);
replayEventsByDocKey.get(doc.getKey())!.push(event);
if (devtoolsStatus === 'synced') {
sendToPanel({
msg: 'doc::sync::partial',
Expand Down Expand Up @@ -148,7 +132,7 @@ export function setupDevtools<T, P extends Indexable>(
sendToPanel({
msg: 'doc::sync::full',
docKey: doc.getKey(),
events: transactionEventsByDocKey.get(doc.getKey())!,
events: replayEventsByDocKey.get(doc.getKey())!,
});
logger.info(`[YD] Devtools subscribed. Doc: ${doc.getKey()}`);
break;
Expand Down
6 changes: 3 additions & 3 deletions packages/sdk/src/devtools/protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
* limitations under the License.
*/

import type { TransactionEvent } from '@yorkie-js-sdk/src/document/document';
import { EventsForDocReplay } from './types';

/**
* `EventSourceDevPanel` is the name of the source representing messages
Expand Down Expand Up @@ -76,15 +76,15 @@ export type SDKToPanelMessage =
| {
msg: 'doc::sync::full';
docKey: string;
events: Array<TransactionEvent>;
events: Array<EventsForDocReplay>;
}
/**
* Sent whenever the document is changed.
chacha912 marked this conversation as resolved.
Show resolved Hide resolved
*/
| {
msg: 'doc::sync::partial';
docKey: string;
event: TransactionEvent;
event: EventsForDocReplay;
};

export type FullPanelToSDKMessage = PanelToSDKMessage & {
chacha912 marked this conversation as resolved.
Show resolved Hide resolved
Expand Down
Loading
Loading