@_linked/react 0.0.1

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 (58) hide show
  1. package/.context/jest-repro-bundler.config.js +20 -0
  2. package/.context/jest-repro.config.js +20 -0
  3. package/.context/notes.md +0 -0
  4. package/.context/todos.md +0 -0
  5. package/.context/tsconfig-repro-bundler.json +14 -0
  6. package/.context/tsconfig-repro-no-paths.json +12 -0
  7. package/.context/tsconfig-repro-node-modules-paths.json +16 -0
  8. package/.context/tsconfig-repro-node16.json +14 -0
  9. package/AGENTS.md +59 -0
  10. package/LICENSE +21 -0
  11. package/README.md +250 -0
  12. package/docs/001-react-extraction.md +361 -0
  13. package/jest.config.js +20 -0
  14. package/lib/cjs/index.d.ts +4 -0
  15. package/lib/cjs/index.js +21 -0
  16. package/lib/cjs/index.js.map +1 -0
  17. package/lib/cjs/package.d.ts +10 -0
  18. package/lib/cjs/package.js +33 -0
  19. package/lib/cjs/package.js.map +1 -0
  20. package/lib/cjs/package.json +3 -0
  21. package/lib/cjs/utils/Hooks.d.ts +5 -0
  22. package/lib/cjs/utils/Hooks.js +54 -0
  23. package/lib/cjs/utils/Hooks.js.map +1 -0
  24. package/lib/cjs/utils/LinkedComponent.d.ts +52 -0
  25. package/lib/cjs/utils/LinkedComponent.js +322 -0
  26. package/lib/cjs/utils/LinkedComponent.js.map +1 -0
  27. package/lib/cjs/utils/LinkedComponentClass.d.ts +11 -0
  28. package/lib/cjs/utils/LinkedComponentClass.js +34 -0
  29. package/lib/cjs/utils/LinkedComponentClass.js.map +1 -0
  30. package/lib/esm/index.d.ts +4 -0
  31. package/lib/esm/index.js +5 -0
  32. package/lib/esm/index.js.map +1 -0
  33. package/lib/esm/package.d.ts +10 -0
  34. package/lib/esm/package.js +22 -0
  35. package/lib/esm/package.js.map +1 -0
  36. package/lib/esm/package.json +3 -0
  37. package/lib/esm/utils/Hooks.d.ts +5 -0
  38. package/lib/esm/utils/Hooks.js +50 -0
  39. package/lib/esm/utils/Hooks.js.map +1 -0
  40. package/lib/esm/utils/LinkedComponent.d.ts +52 -0
  41. package/lib/esm/utils/LinkedComponent.js +284 -0
  42. package/lib/esm/utils/LinkedComponent.js.map +1 -0
  43. package/lib/esm/utils/LinkedComponentClass.d.ts +11 -0
  44. package/lib/esm/utils/LinkedComponentClass.js +27 -0
  45. package/lib/esm/utils/LinkedComponentClass.js.map +1 -0
  46. package/package.json +57 -0
  47. package/scripts/dual-package.js +25 -0
  48. package/src/index.ts +4 -0
  49. package/src/package.ts +62 -0
  50. package/src/tests/react-component-behavior.test.tsx +578 -0
  51. package/src/tests/react-component-integration.test.tsx +378 -0
  52. package/src/utils/Hooks.ts +56 -0
  53. package/src/utils/LinkedComponent.ts +545 -0
  54. package/src/utils/LinkedComponentClass.tsx +37 -0
  55. package/tsconfig-cjs.json +8 -0
  56. package/tsconfig-esm.json +8 -0
  57. package/tsconfig-test.json +15 -0
  58. package/tsconfig.json +29 -0
