From 6ab5ae48650681800ac6ccb0e3122bbfe61b40fc Mon Sep 17 00:00:00 2001 From: Trevor Manz Date: Thu, 28 Sep 2023 16:35:22 -0400 Subject: [PATCH 1/4] feat: replace uuid with cyrpto.randomUUID() --- editor/Editor.tsx | 4 ++-- package.json | 4 +--- src/compiler/gosling-to-higlass.ts | 6 +++--- src/compiler/higlass-model.test.ts | 6 +++--- src/compiler/higlass-model.ts | 8 ++++---- src/compiler/spec-preprocess.ts | 10 +++++----- src/core/gosling-component.tsx | 4 ++-- src/core/higlass-component-wrapper.tsx | 6 +++--- src/core/utils/uuid.ts | 8 ++++++++ src/tracks/gosling-brush/brush-track.ts | 4 ++-- .../gosling-mouse-event/mouse-event-model.ts | 8 ++++---- src/tracks/gosling-track/gosling-track-model.ts | 4 ++-- src/tracks/gosling-track/gosling-track.ts | 6 +++--- vite.config.js | 3 +-- yarn.lock | 5 ----- 15 files changed, 43 insertions(+), 43 deletions(-) create mode 100644 src/core/utils/uuid.ts diff --git a/editor/Editor.tsx b/editor/Editor.tsx index f2c4a369c..83e8410dd 100644 --- a/editor/Editor.tsx +++ b/editor/Editor.tsx @@ -27,7 +27,7 @@ import EditorPanel, { type EditorLangauge } from './EditorPanel'; import EditorExamples from './EditorExamples'; import './Editor.css'; -import { v4 } from 'uuid'; +import { uuid } from '../src/core/utils/uuid'; function json2js(jsonCode: string) { return `var spec = ${jsonCode} \nexport { spec }; \n`; @@ -723,7 +723,7 @@ function Editor(props: RouteComponentProps) { } return (
{ it('Should set default values correctly', () => { @@ -11,7 +11,7 @@ describe('Should produce higlass model correctly', () => { it('Should set domain correctly', () => { const higlass = new HiGlassModel(); - higlass.addDefaultView(uuid.v1()); + higlass.addDefaultView(uuid()); higlass.setDomain({ chromosome: 'chr2' }, { chromosome: 'chr2', interval: [100, 200] }); expect(higlass.spec().views?.[0].initialXDomain).toEqual([ computeChromSizes().interval['chr2'][0] + 1, @@ -23,7 +23,7 @@ describe('Should produce higlass model correctly', () => { it('Should add brush correctly', () => { const higlass = new HiGlassModel(); - higlass.addDefaultView(uuid.v1()); + higlass.addDefaultView(uuid()); higlass.addBrush('linear', higlass.getLastView().uid ?? '', getTheme(), 'from'); expect(JSON.stringify(higlass.spec())).toContain('viewport-projection-horizontal'); }); diff --git a/src/compiler/higlass-model.ts b/src/compiler/higlass-model.ts index d3c818027..dffc9198d 100644 --- a/src/compiler/higlass-model.ts +++ b/src/compiler/higlass-model.ts @@ -1,4 +1,3 @@ -import * as uuid from 'uuid'; import type { HiGlassSpec, Track } from '@gosling-lang/higlass-schema'; import { HiGlassSchema } from '@gosling-lang/higlass-schema'; import type { Assembly, AxisPosition, Domain, DummyTrack, Orientation, ZoomLimits } from '@gosling-lang/gosling-schema'; @@ -9,6 +8,7 @@ import { getAutoCompleteId, computeChromSizes } from '../core/utils/assembly'; import type { CompleteThemeDeep } from '../core/utils/theme'; import exampleHg from '../core/example/hg-view-config-1'; import { insertItemToArray } from '../core/utils/array'; +import { uuid } from '../core/utils/uuid'; export const HIGLASS_AXIS_SIZE = 30; @@ -163,7 +163,7 @@ export class HiGlassModel { (this.getView(viewId) as any)?.tracks.whole.push({ // type: 'viewport-projection-center', type: layout === 'circular' ? 'brush-track' : 'viewport-projection-horizontal', - uid: uuid.v4(), + uid: uuid(), fromViewUid, options: { projectionFillColor: style?.color ?? theme.brush.color, @@ -288,7 +288,7 @@ export class HiGlassModel { this.getLastView().tracks[this.getMainTrackPosition()] = [ { type: 'combined', - uid: `${track.uid ?? uuid.v4()}-${this.getMainTrackPosition()}-combined`, + uid: `${track.uid ?? uuid()}-${this.getMainTrackPosition()}-combined`, // !! Hacky, but it is important to subtract 1px. Currently, HiGlass does not well handle a case where a center track is zero width (e.g., linking between views that contain zero-width center tracks). // https://github.com/higlass/higlass/pull/1041 width: (track as any).width - 1, @@ -324,7 +324,7 @@ export class HiGlassModel { const widthOrHeight = position === 'left' || position === 'right' ? 'width' : 'height'; const axisTrackTemplate: Track = { - // uid: options.id ?? uuid.v1(), // TODO: turning this on makes some tick labels hidden + // uid: options.id ?? uuid(), // TODO: turning this on makes some tick labels hidden type: 'axis-track', chromInfoPath: this.hg.chromInfoPath, options: { diff --git a/src/compiler/spec-preprocess.ts b/src/compiler/spec-preprocess.ts index e082ae4f1..1a45be45f 100644 --- a/src/compiler/spec-preprocess.ts +++ b/src/compiler/spec-preprocess.ts @@ -1,4 +1,3 @@ -import * as uuid from 'uuid'; import type { SingleTrack, GoslingSpec, @@ -31,6 +30,7 @@ import { } from './defaults'; import { spreadTracksByData } from '../core/utils/overlay'; import { getStyleOverridden } from '../core/utils/style'; +import { uuid } from '../core/utils/uuid'; /** * Traverse individual tracks and call the callback function to read and/or update the track definition. @@ -176,7 +176,7 @@ export function traverseToFixSpecDownstream(spec: GoslingSpec | SingleView, pare // ID should be assigned to each view and track for an API usage if (!spec.id) { - spec.id = uuid.v4(); + spec.id = uuid(); } if ('tracks' in spec) { @@ -188,11 +188,11 @@ export function traverseToFixSpecDownstream(spec: GoslingSpec | SingleView, pare */ tracks = spreadTracksByData(tracks); - const linkID = uuid.v4(); + const linkID = uuid(); tracks.forEach((track, i, array) => { // ID should be assigned to each view and track for an API usage if (!track.id) { - track.id = uuid.v4(); + track.id = uuid(); } // If size not defined, set default ones @@ -215,7 +215,7 @@ export function traverseToFixSpecDownstream(spec: GoslingSpec | SingleView, pare track.xe.field // Question: Should we consider mark types? (e.g., link might not be supported?) ) { - const newField = uuid.v4(); + const newField = uuid(); const startField = track.x.field; const endField = track.xe.field; const padding = track.displacement.padding; diff --git a/src/core/gosling-component.tsx b/src/core/gosling-component.tsx index f57600525..a11ed71c4 100644 --- a/src/core/gosling-component.tsx +++ b/src/core/gosling-component.tsx @@ -10,10 +10,10 @@ import { createApi, type GoslingApi } from '../api/api'; import { GoslingTemplates } from '..'; import { omitDeep } from './utils/omit-deep'; import { isEqual } from 'lodash-es'; -import * as uuid from 'uuid'; import { publish } from '../api/pubsub'; import type { IdTable } from '../api/track-and-view-ids'; import { preverseZoomStatus } from './utils/higlass-zoom-config'; +import { uuid } from '../core/utils/uuid'; // Before rerendering, wait for a few time so that HiGlass container is resized already. // If HiGlass is rendered and then the container resizes, the viewport position changes, unmatching `xDomain` specified by users. @@ -59,7 +59,7 @@ export const GoslingComponent = forwardRef((props, const hgRef = useRef(null); const theme = getTheme(props.theme || 'light'); - const wrapperDivId = props.id ?? uuid.v4(); + const wrapperDivId = props.id ?? uuid(); /** * Publishes event if there is a new view added diff --git a/src/core/higlass-component-wrapper.tsx b/src/core/higlass-component-wrapper.tsx index c864c2e9f..6cb92cf96 100644 --- a/src/core/higlass-component-wrapper.tsx +++ b/src/core/higlass-component-wrapper.tsx @@ -1,12 +1,12 @@ /* eslint-disable react/prop-types */ import type * as PIXI from 'pixi.js'; import React, { useEffect, useState, forwardRef, useMemo } from 'react'; -import * as uuid from 'uuid'; import * as gosling from '..'; // @ts-ignore import { HiGlassComponent } from 'higlass'; import type { HiGlassSpec } from '@gosling-lang/higlass-schema'; +import { uuid } from '../core/utils/uuid'; /** * Register plugin tracks and data fetchers to HiGlass. This is necessary for the first time before using Gosling. @@ -39,9 +39,9 @@ export interface HiGlassComponentWrapperProps { export const HiGlassComponentWrapper = forwardRef( (props, ref) => { // div `id` and `className` for detailed customization - const [wrapperDivId, setWrapperDivId] = useState(props.id ?? uuid.v4()); + const [wrapperDivId, setWrapperDivId] = useState(props.id ?? uuid()); useEffect(() => { - setWrapperDivId(props.id ?? uuid.v4()); + setWrapperDivId(props.id ?? uuid()); }, [props.id]); const viewConfig = props.viewConfig || {}; diff --git a/src/core/utils/uuid.ts b/src/core/utils/uuid.ts new file mode 100644 index 000000000..c6fae74e1 --- /dev/null +++ b/src/core/utils/uuid.ts @@ -0,0 +1,8 @@ +// for envs where crypto.randomUUID is not available (i.e., Node). +function fallback(): string { + return Math.random().toString(36).substring(2, 10); +} + +export function uuid(): string { + return globalThis.crypto.randomUUID?.() ?? fallback(); +} diff --git a/src/tracks/gosling-brush/brush-track.ts b/src/tracks/gosling-brush/brush-track.ts index cfc5de50b..728b38d30 100644 --- a/src/tracks/gosling-brush/brush-track.ts +++ b/src/tracks/gosling-brush/brush-track.ts @@ -1,7 +1,7 @@ import { arc as d3arc } from 'd3-shape'; import type { SubjectPosition, D3DragEvent } from 'd3-drag'; -import * as uuid from 'uuid'; import { RADIAN_GAP, valueToRadian } from '../../core/utils/polar'; +import { uuid } from '../../core/utils/uuid'; type CircularBrushData = { type: 'brush' | 'start' | 'end'; @@ -25,7 +25,7 @@ function BrushTrack(HGC: any, ...args: any[]): any { const [context, options] = params; const { registerViewportChanged, removeViewportChanged, setDomainsCallback } = context; - this.uid = uuid.v1(); + this.uid = uuid(); this.options = options; // Is there actually a linked from view? Or is this projection "independent"? diff --git a/src/tracks/gosling-track/gosling-mouse-event/mouse-event-model.ts b/src/tracks/gosling-track/gosling-mouse-event/mouse-event-model.ts index 4cca16122..c6f6d54a4 100644 --- a/src/tracks/gosling-track/gosling-mouse-event/mouse-event-model.ts +++ b/src/tracks/gosling-track/gosling-mouse-event/mouse-event-model.ts @@ -6,7 +6,7 @@ import { isPointNearPoint, isCircleWithinRange } from './polygon'; -import * as uuid from 'uuid'; +import { uuid } from '../../../core/utils/uuid'; export type MouseEventData = PointEventData | LineEventData | PolygonEventData; @@ -52,21 +52,21 @@ export class MouseEventModel { * Add a new mouse event that is polygon-based. */ public addPolygonBasedEvent(value: Datum, polygon: number[]) { - this.data.push({ uid: uuid.v4(), type: 'polygon', value, polygon }); + this.data.push({ uid: uuid(), type: 'polygon', value, polygon }); } /** * Add a new mouse event that is point-based. */ public addPointBasedEvent(value: Datum, pointAndRadius: [number, number, number]) { - this.data.push({ uid: uuid.v4(), type: 'point', value, polygon: pointAndRadius }); + this.data.push({ uid: uuid(), type: 'point', value, polygon: pointAndRadius }); } /** * Add a new mouse event that is line-based. */ public addLineBasedEvent(value: Datum, path: number[]) { - this.data.push({ uid: uuid.v4(), type: 'line', value, polygon: path }); + this.data.push({ uid: uuid(), type: 'line', value, polygon: path }); } /** diff --git a/src/tracks/gosling-track/gosling-track-model.ts b/src/tracks/gosling-track/gosling-track-model.ts index 3c926d9c2..af92f754b 100644 --- a/src/tracks/gosling-track/gosling-track-model.ts +++ b/src/tracks/gosling-track/gosling-track-model.ts @@ -1,4 +1,3 @@ -import * as uuid from 'uuid'; import type { ChannelDeep, PredefinedColors, @@ -42,6 +41,7 @@ import { } from '@gosling-lang/gosling-schema'; import { CHANNEL_DEFAULTS } from '../../core/channel'; import { type CompleteThemeDeep, getTheme } from '../../core/utils/theme'; +import { uuid } from '../../core/utils/uuid'; import { MouseEventModel } from '../gosling-track/gosling-mouse-event'; export type ScaleType = @@ -73,7 +73,7 @@ export class GoslingTrackModel { private mouseEventModel: MouseEventModel; constructor(spec: SingleTrack, data: { [k: string]: number | string }[], theme: Required) { - this.id = uuid.v1(); + this.id = uuid(); this.theme = theme ?? getTheme(); diff --git a/src/tracks/gosling-track/gosling-track.ts b/src/tracks/gosling-track/gosling-track.ts index 1fd74c5da..798fc0aaa 100644 --- a/src/tracks/gosling-track/gosling-track.ts +++ b/src/tracks/gosling-track/gosling-track.ts @@ -1,5 +1,4 @@ import type * as PIXI from 'pixi.js'; -import * as uuid from 'uuid'; import { isEqual, sampleSize, uniqBy } from 'lodash-es'; import type { ScaleLinear } from 'd3-scale'; import type { @@ -52,6 +51,7 @@ import { import { HIGLASS_AXIS_SIZE } from '../../compiler/higlass-model'; import { flatArrayToPairArray } from '../../core/utils/array'; import { createPluginTrack, type PluginTrackFactory, type TrackConfig } from '../../core/utils/define-plugin-track'; +import { uuid } from '../../core/utils/uuid'; // Set `true` to print in what order each function is called export const PRINT_RENDERING_CYCLE = false; @@ -190,10 +190,10 @@ const factory: PluginTrackFactory = (HGC, context, op // Add unique IDs to each of the overlaid tracks that will be rendered independently. if ('overlay' in this.options.spec) { this.options.spec.overlay = (this.options.spec as OverlaidTrack).overlay.map(o => { - return { ...o, _renderingId: uuid.v1() }; + return { ...o, _renderingId: uuid() }; }); } else { - this.options.spec._renderingId = uuid.v1(); + this.options.spec._renderingId = uuid(); } this.fetchedTiles = {}; diff --git a/vite.config.js b/vite.config.js index f4c136834..2495fc300 100644 --- a/vite.config.js +++ b/vite.config.js @@ -63,11 +63,10 @@ const alias = { "@gosling-lang/dummy-track": path.resolve(__dirname, "./src/tracks/dummy-track/index.ts"), "@data-fetchers": path.resolve(__dirname, "./src/data-fetchers/index.ts"), zlib: path.resolve(__dirname, './src/alias/zlib.ts'), - uuid: path.resolve(__dirname, './node_modules/uuid/dist/esm-browser/index.js'), stream: path.resolve(__dirname, './node_modules/stream-browserify') }; -const skipExt = new Set(['@gmod/bbi', 'uuid']); +const skipExt = new Set(['@gmod/bbi']); const external = [...Object.keys(pkg.dependencies), ...Object.keys(pkg.peerDependencies)].filter( dep => !skipExt.has(dep) ); diff --git a/yarn.lock b/yarn.lock index 10af5afc8..2878f5633 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1135,11 +1135,6 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== -"@types/uuid@^8.3.1": - version "8.3.4" - resolved "https://registry.yarnpkg.com/@types/uuid/-/uuid-8.3.4.tgz#bd86a43617df0594787d38b735f55c805becf1bc" - integrity sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw== - "@types/yargs-parser@*": version "21.0.0" resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" From fea260694e4df0122ec7bbec62d5108fa92ffcfd Mon Sep 17 00:00:00 2001 From: Trevor Manz Date: Thu, 28 Sep 2023 16:36:45 -0400 Subject: [PATCH 2/4] chore: formatting --- src/core/utils/uuid.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/utils/uuid.ts b/src/core/utils/uuid.ts index c6fae74e1..b5ef982b2 100644 --- a/src/core/utils/uuid.ts +++ b/src/core/utils/uuid.ts @@ -1,8 +1,8 @@ // for envs where crypto.randomUUID is not available (i.e., Node). function fallback(): string { - return Math.random().toString(36).substring(2, 10); + return Math.random().toString(36).substring(2, 10); } export function uuid(): string { - return globalThis.crypto.randomUUID?.() ?? fallback(); + return globalThis.crypto.randomUUID?.() ?? fallback(); } From c7192754ad60b7142a1719883d7dd5ae9625257c Mon Sep 17 00:00:00 2001 From: etowahadams Date: Thu, 26 Oct 2023 17:21:17 -0400 Subject: [PATCH 3/4] chore: remove uuid type --- package.json | 1 - yarn.lock | 12 ------------ 2 files changed, 13 deletions(-) diff --git a/package.json b/package.json index 76664fb3a..79260f0c2 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,6 @@ "@types/react-dom": "^18.2.0", "@types/react-resize-detector": "^4.2.0", "@types/react-router-dom": "^5.1.6", - "@types/uuid": "^8.3.1", "@typescript-eslint/eslint-plugin": "^5.56.0", "@typescript-eslint/parser": "^5.56.0", "@vitejs/plugin-react": "^4.1.0", diff --git a/yarn.lock b/yarn.lock index fc2563341..aa6ff1fd6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1278,18 +1278,6 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== -"@types/yargs-parser@*": - version "21.0.0" - resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" - integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== - -"@types/yargs@^15.0.0": - version "15.0.15" - resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-15.0.15.tgz#e609a2b1ef9e05d90489c2f5f45bbfb2be092158" - integrity sha512-IziEYMU9XoVj8hWg7k+UJrXALkGFjWJhn5QFEv9q4p+v40oZhSuC135M38st8XPjICL7Ey4TV64ferBGUoJhBg== - dependencies: - "@types/yargs-parser" "*" - "@typescript-eslint/eslint-plugin@^5.56.0": version "5.58.0" resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.58.0.tgz#b1d4b0ad20243269d020ef9bbb036a40b0849829" From cd2de4ea58f65341d75156ccc67ea835d7512a8d Mon Sep 17 00:00:00 2001 From: etowahadams Date: Thu, 26 Oct 2023 17:23:57 -0400 Subject: [PATCH 4/4] fix: add _ to overlay --- src/tracks/gosling-track/gosling-track.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tracks/gosling-track/gosling-track.ts b/src/tracks/gosling-track/gosling-track.ts index 798fc0aaa..91c68f32e 100644 --- a/src/tracks/gosling-track/gosling-track.ts +++ b/src/tracks/gosling-track/gosling-track.ts @@ -189,7 +189,7 @@ const factory: PluginTrackFactory = (HGC, context, op // Add unique IDs to each of the overlaid tracks that will be rendered independently. if ('overlay' in this.options.spec) { - this.options.spec.overlay = (this.options.spec as OverlaidTrack).overlay.map(o => { + this.options.spec.overlay = (this.options.spec as OverlaidTrack)._overlay.map(o => { return { ...o, _renderingId: uuid() }; }); } else {