graphwise-reactodia 0.0.1-TR16 → 0.0.1-TR17

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/README.md +35 -0
  2. package/dist/cjs/error-code-NpXlqCEN.js +28 -0
  3. package/dist/cjs/graphwise-reactodia.cjs.entry.js +232 -37
  4. package/dist/cjs/graphwise-reactodia.cjs.js +1 -1
  5. package/dist/cjs/{index-CII9aUQC.js → index-DtzCybH4.js} +16 -0
  6. package/dist/cjs/index.cjs.js +10 -4
  7. package/dist/cjs/loader.cjs.js +1 -1
  8. package/dist/collection/components/graphwise-reactodia/graphwise-reactodia.js +44 -4
  9. package/dist/collection/components/graphwise-reactodia/menu/graphwise-menu.js +4 -1
  10. package/dist/collection/components/graphwise-reactodia/models/error/error-callback.js +1 -0
  11. package/dist/collection/components/graphwise-reactodia/models/error/error-cause.js +1 -0
  12. package/dist/collection/components/graphwise-reactodia/models/error/error-code.js +18 -0
  13. package/dist/collection/components/graphwise-reactodia/models/error/error-report.js +4 -0
  14. package/dist/collection/components/graphwise-reactodia/reactodia-app.js +53 -19
  15. package/dist/collection/components/graphwise-reactodia/services/diagram-storage/diagram-storage.service.js +20 -4
  16. package/dist/collection/components/graphwise-reactodia/services/error/error.service.js +89 -0
  17. package/dist/collection/index.js +2 -0
  18. package/dist/collection/pages/graphwise-reactodia/main.js +37 -0
  19. package/dist/esm/error-code-7lGYbTwb.js +26 -0
  20. package/dist/esm/graphwise-reactodia.entry.js +228 -33
  21. package/dist/esm/graphwise-reactodia.js +2 -2
  22. package/dist/esm/{index-Cypw7ydc.js → index-DpCR6zMg.js} +16 -1
  23. package/dist/esm/index.js +5 -4
  24. package/dist/esm/loader.js +2 -2
  25. package/dist/graphwise-reactodia/graphwise-reactodia.esm.js +1 -1
  26. package/dist/graphwise-reactodia/index.esm.js +1 -1
  27. package/dist/graphwise-reactodia/p-7lGYbTwb.js +1 -0
  28. package/dist/graphwise-reactodia/p-DpCR6zMg.js +2 -0
  29. package/dist/graphwise-reactodia/p-ec30185a.entry.js +1 -0
  30. package/dist/types/components/graphwise-reactodia/graphwise-reactodia.d.ts +9 -0
  31. package/dist/types/components/graphwise-reactodia/models/error/error-callback.d.ts +5 -0
  32. package/dist/types/components/graphwise-reactodia/models/error/error-cause.d.ts +10 -0
  33. package/dist/types/components/graphwise-reactodia/models/error/error-code.d.ts +17 -0
  34. package/dist/types/components/graphwise-reactodia/models/error/error-report.d.ts +17 -0
  35. package/dist/types/components/graphwise-reactodia/reactodia-app.d.ts +1 -1
  36. package/dist/types/components/graphwise-reactodia/services/diagram-storage/diagram-storage.service.d.ts +1 -0
  37. package/dist/types/components/graphwise-reactodia/services/error/error.service.d.ts +50 -0
  38. package/dist/types/components.d.ts +21 -0
  39. package/dist/types/index.d.ts +3 -0
  40. package/package.json +1 -1
  41. package/dist/graphwise-reactodia/p-20637a6f.entry.js +0 -1
  42. package/dist/graphwise-reactodia/p-Cypw7ydc.js +0 -2
package/README.md CHANGED
@@ -66,6 +66,41 @@ persisted in the DB, so they can't be fetched lazily and must be supplied by the
66
66
 
67
67
  When both are supplied `seedGraph` takes precedence over `seedIris`.
68
68
 
