Skip to content

Commit 5bda615

Browse files
committed
GLSP-1700: Introduce uuid helper
- Add shared uuid util to protocol package. Consuming packages should use the helper when needing uuids instead of depending on their own uuid version - Update code-base to consistently use new helper - Update eslint config to restrict direct 'uuid' imports and adjust import rules for examples Fixes eclipse-glsp/glsp#1700
1 parent 93e67ca commit 5bda615

12 files changed

Lines changed: 174 additions & 38 deletions

File tree

eslint.config.mjs

Lines changed: 80 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,14 @@ export default [
4747
name: 'sprotty-protocol',
4848
message:
4949
"The sprotty-protocol default exports are customized and reexported by GLSP. Please use '@eclipse-glsp/client' instead"
50+
},
51+
{
52+
name: 'uuid',
53+
message: "Use the 'generateUuid'/'isUuid' helpers (from '@eclipse-glsp/protocol') instead of importing 'uuid' directly."
54+
},
55+
{
56+
name: 'uuid/*',
57+
message: "Use the 'generateUuid'/'isUuid' helpers (from '@eclipse-glsp/protocol') instead of importing 'uuid' directly."
5058
}
5159
],
5260
'@typescript-eslint/no-unused-vars': [
@@ -59,7 +67,7 @@ export default [
5967
]
6068
}
6169
},
62-
// packages/protocol: restrict sprotty and circular @eclipse-glsp/client imports
70+
// packages/protocol: restrict sprotty and uuid direct imports
6371
{
6472
files: ['packages/protocol/src/**/*.{ts,tsx}'],
6573
rules: {
@@ -75,14 +83,14 @@ export default [
7583
message: "The protocol package should not have any direct 'sprotty' dependencies. Try to use 'sprotty-protocol' instead"
7684
},
7785
{
78-
name: '@eclipse-glsp/client',
86+
name: 'uuid',
7987
message:
80-
"Circular dependency! This package is consumed by '@eclipse-glsp' client. Consider moving the conflicting file into this package."
88+
"Use the 'generateUuid'/'isUuid' helpers (from this package's 'utils/uuid' module) instead of importing 'uuid' directly."
8189
},
8290
{
83-
name: '@eclipse-glsp/client/*',
91+
name: 'uuid/*',
8492
message:
85-
"Circular dependency! This package is consumed by '@eclipse-glsp' client. Consider moving the conflicting file into this package."
93+
"Use the 'generateUuid'/'isUuid' helpers (from this package's 'utils/uuid' module) instead of importing 'uuid' directly."
8694
}
8795
]
8896
}
@@ -101,6 +109,14 @@ export default [
101109
{
102110
name: 'sprotty-protocol/*',
103111
message: "Please use '@eclipse-glsp/protocol' instead"
112+
},
113+
{
114+
name: 'uuid',
115+
message: "Use the 'generateUuid'/'isUuid' helpers (from '@eclipse-glsp/protocol') instead of importing 'uuid' directly."
116+
},
117+
{
118+
name: 'uuid/*',
119+
message: "Use the 'generateUuid'/'isUuid' helpers (from '@eclipse-glsp/protocol') instead of importing 'uuid' directly."
104120
}
105121
]
106122
}
@@ -135,6 +151,65 @@ export default [
135151
{
136152
name: '@eclipse-glsp/protocol/*',
137153
message: 'Please use @eclipse-glsp/sprotty instead'
154+
},
155+
{
156+
name: 'uuid',
157+
message: "Use the 'generateUuid'/'isUuid' helpers (from '@eclipse-glsp/sprotty') instead of importing 'uuid' directly."
158+
},
159+
{
160+
name: 'uuid/*',
161+
message: "Use the 'generateUuid'/'isUuid' helpers (from '@eclipse-glsp/sprotty') instead of importing 'uuid' directly."
162+
}
163+
]
164+
}
165+
},
166+
// examples: only consume the public '@eclipse-glsp/client' API; the lower layers
167+
// (protocol, sprotty, raw sprotty/sprotty-protocol) are re-exported through it.
168+
{
169+
files: ['examples/*/src/**/*.{ts,tsx}'],
170+
rules: {
171+
'no-restricted-imports': [
172+
'warn',
173+
...restrictedBaseImports,
174+
{
175+
name: 'sprotty',
176+
message: 'Please use @eclipse-glsp/client instead'
177+
},
178+
{
179+
name: 'sprotty/*',
180+
message: 'Please use @eclipse-glsp/client instead'
181+
},
182+
{
183+
name: 'sprotty-protocol',
184+
message: 'Please use @eclipse-glsp/client instead'
185+
},
186+
{
187+
name: 'sprotty-protocol/*',
188+
message: 'Please use @eclipse-glsp/client instead'
189+
},
190+
{
191+
name: '@eclipse-glsp/protocol',
192+
message: 'Please use @eclipse-glsp/client instead'
193+
},
194+
{
195+
name: '@eclipse-glsp/protocol/*',
196+
message: 'Please use @eclipse-glsp/client instead'
197+
},
198+
{
199+
name: '@eclipse-glsp/sprotty',
200+
message: 'Please use @eclipse-glsp/client instead'
201+
},
202+
{
203+
name: '@eclipse-glsp/sprotty/*',
204+
message: 'Please use @eclipse-glsp/client instead'
205+
},
206+
{
207+
name: 'uuid',
208+
message: "Use the 'generateUuid'/'isUuid' helpers (from '@eclipse-glsp/client') instead of importing 'uuid' directly."
209+
},
210+
{
211+
name: 'uuid/*',
212+
message: "Use the 'generateUuid'/'isUuid' helpers (from '@eclipse-glsp/client') instead of importing 'uuid' directly."
138213
}
139214
]
140215
}

examples/workflow-glsp/src/workflow-startup.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,7 @@
1414
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
1515
********************************************************************************/
1616

17-
import { IDiagramStartup, IGridManager } from '@eclipse-glsp/client';
18-
import { MaybePromise, TYPES } from '@eclipse-glsp/sprotty';
17+
import { IDiagramStartup, IGridManager, MaybePromise, TYPES } from '@eclipse-glsp/client';
1918
import { inject, injectable, optional } from 'inversify';
2019

2120
/**

packages/client/src/features/copy-paste/copy-paste-handler.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/********************************************************************************
2-
* Copyright (c) 2019-2024 EclipseSource and others.
2+
* Copyright (c) 2019-2026 EclipseSource and others.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -16,6 +16,7 @@
1616
import {
1717
ClipboardData,
1818
CutOperation,
19+
generateUuid,
1920
IActionDispatcher,
2021
PasteOperation,
2122
RequestClipboardDataAction,
@@ -24,7 +25,6 @@ import {
2425
ViewerOptions
2526
} from '@eclipse-glsp/sprotty';
2627
import { inject, injectable } from 'inversify';
27-
import { v4 as uuid } from 'uuid';
2828
import { EditorContextService } from '../../base/editor-context-service';
2929

3030
export interface ICopyPasteHandler {
@@ -107,7 +107,7 @@ export class ServerCopyPasteHandler implements ICopyPasteHandler {
107107

108108
handleCopy(event: ClipboardEvent): void {
109109
if (event.clipboardData && this.shouldCopy(event)) {
110-
const clipboardId = uuid();
110+
const clipboardId = generateUuid();
111111
event.clipboardData.setData(CLIPBOARD_DATA_FORMAT, toClipboardId(clipboardId));
112112
this.actionDispatcher
113113
.request<SetClipboardDataAction>(RequestClipboardDataAction.create(this.editorContext.get()))

packages/client/src/features/export/glsp-svg-exporter.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,14 @@ import {
1818
Action,
1919
ExportSvgAction,
2020
ExportSvgOptions,
21+
generateUuid,
2122
GModelRoot,
2223
RejectAction,
2324
RequestAction,
2425
RequestExportSvgAction,
2526
SvgExporter
2627
} from '@eclipse-glsp/sprotty';
2728
import { injectable } from 'inversify';
28-
import { v4 as uuid } from 'uuid';
2929

3030
@injectable()
3131
export class GLSPSvgExporter extends SvgExporter {
@@ -82,7 +82,7 @@ export class GLSPSvgExporter extends SvgExporter {
8282
// createSvg requires the svg to have a non-empty id, so we generate one if necessary
8383
const originalId = svgElement.id;
8484
try {
85-
svgElement.id = originalId || uuid();
85+
svgElement.id = originalId || generateUuid();
8686
return super.createSvg(svgElement, root, options, cause);
8787
} finally {
8888
svgElement.id = originalId;

packages/client/src/features/helper-lines/model.ts

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/********************************************************************************
2-
* Copyright (c) 2023-2024 EclipseSource and others.
2+
* Copyright (c) 2023-2026 EclipseSource and others.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -14,8 +14,7 @@
1414
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
1515
********************************************************************************/
1616

17-
import { Args, Bounds, Direction, GChildElement, GModelElement, GShapeElement, Point, Vector } from '@eclipse-glsp/sprotty';
18-
import { v4 as uuid } from 'uuid';
17+
import { Args, Bounds, Direction, GChildElement, GModelElement, GShapeElement, Point, Vector, generateUuid } from '@eclipse-glsp/sprotty';
1918
import { ArgsAware } from '../../base/args-feature';
2019
import { ResizeHandleLocation } from '../change-bounds/model';
2120

@@ -46,7 +45,7 @@ export class HelperLine extends GChildElement implements ArgsAware {
4645
readonly lineType: HelperLineType = HelperLineType.Left
4746
) {
4847
super();
49-
this.id = uuid();
48+
this.id = generateUuid();
5049
this.type = HELPER_LINE;
5150
}
5251

@@ -86,7 +85,7 @@ export class SelectionBounds extends GShapeElement implements ArgsAware {
8685

8786
constructor(bounds?: Bounds) {
8887
super();
89-
this.id = uuid();
88+
this.id = generateUuid();
9089
this.type = SELECTION_BOUNDS;
9190
if (bounds) {
9291
this.bounds = bounds;

packages/client/src/features/tools/node-creation/insert-indicator.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/********************************************************************************
2-
* Copyright (c) 2024 EclipseSource and others.
2+
* Copyright (c) 2024-2026 EclipseSource and others.
33
*
44
* This program and the accompanying materials are made available under the
55
* terms of the Eclipse Public License v. 2.0 which is available at
@@ -14,8 +14,7 @@
1414
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
1515
********************************************************************************/
1616

17-
import { Args, Dimension, FeatureSet, GNode, boundsFeature, createFeatureSet, moveFeature } from '@eclipse-glsp/sprotty';
18-
import { v4 as uuid } from 'uuid';
17+
import { Args, Dimension, FeatureSet, GNode, boundsFeature, createFeatureSet, generateUuid, moveFeature } from '@eclipse-glsp/sprotty';
1918
import { ArgsAware, argsFeature } from '../../../base/args-feature';
2019

2120
export const ARG_LENGTH = 'length';
@@ -25,7 +24,7 @@ export class InsertIndicator extends GNode implements ArgsAware {
2524

2625
static TYPE = 'node:insert-indicator';
2726

28-
override id: string = uuid();
27+
override id: string = generateUuid();
2928
override type: string = InsertIndicator.TYPE;
3029
override features?: FeatureSet = createFeatureSet(InsertIndicator.DEFAULT_FEATURES);
3130
override cssClasses: string[] = ['insert-indicator', 'sprotty-node'];

packages/protocol/package.json

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,9 @@
4646
},
4747
"dependencies": {
4848
"sprotty-protocol": "1.4.0",
49-
"uuid": "~14.0.0",
49+
"uuid": "^14.0.0",
5050
"vscode-jsonrpc": "8.2.0"
5151
},
52-
"devDependencies": {
53-
"@types/uuid": "~9.0.8"
54-
},
5552
"peerDependencies": {
5653
"inversify": "^6.1.3"
5754
},

packages/protocol/src/client-server-protocol/glsp-client.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,19 +13,18 @@
1313
*
1414
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
1515
********************************************************************************/
16-
import { v4 as uuid } from 'uuid';
17-
1816
import { ActionMessage } from '../action-protocol/base-protocol';
1917
import { Disposable } from '../utils/disposable';
2018
import { Event } from '../utils/event';
2119
import { AnyObject, MaybePromise, hasStringProp } from '../utils/type-util';
20+
import { generateUuid } from '../utils/uuid';
2221
import { DisposeClientSessionParameters, InitializeClientSessionParameters, InitializeParameters, InitializeResult } from './types';
2322

2423
export class ApplicationIdProvider {
2524
private static _applicationId?: string;
2625
static get(): string {
2726
if (!ApplicationIdProvider._applicationId) {
28-
ApplicationIdProvider._applicationId = uuid();
27+
ApplicationIdProvider._applicationId = generateUuid();
2928
}
3029
return ApplicationIdProvider._applicationId;
3130
}

packages/protocol/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,3 +61,4 @@ export * from './utils/geometry-util';
6161
export * from './utils/geometry-vector';
6262
export * from './utils/math-util';
6363
export * from './utils/type-util';
64+
export * from './utils/uuid';
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/********************************************************************************
2+
* Copyright (c) 2026 EclipseSource and others.
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License v. 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* This Source Code may also be made available under the following Secondary
9+
* Licenses when the conditions for such availability set forth in the Eclipse
10+
* Public License v. 2.0 are satisfied: GNU General Public License, version 2
11+
* with the GNU Classpath Exception which is available at
12+
* https://www.gnu.org/software/classpath/license.html.
13+
*
14+
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15+
********************************************************************************/
16+
import { expect } from 'chai';
17+
import { generateUuid, isUuid } from './uuid';
18+
19+
describe('Uuid', () => {
20+
describe('isUuid', () => {
21+
it('should return true for a valid UUID', () => {
22+
expect(isUuid('f47ac10b-58cc-4372-a567-0e02b2c3d479')).to.be.true;
23+
});
24+
it('should return true for a generated UUID', () => {
25+
expect(isUuid(generateUuid())).to.be.true;
26+
});
27+
it('should return false for a malformed UUID', () => {
28+
expect(isUuid('not-a-uuid')).to.be.false;
29+
expect(isUuid('')).to.be.false;
30+
});
31+
});
32+
});

0 commit comments

Comments
 (0)