@arpproject/recrate 0.1.7 → 0.1.9

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 (188) hide show
  1. package/dist/index.d.ts +3 -2
  2. package/dist/recrate.css +4 -4
  3. package/dist/recrate.es.js +34674 -114061
  4. package/package.json +41 -32
  5. package/.eslintrc.json +0 -37
  6. package/.storybook/main.ts +0 -40
  7. package/.storybook/preview.tsx +0 -46
  8. package/babel.config.json +0 -5
  9. package/docker-compose.yml +0 -30
  10. package/docs/.nojekyll +0 -1
  11. package/docs/assets/highlight.css +0 -99
  12. package/docs/assets/icons.js +0 -18
  13. package/docs/assets/icons.svg +0 -1
  14. package/docs/assets/main.js +0 -60
  15. package/docs/assets/navigation.js +0 -1
  16. package/docs/assets/search.js +0 -1
  17. package/docs/assets/style.css +0 -1448
  18. package/docs/classes/src_crate_builder_CrateManager_crate_manager.CrateManager.html +0 -240
  19. package/docs/classes/src_crate_builder_CrateManager_profile_manager.ProfileManager.html +0 -42
  20. package/docs/classes/src_crate_builder_editor_state.EditorState.html +0 -28
  21. package/docs/classes/src_crate_builder_types.CrateManagerType.html +0 -57
  22. package/docs/classes/src_crate_builder_types.ProfileManagerType.html +0 -13
  23. package/docs/functions/src_crate_builder_CrateManager_lib.isURL.html +0 -2
  24. package/docs/functions/src_crate_builder_CrateManager_lib.mintNewCrate.html +0 -3
  25. package/docs/functions/src_crate_builder_CrateManager_lib.normalise.html +0 -5
  26. package/docs/functions/src_crate_builder_CrateManager_lib.normaliseEntityType.html +0 -1
  27. package/docs/index.html +0 -58
  28. package/docs/interfaces/src_crate_builder_types.NormalisedCrate.html +0 -3
  29. package/docs/interfaces/src_crate_builder_types.NormalisedEntityDefinition.html +0 -4
  30. package/docs/interfaces/src_crate_builder_types.NormalisedProfile.html +0 -9
  31. package/docs/interfaces/src_crate_builder_types.ProfileLayout.html +0 -2
  32. package/docs/interfaces/src_crate_builder_types.ProfileLayoutGroup.html +0 -9
  33. package/docs/interfaces/src_crate_builder_types.UnverifiedCrate.html +0 -3
  34. package/docs/interfaces/src_crate_builder_types.UnverifiedEntityDefinition.html +0 -4
  35. package/docs/modules/src_crate_builder_CrateManager_crate_manager.html +0 -2
  36. package/docs/modules/src_crate_builder_CrateManager_lib.html +0 -6
  37. package/docs/modules/src_crate_builder_CrateManager_profile_manager.html +0 -2
  38. package/docs/modules/src_crate_builder_editor_state.html +0 -2
  39. package/docs/modules/src_crate_builder_types.html +0 -16
  40. package/docs/types/src_crate_builder_types.EntityReference.html +0 -1
  41. package/docs/types/src_crate_builder_types.NormalisedContext.html +0 -1
  42. package/docs/types/src_crate_builder_types.PrimitiveType.html +0 -1
  43. package/docs/types/src_crate_builder_types.ProfileAssociation.html +0 -1
  44. package/docs/types/src_crate_builder_types.ProfileInput.html +0 -1
  45. package/docs/types/src_crate_builder_types.UnverifiedContext.html +0 -1
  46. package/docs/variables/src_crate_builder_CrateManager_lib.urlProtocols.html +0 -1
  47. package/index.html +0 -13
  48. package/load-data-packs.cjs +0 -38
  49. package/postcss.config.cjs +0 -6
  50. package/public/favicon.ico +0 -0
  51. package/public/index.html +0 -43
  52. package/public/logo192.png +0 -0
  53. package/public/logo512.png +0 -0
  54. package/public/manifest.json +0 -25
  55. package/public/marker-icon.png +0 -0
  56. package/public/marker-shadow.png +0 -0
  57. package/public/robots.txt +0 -3
  58. package/react-app-env.d.ts +0 -1
  59. package/rollup.config.js +0 -26
  60. package/src/app/App.tsx +0 -13
  61. package/src/app/EmbeddedComponent.tsx +0 -432
  62. package/src/app/index.html +0 -20
  63. package/src/app/index.tsx +0 -19
  64. package/src/app/lookup.ts +0 -141
  65. package/src/app/override-styles.css +0 -96
  66. package/src/crate-builder/CrateManager/contexts/1.1-context.jsonld +0 -2660
  67. package/src/crate-builder/CrateManager/contexts/1.2-DRAFT-context.jsonld +0 -2918
  68. package/src/crate-builder/CrateManager/contexts.ts +0 -42
  69. package/src/crate-builder/CrateManager/crate-manager-benchmarking.spec.ts +0 -31
  70. package/src/crate-builder/CrateManager/crate-manager-loading-exporting.spec.ts +0 -431
  71. package/src/crate-builder/CrateManager/crate-manager-operations.spec.ts +0 -298
  72. package/src/crate-builder/CrateManager/crate-manager.spec.ts +0 -2336
  73. package/src/crate-builder/CrateManager/crate-manager.ts +0 -2111
  74. package/src/crate-builder/CrateManager/lib.spec.ts +0 -133
  75. package/src/crate-builder/CrateManager/lib.ts +0 -170
  76. package/src/crate-builder/CrateManager/profile-manager.spec.ts +0 -593
  77. package/src/crate-builder/CrateManager/profile-manager.ts +0 -367
  78. package/src/crate-builder/CrateManager/schema-type-definitions.json +0 -35122
  79. package/src/crate-builder/CrateManager/validate-identifier.spec.ts +0 -82
  80. package/src/crate-builder/CrateManager/validate-identifier.ts +0 -65
  81. package/src/crate-builder/RenderEntity/Add.tsx +0 -249
  82. package/src/crate-builder/RenderEntity/AddControl.stories.tsx +0 -126
  83. package/src/crate-builder/RenderEntity/AddControl.tsx +0 -84
  84. package/src/crate-builder/RenderEntity/AutoComplete.tsx +0 -215
  85. package/src/crate-builder/RenderEntity/BulkAdd.tsx +0 -136
  86. package/src/crate-builder/RenderEntity/DeleteProperty.tsx +0 -33
  87. package/src/crate-builder/RenderEntity/DialogAddProperty.tsx +0 -83
  88. package/src/crate-builder/RenderEntity/DialogBrowseEntities.tsx +0 -136
  89. package/src/crate-builder/RenderEntity/DialogEditContext.tsx +0 -107
  90. package/src/crate-builder/RenderEntity/DialogPreviewCrate.tsx +0 -54
  91. package/src/crate-builder/RenderEntity/DialogSaveCrateAsTemplate.tsx +0 -65
  92. package/src/crate-builder/RenderEntity/DialogSaveEntityTemplate.tsx +0 -87
  93. package/src/crate-builder/RenderEntity/DisplayPropertyName.stories.tsx +0 -30
  94. package/src/crate-builder/RenderEntity/DisplayPropertyName.tsx +0 -21
  95. package/src/crate-builder/RenderEntity/EntityId.tsx +0 -75
  96. package/src/crate-builder/RenderEntity/EntityName.tsx +0 -49
  97. package/src/crate-builder/RenderEntity/EntityProperty.tsx +0 -188
  98. package/src/crate-builder/RenderEntity/EntityPropertyInstance.tsx +0 -255
  99. package/src/crate-builder/RenderEntity/EntityType.tsx +0 -95
  100. package/src/crate-builder/RenderEntity/ItemLink.tsx +0 -37
  101. package/src/crate-builder/RenderEntity/PaginateLinkedEntities.stories.tsx +0 -43
  102. package/src/crate-builder/RenderEntity/PaginateLinkedEntities.tsx +0 -141
  103. package/src/crate-builder/RenderEntity/PropertyHelp.tsx +0 -39
  104. package/src/crate-builder/RenderEntity/RenderControls.tsx +0 -278
  105. package/src/crate-builder/RenderEntity/RenderLinkedItem.tsx +0 -139
  106. package/src/crate-builder/RenderEntity/RenderPropertyHelp.tsx +0 -41
  107. package/src/crate-builder/RenderEntity/RenderReverseConnections.tsx +0 -150
  108. package/src/crate-builder/RenderEntity/RenderTypes.tsx +0 -102
  109. package/src/crate-builder/RenderEntity/Shell2.tsx +0 -576
  110. package/src/crate-builder/RenderEntity/UnlinkEntity.tsx +0 -30
  111. package/src/crate-builder/RenderEntity/auto-complete.lib.ts +0 -184
  112. package/src/crate-builder/RenderEntity/keys.ts +0 -4
  113. package/src/crate-builder/RenderEntity/layout.spec.js +0 -593
  114. package/src/crate-builder/RenderEntity/layout.ts +0 -220
  115. package/src/crate-builder/Shell.tsx +0 -337
  116. package/src/crate-builder/component.css +0 -65
  117. package/src/crate-builder/editor-state.ts +0 -114
  118. package/src/crate-builder/emotionCache.ts +0 -8
  119. package/src/crate-builder/helpers.ts +0 -16
  120. package/src/crate-builder/i18n.ts +0 -22
  121. package/src/crate-builder/lib/validate-iri.js +0 -69
  122. package/src/crate-builder/lib/validate-iri.ts +0 -57
  123. package/src/crate-builder/locales/en.js +0 -149
  124. package/src/crate-builder/locales/hu.js +0 -147
  125. package/src/crate-builder/primitives/Boolean.stories.tsx +0 -33
  126. package/src/crate-builder/primitives/Boolean.tsx +0 -67
  127. package/src/crate-builder/primitives/Date.stories.tsx +0 -32
  128. package/src/crate-builder/primitives/Date.tsx +0 -58
  129. package/src/crate-builder/primitives/DateTime.stories.tsx +0 -32
  130. package/src/crate-builder/primitives/DateTime.tsx +0 -64
  131. package/src/crate-builder/primitives/Geo.stories.tsx +0 -57
  132. package/src/crate-builder/primitives/Geo.tsx +0 -225
  133. package/src/crate-builder/primitives/Map.SelectArea.js +0 -359
  134. package/src/crate-builder/primitives/Map.stories.tsx +0 -61
  135. package/src/crate-builder/primitives/Map.tsx +0 -124
  136. package/src/crate-builder/primitives/Number.stories.tsx +0 -74
  137. package/src/crate-builder/primitives/Number.tsx +0 -166
  138. package/src/crate-builder/primitives/Select.stories.tsx +0 -66
  139. package/src/crate-builder/primitives/Select.tsx +0 -121
  140. package/src/crate-builder/primitives/SelectObject.stories.tsx +0 -29
  141. package/src/crate-builder/primitives/SelectObject.tsx +0 -105
  142. package/src/crate-builder/primitives/SelectUrl.stories.tsx +0 -42
  143. package/src/crate-builder/primitives/SelectUrl.tsx +0 -110
  144. package/src/crate-builder/primitives/Text.stories.tsx +0 -106
  145. package/src/crate-builder/primitives/Text.tsx +0 -197
  146. package/src/crate-builder/primitives/Time.stories.tsx +0 -38
  147. package/src/crate-builder/primitives/Time.tsx +0 -71
  148. package/src/crate-builder/primitives/Url.stories.tsx +0 -43
  149. package/src/crate-builder/primitives/Url.tsx +0 -75
  150. package/src/crate-builder/primitives/Value.stories.tsx +0 -37
  151. package/src/crate-builder/primitives/Value.tsx +0 -30
  152. package/src/crate-builder/primitives/date-libs.ts +0 -12
  153. package/src/crate-builder/profile-schema.json +0 -145
  154. package/src/crate-builder/property-definitions.ts +0 -78
  155. package/src/crate-builder/recrate.css +0 -3
  156. package/src/crate-builder/store.ts +0 -14
  157. package/src/crate-builder/tailwind.css +0 -5
  158. package/src/crate-builder/types.d.ts +0 -318
  159. package/src/examples/collection/collections-entity-example.json +0 -131
  160. package/src/examples/collection/crate-builder-entity-example.json +0 -33
  161. package/src/examples/item/complex-collection/ro-crate-metadata.json +0 -174
  162. package/src/examples/item/complex-item/ro-crate-metadata.json +0 -769
  163. package/src/examples/item/crate-with-language.json +0 -38
  164. package/src/examples/item/empty/ro-crate-metadata.json +0 -20
  165. package/src/examples/item/item-with-relationship-and-action/ro-crate-metadata.json +0 -66
  166. package/src/examples/item/large-crate/ro-crate-metadata.json +0 -5762
  167. package/src/examples/item/multiple-types/ro-crate-metadata.json +0 -20
  168. package/src/examples/item/ridiculously-big-collection/ro-crate-metadata.json +0 -162977
  169. package/src/examples/profile/aroma.complex.profile.json +0 -11098
  170. package/src/examples/profile/aroma.profile.json +0 -9158
  171. package/src/examples/profile/nyingarn-item-profile.json +0 -426
  172. package/src/examples/profile/profile-to-test-inverse-associations.json +0 -73
  173. package/src/examples/profile/profile-to-test-multiple-types.json +0 -31
  174. package/src/examples/profile/profile-with-all-primitives-and-groups.json +0 -207
  175. package/src/examples/profile/profile-with-all-primitives.json +0 -244
  176. package/src/examples/profile/profile-with-constraints.json +0 -446
  177. package/src/examples/profile/profile-with-resolve.json +0 -57
  178. package/src/examples/profile/vocabulary-creation-profile.json +0 -231
  179. package/src/images.d.ts +0 -5
  180. package/src/index.ts +0 -12
  181. package/src/types.ts +0 -104
  182. package/tailwind.config.js +0 -21
  183. package/tsconfig.app.json +0 -31
  184. package/tsconfig.json +0 -26
  185. package/typedoc.json +0 -11
  186. package/update-deps.sh +0 -4
  187. package/vite-env.d.ts +0 -1
  188. package/vite.config.ts +0 -46