69
+ ## Error handling
70
+
71
+ The element dispatches a `graphwiseReactodiaError` DOM event for every error it reports; the codes below
72
+ list them. The event only informs the host and it bubbles. Its name is exported as
73
+ `GRAPHWISE_REACTODIA_ERROR_EVENT`.
74
+
75
+ ```js
76
+ element.addEventListener('graphwiseReactodiaError', (event) => {
77
+ const {code, error} = event.detail;
78
+ });
79
+ ```
80
+
81
+ `detail` is an `ErrorReport`:
82
+
83
+ | Field | Description |
84
+ |---------|-----------------------------------------------------------------------------------------|
85
+ | `code` | An `ErrorCode`. The host translates by it. |
86
+ | `error` | Always an `Error`; its `message` is untranslated developer text, meant for the logs. |
87
+
88
+ `ErrorCode`:
89
+
90
+ | Code | Reported when |
91
+ |-------------------------|------------------------------------------------------------|
92
+ | `missing-required-prop` | A required prop is missing. |
93
+ | `data-fetch` | A SPARQL data provider call failed. |
94
+ | `diagram-load` | The startup load, a reload or a repository switch failed. |
95
+ | `diagram-import` | The uploaded file was rejected or its import failed. |
96
+ | `local-diagram-read` | Reading the diagram from local storage failed. |
97
+ | `local-diagram-save` | Saving the diagram in local storage failed. |
98
+
99
+ Failed PNG/SVG exports and printing are not reported.
100
+
101
+ Every failure is reported once: an error is skipped when it, or an error in its `cause` chain, is already reported.
102
+ Aborted requests are not reported.
103
+
69
104
  ## Editing the fork
70
105
 