@@ -0,0 +1,284 @@
1
+ import { SelectQueryFactory, } from '@_linked/core/queries/SelectQuery';
2
+ import { Shape } from '@_linked/core/shapes/Shape';
3
+ import React, { useCallback, useEffect, useState } from 'react';
4
+ import { LinkedStorage } from '@_linked/core/utils/LinkedStorage';
5
+ import { DEFAULT_LIMIT } from '@_linked/core/utils/Package';
6
+ import { ShapeSet } from '@_linked/core/collections/ShapeSet';
7
+ import { isNodeReferenceValue } from '@_linked/core/utils/NodeReference';
8
+ import { getShapeClass, hasSuperClass } from '@_linked/core/utils/ShapeClass';
9
+ export function createLinkedComponentFn(registerPackageExport, registerComponent) {
10
+ return function linkedComponent(query, functionalComponent) {
11
+ let [shapeClass, actualQuery] = processQuery(query);
12
+ let _wrappedComponent = React.forwardRef((props, ref) => {
13
+ var _a;
14
+ let [queryResult, setQueryResult] = useState(undefined);
15
+ let [loadingData, setLoadingData] = useState();
16
+ let linkedProps = getLinkedComponentProps(props, shapeClass);
17
+ if (ref) {
18
+ linkedProps.ref = ref;
19
+ }
20
+ const loadData = () => {
21
+ var _a, _b;
22
+ const sourceId = (_a = linkedProps.source) === null || _a === void 0 ? void 0 : _a.id;
23
+ if (!loadingData || loadingData !== sourceId) {
24
+ let requestQuery = actualQuery.clone();
25
+ if (linkedProps.source) {
26
+ requestQuery.setSubject(linkedProps.source);
27
+ }
28
+ setLoadingData(sourceId || ((_b = requestQuery.subject) === null || _b === void 0 ? void 0 : _b.id));
29
+ const parser = shapeClass.queryParser || Shape.queryParser;
30
+ if (!parser) {
31
+ throw new Error(`No query parser configured for ${(shapeClass === null || shapeClass === void 0 ? void 0 : shapeClass.name) || 'shape'}.`);
32
+ }
33
+ parser.selectQuery(requestQuery).then((result) => {
34
+ setQueryResult(result);
35
+ setLoadingData(null);
36
+ });
37
+ }
38
+ else {
39
+ console.warn(`Already loading data for source ${loadingData}, ignoring request`);
40
+ }
41
+ };
42
+ let sourceIsValidQResult = isValidQResult(props.of, query);
43
+ if (queryResult || sourceIsValidQResult) {
44
+ linkedProps = Object.assign(linkedProps, queryResult || props.of);
45
+ }
46
+ linkedProps._refresh = useCallback((updatedProps) => {
47
+ if (updatedProps) {
48
+ if (queryResult) {
49
+ setQueryResult(Object.assign(Object.assign({}, queryResult), updatedProps));
50
+ }
51
+ else if (sourceIsValidQResult) {
52
+ setQueryResult(Object.assign(Object.assign({}, props.of), updatedProps));
53
+ }
54
+ }
55
+ else {
56
+ loadData();
57
+ }
58
+ }, [queryResult, props.of]);
59
+ if (!linkedProps.source && !actualQuery.subject) {
60
+ console.warn('This component requires a source to be provided (use the property "of"): ' +
61
+ functionalComponent.name);
62
+ return null;
63
+ }
64
+ let usingStorage = LinkedStorage.isInitialised();
65
+ useEffect(() => {
66
+ if (queryResult) {
67
+ setQueryResult(undefined);
68
+ }
69
+ if (usingStorage && !sourceIsValidQResult) {
70
+ loadData();
71
+ }
72
+ }, [(_a = linkedProps.source) === null || _a === void 0 ? void 0 : _a.id]);
73
+ let dataIsLoaded = queryResult || !usingStorage || sourceIsValidQResult;
74
+ // Keep legacy client-side guard to avoid hydration drift.
75
+ if (dataIsLoaded && typeof window !== 'undefined') {
76
+ return React.createElement(functionalComponent, linkedProps);
77
+ }
78
+ else {
79
+ return createLoadingSpinner();
80
+ }
81
+ });
82
+ _wrappedComponent.original = functionalComponent;
83
+ _wrappedComponent.query = query;
84
+ _wrappedComponent.shape = shapeClass;
85
+ if (functionalComponent.name) {
86
+ Object.defineProperty(_wrappedComponent, 'name', {
87
+ value: functionalComponent.name,
88
+ });
89
+ registerPackageExport(_wrappedComponent);
90
+ }
91
+ registerComponent(_wrappedComponent, shapeClass);
92
+ return _wrappedComponent;
93
+ };
94
+ }
95
+ export function createLinkedSetComponentFn(registerPackageExport, registerComponent) {
96
+ return function linkedSetComponent(query, functionalComponent) {
97
+ let [shapeClass, actualQuery] = processQuery(query, true);
98
+ let usingStorage = LinkedStorage.isInitialised();
99
+ let _wrappedComponent = React.forwardRef((props, ref) => {
100
+ var _a;
101
+ let [queryResult, setQueryResult] = useState(undefined);
102
+ let linkedProps = getLinkedSetComponentProps(props, shapeClass, functionalComponent);
103
+ let defaultLimit = actualQuery.getLimit() || DEFAULT_LIMIT;
104
+ let [limit, setLimit] = useState(defaultLimit);
105
+ let [offset, setOffset] = useState(0);
106
+ if (ref) {
107
+ linkedProps.ref = ref;
108
+ }
109
+ let sourceIsValidQResult = Array.isArray(props.of) &&
110
+ props.of.length > 0 &&
111
+ typeof ((_a = props.of[0]) === null || _a === void 0 ? void 0 : _a.id) === 'string' &&
112
+ actualQuery.isValidSetResult(props.of);
113
+ if (queryResult || sourceIsValidQResult) {
114
+ let dataResult;
115
+ if (queryResult) {
116
+ dataResult = queryResult;
117
+ }
118
+ else {
119
+ if (limit) {
120
+ dataResult = props.of.slice(offset || 0, offset + limit);
121
+ }
122
+ else {
123
+ dataResult = props.of;
124
+ }
125
+ }
126
+ if (query instanceof SelectQueryFactory) {
127
+ linkedProps = Object.assign(linkedProps, {
128
+ linkedData: dataResult,
129
+ });
130
+ }
131
+ else {
132
+ let key = Object.keys(query)[0];
133
+ linkedProps[key] = dataResult;
134
+ }
135
+ }
136
+ if (limit) {
137
+ linkedProps.query = {
138
+ nextPage: () => {
139
+ setOffset(offset + limit);
140
+ },
141
+ previousPage: () => {
142
+ setOffset(Math.max(0, offset - limit));
143
+ },
144
+ setLimit: (newLimit) => {
145
+ setLimit(newLimit);
146
+ },
147
+ setPage: (page) => {
148
+ setOffset(page * limit);
149
+ },
150
+ };
151
+ }
152
+ useEffect(() => {
153
+ if (usingStorage && !sourceIsValidQResult) {
154
+ let requestQuery = actualQuery.clone();
155
+ requestQuery.setSubject(linkedProps.sources);
156
+ if (limit) {
157
+ requestQuery.setLimit(limit);
158
+ }
159
+ if (offset) {
160
+ requestQuery.setOffset(offset);
161
+ }
162
+ const parser = shapeClass.queryParser || Shape.queryParser;
163
+ if (!parser) {
164
+ throw new Error(`No query parser configured for ${(shapeClass === null || shapeClass === void 0 ? void 0 : shapeClass.name) || 'shape'}.`);
165
+ }
166
+ parser.selectQuery(requestQuery).then((result) => {
167
+ setQueryResult(result);
168
+ });
169
+ }
170
+ }, [props.of, limit, offset]);
171
+ let dataIsLoaded = queryResult || !usingStorage || sourceIsValidQResult;
172
+ if (typeof queryResult === 'undefined' &&
173
+ usingStorage &&
174
+ !sourceIsValidQResult) {
175
+ dataIsLoaded = false;
176
+ }
177
+ if (dataIsLoaded) {
178
+ return React.createElement(functionalComponent, linkedProps);
179
+ }
180
+ else {
181
+ return createLoadingSpinner();
182
+ }
183
+ });
184
+ _wrappedComponent.original = functionalComponent;
185
+ _wrappedComponent.query = query;
186
+ _wrappedComponent.shape = shapeClass;
187
+ if (functionalComponent.name) {
188
+ Object.defineProperty(_wrappedComponent, 'name', {
189
+ value: functionalComponent.name,
190
+ });
191
+ registerPackageExport(_wrappedComponent);
192
+ }
193
+ registerComponent(_wrappedComponent, shapeClass);
194
+ return _wrappedComponent;
195
+ };
196
+ }
197
+ function getLinkedComponentProps(props, shapeClass) {
198
+ let newProps = Object.assign(Object.assign({}, props), { source: getSourceFromInputProps(props, shapeClass) });
199
+ if (newProps.of) {
200
+ for (let key of Object.getOwnPropertyNames(newProps.of)) {
201
+ if (key !== 'shape' && key !== 'id') {
202
+ newProps[key] = newProps.of[key];
203
+ }
204
+ }
205
+ }
206
+ delete newProps.of;
207
+ return newProps;
208
+ }
209
+ function processQuery(requiredData, setComponent = false) {
210
+ let shapeClass;
211
+ let query;
212
+ if (requiredData instanceof SelectQueryFactory) {
213
+ query = requiredData;
214
+ shapeClass = requiredData.shape;
215
+ }
216
+ else if (typeof requiredData === 'object' && setComponent) {
217
+ if (Object.keys(requiredData).length > 1) {
218
+ throw new Error('Only one key is allowed to map a query to a property for linkedSetComponents');
219
+ }
220
+ for (let key in requiredData) {
221
+ if (requiredData[key] instanceof SelectQueryFactory) {
222
+ shapeClass = requiredData[key].shape;
223
+ query = requiredData[key];
224
+ }
225
+ else {
226
+ throw new Error('Unknown value type for query object. Keep to this format: {propName: Shape.query(s => ...)}');
227
+ }
228
+ }
229
+ }
230
+ else {
231
+ throw new Error('Unknown data query type. Expected a LinkedQuery (from Shape.query()) or an object with 1 key whose value is a LinkedQuery');
232
+ }
233
+ return [shapeClass, query];
234
+ }
235
+ function getLinkedSetComponentProps(props, shapeClass, functionalComponent) {
236
+ if (props.of &&
237
+ !(props.of instanceof ShapeSet) &&
238
+ !Array.isArray(props.of)) {
239
+ throw Error("Invalid argument 'of' provided to " +
240
+ functionalComponent.name.replace('_implementation', '') +
241
+ ' component: ' +
242
+ props.of +
243
+ '. Make sure to provide a ShapeSet, an array of QResults, or no argument at all to load all instances.');
244
+ }
245
+ let sources;
246
+ if (props.of instanceof ShapeSet) {
247
+ sources = props.of;
248
+ }
249
+ else if (Array.isArray(props.of)) {
250
+ sources = new ShapeSet(props.of.map((item) => {
251
+ return getSourceFromInputProps({ of: item }, shapeClass);
252
+ }));
253
+ }
254
+ const newProps = Object.assign(Object.assign({}, props), { sources });
255
+ delete newProps.of;
256
+ return newProps;
257
+ }
258
+ export function getSourceFromInputProps(props, shapeClass) {
259
+ const input = props === null || props === void 0 ? void 0 : props.of;
260
+ if (input instanceof Shape) {
261
+ if (input.nodeShape !== shapeClass.shape &&
262
+ !hasSuperClass(getShapeClass(input.nodeShape.id), shapeClass)) {
263
+ return new shapeClass(input.id);
264
+ }
265
+ return input;
266
+ }
267
+ if (isNodeReferenceValue(input)) {
268
+ return new shapeClass(input);
269
+ }
270
+ // If nothing is provided, keep undefined; callers handle required source checks.
271
+ return input;
272
+ }
273
+ function isValidQResult(of, query) {
274
+ return (typeof (of === null || of === void 0 ? void 0 : of.id) === 'string' &&
275
+ query.isValidResult(of));
276
+ }
277
+ function createLoadingSpinner() {
278
+ return React.createElement('div', {
279
+ className: 'ld-loader',
280
+ 'aria-label': 'Loading',
281
+ role: 'status',
282
+ });
283
+ }
284
+ //# sourceMappingURL=LinkedComponent.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkedComponent.js","sourceRoot":"","sources":["../../../src/utils/LinkedComponent.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import React from 'react';
2
+ import { Shape } from '@_linked/core/shapes/Shape';
3
+ import { LinkedComponentProps } from './LinkedComponent.js';
4
+ /**
5
+ * Class component base for linked components.
6
+ */
7
+ export declare class LinkedComponentClass<ShapeClass extends Shape, P = {}, S = any> extends React.Component<P & LinkedComponentProps<ShapeClass>, S> {
8
+ private _shape;
9
+ get sourceShape(): ShapeClass;
10
+ componentDidUpdate(prevProps: Readonly<P & LinkedComponentProps<ShapeClass>>): void;
11
+ }
@@ -0,0 +1,27 @@
1
+ import React from 'react';
2
+ /**
3
+ * Class component base for linked components.
4
+ */
5
+ export class LinkedComponentClass extends React.Component {
6
+ get sourceShape() {
7
+ if (typeof this._shape === 'undefined') {
8
+ if (!this.props.source) {
9
+ this._shape = null;
10
+ }
11
+ else {
12
+ let shapeClass = this.constructor['shape'];
13
+ if (!shapeClass) {
14
+ throw new Error(`${this.constructor.name} is not linked to a shape`);
15
+ }
16
+ this._shape = new shapeClass(this.props.source);
17
+ }
18
+ }
19
+ return this._shape;
20
+ }
21
+ componentDidUpdate(prevProps) {
22
+ if (prevProps.source !== this.props.source) {
23
+ this._shape = undefined;
24
+ }
25
+ }
26
+ }
27
+ //# sourceMappingURL=LinkedComponentClass.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LinkedComponentClass.js","sourceRoot":"","sources":["../../../src/utils/LinkedComponentClass.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAI1B;;GAEG;AACH,MAAM,OAAO,oBAIX,SAAQ,KAAK,CAAC,SAAkD;IAGhE,IAAI,WAAW;QACb,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,WAAW,EAAE,CAAC;YACvC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;gBACvB,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;YACrB,CAAC;iBAAM,CAAC;gBACN,IAAI,UAAU,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC;gBAC3C,IAAI,CAAC,UAAU,EAAE,CAAC;oBAChB,MAAM,IAAI,KAAK,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,IAAI,2BAA2B,CAAC,CAAC;gBACvE,CAAC;gBACD,IAAI,CAAC,MAAM,GAAG,IAAI,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAe,CAAC;YAChE,CAAC;QACH,CAAC;QACD,OAAO,IAAI,CAAC,MAAM,CAAC;IACrB,CAAC;IAED,kBAAkB,CAChB,SAAyD;QAEzD,IAAI,SAAS,CAAC,MAAM,KAAK,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;YAC3C,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC;QAC1B,CAAC;IACH,CAAC;CACF"}
package/package.json ADDED
@@ -0,0 +1,57 @@
1
+ {
2
+ "name": "@_linked/react",
3
+ "version": "0.0.1",
4
+ "license": "MIT",
5
+ "description": "React bindings for @_linked/core",
6
+ "main": "lib/cjs/index.js",
7
+ "module": "lib/esm/index.js",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./lib/esm/index.d.ts",
11
+ "import": "./lib/esm/index.js",
12
+ "require": "./lib/cjs/index.js"
13
+ },
14
+ "./*": {
15
+ "types": "./lib/esm/*.d.ts",
16
+ "import": "./lib/esm/*.js",
17
+ "require": "./lib/cjs/*.js"
18
+ }
19
+ },
20
+ "typesVersions": {
21
+ "*": {
22
+ "*": [
23
+ "lib/esm/*"
24
+ ]
25
+ }
26
+ },
27
+ "scripts": {
28
+ "build": "npx rimraf ./lib && npx tsc -p tsconfig-cjs.json && npx tsc -p tsconfig-esm.json && node ./scripts/dual-package.js",
29
+ "compile": "echo '💫 Compiling CJS' && npx tsc -p tsconfig-cjs.json && echo '💫 Compiling ESM' && npx tsc -p tsconfig-esm.json",
30
+ "dual-package": "node ./scripts/dual-package.js",
31
+ "test": "npx jest --config jest.config.js"
32
+ },
33
+ "peerDependencies": {
34
+ "@_linked/core": "^1.0.0",
35
+ "react": "^18.2.0"
36
+ },
37
+ "dependencies": {
38
+ "react-usestateref": "^1.0.8"
39
+ },
40
+ "devDependencies": {
41
+ "@_linked/core": "^1.0.0",
42
+ "@_linked/rdf-mem-store": "^1.0.0",
43
+ "@testing-library/react": "^14.2.1",
44
+ "@jest/globals": "^29.7.0",
45
+ "@types/jest": "^29.5.12",
46
+ "@types/node": "^20.12.7",
47
+ "@types/react": "^18.2.61",
48
+ "@types/react-dom": "^18.2.19",
49
+ "jest": "^29.7.0",
50
+ "jest-environment-jsdom": "^29.7.0",
51
+ "react": "^18.2.0",
52
+ "react-dom": "^18.2.0",
53
+ "rimraf": "^5.0.7",
54
+ "ts-jest": "^29.1.2",
55
+ "typescript": "^5.7.3"
56
+ }
57
+ }
@@ -0,0 +1,25 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ const root = path.resolve(__dirname,'..');
5
+ const libDir = path.join(root,'lib');
6
+ const cjsDir = path.join(libDir,'cjs');
7
+ const esmDir = path.join(libDir,'esm');
8
+
9
+ const ensureDir = (dir) => {
10
+ if (!fs.existsSync(dir)) {
11
+ fs.mkdirSync(dir,{recursive: true});
12
+ }
13
+ };
14
+
15
+ const writePackageJson = (dir,type) => {
16
+ ensureDir(dir);
17
+ const pkgPath = path.join(dir,'package.json');
18
+ const data = {
19
+ type,
20
+ };
21
+ fs.writeFileSync(pkgPath,JSON.stringify(data,null,2));
22
+ };
23
+
24
+ writePackageJson(cjsDir,'commonjs');
25
+ writePackageJson(esmDir,'module');
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './package.js';
2
+ export * from './utils/LinkedComponent.js';
3
+ export * from './utils/LinkedComponentClass.js';
4
+ export * from './utils/Hooks.js';
package/src/package.ts ADDED
@@ -0,0 +1,62 @@
1
+ import {CoreSet} from '@_linked/core/collections/CoreSet';
2
+ import {linkedPackage} from '@_linked/core/utils/Package';
3
+ import {Shape} from '@_linked/core/shapes/Shape';
4
+ import {
5
+ Component,
6
+ createLinkedComponentFn,
7
+ createLinkedSetComponentFn,
8
+ } from './utils/LinkedComponent.js';
9
+
10
+ let shapeToComponents: Map<typeof Shape, CoreSet<Component>> = new Map();
11
+
12
+ const {
13
+ linkedUtil,
14
+ linkedOntology,
15
+ linkedShape,
16
+ registerPackageExport,
17
+ registerPackageModule,
18
+ packageExports,
19
+ getPackageShape,
20
+ } = linkedPackage('@_linked/react');
21
+
22
+ function registerComponent(exportedComponent: Component, shape?: typeof Shape) {
23
+ if (!shape) {
24
+ if (!Object.prototype.hasOwnProperty.call(exportedComponent, 'shape')) {
25
+ console.warn(
26
+ `Component ${
27
+ exportedComponent.displayName || exportedComponent.name
28
+ } is not linked to a shape.`,
29
+ );
30
+ return;
31
+ }
32
+ shape = exportedComponent.shape;
33
+ }
34
+
35
+ if (!shapeToComponents.has(shape)) {
36
+ shapeToComponents.set(shape, new CoreSet<any>());
37
+ }
38
+
39
+ shapeToComponents.get(shape).add(exportedComponent);
40
+ }
41
+
42
+ const linkedComponent = createLinkedComponentFn(
43
+ registerPackageExport,
44
+ registerComponent,
45
+ );
46
+
47
+ const linkedSetComponent = createLinkedSetComponentFn(
48
+ registerPackageExport,
49
+ registerComponent,
50
+ );
51
+
52
+ export {
53
+ linkedComponent,
54
+ linkedSetComponent,
55
+ linkedShape,
56
+ linkedUtil,
57
+ linkedOntology,
58
+ registerPackageExport,
59
+ registerPackageModule,
60
+ packageExports,
61
+ getPackageShape,
62
+ };