@@ -1,2336 +0,0 @@
1
- import { describe, test, expect, beforeAll, beforeEach, vi } from "vitest";
2
- import { CrateManager } from "./crate-manager";
3
- import { ProfileManager } from "./profile-manager";
4
- import { readJSON } from "fs-extra";
5
- import Chance from "chance";
6
- const chance = Chance();
7
- import type {
8
- CrateManagerType,
9
- EntityReference,
10
- NormalisedEntityDefinition,
11
- NormalisedProfile,
12
- ProfileManagerType,
13
- UnverifiedCrate,
14
- UnverifiedEntityDefinition,
15
- } from "../types";
16
-
17
- describe("Test interacting with the crate", () => {
18
- let crate: UnverifiedCrate, cm: CrateManagerType;
19
- beforeAll(() => {
20
- vi.spyOn(console, "debug").mockImplementation(() => {});
21
- });
22
- beforeEach(async () => {
23
- crate = getBaseCrate();
24
- crate["@graph"].push({
25
- "@id": "./",
26
- "@type": "Dataset",
27
- name: "root dataset",
28
- text: "something",
29
- });
30
- cm = new CrateManager({ crate });
31
- });
32
- test("get root dataset", () => {
33
- let rd = cm.getRootDataset();
34
- expect(rd["@id"]).toEqual("./");
35
- });
36
- test("normalising contexts with varying shapes", () => {
37
- let context: any = "https://w3id.org/ro/crate/1.1/context";
38
- let normalisedContext = cm.__normaliseContext(context);
39
- expect(normalisedContext).toEqual(["https://w3id.org/ro/crate/1.1/context"]);
40
-
41
- context = ["https://w3id.org/ro/crate/1.1/context"];
42
- normalisedContext = cm.__normaliseContext(context);
43
- expect(normalisedContext).toEqual(["https://w3id.org/ro/crate/1.1/context"]);
44
-
45
- context = [
46
- "https://w3id.org/ro/crate/1.1/context",
47
- { hasPart: "https://schema.org/hasPart" },
48
- { schema: "https://schema.org" },
49
- ];
50
- normalisedContext = cm.__normaliseContext(context);
51
- expect(normalisedContext).toEqual([
52
- "https://w3id.org/ro/crate/1.1/context",
53
- {
54
- hasPart: "https://schema.org/hasPart",
55
- schema: "https://schema.org",
56
- },
57
- ]);
58
- });
59
- test("get context", () => {
60
- let context = cm.getContext();
61
- expect(context).toEqual(["https://w3id.org/ro/crate/1.1/context"]);
62
- });
63
- test("set context", () => {
64
- cm.setContext({} as any);
65
- expect(cm.getContext()).toEqual([]);
66
- });
67
- test("set profile manager", () => {
68
- const profile: any = {
69
- metadata: {},
70
- classes: {},
71
- };
72
- const pm: ProfileManagerType = new ProfileManager({ profile }) as ProfileManagerType;
73
- expect(pm).toMatchObject({ profile: { metadata: {}, classes: {} } });
74
-
75
- cm.setProfileManager(pm);
76
- expect(cm.pm).toMatchObject({ profile: { metadata: {}, classes: {} } });
77
- });
78
- test(`getting entities from the crate`, () => {
79
- // no id provided
80
- try {
81
- let match = cm.getEntity({} as any);
82
- } catch (error) {
83
- expect((error as Error).message).toEqual("An id must be provided");
84
- }
85
-
86
- // materialise an entity
87
- let match = cm.getEntity({ id: chance.url() });
88
- expect(match).toMatchObject({ "@type": ["URL"] });
89
-
90
- // matching entity
91
- match = cm.getEntity({ id: "./" });
92
- expect(match).toMatchObject({
93
- "@id": "./",
94
- "@type": ["Dataset"],
95
- name: "root dataset",
96
- text: ["something"],
97
- });
98
-
99
- // matching entity - stub only
100
- match = cm.getEntity({ id: "./", stub: true });
101
- expect(match).toMatchObject({
102
- "@id": "./",
103
- "@type": ["Dataset"],
104
- name: "root dataset",
105
- });
106
- });
107
- test("add a simple entity to the crate", () => {
108
- // test 1
109
- let entity: UnverifiedEntityDefinition = {
110
- "@id": chance.url(),
111
- "@type": "Person",
112
- name: chance.sentence(),
113
- };
114
- let r = cm.addEntity(entity);
115
- let ec = cm.exportCrate();
116
- expect(ec["@graph"].length).toEqual(3);
117
- expect(r).toBeTruthy;
118
-
119
- // test 2
120
- entity = {
121
- "@id": "something",
122
- "@type": "Thing",
123
- };
124
- r = cm.addEntity(entity);
125
- ec = cm.exportCrate();
126
- expect(ec["@graph"].length).toEqual(4);
127
- expect(r).toBeTruthy;
128
-
129
- // test 3
130
- entity = {
131
- "@id": "something",
132
- "@type": "Person",
133
- };
134
- r = cm.addEntity(entity);
135
- ec = cm.exportCrate();
136
- expect(ec["@graph"].length).toEqual(5);
137
- expect(r).toBeTruthy;
138
-
139
- // test 4
140
- try {
141
- entity = {
142
- "@id": "http://something.com",
143
- };
144
- r = cm.addEntity(entity);
145
- } catch (error) {
146
- expect((error as Error).message).toEqual(
147
- `You can't add an entity without defining the type : '@type'.`
148
- );
149
- }
150
-
151
- // test 5
152
- try {
153
- entity = {
154
- name: "some thing",
155
- };
156
- r = cm.addEntity({ entity } as UnverifiedEntityDefinition);
157
- } catch (error) {
158
- expect((error as Error).message).toEqual(
159
- `You can't add an entity without an identifier: '@id'.`
160
- );
161
- }
162
-
163
- // test 6
164
- try {
165
- entity = {
166
- "@id": "./",
167
- "@type": "Dataset",
168
- };
169
- r = cm.addEntity(entity);
170
- } catch (error) {
171
- expect((error as Error).message).toEqual(
172
- `You can't add an entity with id: './' as that will clash with the root dataset.`
173
- );
174
- }
175
-
176
- // test 7
177
- try {
178
- entity = {
179
- "@id": "#person",
180
- };
181
- r = cm.addEntity({ entity } as UnverifiedEntityDefinition);
182
- } catch (error) {
183
- expect((error as Error).message).toEqual(
184
- `You can't add an entity without an identifier: '@id'.`
185
- );
186
- }
187
- });
188
- test(`prevent adding entities with id's that clash with root dataset or descriptor`, () => {
189
- try {
190
- cm.addEntity({ "@id": "./", "@type": "Dataset" });
191
- } catch (error) {
192
- expect((error as Error).message).toEqual(
193
- `You can't add an entity with id: './' as that will clash with the root dataset.`
194
- );
195
- }
196
- try {
197
- cm.addEntity({ "@id": "ro-crate-metadata.json", "@type": "CreativeWork" });
198
- } catch (error) {
199
- expect((error as Error).message).toEqual(
200
- `You can't add an entity with id: 'ro-crate-metadata.json' as that will clash with the root descriptor.`
201
- );
202
- }
203
- // ensure it fails even when the type is different
204
- try {
205
- cm.addEntity({ "@id": "ro-crate-metadata.json", "@type": "Person" });
206
- } catch (error) {
207
- expect((error as Error).message).toEqual(
208
- `You can't add an entity with id: 'ro-crate-metadata.json' as that will clash with the root descriptor.`
209
- );
210
- }
211
- });
212
- test("add a simple entity to the crate and export as a template", () => {
213
- let entity = {
214
- "@id": "#person",
215
- "@type": "Person",
216
- name: "person",
217
- data: "value",
218
- };
219
- let e = cm.addEntity(entity);
220
-
221
- let template = cm.exportEntityTemplate({ id: e["@id"], resolveDepth: 1 });
222
- expect(template).toMatchObject({
223
- "@id": "#person",
224
- "@type": ["Person"],
225
- name: "person",
226
- data: "value",
227
- });
228
- });
229
- test(`Ensure no id clashes when entity type is different`, () => {
230
- let topic = {
231
- "@id": "#1234",
232
- "@type": "Topic",
233
- name: "topic",
234
- };
235
- let e = cm.addEntity(topic);
236
- expect(e).toEqual({ "@id": "#1234", "@type": ["Topic"], name: "topic" });
237
-
238
- let theme = {
239
- "@id": "#1234",
240
- "@type": "Theme",
241
- name: "theme",
242
- };
243
- e = cm.addEntity(theme);
244
- expect(e).toEqual({ "@id": "#e4", "@type": ["Theme"], name: "theme" });
245
-
246
- e = cm.addEntity(e);
247
- expect(e).toMatchObject({ "@id": "#e4", "@type": ["Theme"], name: "theme" });
248
- });
249
- test("add a complex entity to the crate and export as a template", () => {
250
- let entity: UnverifiedEntityDefinition = {
251
- "@id": "#person",
252
- "@type": "Person",
253
- name: "person",
254
- data: "value",
255
- };
256
- let e = cm.addEntity(entity);
257
- entity = {
258
- "@id": "#organisation",
259
- "@type": "Organisation",
260
- name: "organisation",
261
- ceo: { "@id": "http://person.name" },
262
- };
263
- e = cm.addEntity(entity);
264
- cm.linkEntity({
265
- id: "#person",
266
- property: "organisation",
267
- value: { "@id": "#organisation" },
268
- });
269
-
270
- let template = cm.exportEntityTemplate({
271
- id: "#person",
272
- resolveDepth: 1,
273
- });
274
- expect(template).toEqual({
275
- "@id": "#person",
276
- "@type": ["Person"],
277
- name: "person",
278
- data: "value",
279
- organisation: {
280
- "@id": "#organisation",
281
- "@type": ["Organisation"],
282
- name: "organisation",
283
- },
284
- });
285
- });
286
- test(`fail template export - bad resolve depth`, () => {
287
- // test bad resolveDepth
288
- try {
289
- let _template = cm.exportEntityTemplate({
290
- id: "#person",
291
- resolveDepth: 4,
292
- });
293
- } catch (error) {
294
- expect((error as Error).message).toEqual(`resolveDepth can only be 0 or 1`);
295
- }
296
- });
297
- test("add a complex entity to the crate", () => {
298
- let url = chance.url();
299
- let entity = {
300
- "@id": url,
301
- "@type": "Person",
302
- name: "a person",
303
- text: "some text",
304
- author: [{ "@id": url }],
305
- };
306
- let e = cm.addEntity(entity);
307
- let match = cm.getEntity({ id: e["@id"] });
308
- expect(match).toMatchObject({
309
- "@id": url,
310
- "@type": ["Person"],
311
- name: "a person",
312
- text: ["some text"],
313
- author: [{ "@id": url }],
314
- });
315
- });
316
- test("update entity name", () => {
317
- const url = chance.url();
318
- let entity = {
319
- "@id": url,
320
- "@type": "Person",
321
- name: chance.sentence(),
322
- };
323
- let e: NormalisedEntityDefinition = cm.addEntity(entity);
324
- expect(e).toBeTruthy;
325
-
326
- let r = cm.updateProperty({
327
- id: entity["@id"],
328
- idx: 0,
329
- property: "name",
330
- value: "something else",
331
- });
332
- expect(r).toBeTruthy;
333
- e = cm.getEntity({ id: entity["@id"] }) as NormalisedEntityDefinition;
334
- expect(e.name).toEqual("something else");
335
- });
336
- test("update entity @type", () => {
337
- const url = chance.url();
338
- let entity = {
339
- "@id": url,
340
- "@type": "Person",
341
- name: chance.sentence(),
342
- };
343
- let e: NormalisedEntityDefinition = cm.addEntity(entity);
344
- expect(e).toBeTruthy;
345
-
346
- // test 1
347
- let r = cm.updateProperty({
348
- id: entity["@id"],
349
- property: "@type",
350
- idx: 0,
351
- value: ["Person", "Adult"],
352
- });
353
- expect(r).toBeTruthy;
354
- e = cm.getEntity({ id: entity["@id"] }) as NormalisedEntityDefinition;
355
- expect(e["@type"]).toEqual(["Person", "Adult"]);
356
-
357
- // test 2
358
- r = cm.updateProperty({
359
- id: entity["@id"],
360
- property: "@type",
361
- value: ["Adult", "Person", "Adult"],
362
- });
363
- expect(r).toBeTruthy;
364
- e = cm.getEntity({ id: entity["@id"] }) as NormalisedEntityDefinition;
365
- expect(e["@type"]).toEqual(["Adult", "Person"]);
366
- });
367
- test("update entity '@id'", () => {
368
- crate = getBaseCrate();
369
-
370
- const authorId = "http://schema.org/person";
371
- const newAuthorId = "http://schema.org/author";
372
- crate["@graph"].push({
373
- "@id": "./",
374
- "@type": ["Dataset"],
375
- name: "rd",
376
- author: [{ "@id": authorId }],
377
- });
378
- crate["@graph"].push({
379
- "@id": authorId,
380
- "@type": ["Person"],
381
- name: "a person",
382
- group: [{ "@id": "#g1" }],
383
- });
384
- crate["@graph"].push({
385
- "@id": "#g1",
386
- "@type": ["Group"],
387
- name: "a group",
388
- });
389
- cm = new CrateManager({ crate });
390
-
391
- cm.updateProperty({
392
- id: authorId,
393
- property: "@id",
394
- value: newAuthorId,
395
- });
396
-
397
- let ec = cm.exportCrate();
398
-
399
- // console.log(JSON.stringify(ec["@graph"], null, 2));
400
- expect(ec["@graph"]).toMatchObject([
401
- { "@id": "ro-crate-metadata.json" },
402
- { "@id": "./", author: { "@id": newAuthorId } },
403
- {
404
- "@id": newAuthorId,
405
- "@reverse": {
406
- author: {
407
- "@id": "./",
408
- },
409
- },
410
- },
411
- {
412
- "@id": "#g1",
413
- "@reverse": {
414
- group: {
415
- "@id": "http://schema.org/author",
416
- },
417
- },
418
- },
419
- ]);
420
- });
421
- test(`trying to set a property on a non-existent entity`, () => {
422
- let result = cm.updateProperty({
423
- id: "http://schema.org/person",
424
- property: "@id",
425
- value: "new",
426
- });
427
- expect(result).toEqual(undefined);
428
- });
429
- test("delete an entity", () => {
430
- const f1 = cm.addFile("/file1.txt");
431
- const f2 = cm.addFile("/file2.txt");
432
- let r1 = cm.addEntity({ "@id": "_:r1", "@type": "Relationship", name: "r1" });
433
- let r2 = cm.addEntity({ "@id": "_:r2", "@type": "Relationship", name: "r2" });
434
-
435
- // cm.linkEntity({ id: "./", property: "hasPart", value: r1 });
436
- // cm.linkEntity({ id: "./", property: "hasPart", value: r2 });
437
-
438
- // delete an entity that is not linked to anything
439
- cm.deleteEntity({ id: r1["@id"] });
440
- expect(cm.exportCrate()["@graph"]).toMatchObject([
441
- { "@id": "ro-crate-metadata.json" },
442
- { "@id": "./" },
443
- { "@id": "file1.txt" },
444
- { "@id": "file2.txt" },
445
- { "@id": "_:r2" },
446
- ]);
447
-
448
- // console.log(JSON.stringify(cm.exportCrate()["@graph"], null, 2));
449
-
450
- // re-add the entity and link a file to it
451
- r1 = cm.addEntity({ "@id": "_:r1", "@type": "Relationship", name: "r1" });
452
- cm.linkEntity({ id: "./", property: "hasPart", value: r1 });
453
- cm.setProperty({
454
- id: r1["@id"],
455
- property: "object",
456
- propertyId: "",
457
- value: f1,
458
- });
459
- expect(cm.exportCrate()["@graph"]).toMatchObject([
460
- { "@id": "ro-crate-metadata.json" },
461
- { "@id": "./" },
462
- { "@id": "file1.txt" },
463
- { "@id": "file2.txt" },
464
- { "@id": "_:r2" },
465
- { "@id": "_:r1", object: { "@id": "file1.txt" } },
466
- ]);
467
-
468
- // now delete it and check everything else is still there
469
- cm.deleteEntity({ id: r1["@id"] });
470
- expect(cm.exportCrate()["@graph"]).toMatchObject([
471
- { "@id": "ro-crate-metadata.json" },
472
- { "@id": "./" },
473
- { "@id": "file1.txt" },
474
- { "@id": "file2.txt" },
475
- { "@id": "_:r2" },
476
- ]);
477
- // console.log(JSON.stringify(cm.exportCrate()["@graph"], null, 2));
478
-
479
- // re-add the entity and link a file to it
480
- r1 = cm.addEntity({ "@id": "_:r1", "@type": "Relationship", name: "r1" });
481
- // cm.linkEntity({ id: "./", property: "hasPart", value: r1 });
482
- cm.setProperty({
483
- id: r1["@id"],
484
- property: "object",
485
- propertyId: "",
486
- value: f1,
487
- });
488
-
489
- // link the same file to a different entity
490
- cm.setProperty({
491
- id: r2["@id"],
492
- property: "object",
493
- propertyId: "",
494
- value: f1,
495
- });
496
- expect(cm.exportCrate()["@graph"]).toMatchObject([
497
- { "@id": "ro-crate-metadata.json" },
498
- { "@id": "./" },
499
- { "@id": "file1.txt" },
500
- { "@id": "file2.txt" },
501
- { "@id": "_:r2", object: { "@id": "file1.txt" } },
502
- { "@id": "_:r1", object: { "@id": "file1.txt" } },
503
- ]);
504
-
505
- // now delete it and check everything else is still there
506
- cm.deleteEntity({ id: r1["@id"] });
507
- // console.log(JSON.stringify(cm.exportCrate()["@graph"], null, 2));
508
- expect(cm.exportCrate()["@graph"]).toMatchObject([
509
- { "@id": "ro-crate-metadata.json" },
510
- { "@id": "./" },
511
- { "@id": "file1.txt" },
512
- { "@id": "file2.txt" },
513
- { "@id": "_:r2" },
514
- ]);
515
- });
516
- test("prevent deleting the root dataset and the root descriptor", () => {
517
- try {
518
- cm.deleteEntity({ id: "./" });
519
- } catch (error) {
520
- expect((error as Error).message).toEqual(
521
- `You can't delete the root dataset or the root descriptor.`
522
- );
523
- }
524
- try {
525
- cm.deleteEntity({ id: "ro-crate-metadata.json" });
526
- } catch (error) {
527
- expect((error as Error).message).toEqual(
528
- `You can't delete the root dataset or the root descriptor.`
529
- );
530
- }
531
- });
532
- test(`fail - property updates `, () => {
533
- // fail updating core property
534
- try {
535
- cm.setProperty({
536
- id: "./",
537
- property: "@id",
538
- value: "something else",
539
- });
540
- } catch (error) {
541
- expect((error as Error).message).toEqual(
542
- `This method does not operate on @id, @type, @reverse, name`
543
- );
544
- }
545
- // fail bad value
546
- try {
547
- cm.setProperty({
548
- id: "./",
549
- property: "new",
550
- value: {} as EntityReference,
551
- });
552
- } catch (error) {
553
- expect((error as Error).message).toEqual(
554
- `value must be a string, number, boolean or object with '@id'`
555
- );
556
- }
557
- try {
558
- cm.setProperty({
559
- id: "./",
560
- property: "new",
561
- value: [] as any,
562
- });
563
- } catch (error) {
564
- expect((error as Error).message).toEqual(
565
- `value must be a string, number, boolean or object with '@id'`
566
- );
567
- }
568
- // fail - wrong method
569
- try {
570
- cm.updateProperty({
571
- id: "./",
572
- property: "@id",
573
- value: [],
574
- });
575
- } catch (error) {
576
- expect((error as Error).message).toEqual(
577
- `'@id' property must be a string or not defined at all`
578
- );
579
- }
580
- });
581
- test("adding a property to an entity", () => {
582
- const url = chance.url();
583
- let entity = {
584
- "@id": url,
585
- "@type": "Person",
586
- name: chance.sentence(),
587
- };
588
- let e = cm.addEntity(entity);
589
-
590
- cm.setProperty({
591
- id: e["@id"],
592
- property: "author",
593
- value: "something else",
594
- });
595
- e = cm.getEntity({ id: e["@id"] }) as NormalisedEntityDefinition;
596
- expect(e.author.length).toEqual(1);
597
- expect(e.author[0]).toEqual("something else");
598
- });
599
- test("a sequence of operations around adding and manipulating properties on an entity", () => {
600
- cm.setProperty({ id: "./", property: "new", value: "some text" });
601
- const authorId = chance.url();
602
- cm.setProperty({ id: "./", property: "author", value: { "@id": authorId } });
603
- cm.setProperty({ id: "./", property: "author", value: "text" });
604
- cm.setProperty({ id: "./", property: "author", value: 3 });
605
-
606
- let entity = cm.getEntity({ id: "./" });
607
- expect(entity).toMatchObject({
608
- "@id": "./",
609
- new: ["some text"],
610
- author: [{ "@id": authorId }, "text", 3],
611
- });
612
- // console.log(entity);
613
-
614
- entity = cm.getEntity({ id: "./" });
615
- expect(entity).toMatchObject({
616
- "@id": "./",
617
- new: ["some text"],
618
- author: [{ "@id": authorId }, "text", 3],
619
- });
620
-
621
- cm.updateProperty({ id: "./", property: "author", idx: 1, value: "new" });
622
- entity = cm.getEntity({ id: "./" });
623
- expect(entity).toMatchObject({
624
- "@id": "./",
625
- author: [{ "@id": authorId }, "new", 3],
626
- });
627
-
628
- cm.setProperty({ id: "./", property: "author", value: 3 });
629
- cm.updateProperty({ id: "./", property: "author", idx: 1, value: "new" });
630
- entity = cm.getEntity({ id: "./" });
631
- expect(entity).toMatchObject({
632
- "@id": "./",
633
- author: [{ "@id": authorId }, "new", 3, 3],
634
- });
635
- // console.log(entity);
636
- });
637
- test("delete a instance of data attached to a property", () => {
638
- const url = chance.url();
639
- let entity = {
640
- "@id": url,
641
- "@type": "Person",
642
- name: chance.sentence(),
643
- text: "some text",
644
- };
645
- let e = cm.addEntity(entity);
646
- e = cm.getEntity({ id: e["@id"] }) as NormalisedEntityDefinition;
647
-
648
- cm.deleteProperty({
649
- id: e["@id"],
650
- property: "text",
651
- idx: 0,
652
- });
653
-
654
- e = cm.getEntity({ id: e["@id"] }) as NormalisedEntityDefinition;
655
- expect(e).not.toHaveProperty("text");
656
- });
657
- test("delete all data connected to a property", () => {
658
- let entity: UnverifiedEntityDefinition = {
659
- "@id": "#person1",
660
- "@type": "Person",
661
- name: "person1",
662
- text: ["some text", "some other text"],
663
- };
664
- let e1 = cm.addEntity(entity);
665
- e1 = cm.getEntity({ id: e1["@id"] }) as NormalisedEntityDefinition;
666
-
667
- // link it to another entity
668
- entity = {
669
- "@id": "#person2",
670
- "@type": "Person",
671
- name: "person2",
672
- };
673
- let e2 = cm.addEntity(entity);
674
- e2 = cm.getEntity({ id: e2["@id"] }) as NormalisedEntityDefinition;
675
-
676
- cm.linkEntity({ id: e1["@id"], property: "knows", value: e2 });
677
-
678
- let crate = cm.exportCrate();
679
- expect(crate["@graph"]).toMatchObject([
680
- {
681
- "@id": "ro-crate-metadata.json",
682
- },
683
- {
684
- "@id": "./",
685
- },
686
- {
687
- "@id": "#person1",
688
- "@type": "Person",
689
- name: "person1",
690
- text: ["some text", "some other text"],
691
- knows: { "@id": "#person2" },
692
- },
693
- {
694
- "@id": "#person2",
695
- "@type": "Person",
696
- name: "person2",
697
- },
698
- ]);
699
-
700
- // delete a property without associations
701
- cm.deleteProperty({
702
- id: e1["@id"],
703
- property: "text",
704
- });
705
-
706
- e1 = cm.getEntity({ id: e1["@id"] }) as NormalisedEntityDefinition;
707
- expect(e1).not.toHaveProperty("text");
708
-
709
- // ensure it doesn't fail when that same prop doesn't exist
710
- cm.deleteProperty({
711
- id: e1["@id"],
712
- property: "text",
713
- });
714
- e1 = cm.getEntity({ id: e1["@id"] }) as NormalisedEntityDefinition;
715
- expect(e1).not.toHaveProperty("text");
716
-
717
- expect(crate["@graph"]).toMatchObject([
718
- {
719
- "@id": "ro-crate-metadata.json",
720
- },
721
- {
722
- "@id": "./",
723
- },
724
- {
725
- "@id": "#person1",
726
- "@type": "Person",
727
- name: "person1",
728
- knows: { "@id": "#person2" },
729
- },
730
- {
731
- "@id": "#person2",
732
- "@type": "Person",
733
- name: "person2",
734
- },
735
- ]);
736
-
737
- // delete a property with associations
738
- cm.deleteProperty({
739
- id: e1["@id"],
740
- property: "knows",
741
- });
742
- e1 = cm.getEntity({ id: e1["@id"] }) as NormalisedEntityDefinition;
743
- expect(e1).not.toHaveProperty("text");
744
-
745
- crate = cm.exportCrate();
746
- expect(crate["@graph"]).toMatchObject([
747
- {
748
- "@id": "ro-crate-metadata.json",
749
- },
750
- {
751
- "@id": "./",
752
- },
753
- {
754
- "@id": "#person1",
755
- },
756
- {
757
- "@id": "#person2",
758
- },
759
- ]);
760
- });
761
- test("a sequence of operations around deleting a property on an entity", () => {
762
- cm.setProperty({ id: "./", property: "new", value: "some text" });
763
- const authorId = chance.url();
764
- cm.setProperty({ id: "./", property: "author", value: { "@id": authorId } });
765
- cm.setProperty({ id: "./", property: "author", value: "text" });
766
- cm.setProperty({ id: "./", property: "author", value: 3 });
767
-
768
- let entity = cm.getEntity({ id: "./" });
769
- expect(entity).toMatchObject({
770
- "@id": "./",
771
- new: ["some text"],
772
- author: [{ "@id": authorId }, "text", 3],
773
- });
774
-
775
- cm.deleteProperty({ id: "./", property: "author", idx: 1 });
776
- entity = cm.getEntity({ id: "./" });
777
- expect(entity).toMatchObject({
778
- "@id": "./",
779
- author: [{ "@id": authorId }, 3],
780
- });
781
-
782
- cm.setProperty({ id: "./", property: "author", value: 3 });
783
- entity = cm.getEntity({ id: "./" });
784
- cm.deleteProperty({ id: "./", property: "author", idx: 0 });
785
- cm.deleteProperty({ id: "./", property: "author", idx: 1 });
786
- entity = cm.getEntity({ id: "./" });
787
- expect(entity).toMatchObject({
788
- "@id": "./",
789
- author: [3],
790
- });
791
- });
792
- test("link two entities", () => {
793
- const url = chance.url();
794
- let entity = {
795
- "@id": url,
796
- "@type": "Person",
797
- name: chance.sentence(),
798
- text: "some text",
799
- };
800
- let e = cm.addEntity(entity);
801
-
802
- cm.linkEntity({
803
- id: "./",
804
- property: "author",
805
- value: { "@id": e["@id"] },
806
- });
807
-
808
- let ec = cm.exportCrate();
809
- // console.log(JSON.stringify(ec["@graph"], null, 2));
810
- expect(ec["@graph"]).toMatchObject([
811
- {
812
- "@id": "ro-crate-metadata.json",
813
- },
814
- {
815
- "@id": "./",
816
- author: {
817
- "@id": e["@id"],
818
- },
819
- },
820
- {
821
- "@id": e["@id"],
822
- "@reverse": {
823
- author: {
824
- "@id": "./",
825
- },
826
- },
827
- },
828
- ]);
829
- });
830
- test("unlink two entities", () => {
831
- const url = chance.url();
832
- let entity = {
833
- "@id": url,
834
- "@type": "Person",
835
- name: chance.sentence(),
836
- text: "some text",
837
- };
838
- let e = cm.addEntity(entity);
839
-
840
- cm.linkEntity({
841
- id: "./",
842
- property: "author",
843
- value: { "@id": e["@id"] },
844
- });
845
-
846
- cm.unlinkEntity({
847
- id: "./",
848
- property: "author",
849
- value: {
850
- "@id": e["@id"],
851
- },
852
- });
853
-
854
- let ec = cm.exportCrate();
855
- // console.log(JSON.stringify(ec["@graph"], null, 2));
856
-
857
- expect(ec["@graph"]).toMatchObject([
858
- { "@id": "ro-crate-metadata.json" },
859
- { "@id": "./" },
860
- { "@id": url },
861
- ]);
862
- expect(ec["@graph"][1]).not.toHaveProperty("author");
863
- });
864
- test("fail - fail linking / unlinking entities", () => {
865
- try {
866
- cm.linkEntity({
867
- id: "./",
868
- property: "author",
869
- value: "string" as any,
870
- });
871
- } catch (error) {
872
- expect((error as Error).message).toEqual(`value must be an object with '@id' defined`);
873
- }
874
-
875
- try {
876
- cm.unlinkEntity({
877
- id: "./",
878
- property: "author",
879
- value: "string" as any,
880
- });
881
- } catch (error) {
882
- expect((error as Error).message).toEqual(`value must be an object with '@id' defined`);
883
- }
884
- });
885
- test("linking / unlinking two entities and handling inverse property associations", () => {
886
- const profile: NormalisedProfile = {
887
- metadata: {} as any,
888
- classes: [] as any,
889
- propertyAssociations: [
890
- {
891
- property: "keywords",
892
- propertyId: "https://schema.org/keywords",
893
- inverse: {
894
- property: "isKeywordOf",
895
- propertyId: "https://schema.org/isKeywordOf",
896
- },
897
- },
898
- {
899
- property: "hasMember",
900
- propertyId: "https://schema.org/hasMember",
901
- inverse: {
902
- property: "isMemberOf",
903
- propertyId: "https://schema.org/isMemberOf",
904
- },
905
- },
906
- ],
907
- };
908
-
909
- const pm = new ProfileManager({ profile }) as ProfileManagerType;
910
- cm.setProfileManager(pm);
911
-
912
- let entity = {
913
- "@id": "#term",
914
- "@type": "DefinedTerm",
915
- name: "a term",
916
- };
917
- const e = cm.addEntity(entity);
918
-
919
- // link to root dataset and check
920
- cm.linkEntity({
921
- id: "./",
922
- property: "keywords",
923
- propertyId: "http://schema.org/keywords",
924
- value: { "@id": e["@id"] },
925
- });
926
- let crate = cm.exportCrate();
927
- // console.log(JSON.stringify(crate["@graph"], null, 2));
928
- expect(crate["@graph"][1]).toMatchObject({
929
- "@id": "./",
930
- keywords: {
931
- "@id": "#term",
932
- },
933
- "@reverse": {
934
- isKeywordOf: {
935
- "@id": "#term",
936
- },
937
- },
938
- });
939
- expect(crate["@graph"][2]).toMatchObject({
940
- "@id": "#term",
941
- isKeywordOf: {
942
- "@id": "./",
943
- },
944
- "@reverse": {
945
- keywords: {
946
- "@id": "./",
947
- },
948
- },
949
- });
950
-
951
- cm.unlinkEntity({
952
- id: "./",
953
- property: "keywords",
954
- value: { "@id": e["@id"] },
955
- });
956
- crate = cm.exportCrate();
957
- expect(crate["@graph"][1]).toMatchObject({
958
- "@id": "./",
959
- "@reverse": {},
960
- });
961
- expect(crate["@graph"][2]).toMatchObject({
962
- "@id": "#term",
963
- "@reverse": {},
964
- });
965
- // console.log(JSON.stringify(crate["@graph"], null, 2));
966
- });
967
- test("more complex:: linking / unlinking two entities and handling inverse property associations", () => {
968
- const profile = {
969
- metadata: {} as any,
970
- classes: [] as any,
971
- propertyAssociations: [
972
- {
973
- property: "keywords",
974
- propertyId: "https://schema.org/keywords",
975
- inverse: {
976
- property: "isKeywordOf",
977
- propertyId: "https://schema.org/isKeywordOf",
978
- },
979
- },
980
- {
981
- property: "hasMember",
982
- propertyId: "https://schema.org/hasMember",
983
- inverse: {
984
- property: "isMemberOf",
985
- propertyId: "https://schema.org/isMemberOf",
986
- },
987
- },
988
- ],
989
- };
990
-
991
- const pm = new ProfileManager({ profile }) as ProfileManagerType;
992
- cm.setProfileManager(pm);
993
-
994
- let entity = {
995
- "@id": "#term",
996
- "@type": "DefinedTerm",
997
- name: "a term",
998
- };
999
- const e = cm.addEntity(entity);
1000
-
1001
- // link to root dataset and check
1002
- cm.linkEntity({
1003
- id: "./",
1004
- property: "keywords",
1005
- propertyId: "http://schema.org/keywords",
1006
- value: { "@id": e["@id"] },
1007
- });
1008
- let crate = cm.exportCrate();
1009
- // console.log(JSON.stringify(crate["@graph"], null, 2));
1010
- expect(crate["@context"][1]).toMatchObject({
1011
- isKeywordOf: "https://schema.org/isKeywordOf",
1012
- });
1013
- expect(crate["@graph"][1].keywords).toEqual({ "@id": "#term" });
1014
- expect((crate["@graph"][1]["@reverse"] as any).isKeywordOf).toEqual({ "@id": "#term" });
1015
- expect(crate["@graph"][2].isKeywordOf).toEqual({ "@id": "./" });
1016
- expect((crate["@graph"][2]["@reverse"] as any).keywords).toEqual({ "@id": "./" });
1017
-
1018
- // link to itself and check
1019
- cm.linkEntity({
1020
- id: e["@id"],
1021
- property: "keywords",
1022
- value: { "@id": e["@id"] },
1023
- });
1024
- crate = cm.exportCrate();
1025
- // console.log(JSON.stringify(crate["@graph"], null, 2));
1026
- expect(crate["@graph"][2]).toMatchObject({
1027
- isKeywordOf: [{ "@id": "./" }, { "@id": "#term" }],
1028
- keywords: { "@id": "#term" },
1029
- "@reverse": {
1030
- keywords: [{ "@id": "./" }, { "@id": "#term" }],
1031
- isKeywordOf: { "@id": "#term" },
1032
- },
1033
- });
1034
-
1035
- // link to root dataset via an inverse association
1036
- cm.linkEntity({
1037
- id: e["@id"],
1038
- property: "isMemberOf",
1039
- value: { "@id": "./" },
1040
- });
1041
- crate = cm.exportCrate();
1042
-
1043
- expect(crate["@graph"][2]).toMatchObject({
1044
- isMemberOf: { "@id": "./" },
1045
- "@reverse": {
1046
- keywords: [{ "@id": "./" }, { "@id": "#term" }],
1047
- isKeywordOf: { "@id": "#term" },
1048
- hasMember: { "@id": "./" },
1049
- },
1050
- });
1051
- expect(crate["@graph"][1]).toMatchObject({
1052
- hasMember: { "@id": "#term" },
1053
- "@reverse": { isMemberOf: { "@id": "#term" } },
1054
- });
1055
- // console.log(JSON.stringify(crate["@graph"], null, 2));
1056
-
1057
- cm.unlinkEntity({
1058
- id: e["@id"],
1059
- property: "keywords",
1060
- value: {
1061
- "@id": e["@id"],
1062
- },
1063
- });
1064
- crate = cm.exportCrate();
1065
- // console.log(JSON.stringify(crate["@graph"][1], null, 2));
1066
- // console.log(JSON.stringify(crate["@graph"], null, 2));
1067
- expect(crate["@graph"][1]).toMatchObject({
1068
- "@id": "./",
1069
- "@type": "Dataset",
1070
- keywords: {
1071
- "@id": "#term",
1072
- },
1073
- hasMember: {
1074
- "@id": "#term",
1075
- },
1076
- "@reverse": {
1077
- about: {
1078
- "@id": "ro-crate-metadata.json",
1079
- },
1080
- isKeywordOf: {
1081
- "@id": "#term",
1082
- },
1083
- isMemberOf: {
1084
- "@id": "#term",
1085
- },
1086
- },
1087
- });
1088
- expect(crate["@graph"][2]).toMatchObject({
1089
- "@id": "#term",
1090
- "@type": "DefinedTerm",
1091
- name: "a term",
1092
- isKeywordOf: {
1093
- "@id": "./",
1094
- },
1095
- isMemberOf: {
1096
- "@id": "./",
1097
- },
1098
- "@reverse": {
1099
- keywords: {
1100
- "@id": "./",
1101
- },
1102
- hasMember: {
1103
- "@id": "./",
1104
- },
1105
- },
1106
- });
1107
-
1108
- // cm.deleteEntity({ id: e["@id"] });
1109
-
1110
- // console.log("BEFORE");
1111
- // crate = cm.exportCrate();
1112
- // // console.log(JSON.stringify(crate["@graph"], null, 2));
1113
- // expect(crate["@graph"].length).toEqual(2);
1114
-
1115
- // // add it back in and link it to root dataset via keywords
1116
- // cm.addEntity(entity);
1117
- // cm.linkEntity({
1118
- // id: "./",
1119
- // property: "keywords",
1120
- // value: { "@id": e["@id"] },
1121
- // });
1122
- // crate = cm.exportCrate();
1123
- // // console.log(JSON.stringify(crate["@graph"], null, 2));
1124
-
1125
- // // now unlink from the root dataset via keywords prop
1126
- // cm.unlinkEntity({
1127
- // id: "./",
1128
- // property: "keywords",
1129
- // value: {
1130
- // "@id": e["@id"],
1131
- // },
1132
- // });
1133
- // crate = cm.exportCrate();
1134
- // expect(crate["@graph"][2]).toMatchObject({
1135
- // "@id": "#term",
1136
- // "@type": "DefinedTerm",
1137
- // name: "a term",
1138
- // "@reverse": {},
1139
- // });
1140
- });
1141
- test("a sequence of complex '@id' updates across the crate", () => {
1142
- let entity = {
1143
- "@id": "an id",
1144
- "@type": "Person",
1145
- name: "person",
1146
- };
1147
- let e1 = cm.addEntity(entity);
1148
- cm.linkEntity({ id: "./", property: "author", value: { "@id": e1["@id"] } });
1149
-
1150
- e1 = cm.getEntity({ id: e1["@id"] }) as NormalisedEntityDefinition;
1151
- expect(e1).toMatchObject({ "@id": "#an%20id", "@type": ["Person"], name: "person" });
1152
-
1153
- let entityChild = {
1154
- "@id": "child id",
1155
- "@type": "Person",
1156
- name: "child",
1157
- };
1158
- let e2 = cm.addEntity(entityChild);
1159
- cm.linkEntity({ id: "#an%20id", property: "child", value: { "@id": e2["@id"] } });
1160
- e2 = cm.getEntity({ id: e2["@id"] }) as NormalisedEntityDefinition;
1161
- expect(e2).toMatchObject({ "@id": "#child%20id", "@type": ["Person"], name: "child" });
1162
-
1163
- let ec = cm.exportCrate();
1164
- // console.log(JSON.stringify(ec["@graph"], null, 2));
1165
- expect(ec["@graph"]).toMatchObject([
1166
- { "@id": "ro-crate-metadata.json" },
1167
- { "@id": "./", author: { "@id": "#an%20id" } },
1168
- {
1169
- "@id": "#an%20id",
1170
- child: {
1171
- "@id": "#child%20id",
1172
- },
1173
- "@reverse": {
1174
- author: {
1175
- "@id": "./",
1176
- },
1177
- },
1178
- },
1179
- {
1180
- "@id": "#child%20id",
1181
- "@reverse": {
1182
- child: {
1183
- "@id": "#an%20id",
1184
- },
1185
- },
1186
- },
1187
- ]);
1188
-
1189
- // change the id to #a new id
1190
- cm.updateProperty({ id: e1["@id"], property: "@id", value: "a new id" });
1191
- ec = cm.exportCrate();
1192
- // console.log(JSON.stringify(ec["@graph"], null, 2));
1193
- expect(ec["@graph"]).toMatchObject([
1194
- { "@id": "ro-crate-metadata.json" },
1195
- { "@id": "./", author: { "@id": "#a%20new%20id" } },
1196
- {
1197
- "@id": "#a%20new%20id",
1198
- },
1199
- {
1200
- "@id": "#child%20id",
1201
- "@reverse": {
1202
- child: {
1203
- "@id": "#a%20new%20id",
1204
- },
1205
- },
1206
- },
1207
- ]);
1208
- // console.log(JSON.stringify(ec["@graph"], null, 2));
1209
-
1210
- // change the id to http://schema.org/person
1211
- cm.updateProperty({
1212
- id: "#a%20new%20id",
1213
- property: "@id",
1214
- value: "http://schema.org/person",
1215
- });
1216
- ec = cm.exportCrate();
1217
- expect(ec["@graph"]).toMatchObject([
1218
- { "@id": "ro-crate-metadata.json" },
1219
- { "@id": "./", author: { "@id": "http://schema.org/person" } },
1220
- {
1221
- "@id": "http://schema.org/person",
1222
- },
1223
- {
1224
- "@id": "#child%20id",
1225
- "@reverse": {
1226
- child: {
1227
- "@id": "http://schema.org/person",
1228
- },
1229
- },
1230
- },
1231
- ]);
1232
-
1233
- // change the id to #a new id
1234
- cm.updateProperty({
1235
- id: "http://schema.org/person",
1236
- property: "@id",
1237
- value: "a new id",
1238
- });
1239
- ec = cm.exportCrate();
1240
- expect(ec["@graph"]).toMatchObject([
1241
- { "@id": "ro-crate-metadata.json" },
1242
- { "@id": "./", author: { "@id": "#a%20new%20id" } },
1243
- {
1244
- "@id": "#a%20new%20id",
1245
- },
1246
- {
1247
- "@id": "#child%20id",
1248
- "@reverse": {
1249
- child: {
1250
- "@id": "#a%20new%20id",
1251
- },
1252
- },
1253
- },
1254
- ]);
1255
-
1256
- // change the id to http://schema.org/person
1257
- cm.updateProperty({
1258
- id: "#a%20new%20id",
1259
- property: "@id",
1260
- value: "http://schema.org/person",
1261
- });
1262
- ec = cm.exportCrate();
1263
- expect(ec["@graph"]).toMatchObject([
1264
- { "@id": "ro-crate-metadata.json" },
1265
- { "@id": "./", author: { "@id": "http://schema.org/person" } },
1266
- {
1267
- "@id": "http://schema.org/person",
1268
- },
1269
- {
1270
- "@id": "#child%20id",
1271
- "@reverse": {
1272
- child: {
1273
- "@id": "http://schema.org/person",
1274
- },
1275
- },
1276
- },
1277
- ]);
1278
- });
1279
- test("adding a property that is a link to another entity in the crate", () => {
1280
- crate = getBaseCrate();
1281
- crate["@graph"].push({
1282
- "@id": "./",
1283
- "@type": "Dataset",
1284
- name: "rd",
1285
- });
1286
- crate["@graph"].push({
1287
- "@id": "#person",
1288
- "@type": "Person",
1289
- name: "author",
1290
- });
1291
-
1292
- let cm = new CrateManager({ crate });
1293
- cm.setProperty({ id: "./", property: "author", value: { "@id": "#person" } });
1294
-
1295
- let ec = cm.exportCrate();
1296
- // console.log(JSON.stringify(ec["@graph"], null, 2));
1297
- expect(ec["@graph"]).toMatchObject([
1298
- { "@id": "ro-crate-metadata.json" },
1299
- { "@id": "./", author: { "@id": "#person" } },
1300
- { "@id": "#person", "@reverse": { author: { "@id": "./" } } },
1301
- ]);
1302
- });
1303
- test("adding a property that is not a link to another entity in the crate", () => {
1304
- crate = getBaseCrate();
1305
- crate["@graph"].push({
1306
- "@id": "./",
1307
- "@type": "Dataset",
1308
- name: "rd",
1309
- });
1310
-
1311
- let cm = new CrateManager({ crate });
1312
- cm.setProperty({ id: "./", property: "author", value: { "@id": "#person" } });
1313
-
1314
- let ec = cm.exportCrate();
1315
- expect(ec["@graph"]).toMatchObject([
1316
- { "@id": "ro-crate-metadata.json" },
1317
- { "@id": "./", author: { "@id": "#person" } },
1318
- ]);
1319
- });
1320
- test("add an entity to the crate and then get it back", () => {
1321
- let entity = {
1322
- "@id": chance.url(),
1323
- "@type": "Person",
1324
- name: chance.sentence(),
1325
- };
1326
- let e = cm.addEntity(entity);
1327
- let match = cm.getEntity({ id: entity["@id"] });
1328
- expect(match).toMatchObject(e);
1329
- });
1330
- test("find entities by id, type, name", () => {
1331
- let id = chance.url();
1332
- let name = chance.sentence();
1333
- let entity = {
1334
- "@id": id,
1335
- "@type": "Person",
1336
- name: name,
1337
- };
1338
- let e = cm.addEntity(entity);
1339
- let match = [...cm.getEntities({ query: id })];
1340
- expect(match.length).toEqual(1);
1341
-
1342
- match = [...cm.getEntities({ query: id, type: "Person" })];
1343
- expect(match.length).toEqual(1);
1344
-
1345
- match = [...cm.getEntities({ query: name.slice(0, 3), type: "Person" })];
1346
- expect(match.length).toEqual(1);
1347
-
1348
- match = [...cm.getEntities({ type: "Pers" })];
1349
- expect(match.length).toEqual(1);
1350
-
1351
- match = [
1352
- ...cm.getEntities({
1353
- limit: 0,
1354
- type: "Perso",
1355
- query: name.slice(0, 3),
1356
- }),
1357
- ];
1358
- expect(match.length).toEqual(1);
1359
-
1360
- try {
1361
- [...cm.getEntities({ query: {} as any })];
1362
- } catch (error) {
1363
- expect((error as Error).message).toEqual(`query must be a string`);
1364
- }
1365
- try {
1366
- [...cm.getEntities({ type: {} as any })];
1367
- } catch (error) {
1368
- expect((error as Error).message).toEqual(`type must be a string`);
1369
- }
1370
- });
1371
- test("add an entity then delete it and confirm it's gone", () => {
1372
- let entity = {
1373
- "@id": chance.url(),
1374
- "@type": "Person",
1375
- name: chance.sentence(),
1376
- };
1377
- let e = cm.addEntity(entity);
1378
- cm.deleteEntity({ id: e["@id"] });
1379
- let match = cm.getEntity({ id: entity["@id"] });
1380
- expect(match).toBeUndefined;
1381
- });
1382
- test("exporting a simple crate file without unlinked entities", async () => {
1383
- let crate = getBaseCrate();
1384
- crate = addRootDataset({ crate });
1385
-
1386
- let cm = new CrateManager({ crate });
1387
- let entity = {
1388
- "@id": chance.url(),
1389
- "@type": "Person",
1390
- name: chance.sentence(),
1391
- };
1392
- let e = cm.addEntity(entity);
1393
- cm.deleteEntity({ id: e["@id"] });
1394
-
1395
- let ec = cm.exportCrate();
1396
- expect(ec["@graph"]).toMatchObject([
1397
- {
1398
- "@id": "ro-crate-metadata.json",
1399
- },
1400
- {
1401
- "@id": "./",
1402
- },
1403
- ]);
1404
- });
1405
- test("crate exporting", async () => {
1406
- let crate = getBaseCrate();
1407
- crate = addRootDataset({ crate });
1408
-
1409
- let cm = new CrateManager({ crate });
1410
-
1411
- // export base crate
1412
- let ec = cm.exportCrate();
1413
- expect(ec["@graph"]).toMatchObject([{ "@id": "ro-crate-metadata.json" }, { "@id": "./" }]);
1414
-
1415
- // add entity and export
1416
- let entity = {
1417
- "@id": chance.url(),
1418
- "@type": "Person",
1419
- name: chance.sentence(),
1420
- };
1421
- cm.addEntity(entity);
1422
- ec = cm.exportCrate();
1423
- expect(ec["@graph"]).toMatchObject([
1424
- { "@id": "ro-crate-metadata.json" },
1425
- { "@id": "./" },
1426
- { "@id": entity["@id"] },
1427
- ]);
1428
-
1429
- // link ./ -> entity and export
1430
- cm.setProperty({ id: "./", property: "author", value: entity });
1431
- ec = cm.exportCrate();
1432
- expect(ec["@graph"]).toMatchObject([
1433
- { "@id": "ro-crate-metadata.json" },
1434
- { "@id": "./", author: { "@id": entity["@id"] } },
1435
- { "@id": entity["@id"], "@reverse": { author: { "@id": "./" } } },
1436
- ]);
1437
-
1438
- // link entity -> ./ and export - ie ensure it can handle circular refs
1439
- cm.setProperty({ id: entity["@id"], property: "isAuthorOf", value: { "@id": "./" } });
1440
- ec = cm.exportCrate();
1441
- // console.log(JSON.stringify(ec["@graph"], null, 2));
1442
- expect(ec["@graph"]).toMatchObject([
1443
- { "@id": "ro-crate-metadata.json" },
1444
- { "@id": "./", "@reverse": { isAuthorOf: { "@id": entity["@id"] } } },
1445
- { "@id": entity["@id"], isAuthorOf: { "@id": "./" } },
1446
- ]);
1447
- });
1448
- test("fail flattening", () => {
1449
- try {
1450
- let flattened = cm.flatten([] as any);
1451
- } catch (error) {
1452
- expect((error as Error).message).toEqual(`flatten only takes an object.`);
1453
- }
1454
- });
1455
- test(`should be able to flatten a complex entity - like one coming from a datapack`, async () => {
1456
- const json = {
1457
- "@id": "http://some.thing",
1458
- "@type": "Thing",
1459
- name: "level1",
1460
- level: {
1461
- "@id": "http://2.some.thing",
1462
- "@type": "Thing",
1463
- name: "level2",
1464
- level: {
1465
- "@id": "http://3.some.thing",
1466
- "@type": "Thing",
1467
- name: "level3",
1468
- },
1469
- other: [
1470
- {
1471
- "@id": "http://4.some.thing",
1472
- "@type": "Thing",
1473
- name: "level4",
1474
- },
1475
- {
1476
- "@id": "http://5.some.thing",
1477
- "@type": "Thing",
1478
- name: "level5",
1479
- },
1480
- {
1481
- "@id": "http://5.some.thing",
1482
- "@type": "Thing",
1483
- name: "level5",
1484
- },
1485
- ],
1486
- },
1487
- };
1488
- let flattened = cm.flatten(json);
1489
- // console.log(JSON.stringify(flattened, null, 2));
1490
-
1491
- expect(flattened).toMatchObject([
1492
- {
1493
- "@id": "http://some.thing",
1494
- "@type": "Thing",
1495
- name: "level1",
1496
- level: [
1497
- {
1498
- "@id": "http://2.some.thing",
1499
- },
1500
- ],
1501
- },
1502
- {
1503
- "@id": "http://2.some.thing",
1504
- "@type": "Thing",
1505
- name: "level2",
1506
- level: [
1507
- {
1508
- "@id": "http://3.some.thing",
1509
- },
1510
- ],
1511
- other: [
1512
- {
1513
- "@id": "http://4.some.thing",
1514
- },
1515
- {
1516
- "@id": "http://5.some.thing",
1517
- },
1518
- {
1519
- "@id": "http://5.some.thing",
1520
- },
1521
- ],
1522
- },
1523
- {
1524
- "@id": "http://3.some.thing",
1525
- "@type": "Thing",
1526
- name: "level3",
1527
- },
1528
- {
1529
- "@id": "http://4.some.thing",
1530
- "@type": "Thing",
1531
- name: "level4",
1532
- },
1533
- {
1534
- "@id": "http://5.some.thing",
1535
- "@type": "Thing",
1536
- name: "level5",
1537
- },
1538
- {
1539
- "@id": "http://5.some.thing",
1540
- "@type": "Thing",
1541
- name: "level5",
1542
- },
1543
- ]);
1544
-
1545
- cm.ingestAndLink({
1546
- id: "./",
1547
- property: "language",
1548
- propertyId: "https://schema.org/languageId",
1549
- json,
1550
- });
1551
- let ec = cm.exportCrate();
1552
- // console.log(JSON.stringify(ec["@graph"], null, 2));
1553
- expect(ec["@graph"]).toMatchObject([
1554
- {
1555
- "@id": "ro-crate-metadata.json",
1556
- },
1557
- {
1558
- "@id": "./",
1559
- language: {
1560
- "@id": "http://some.thing",
1561
- },
1562
- },
1563
- {
1564
- "@id": "http://some.thing",
1565
- name: "level1",
1566
- level: {
1567
- "@id": "http://2.some.thing",
1568
- },
1569
- "@reverse": {
1570
- language: { "@id": "./" },
1571
- },
1572
- },
1573
- {
1574
- "@id": "http://2.some.thing",
1575
- name: "level2",
1576
- level: {
1577
- "@id": "http://3.some.thing",
1578
- },
1579
- other: [
1580
- {
1581
- "@id": "http://4.some.thing",
1582
- },
1583
- {
1584
- "@id": "http://5.some.thing",
1585
- },
1586
- {
1587
- "@id": "http://5.some.thing",
1588
- },
1589
- ],
1590
- "@reverse": {
1591
- level: { "@id": "http://some.thing" },
1592
- },
1593
- },
1594
- {
1595
- "@id": "http://3.some.thing",
1596
- name: "level3",
1597
- "@reverse": {
1598
- level: { "@id": "http://2.some.thing" },
1599
- },
1600
- },
1601
- {
1602
- "@id": "http://4.some.thing",
1603
- name: "level4",
1604
- "@reverse": {
1605
- other: { "@id": "http://2.some.thing" },
1606
- },
1607
- },
1608
- {
1609
- "@id": "http://5.some.thing",
1610
- name: "level5",
1611
- "@reverse": {
1612
- other: { "@id": "http://2.some.thing" },
1613
- },
1614
- },
1615
- ]);
1616
- });
1617
- test(`it should handle ingesting json objects with text arrays`, async () => {
1618
- let json = {
1619
- "@id": "http://some.thing",
1620
- "@type": "Thing",
1621
- alternateName: ["name1", "name2", "name3"],
1622
- };
1623
- cm.ingestAndLink({
1624
- id: "./",
1625
- property: "language",
1626
- propertyId: "https://schema.org/languageId",
1627
- json,
1628
- });
1629
- let ec = cm.exportCrate();
1630
- expect(ec["@graph"]).toMatchObject([
1631
- {
1632
- "@id": "ro-crate-metadata.json",
1633
- },
1634
- {
1635
- "@id": "./",
1636
- language: {
1637
- "@id": "http://some.thing",
1638
- },
1639
- },
1640
- {
1641
- "@id": "http://some.thing",
1642
- "@reverse": {
1643
- language: {
1644
- "@id": "./",
1645
- },
1646
- },
1647
- },
1648
- ]);
1649
- });
1650
- test(`it should handle ingesting json objects whilst ignoring empty properties`, async () => {
1651
- let json = {
1652
- "@id": "http://some.thing",
1653
- "@type": "Thing",
1654
- alternateName: "",
1655
- };
1656
- cm.ingestAndLink({
1657
- id: "./",
1658
- property: "language",
1659
- propertyId: "https://schema.org/languageId",
1660
- json,
1661
- });
1662
- let ec = cm.exportCrate();
1663
- expect(ec["@graph"]).toMatchObject([
1664
- {
1665
- "@id": "ro-crate-metadata.json",
1666
- },
1667
- {
1668
- "@id": "./",
1669
- language: {
1670
- "@id": "http://some.thing",
1671
- },
1672
- },
1673
- {
1674
- "@id": "http://some.thing",
1675
- "@reverse": {
1676
- language: {
1677
- "@id": "./",
1678
- },
1679
- },
1680
- },
1681
- ]);
1682
- expect(ec["@graph"][2]).not.toHaveProperty("alternateName");
1683
- });
1684
- test(`it should be able to handle self links`, async () => {
1685
- const json = {
1686
- "@id": "http://some.thing",
1687
- "@type": "Thing",
1688
- name: "level1",
1689
- level: {
1690
- "@id": "http://some.thing",
1691
- "@type": "Thing",
1692
- name: "level2",
1693
- },
1694
- };
1695
- cm.ingestAndLink({
1696
- id: "./",
1697
- property: "author",
1698
- propertyId: "https://schema.org/author",
1699
- json,
1700
- });
1701
- let ec = cm.exportCrate();
1702
- // console.log(JSON.stringify(ec["@graph"], null, 2));
1703
-
1704
- // delete the author property from the root dataset
1705
- cm.deleteProperty({
1706
- id: "./",
1707
- property: "author",
1708
- idx: 0,
1709
- });
1710
-
1711
- ec = cm.exportCrate();
1712
- // console.log(JSON.stringify(ec["@graph"], null, 2));
1713
-
1714
- expect(ec["@graph"].length).toEqual(3);
1715
- expect(ec["@graph"]).toMatchObject([
1716
- {
1717
- "@id": "ro-crate-metadata.json",
1718
- },
1719
- {
1720
- "@id": "./",
1721
- "@type": "Dataset",
1722
- },
1723
- {
1724
- "@id": "http://some.thing",
1725
- level: {
1726
- "@id": "http://some.thing",
1727
- },
1728
- },
1729
- ]);
1730
- });
1731
- test(`it should be able to ingest a complex entity, unlink it, and remove all descendants`, async () => {
1732
- const json = {
1733
- "@id": "http://some.thing",
1734
- "@type": "Thing",
1735
- name: "level1",
1736
- level: {
1737
- "@id": "http://some.other.thing",
1738
- "@type": "Thing",
1739
- name: "level2",
1740
- },
1741
- };
1742
- cm.ingestAndLink({
1743
- id: "./",
1744
- property: "author",
1745
- propertyId: "https://schema.org/author",
1746
- json,
1747
- });
1748
-
1749
- // delete the author property from the root dataset
1750
- cm.deleteProperty({
1751
- id: "./",
1752
- property: "author",
1753
- idx: 0,
1754
- });
1755
-
1756
- cm.purgeUnlinkedEntities();
1757
- let ec = cm.exportCrate();
1758
- expect(ec["@graph"]).toMatchObject([{ "@id": "ro-crate-metadata.json" }, { "@id": "./" }]);
1759
- });
1760
- test(`check purging unlinked nodes; confirm it handles linking type entities like relationships`, () => {
1761
- // add a blank node not linked to anything
1762
- cm.addBlankNode("Relationship");
1763
-
1764
- // and an entity linked to root dataset
1765
- cm.ingestAndLink({
1766
- id: "./",
1767
- property: "people",
1768
- propertyId: "https://schema.org/author",
1769
- json: { "@id": "#1", "@type": "Person", name: "#1" },
1770
- });
1771
-
1772
- // confirm they are both there
1773
- expect(cm.exportCrate()["@graph"]).toMatchObject([
1774
- { "@id": "ro-crate-metadata.json" },
1775
- { "@id": "./" },
1776
- { "@id": "_:Relationship1" },
1777
- { "@id": "#1" },
1778
- ]);
1779
-
1780
- // purge unlinked and confirm blank node gone
1781
- cm.purgeUnlinkedEntities();
1782
- expect(cm.exportCrate()["@graph"]).toMatchObject([
1783
- { "@id": "ro-crate-metadata.json" },
1784
- { "@id": "./" },
1785
- { "@id": "#1" },
1786
- ]);
1787
-
1788
- // re add blank node and link to the entity in the graph
1789
- const e = cm.addBlankNode("Relationship");
1790
- cm.setProperty({
1791
- id: e["@id"],
1792
- property: "object",
1793
- propertyId: "https://schema.org/object",
1794
- value: { "@id": "#1" },
1795
- });
1796
- // console.log(cm.exportCrate()["@graph"]);
1797
- cm.purgeUnlinkedEntities();
1798
- expect(cm.exportCrate()["@graph"]).toMatchObject([
1799
- { "@id": "ro-crate-metadata.json" },
1800
- { "@id": "./" },
1801
- { "@id": "#1" },
1802
- { "@id": "_:Relationship2" },
1803
- ]);
1804
- // console.log(cm.exportCrate()["@graph"]);
1805
- });
1806
- test("resolve entity associations", async () => {
1807
- crate = getBaseCrate();
1808
- crate["@graph"].push({
1809
- "@id": "./",
1810
- "@type": "Dataset",
1811
- name: "root dataset",
1812
- text: "something",
1813
- });
1814
- cm = new CrateManager({ crate });
1815
- let profile = await readJSON("./src/examples/profile/profile-with-resolve.json");
1816
-
1817
- let entity: any = {
1818
- "@id": "#createAction1",
1819
- "@type": ["CreateAction"],
1820
- name: "A very long named create action to demonstrate what happens with display of long names",
1821
- object: { "@id": "#person2" },
1822
- participant: { "@id": "#participant1" },
1823
- agent: { "@id": "#agent1" },
1824
- };
1825
- let associations = cm.resolveLinkedEntityAssociations({ entity, profile });
1826
- expect(associations).toMatchObject([
1827
- {
1828
- property: "object",
1829
- "@id": "#person2",
1830
- },
1831
- {
1832
- property: "participant",
1833
- "@id": "#participant1",
1834
- },
1835
- {
1836
- property: "agent",
1837
- "@id": "#agent1",
1838
- },
1839
- ]);
1840
-
1841
- entity = {
1842
- "@id": "#relationship",
1843
- "@type": ["Relationship", "RelatedEntity"],
1844
- source: [{ "@id": "#person1" }, { "@id": "#person2" }],
1845
- target: { "@id": "#thing1" } as any,
1846
- };
1847
- associations = cm.resolveLinkedEntityAssociations({ entity, profile });
1848
- expect(associations).toMatchObject([
1849
- {
1850
- property: "source",
1851
- "@id": "#person1",
1852
- },
1853
- {
1854
- property: "source",
1855
- "@id": "#person2",
1856
- },
1857
- {
1858
- property: "target",
1859
- "@id": "#thing1",
1860
- },
1861
- ]);
1862
- });
1863
- test(`context handling - pass in context to be used as is`, () => {
1864
- cm = new CrateManager({
1865
- crate,
1866
- context: "https://www.researchobject.org/ro-crate/1.1/context.jsonld",
1867
- });
1868
- let context = cm.getContext();
1869
- // console.log(context);
1870
- expect(context).toEqual(["https://www.researchobject.org/ro-crate/1.1/context.jsonld"]);
1871
-
1872
- cm = new CrateManager({
1873
- crate,
1874
- context: ["https://www.researchobject.org/ro-crate/1.1/context.jsonld"],
1875
- });
1876
- context = cm.getContext();
1877
- expect(context).toEqual(["https://www.researchobject.org/ro-crate/1.1/context.jsonld"]);
1878
-
1879
- cm = new CrateManager({
1880
- crate,
1881
- context: [
1882
- "https://w3id.org/ro/crate/1.1/context",
1883
- { foaf: "http://xmlns.com/foaf/0.1" },
1884
- { dcterms: "https://www.dublincore.org/specifications/dublin-core/dcmi-terms/" },
1885
- ],
1886
- });
1887
- context = cm.getContext();
1888
- expect(context).toEqual([
1889
- "https://w3id.org/ro/crate/1.1/context",
1890
- {
1891
- foaf: "http://xmlns.com/foaf/0.1",
1892
- dcterms: "https://www.dublincore.org/specifications/dublin-core/dcmi-terms/",
1893
- },
1894
- ]);
1895
- });
1896
- test(`context handling - adding properties to the crate`, () => {
1897
- crate["@context"] = [
1898
- "https://w3id.org/ro/crate/1.1/context",
1899
- "https://my.domain.com/ontology",
1900
- { foaf: "http://xmlns.com/foaf/0.1/" },
1901
- { dcterms: "https://www.dublincore.org/specifications/dublin-core/dcmi-terms/" },
1902
- {
1903
- somePropertyInYourDomain:
1904
- "https://your.domain/path/to/definition#somePropertyInYourDomain",
1905
- },
1906
- ];
1907
- let cm = new CrateManager({ crate });
1908
- let context = cm.getContext();
1909
- // console.log(context);
1910
- expect(context).toMatchObject([
1911
- "https://w3id.org/ro/crate/1.1/context",
1912
- "https://my.domain.com/ontology",
1913
- {
1914
- foaf: "http://xmlns.com/foaf/0.1/",
1915
- dcterms: "https://www.dublincore.org/specifications/dublin-core/dcmi-terms/",
1916
- somePropertyInYourDomain:
1917
- "https://your.domain/path/to/definition#somePropertyInYourDomain",
1918
- },
1919
- ]);
1920
-
1921
- // property already defined in context - not added
1922
- cm.setProperty({
1923
- id: "./",
1924
- property: "model",
1925
- propertyId: "http://schema.org/Person",
1926
- value: { "@id": "#model" },
1927
- });
1928
- context = cm.getContext();
1929
- // console.log(context);
1930
- expect(context).toMatchObject([
1931
- "https://w3id.org/ro/crate/1.1/context",
1932
- "https://my.domain.com/ontology",
1933
- {
1934
- foaf: "http://xmlns.com/foaf/0.1/",
1935
- dcterms: "https://www.dublincore.org/specifications/dublin-core/dcmi-terms/",
1936
- somePropertyInYourDomain:
1937
- "https://your.domain/path/to/definition#somePropertyInYourDomain",
1938
- },
1939
- ]);
1940
-
1941
- // property not defined - is added
1942
- cm.setProperty({
1943
- id: "./",
1944
- property: "model",
1945
- propertyId: "http://www.w3.org/ns/prov#actedOnBehalfOf",
1946
- value: { "@id": "#model" },
1947
- });
1948
- context = cm.getContext();
1949
- // console.log(context);
1950
- expect(context).toMatchObject([
1951
- "https://w3id.org/ro/crate/1.1/context",
1952
- "https://my.domain.com/ontology",
1953
- {
1954
- foaf: "http://xmlns.com/foaf/0.1/",
1955
- dcterms: "https://www.dublincore.org/specifications/dublin-core/dcmi-terms/",
1956
- somePropertyInYourDomain:
1957
- "https://your.domain/path/to/definition#somePropertyInYourDomain",
1958
- model: "http://www.w3.org/ns/prov#actedOnBehalfOf",
1959
- },
1960
- ]);
1961
-
1962
- // property now defined - not re-added
1963
- cm.setProperty({
1964
- id: "./",
1965
- property: "model",
1966
- propertyId: "http://www.w3.org/ns/prov#actedOnBehalfOf",
1967
- value: { "@id": "#model" },
1968
- });
1969
- context = cm.getContext();
1970
- expect(context).toMatchObject([
1971
- "https://w3id.org/ro/crate/1.1/context",
1972
- "https://my.domain.com/ontology",
1973
- {
1974
- foaf: "http://xmlns.com/foaf/0.1/",
1975
- dcterms: "https://www.dublincore.org/specifications/dublin-core/dcmi-terms/",
1976
- somePropertyInYourDomain:
1977
- "https://your.domain/path/to/definition#somePropertyInYourDomain",
1978
- model: "http://www.w3.org/ns/prov#actedOnBehalfOf",
1979
- },
1980
- ]);
1981
-
1982
- let ec = cm.exportCrate();
1983
- // console.log(JSON.stringify(ec, null, 2));
1984
- expect(ec).toMatchObject({
1985
- "@context": [
1986
- "https://w3id.org/ro/crate/1.1/context",
1987
- "https://my.domain.com/ontology",
1988
- {
1989
- foaf: "http://xmlns.com/foaf/0.1/",
1990
- dcterms: "https://www.dublincore.org/specifications/dublin-core/dcmi-terms/",
1991
- somePropertyInYourDomain:
1992
- "https://your.domain/path/to/definition#somePropertyInYourDomain",
1993
- model: "http://www.w3.org/ns/prov#actedOnBehalfOf",
1994
- },
1995
- ],
1996
- "@graph": [
1997
- {
1998
- "@id": "ro-crate-metadata.json",
1999
- },
2000
- {
2001
- "@id": "./",
2002
- "@type": "Dataset",
2003
- model: {
2004
- "@id": "#model",
2005
- },
2006
- },
2007
- ],
2008
- });
2009
- });
2010
- test(`storing / removing entity types for lookups`, () => {
2011
- let cm = new CrateManager({ crate });
2012
-
2013
- expect(cm.entityTypes).toEqual({ CreativeWork: 1, Dataset: 1 });
2014
- expect(cm.getEntityTypes()).toEqual(["CreativeWork", "Dataset"]);
2015
-
2016
- let entity = {
2017
- "@id": "file1.jpg",
2018
- "@type": "File",
2019
- name: "file1.jpg",
2020
- };
2021
- let r = cm.addEntity(entity);
2022
- expect(cm.getEntityTypes()).toEqual(["CreativeWork", "Dataset", "File"]);
2023
-
2024
- cm.updateProperty({ id: r["@id"], property: "@type", idx: 0, value: "Cow" });
2025
- expect(cm.getEntityTypes()).toEqual(["Cow", "CreativeWork", "Dataset"]);
2026
-
2027
- cm.deleteEntity({ id: r["@id"] });
2028
- expect(cm.getEntityTypes()).toEqual(["CreativeWork", "Dataset"]);
2029
- });
2030
- test("test creating blank nodes", () => {
2031
- let cm = new CrateManager({ crate });
2032
-
2033
- let e = cm.addBlankNode("Relationship");
2034
- expect(e).toEqual({
2035
- "@id": "_:Relationship1",
2036
- "@type": ["Relationship"],
2037
- name: "_:Relationship1",
2038
- });
2039
-
2040
- e = cm.addBlankNode("Relationship");
2041
- expect(e).toEqual({
2042
- "@id": "_:Relationship2",
2043
- "@type": ["Relationship"],
2044
- name: "_:Relationship2",
2045
- });
2046
-
2047
- e = cm.addBlankNode("GeoShape");
2048
- expect(e).toEqual({
2049
- "@id": "_:GeoShape1",
2050
- "@type": ["GeoShape"],
2051
- name: "_:GeoShape1",
2052
- });
2053
-
2054
- e = cm.addBlankNode("CreateAction");
2055
- expect(e).toEqual({
2056
- "@id": "_:CreateAction1",
2057
- "@type": ["CreateAction"],
2058
- name: "_:CreateAction1",
2059
- });
2060
-
2061
- // ensure we don't clash with pre-existing blank nodes
2062
- e = cm.addBlankNode("Relationship");
2063
- expect(e).toMatchObject({
2064
- "@id": "_:Relationship3",
2065
- "@type": ["Relationship"],
2066
- name: "_:Relationship3",
2067
- });
2068
- });
2069
- test(`test locating entities - strict matching`, () => {
2070
- let cm = new CrateManager({ crate });
2071
-
2072
- const r1 = cm.addBlankNode("Relationship");
2073
- const r2 = cm.addBlankNode("Relationship");
2074
- const e1 = cm.addEntity({ "@id": "/a/b/file1.txt", "@type": "File", name: "/file1.txt" });
2075
- const e2 = cm.addEntity({ "@id": "/file2.txt", "@type": "File", name: "/file2.txt" });
2076
- const e3 = cm.addFile("/a/c/d/file.png");
2077
- const e4 = cm.addFile("/a/c/d/file with spaces.png");
2078
-
2079
- // link e1 and e2 entities to r1
2080
- cm.linkEntity({
2081
- id: r1["@id"],
2082
- property: "object",
2083
- propertyId: "https://schema.org/object",
2084
- value: { "@id": e1["@id"] },
2085
- });
2086
-
2087
- cm.linkEntity({
2088
- id: r1["@id"],
2089
- property: "object",
2090
- propertyId: "https://schema.org/object",
2091
- value: { "@id": e2["@id"] },
2092
- });
2093
-
2094
- // link all of the entities to r2
2095
- cm.linkEntity({
2096
- id: r2["@id"],
2097
- property: "object",
2098
- propertyId: "https://schema.org/object",
2099
- value: { "@id": e2["@id"] },
2100
- });
2101
- cm.linkEntity({
2102
- id: r2["@id"],
2103
- property: "object",
2104
- propertyId: "https://schema.org/object",
2105
- value: { "@id": e3["@id"] },
2106
- });
2107
- cm.linkEntity({
2108
- id: r2["@id"],
2109
- property: "object",
2110
- propertyId: "https://schema.org/object",
2111
- value: { "@id": e4["@id"] },
2112
- });
2113
-
2114
- // console.log(JSON.stringify(cm.exportCrate()["@graph"], null, 2));
2115
-
2116
- // won't find a matching entity
2117
- let matches = cm.locateEntity({ entityIds: ["file1.txt", "/file2.txt"] });
2118
- expect(matches).toEqual(undefined);
2119
-
2120
- // will not find a matching entity - not an exact match
2121
- matches = cm.locateEntity({ entityIds: ["/file1.txt"] });
2122
- expect(matches).toEqual(undefined);
2123
-
2124
- // will find a matching entity - an exact match
2125
- matches = cm.locateEntity({ entityIds: ["/a/b/file1.txt", "/file2.txt"] });
2126
- expect(matches).toMatchObject([
2127
- {
2128
- "@id": "_:Relationship1",
2129
- "@type": ["Relationship"],
2130
- name: "_:Relationship1",
2131
- },
2132
- ]);
2133
-
2134
- // will find a matching entity - an exact match
2135
- matches = cm.locateEntity({ entityIds: ["/file2.txt", "/a/b/file1.txt"] });
2136
- expect(matches).toMatchObject([
2137
- {
2138
- "@id": "_:Relationship1",
2139
- "@type": ["Relationship"],
2140
- name: "_:Relationship1",
2141
- },
2142
- ]);
2143
-
2144
- // will not find a matching entity - no match
2145
- matches = cm.locateEntity({ entityIds: ["/file2.pdf", "/file1.txt"] });
2146
- expect(matches).toEqual(undefined);
2147
-
2148
- // will find a matching entity - an exact match
2149
- matches = cm.locateEntity({
2150
- entityIds: ["a/c/d/file.png", "/file2.txt", "a/c/d/file with spaces.png"],
2151
- });
2152
- expect(matches).toMatchObject([
2153
- {
2154
- "@id": "_:Relationship2",
2155
- "@type": ["Relationship"],
2156
- name: "_:Relationship2",
2157
- },
2158
- ]);
2159
-
2160
- matches = cm.locateEntity({
2161
- entityIds: ["/file2.txt", "a/c/d/file.png", "a/c/d/file with spaces.png"],
2162
- });
2163
- expect(matches).toMatchObject([
2164
- {
2165
- "@id": "_:Relationship2",
2166
- "@type": ["Relationship"],
2167
- name: "_:Relationship2",
2168
- },
2169
- ]);
2170
-
2171
- matches = cm.locateEntity({
2172
- entityIds: ["/file2.txt", "a/c/d/file.png", "a/c/d/file with spaces.png"],
2173
- });
2174
- expect(matches).toMatchObject([
2175
- {
2176
- "@id": "_:Relationship2",
2177
- "@type": ["Relationship"],
2178
- name: "_:Relationship2",
2179
- },
2180
- ]);
2181
- });
2182
- test(`test locating entities - subset matching`, () => {
2183
- let cm = new CrateManager({ crate });
2184
-
2185
- const r1 = cm.addBlankNode("Relationship");
2186
- const r2 = cm.addBlankNode("Relationship");
2187
- const e1 = cm.addEntity({ "@id": "/a/b/file1.txt", "@type": "File", name: "/file1.txt" });
2188
- const e2 = cm.addEntity({ "@id": "/file2.txt", "@type": "File", name: "/file2.txt" });
2189
- const e3 = cm.addFile("/a/c/d/file.png");
2190
- const e4 = cm.addFile("/a/c/d/file with spaces.png");
2191
-
2192
- // link e1 and e2 entities to r1
2193
- cm.linkEntity({
2194
- id: r1["@id"],
2195
- property: "object",
2196
- propertyId: "https://schema.org/object",
2197
- value: { "@id": e1["@id"] },
2198
- });
2199
-
2200
- cm.linkEntity({
2201
- id: r1["@id"],
2202
- property: "object",
2203
- propertyId: "https://schema.org/object",
2204
- value: { "@id": e2["@id"] },
2205
- });
2206
-
2207
- // link e2, e3 and e4 to r2
2208
- cm.linkEntity({
2209
- id: r2["@id"],
2210
- property: "object",
2211
- propertyId: "https://schema.org/object",
2212
- value: { "@id": e2["@id"] },
2213
- });
2214
- cm.linkEntity({
2215
- id: r2["@id"],
2216
- property: "object",
2217
- propertyId: "https://schema.org/object",
2218
- value: { "@id": e3["@id"] },
2219
- });
2220
- cm.linkEntity({
2221
- id: r2["@id"],
2222
- property: "object",
2223
- propertyId: "https://schema.org/object",
2224
- value: { "@id": e4["@id"] },
2225
- });
2226
-
2227
- // console.log(JSON.stringify(cm.exportCrate()["@graph"], null, 2));
2228
-
2229
- // won't find a matching entity
2230
- let matches = cm.locateEntity({ entityIds: ["file1.txt", "/file2.txt"] });
2231
- expect(matches).toEqual(undefined);
2232
-
2233
- // will find a matching entity - subset match
2234
- matches = cm.locateEntity({ entityIds: ["/file2.txt"], strict: false });
2235
- expect(matches).toMatchObject([{ "@id": "_:Relationship1" }, { "@id": "_:Relationship2" }]);
2236
-
2237
- // will find a matching entity - an exact match
2238
- matches = cm.locateEntity({ entityIds: ["/a/b/file1.txt", "/file2.txt"], strict: false });
2239
- expect(matches).toMatchObject([
2240
- {
2241
- "@id": "_:Relationship1",
2242
- },
2243
- ]);
2244
- });
2245
- test("add files and folders to the crate", () => {
2246
- let e = cm.addFile("/file.txt");
2247
- expect(cm.exportCrate()["@graph"]).toMatchObject([
2248
- { "@id": "ro-crate-metadata.json" },
2249
- { "@id": "./" },
2250
- { "@id": "file.txt", "@type": "File" },
2251
- ]);
2252
- expect(e).toEqual({ "@id": "file.txt", "@type": ["File"], name: "file.txt" });
2253
-
2254
- e = cm.addFolder("images");
2255
- expect(cm.exportCrate()["@graph"]).toMatchObject([
2256
- { "@id": "ro-crate-metadata.json" },
2257
- { "@id": "./" },
2258
- { "@id": "file.txt", "@type": "File" },
2259
- { "@id": "images/", "@type": "Dataset" },
2260
- ]);
2261
- expect(e).toEqual({ "@id": "images/", "@type": ["Dataset"], name: "images/" });
2262
-
2263
- cm.addFile("/folder/file.txt");
2264
- // console.log(cm.exportCrate()["@graph"]);
2265
- expect(cm.exportCrate()["@graph"]).toMatchObject([
2266
- { "@id": "ro-crate-metadata.json" },
2267
- { "@id": "./" },
2268
- { "@id": "file.txt", "@type": "File" },
2269
- { "@id": "images/", "@type": "Dataset" },
2270
- { "@id": "folder/", "@type": "Dataset" },
2271
- { "@id": "folder/file.txt", "@type": "File" },
2272
- ]);
2273
-
2274
- cm.addFile("/a/b/c/d/file.png");
2275
- expect(cm.exportCrate()["@graph"]).toMatchObject([
2276
- { "@id": "ro-crate-metadata.json" },
2277
- { "@id": "./" },
2278
- { "@id": "file.txt", "@type": "File" },
2279
- { "@id": "images/", "@type": "Dataset" },
2280
- { "@id": "folder/", "@type": "Dataset" },
2281
- { "@id": "folder/file.txt", "@type": "File" },
2282
- { "@id": "a/", "@type": "Dataset" },
2283
- { "@id": "a/b/", "@type": "Dataset" },
2284
- { "@id": "a/b/c/", "@type": "Dataset" },
2285
- { "@id": "a/b/c/d/", "@type": "Dataset" },
2286
- { "@id": "a/b/c/d/file.png", "@type": "File" },
2287
- ]);
2288
-
2289
- e = cm.addFolder("/a/j/f/g");
2290
- // console.log(JSON.ddstringify(cm.exportCrate()["@graph"], null, 2));
2291
- expect(cm.exportCrate()["@graph"]).toMatchObject([
2292
- { "@id": "ro-crate-metadata.json" },
2293
- { "@id": "./" },
2294
- { "@id": "file.txt", "@type": "File" },
2295
- { "@id": "images/", "@type": "Dataset" },
2296
- { "@id": "folder/", "@type": "Dataset" },
2297
- { "@id": "folder/file.txt", "@type": "File" },
2298
- { "@id": "a/", "@type": "Dataset" },
2299
- { "@id": "a/b/", "@type": "Dataset" },
2300
- { "@id": "a/b/c/", "@type": "Dataset" },
2301
- { "@id": "a/b/c/d/", "@type": "Dataset" },
2302
- { "@id": "a/b/c/d/file.png", "@type": "File" },
2303
- { "@id": "a/j/", "@type": "Dataset" },
2304
- { "@id": "a/j/f/", "@type": "Dataset" },
2305
- { "@id": "a/j/f/g/", "@type": "Dataset" },
2306
- ]);
2307
- expect(e).toEqual({ "@id": "a/j/f/g/", "@type": ["Dataset"], name: "a/j/f/g/" });
2308
- });
2309
- });
2310
-
2311
- function getBaseCrate(): UnverifiedCrate {
2312
- return {
2313
- "@context": ["https://w3id.org/ro/crate/1.1/context"],
2314
- "@graph": [
2315
- {
2316
- "@id": "ro-crate-metadata.json",
2317
- "@type": "CreativeWork",
2318
- conformsTo: {
2319
- "@id": "https://w3id.org/ro/crate/1.1/context",
2320
- },
2321
- about: {
2322
- "@id": "./",
2323
- },
2324
- },
2325
- ],
2326
- };
2327
- }
2328
-
2329
- function addRootDataset({ crate }: { crate: UnverifiedCrate }) {
2330
- crate["@graph"].push({
2331
- "@id": "./",
2332
- "@type": "Dataset",
2333
- name: "Dataset",
2334
- });
2335
- return crate;
2336
- }