71
106
  Reactodia lives in the `reactodia-workspace/` submodule, which is its own git repo (remote:
@@ -0,0 +1,28 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Event name for clearing the local store state of the diagram. There is an event listener listening for it, which
5
+ * will clear the local store state, whenever this event is fired.
6
+ */
7
+ const CLEAR_DIAGRAM_STORAGE_EVENT = 'graphwise-reactodia:clear-diagram-storage';
8
+
9
+ /**
10
+ * The stable category of a reported error. The host uses it to choose its own message.
11
+ */
12
+ exports.ErrorCode = void 0;
13
+ (function (ErrorCode) {
14
+ /** A required prop is missing. */
15
+ ErrorCode["MISSING_REQUIRED_PROP"] = "missing-required-prop";
16
+ /** A SPARQL data provider call failed. */
17
+ ErrorCode["DATA_FETCH"] = "data-fetch";
18
+ /** The startup load, a reload or a repository switch failed. */
19
+ ErrorCode["DIAGRAM_LOAD"] = "diagram-load";
20
+ /** The uploaded file was rejected or its import failed. */
21
+ ErrorCode["DIAGRAM_IMPORT"] = "diagram-import";
22
+ /** Reading the diagram from local storage failed. */
23
+ ErrorCode["LOCAL_DIAGRAM_READ"] = "local-diagram-read";
24
+ /** Saving the diagram in local storage failed. */
25
+ ErrorCode["LOCAL_DIAGRAM_SAVE"] = "local-diagram-save";
26
+ })(exports.ErrorCode || (exports.ErrorCode = {}));
27
+
28
+ exports.CLEAR_DIAGRAM_STORAGE_EVENT = CLEAR_DIAGRAM_STORAGE_EVENT;
@@ -1,7 +1,7 @@
1
1
  'use strict';
2
2
 
3
- var index$1 = require('./index-CII9aUQC.js');
4
- var index = require('./index.cjs.js');
3
+ var index = require('./index-DtzCybH4.js');
4
+ var errorCode = require('./error-code-NpXlqCEN.js');
5
5
 
6
6
  var commonjsGlobal = typeof globalThis !== 'undefined' ? globalThis : typeof window !== 'undefined' ? window : typeof global !== 'undefined' ? global : typeof self !== 'undefined' ? self : {};
7
7
 
@@ -6331,6 +6331,57 @@ var DefaultColorVariants = [
6331
6331
  "danger"
6332
6332
  ];
6333
6333
  //#endregion
6334
+ //#region src/data/decorated/decoratedDataProvider.ts
6335
+ /**
6336
+ * Utility graph data provider to wrap over another provider to modify
6337
+ * how the requests are made or alter the results.
6338
+ *
6339
+ * @category Data
6340
+ */
6341
+ var DecoratedDataProvider = class {
6342
+ baseProvider;
6343
+ decorator;
6344
+ constructor(options) {
6345
+ this.baseProvider = options.baseProvider;
6346
+ this.decorator = options.decorator;
6347
+ }
6348
+ get factory() {
6349
+ return this.baseProvider.factory;
6350
+ }
6351
+ decorate(method, params) {
6352
+ const bound = this.baseProvider[method].bind(this.baseProvider);
6353
+ const { decorator } = this;
6354
+ return decorator(method, params[0], bound);
6355
+ }
6356
+ knownElementTypes(params) {
6357
+ return this.decorate("knownElementTypes", [params]);
6358
+ }
6359
+ knownLinkTypes(params) {
6360
+ return this.decorate("knownLinkTypes", [params]);
6361
+ }
6362
+ elementTypes(params) {
6363
+ return this.decorate("elementTypes", [params]);
6364
+ }
6365
+ propertyTypes(params) {
6366
+ return this.decorate("propertyTypes", [params]);
6367
+ }
6368
+ linkTypes(params) {
6369
+ return this.decorate("linkTypes", [params]);
6370
+ }
6371
+ elements(params) {
6372
+ return this.decorate("elements", [params]);
6373
+ }
6374
+ links(params) {
6375
+ return this.decorate("links", [params]);
6376
+ }
6377
+ connectedLinkStats(params) {
6378
+ return this.decorate("connectedLinkStats", [params]);
6379
+ }
6380
+ lookup(params) {
6381
+ return this.decorate("lookup", [params]);
6382
+ }
6383
+ };
6384
+ //#endregion
6334
6385
  //#region src/data/decorated/emptyDataProvider.ts
6335
6386
  /**
6336
6387
  * Empty graph data provider, which always return nothing.
@@ -31333,7 +31384,7 @@ function Service(_serviceClass) {
31333
31384
  // no implementation needed. We only use the type checking of the parameter
31334
31385
  }
31335
31386
 
31336
- var __decorate$4 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
31387
+ var __decorate$5 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
31337
31388
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
31338
31389
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
31339
31390
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
@@ -31395,11 +31446,11 @@ let DiagramService = DiagramService_1 = class DiagramService {
31395
31446
  DiagramService.ID = 'DiagramService';
31396
31447
  DiagramService.NOTIFY_DEBOUNCE_MS = 300;
31397
31448
  DiagramService.HISTORY_CHANGED_EVENT = 'historyChanged';
31398
- DiagramService = DiagramService_1 = __decorate$4([
31449
+ DiagramService = DiagramService_1 = __decorate$5([
31399
31450
  Service
31400
31451
  ], DiagramService);
31401
31452
 
31402
- var __decorate$3 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
31453
+ var __decorate$4 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
31403
31454
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
31404
31455
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
31405
31456
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
@@ -31414,10 +31465,94 @@ let WindowService = class WindowService {
31414
31465
  }
31415
31466
  };
31416
31467
  WindowService.ID = 'WindowService';
31417
- WindowService = __decorate$3([
31468
+ WindowService = __decorate$4([
31418
31469
  Service
31419
31470
  ], WindowService);
31420
31471
 
31472
+ var __decorate$3 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
31473
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
31474
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
31475
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
31476
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
31477
+ };
31478
+ var ErrorService_1;
31479
+ /**
31480
+ * Service that collects the failures of the wrapper and the fork, so they can be announced to the host.
31481
+ */
31482
+ let ErrorService = ErrorService_1 = class ErrorService {
31483
+ constructor() {
31484
+ this.reported = new WeakSet();
31485
+ }
31486
+ /**
31487
+ * Reports a failure to the host, unless it's an abort, or this exact error object is already reported
31488
+ * from another place.
31489
+ *
31490
+ * The same error object may be reported from different places. E.g. a query that fails while a diagram loads is
31491
+ * reported by the data provider decorator as `data-fetch`, and then reaches the `catch` around the load, which
31492
+ * reports it as `diagram-load`. Only the first one is announced.
31493
+ *
31494
+ * The `cause` is checked because the fork wraps whatever fails during a diagram import in a new error:
31495
+ *
31496
+ * ```ts
31497
+ * // reactodia-workspace/src/editor/dataDiagramModel.ts, importLayout
31498
+ * } catch (error) {
31499
+ * throw new Error('Reactodia: failed to import a layout', {cause: error});
31500
+ * }
31501
+ * ```
31502
+ *
31503
+ * We need to check the cause to make sure we don't report the same error/abort more than once.
31504
+ *
31505
+ * @param code The category of the failure.
31506
+ * @param thrown The thrown value.
31507
+ */
31508
+ report(code, thrown) {
31509
+ var _a;
31510
+ const causes = this.causeChain(thrown);
31511
+ if (this.isAbortedOrAlreadyReported(causes)) {
31512
+ return;
31513
+ }
31514
+ causes.forEach((cause) => this.reported.add(cause));
31515
+ (_a = this.callback) === null || _a === void 0 ? void 0 : _a.call(this, { code, error: thrown });
31516
+ }
31517
+ /**
31518
+ * Subscribes to the reported errors, replacing the previous subscriber.
31519
+ *
31520
+ * @param callback Called with every reported error.
31521
+ * @returns A {@link Subscription} that, when called, removes the callback, unless it has already been replaced.
31522
+ */
31523
+ subscribe(callback) {
31524
+ this.callback = callback;
31525
+ return () => {
31526
+ if (this.callback === callback) {
31527
+ this.callback = undefined;
31528
+ }
31529
+ };
31530
+ }
31531
+ /**
31532
+ * Whether any link of the given cause chain is an abort or is already reported.
31533
+ */
31534
+ isAbortedOrAlreadyReported(causes) {
31535
+ return causes.some((cause) => cause.name === ErrorService_1.ABORT_ERROR_NAME || this.reported.has(cause));
31536
+ }
31537
+ /**
31538
+ * The thrown value followed by its `cause`, the cause of that, and so on, for as long as they are objects.
31539
+ */
31540
+ causeChain(thrown) {
31541
+ const causes = [];
31542
+ let current = thrown;
31543
+ while (typeof current === 'object' && current !== null && !causes.includes(current)) {
31544
+ causes.push(current);
31545
+ current = current.cause;
31546
+ }
31547
+ return causes;
31548
+ }
31549
+ };
31550
+ ErrorService.ID = 'ErrorService';
31551
+ ErrorService.ABORT_ERROR_NAME = 'AbortError';
31552
+ ErrorService = ErrorService_1 = __decorate$3([
31553
+ Service
31554
+ ], ErrorService);
31555
+
31421
31556
  var __decorate$2 = (undefined && undefined.__decorate) || function (decorators, target, key, desc) {
31422
31557
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
31423
31558
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -31429,22 +31564,36 @@ var DiagramStorageService_1;
31429
31564
  * Service for local store-related diagram operations
31430
31565
  */
31431
31566
  let DiagramStorageService = DiagramStorageService_1 = class DiagramStorageService {
31567
+ constructor() {
31568
+ this.errorService = service(ErrorService);
31569
+ }
31432
31570
  /**
31433
31571
  * Load the persisted diagram from the local store, or `undefined` when nothing is stored (or the stored value
31434
31572
  * is unreadable).
31435
31573
  */
31436
31574
  load() {
31437
- const raw = this.storage.getItem(DiagramStorageService_1.STORAGE_KEY);
31438
- if (!raw) {
31575
+ try {
31576
+ const raw = this.storage.getItem(DiagramStorageService_1.STORAGE_KEY);
31577
+ if (!raw) {
31578
+ return undefined;
31579
+ }
31580
+ return JSON.parse(raw);
31581
+ }
31582
+ catch (error) {
31583
+ this.errorService.report(errorCode.ErrorCode.LOCAL_DIAGRAM_READ, error);
31439
31584
  return undefined;
31440
31585
  }
31441
- return JSON.parse(raw);
31442
31586
  }
31443
31587
  /**
31444
31588
  * Persists the given diagram serialization.
31445
31589
  */
31446
31590
  save(diagram) {
31447
- this.storage.setItem(DiagramStorageService_1.STORAGE_KEY, JSON.stringify(diagram));
31591
+ try {
31592
+ this.storage.setItem(DiagramStorageService_1.STORAGE_KEY, JSON.stringify(diagram));
31593
+ }
31594
+ catch (error) {
31595
+ this.errorService.report(errorCode.ErrorCode.LOCAL_DIAGRAM_SAVE, error);
31596
+ }
31448
31597
  }
31449
31598
  /**
31450
31599
  * Removes the persisted diagram. Used when a new view (a seed) should take precedence over
@@ -31484,8 +31633,8 @@ let EventService = class EventService {
31484
31633
  */
31485
31634
  subscribeToClearDiagramStorage(onClear) {
31486
31635
  const target = service(WindowService).getWindow();
31487
- target.addEventListener(index.CLEAR_DIAGRAM_STORAGE_EVENT, onClear);
31488
- return () => target.removeEventListener(index.CLEAR_DIAGRAM_STORAGE_EVENT, onClear);
31636
+ target.addEventListener(errorCode.CLEAR_DIAGRAM_STORAGE_EVENT, onClear);
31637
+ return () => target.removeEventListener(errorCode.CLEAR_DIAGRAM_STORAGE_EVENT, onClear);
31489
31638
  }
31490
31639
  };
31491
31640
  EventService.ID = 'EventService';
@@ -31654,6 +31803,7 @@ function GraphwiseMenu() {
31654
31803
  const t = useTranslation();
31655
31804
  const diagramFileService = service(DiagramFileService);
31656
31805
  const diagramService = service(DiagramService);
31806
+ const errorService = service(ErrorService);
31657
31807
  const downloadDiagram = () => {
31658
31808
  const timestamp = new Date().toISOString().replace(/[-:]|\.\d+Z$/g, '');
31659
31809
  diagramFileService.download(model.exportLayout(), `diagram-${timestamp}${DiagramFileService.FILE_EXTENSION}`);
@@ -31664,7 +31814,7 @@ function GraphwiseMenu() {
31664
31814
  await diagramService.importDiagram(model, model.dataProvider, diagram);
31665
31815
  }
31666
31816
  catch (error) {
31667
- console.error('Failed to upload the diagram', error);
31817
+ errorService.report(errorCode.ErrorCode.DIAGRAM_IMPORT, error);
31668
31818
  }
31669
31819
  };
31670
31820
  return reactExports.createElement(reactExports.Fragment, null, reactExports.createElement(ToolbarActionClearAll, {}), reactExports.createElement(ToolbarActionExport, { kind: 'exportRaster' }), reactExports.createElement(ToolbarActionExport, { kind: 'exportSvg' }), reactExports.createElement(ToolbarActionExport, { kind: 'print' }), reactExports.createElement(ToolbarAction,
@@ -31703,17 +31853,35 @@ let diagramStorageSubscription;
31703
31853
  const diagramService = service(DiagramService);
31704
31854
  const diagramStorageService = service(DiagramStorageService);
31705
31855
  const eventService = service(EventService);
31856
+ const errorService$1 = service(ErrorService);
31857
+ /**
31858
+ * Reports every failed data provider call, unless the call was aborted, and passes the failure on to the caller.
31859
+ */
31860
+ const reportDataFetchError = async (_method, params, body) => {
31861
+ var _a;
31862
+ try {
31863
+ return await body(params);
31864
+ }
31865
+ catch (error) {
31866
+ if (!((_a = params.signal) === null || _a === void 0 ? void 0 : _a.aborted)) {
31867
+ errorService$1.report(errorCode.ErrorCode.DATA_FETCH, error);
31868
+ }
31869
+ throw error;
31870
+ }
31871
+ };
31706
31872
  /**
31707
31873
  * Builds a Reactodia {@link SparqlDataProvider} for the given endpoint using the supplied
31708
31874
  * query preset. The host owns the query configuration and always passes it in via props.
31875
+ * The provider is decorated, so its failed calls are reported.
31709
31876
  */
31710
31877
  function createDataProvider(props) {
31711
31878
  const { currentRepository, config, providerSettings } = props;
31712
- return new SparqlDataProvider({
31879
+ const baseProvider = new SparqlDataProvider({
31713
31880
  endpointUrl: currentRepository,
31714
31881
  queryMethod: 'POST',
31715
31882
  queryFunction: config.queryFunction
31716
31883
  }, providerSettings);
31884
+ return new DecoratedDataProvider({ baseProvider, decorator: reportDataFetchError });
31717
31885
  }
31718
31886
  /**
31719
31887
  * Places the seed entities on the canvas. Each IRI is added as a placeholder element, and data is then loaded for the
@@ -31808,22 +31976,31 @@ function ReactodiaApp(props) {
31808
31976
  const dataProvider = createDataProvider(props);
31809
31977
  const isReload = props.isReload;
31810
31978
  const savedDiagram = diagramStorageService.load();
31811
- if (isReload) {
31812
- // Reload the diagram that is currently on the canvas. This may happen when the host changes the provider
31813
- // settings, or when the user switches the language at runtime, since there is no existing mechanism to
31814
- // re-translate the UI at runtime (not for the UI labels at least)
31815
- await diagramService.importDiagram(model, dataProvider, currentDiagram, signal);
31816
- }
31817
- else if ((_a = config.seedIris) === null || _a === void 0 ? void 0 : _a.length) {
31818
- await seedIrisToCanvas(context, dataProvider, config.seedIris, signal);
31819
- }
31820
- else if ((_b = config.seedGraph) === null || _b === void 0 ? void 0 : _b.length) {
31821
- await seedGraphToCanvas(context, dataProvider, config.seedGraph, signal);
31979
+ try {
31980
+ if (isReload) {
31981
+ // Reload the diagram that is currently on the canvas. This may happen when the host changes the provider
31982
+ // settings, or when the user switches the language at runtime, since there is no existing mechanism to
31983
+ // re-translate the UI at runtime (not for the UI labels at least)
31984
+ await diagramService.importDiagram(model, dataProvider, currentDiagram, signal);
31985
+ }
31986
+ else if ((_a = config.seedIris) === null || _a === void 0 ? void 0 : _a.length) {
31987
+ await seedIrisToCanvas(context, dataProvider, config.seedIris, signal);
31988
+ }
31989
+ else if ((_b = config.seedGraph) === null || _b === void 0 ? void 0 : _b.length) {
31990
+ await seedGraphToCanvas(context, dataProvider, config.seedGraph, signal);
31991
+ }
31992
+ else {
31993
+ // Restore the previously saved layout when present, otherwise start empty. Either way this binds the
31994
+ // data provider (savedDiagram is undefined -> empty diagram), so the unified search/lookup works.
31995
+ await diagramService.importDiagram(model, dataProvider, savedDiagram, signal);
31996
+ }
31822
31997
  }
31823
- else {
31824
- // Restore the previously saved layout when present, otherwise start empty. Either way this binds the
31825
- // data provider (savedDiagram is undefined -> empty diagram), so the unified search/lookup works.
31826
- await diagramService.importDiagram(model, dataProvider, savedDiagram, signal);
31998
+ catch (error) {
31999
+ if (!signal.aborted) {
32000
+ errorService$1.report(errorCode.ErrorCode.DIAGRAM_LOAD, error);
32001
+ }
32002
+ // rethrow, so the workspace shows the failure on its loading spinner
32003
+ throw error;
31827
32004
  }
31828
32005
  }, [language]);
31829
32006
  /**
@@ -31860,7 +32037,7 @@ function mountReactodia(container, props) {
31860
32037
  /**
31861
32038
  * Re-points the diagram at a new SPARQL endpoint by recreating it with a fresh data provider.
31862
32039
  * The canvas is reset to empty, matching the initial mount, since the data of another repository
31863
- * has nothing to do with the current graph.
32040
+ * has nothing to do with the current graph. A failure is reported, not thrown.
31864
32041
  */
31865
32042
  async function updateReactodia(props) {
31866
32043
  if (!workspaceContext) {
@@ -31868,7 +32045,12 @@ async function updateReactodia(props) {
31868
32045
  }
31869
32046
  const { model } = workspaceContext;
31870
32047
  const dataProvider = createDataProvider(props);
31871
- await model.createNewDiagram({ dataProvider });
32048
+ try {
32049
+ await model.createNewDiagram({ dataProvider });
32050
+ }
32051
+ catch (error) {
32052
+ errorService$1.report(errorCode.ErrorCode.DIAGRAM_LOAD, error);
32053
+ }
31872
32054
  }
31873
32055
  /**
31874
32056
  * Serializes the current diagram so it can be restored after a remount (e.g. when a
@@ -31887,9 +32069,12 @@ function unmountReactodia(root) {
31887
32069
 
31888
32070
  const graphwiseReactodiaCss = "graphwise-reactodia{--_graphwise-reactodia-type-color-01:var(--graphwise-reactodia-type-color-01);--_graphwise-reactodia-type-color-02:var(--graphwise-reactodia-type-color-02);--_graphwise-reactodia-type-color-03:var(--graphwise-reactodia-type-color-03);--_graphwise-reactodia-type-color-04:var(--graphwise-reactodia-type-color-04);--_graphwise-reactodia-type-color-05:var(--graphwise-reactodia-type-color-05);--_graphwise-reactodia-type-color-06:var(--graphwise-reactodia-type-color-06);--_graphwise-reactodia-type-color-07:var(--graphwise-reactodia-type-color-07);--_graphwise-reactodia-type-color-08:var(--graphwise-reactodia-type-color-08);--_graphwise-reactodia-type-color-09:var(--graphwise-reactodia-type-color-09);--_graphwise-reactodia-type-color-10:var(--graphwise-reactodia-type-color-10);--_graphwise-reactodia-type-color-11:var(--graphwise-reactodia-type-color-11);--_graphwise-reactodia-type-color-12:var(--graphwise-reactodia-type-color-12);--_graphwise-reactodia-type-color-13:var(--graphwise-reactodia-type-color-13);--_graphwise-reactodia-type-color-14:var(--graphwise-reactodia-type-color-14);--_graphwise-reactodia-type-color-15:var(--graphwise-reactodia-type-color-15);--_graphwise-reactodia-type-color-16:var(--graphwise-reactodia-type-color-16);--_graphwise-reactodia-type-color-17:var(--graphwise-reactodia-type-color-17);--_graphwise-reactodia-type-color-18:var(--graphwise-reactodia-type-color-18);--_graphwise-reactodia-type-color-19:var(--graphwise-reactodia-type-color-19);--_graphwise-reactodia-type-color-20:var(--graphwise-reactodia-type-color-20);--_graphwise-reactodia-type-color-contrast:var(--graphwise-reactodia-type-color-contrast, #fff)}graphwise-reactodia{display:block;width:100%;height:100%}graphwise-reactodia .reactodia-container{position:relative;width:100%;height:100%}graphwise-reactodia .reactodia-selection-action__link{display:none}graphwise-reactodia .reactodia-standard-element__thumbnail:not(:has(img)){background:var(--reactodia-element-style-color);border-radius:50%;color:var(--_graphwise-reactodia-type-color-contrast)}";
31889
32071
 
32072
+ const errorService = service(ErrorService);
31890
32073
  const GraphwiseReactodia = class {
31891
32074
  constructor(hostRef) {
31892
- index$1.registerInstance(this, hostRef);
32075
+ index.registerInstance(this, hostRef);
32076
+ this.errorEmitter = index.createEvent(this, "graphwiseReactodiaError");
32077
+ this.subscriptions = new SubscriptionList();
31893
32078
  /**
31894
32079
  * UI language code (e.g. `en`, `fr`) for the Reactodia interface. Defaults to English.
31895
32080
  */
@@ -31917,6 +32102,7 @@ const GraphwiseReactodia = class {
31917
32102
  this.renderGraph(true);
31918
32103
  }
31919
32104
  connectedCallback() {
32105
+ this.subscribeToErrors();
31920
32106
  this.renderGraph();
31921
32107
  }
31922
32108
  componentDidLoad() {
@@ -31924,13 +32110,17 @@ const GraphwiseReactodia = class {
31924
32110
  this.renderGraph();
31925
32111
  }
31926
32112
  disconnectedCallback() {
32113
+ this.subscriptions.unsubscribeAll();
31927
32114
  if (this.reactRoot) {
31928
32115
  unmountReactodia(this.reactRoot);
31929
32116
  this.reactRoot = undefined;
31930
32117
  }
31931
32118
  }
31932
32119
  render() {
31933
- return (index$1.h(index$1.Host, { key: 'a03aad892cb1947ab2426d77b3229e1324776c2c' }));
32120
+ return (index.h(index.Host, { key: 'a96eea05561061bbed34b5134abc44f07402211f' }));
32121
+ }
32122
+ subscribeToErrors() {
32123
+ this.subscriptions.add(errorService.subscribe((error) => this.errorEmitter.emit(error)));
31934
32124
  }
31935
32125
  renderGraph(isReloading) {
31936
32126
  var _a;
@@ -31938,13 +32128,13 @@ const GraphwiseReactodia = class {
31938
32128
  return;
31939
32129
  }
31940
32130
  if (!this.currentRepository) {
31941
- throw new Error('currentRepository is required');
32131
+ throw this.reportMissingPropError('currentRepository is required');
31942
32132
  }
31943
32133
  if (!((_a = this.config) === null || _a === void 0 ? void 0 : _a.queryFunction)) {
31944
- throw new Error('config.queryFunction is required');
32134
+ throw this.reportMissingPropError('config.queryFunction is required');
31945
32135
  }
31946
32136
  if (!this.providerSettings) {
31947
- throw new Error('providerSettings is required');
32137
+ throw this.reportMissingPropError('providerSettings is required');
31948
32138
  }
31949
32139
  if (!this.hostElement) {
31950
32140
  return;
@@ -31964,7 +32154,12 @@ const GraphwiseReactodia = class {
31964
32154
  this.reactRoot = mountReactodia(this.hostElement, props);
31965
32155
  }
31966
32156
  }
31967
- get hostElement() { return index$1.getElement(this); }
32157
+ reportMissingPropError(message) {
32158
+ const error = new Error(message);
32159
+ errorService.report(errorCode.ErrorCode.MISSING_REQUIRED_PROP, error);
32160
+ return error;
32161
+ }
32162
+ get hostElement() { return index.getElement(this); }
31968
32163
  static get watchers() { return {
31969
32164
  "currentRepository": ["onCurrentRepositoryChange"],
31970
32165
  "language": ["onLanguageOrSettingsChange"],
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-CII9aUQC.js');
3
+ var index = require('./index-DtzCybH4.js');
4
4
  var appGlobals = require('./app-globals-CcJr5lkF.js');
5
5
 
6
6
  var _documentCurrentScript = typeof document !== 'undefined' ? document.currentScript : null;
@@ -289,6 +289,21 @@ var parsePropertyValue = (propValue, propType, isFormAssociated) => {
289
289
  return propValue;
290
290
  };
291
291
  var getElement = (ref) => getHostRef(ref).$hostElement$ ;
292
+
293
+ // src/runtime/event-emitter.ts
294
+ var createEvent = (ref, name, flags) => {
295
+ const elm = getElement(ref);
296
+ return {
297
+ emit: (detail) => {
298
+ return emitEvent(elm, name, {
299
+ bubbles: true,
300
+ composed: true,
301
+ cancelable: true,
302
+ detail
303
+ });
304
+ }
305
+ };
306
+ };
292
307
  var emitEvent = (elm, name, opts) => {
293
308
  const ev = plt.ce(name, opts);
294
309
  elm.dispatchEvent(ev);
@@ -1205,6 +1220,7 @@ var setNonce = (nonce) => plt.$nonce$ = nonce;
1205
1220
 
1206
1221
  exports.Host = Host;
1207
1222
  exports.bootstrapLazy = bootstrapLazy;
1223
+ exports.createEvent = createEvent;
1208
1224
  exports.getElement = getElement;
1209
1225
  exports.h = h;
1210
1226
  exports.promiseResolve = promiseResolve;
@@ -1,9 +1,15 @@
1
1
  'use strict';
2
2
 
3
+ var errorCode = require('./error-code-NpXlqCEN.js');
4
+
3
5
  /**
4
- * Event name for clearing the local store state of the diagram. There is an event listener listening for it, which
5
- * will clear the local store state, whenever this event is fired.
6
+ * Name of the DOM event the `graphwise-reactodia` element dispatches for every reported error.
6
7
  */
7
- const CLEAR_DIAGRAM_STORAGE_EVENT = 'graphwise-reactodia:clear-diagram-storage';
8
+ const GRAPHWISE_REACTODIA_ERROR_EVENT = 'graphwiseReactodiaError';
8
9
 
9
- exports.CLEAR_DIAGRAM_STORAGE_EVENT = CLEAR_DIAGRAM_STORAGE_EVENT;
10
+ exports.CLEAR_DIAGRAM_STORAGE_EVENT = errorCode.CLEAR_DIAGRAM_STORAGE_EVENT;
11
+ Object.defineProperty(exports, "ErrorCode", {
12
+ enumerable: true,
13
+ get: function () { return errorCode.ErrorCode; }
14
+ });
15
+ exports.GRAPHWISE_REACTODIA_ERROR_EVENT = GRAPHWISE_REACTODIA_ERROR_EVENT;
@@ -1,6 +1,6 @@
1
1
  'use strict';
2
2
 
3
- var index = require('./index-CII9aUQC.js');
3
+ var index = require('./index-DtzCybH4.js');
4
4
  var appGlobals = require('./app-globals-CcJr5lkF.js');
5
5
 
6
6
  const defineCustomElements = async (win, options) => {