Updated subscribable dataset

main
jaxoncreed 2 years ago
parent d78858dbbc
commit 9d82cb3390
  1. 190
      package-lock.json
  2. 4
      packages/rdf-utils/package.json
  3. 2
      packages/rdf-utils/src/nodeSerialization.ts
  4. 234
      packages/subscribable-dataset/src/WrapperSubscribableDataset.ts
  5. 10
      packages/subscribable-dataset/src/types.ts
  6. 177
      packages/subscribable-dataset/test/WrapperSubscribableDataset.test.ts

190
package-lock.json generated

@ -865,7 +865,6 @@
"version": "7.21.0-placeholder-for-preset-env.2",
"resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
"integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==",
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead.",
"engines": {
"node": ">=6.9.0"
},
@ -4273,9 +4272,9 @@
}
},
"node_modules/@inrupt/solid-client-authn-browser/node_modules/@types/node": {
"version": "18.17.12",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.12.tgz",
"integrity": "sha512-d6xjC9fJ/nSnfDeU0AMDsaJyb1iHsqCSOdi84w4u+SlN/UgQdY5tRhpMzaFYsI4mnpvgTivEaQd0yOUhAtOnEQ=="
"version": "18.17.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.14.tgz",
"integrity": "sha512-ZE/5aB73CyGqgQULkLG87N9GnyGe5TcQjv34pwS8tfBs1IkCh0ASM69mydb2znqd6v0eX+9Ytvk6oQRqu8T1Vw=="
},
"node_modules/@inrupt/solid-client-authn-core": {
"version": "1.17.1",
@ -7610,9 +7609,9 @@
}
},
"node_modules/@types/node": {
"version": "20.5.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.7.tgz",
"integrity": "sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA=="
"version": "20.5.9",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz",
"integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ=="
},
"node_modules/@types/normalize-package-data": {
"version": "2.4.1",
@ -10989,21 +10988,29 @@
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"node_modules/cosmiconfig": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz",
"integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==",
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.2.tgz",
"integrity": "sha512-/PvU3MjSLVKJMRHsL6GW+wHQ9RaJuMW6fnn56sXNy+kP1L8nI/SHk9F9giIA+dnfzjKNJAulRjOR/fi9kzGuNA==",
"dev": true,
"dependencies": {
"import-fresh": "^3.2.1",
"import-fresh": "^3.3.0",
"js-yaml": "^4.1.0",
"parse-json": "^5.0.0",
"parse-json": "^5.2.0",
"path-type": "^4.0.0"
},
"engines": {
"node": ">=14"
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/d-fischer"
},
"peerDependencies": {
"typescript": ">=4.9.5"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/cosmiconfig-typescript-loader": {
@ -13776,9 +13783,9 @@
}
},
"node_modules/expo": {
"version": "49.0.8",
"resolved": "https://registry.npmjs.org/expo/-/expo-49.0.8.tgz",
"integrity": "sha512-lkTRwMvJP8j7KAHJB+aZqI9dH1hw7j2QE1X9Okpcf+t0deGqH36XqkjUCcU6KYgCOjSnt8fvRm89TJR5Oq0ElA==",
"version": "49.0.9",
"resolved": "https://registry.npmjs.org/expo/-/expo-49.0.9.tgz",
"integrity": "sha512-x68r9sJ3HP5AedtGFZ5ufEYLWWrbWN9LN/jKavFMe22vRRyTGDMyIhKcoLCikqRDpYHFtIEuLh1P8H85Oz800Q==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.20.0",
@ -13790,11 +13797,11 @@
"expo-application": "~5.3.0",
"expo-asset": "~8.10.1",
"expo-constants": "~14.4.2",
"expo-file-system": "~15.4.3",
"expo-file-system": "~15.4.4",
"expo-font": "~11.4.0",
"expo-keep-awake": "~12.3.0",
"expo-modules-autolinking": "1.5.1",
"expo-modules-core": "1.5.10",
"expo-modules-core": "1.5.11",
"fbemitter": "^3.0.0",
"invariant": "^2.2.4",
"md5-file": "^3.2.3",
@ -13854,9 +13861,9 @@
}
},
"node_modules/expo-file-system": {
"version": "15.4.3",
"resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-15.4.3.tgz",
"integrity": "sha512-HaaCBTUATs2+i7T4jxIvoU9rViAHMvOD2eBaJ1H7xPHlwZlMORjQs7bsNKonR/TQoduxZBJLVZGawvaAJNCH8g==",
"version": "15.4.4",
"resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-15.4.4.tgz",
"integrity": "sha512-F0xS88D85F7qVQ61r0qBnzh6VW/s6iIl+VaQEEi2nAIOQHw1JIEj4yCXPLTtbyn5VmArbe2dSL3KYz1V+BLkKA==",
"peer": true,
"dependencies": {
"uuid": "^3.4.0"
@ -13938,9 +13945,9 @@
}
},
"node_modules/expo-modules-core": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-1.5.10.tgz",
"integrity": "sha512-+m+poHkhjAhRZmngSLUpJJoxhjoExYKSr4J5luy4N+YMlowK31Zewztg4xsPrNRoPvGK/B5uCm0UEzIQvLsNGg==",
"version": "1.5.11",
"resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-1.5.11.tgz",
"integrity": "sha512-1Dj2t74nVjxq6xEQf2b9WFfAMhPzVnR0thY0PfRFgob4STyj3sq1U4PIHVWvKQBtDKIa227DrNRb+Hu+LqKWQg==",
"peer": true,
"dependencies": {
"compare-versions": "^3.4.0",
@ -18014,9 +18021,9 @@
"peer": true
},
"node_modules/jose": {
"version": "4.14.4",
"resolved": "https://registry.npmjs.org/jose/-/jose-4.14.4.tgz",
"integrity": "sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g==",
"version": "4.14.5",
"resolved": "https://registry.npmjs.org/jose/-/jose-4.14.5.tgz",
"integrity": "sha512-56ns1XlSI8d5V0t7hilPu8dMbE4YIwrTJU6e7bV1Abyu6oel4tSc4YmD742MoWV3U+vn7O0WlKpinzu2DP0HWw==",
"funding": {
"url": "https://github.com/sponsors/panva"
}
@ -18275,9 +18282,9 @@
}
},
"node_modules/jsonld-context-parser/node_modules/@types/node": {
"version": "18.17.12",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.12.tgz",
"integrity": "sha512-d6xjC9fJ/nSnfDeU0AMDsaJyb1iHsqCSOdi84w4u+SlN/UgQdY5tRhpMzaFYsI4mnpvgTivEaQd0yOUhAtOnEQ=="
"version": "18.17.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.14.tgz",
"integrity": "sha512-ZE/5aB73CyGqgQULkLG87N9GnyGe5TcQjv34pwS8tfBs1IkCh0ASM69mydb2znqd6v0eX+9Ytvk6oQRqu8T1Vw=="
},
"node_modules/jsonld-streaming-parser": {
"version": "3.2.0",
@ -30933,12 +30940,11 @@
"license": "MIT",
"dependencies": {
"@ldo/dataset": "^0.0.0",
"@ldo/rdf-utils": "^0.0.0",
"@ldo/subscribable-dataset": "^0.0.0",
"@rdfjs/data-model": "^1.2.0",
"jsonld2graphobject": "^0.0.4"
},
"devDependencies": {
"@rdfjs/types": "^1.0.1",
"@types/jest": "^27.0.3",
"@types/jsonld": "^1.5.6",
"@types/n3": "^1.10.4",
@ -31015,14 +31021,12 @@
"dependencies": {
"@ldo/dataset": "^0.0.0",
"@ldo/jsonld-dataset-proxy": "^0.0.0",
"@ldo/rdf-utils": "^0.0.0",
"@ldo/subscribable-dataset": "^0.0.0",
"@rdfjs/data-model": "^1.2.0",
"buffer": "^6.0.3",
"n3": "^1.16.2",
"readable-stream": "^4.3.0"
},
"devDependencies": {
"@rdfjs/types": "^1.1.0",
"@types/jest": "^27.0.3",
"@types/jsonld": "^1.5.6",
"@types/n3": "^1.10.4",
@ -31096,8 +31100,8 @@
"version": "0.0.0",
"license": "MIT",
"dependencies": {
"@rdfjs/data-model": "^2.0.1",
"@rdfjs/types": "^1.1.0",
"@rdfjs/data-model": "^1.2.0",
"@rdfjs/types": "^1.0.1",
"n3": "^1.17.1",
"rdf-string": "^1.6.3"
},
@ -31105,14 +31109,6 @@
"@types/jsonld": "^1.5.9"
}
},
"packages/rdf-utils/node_modules/@rdfjs/data-model": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@rdfjs/data-model/-/data-model-2.0.1.tgz",
"integrity": "sha512-oRDYpy7/fJ9NNjS+M7m+dbnhi4lOWYGbBiM/A+u9bBExnN6ifXUF5mUsFxwZaQulmwTDaMhKERdV6iKTBUMgtw==",
"bin": {
"rdfjs-data-model-test": "bin/test.js"
}
},
"packages/schema-converter-shex": {
"name": "@ldo/schema-converter-shex",
"version": "0.0.0",
@ -31236,16 +31232,13 @@
"version": "0.0.0",
"license": "MIT",
"dependencies": {
"@inrupt/solid-client": "^1.29.0",
"@ldo/dataset": "^0.0.0",
"@ldo/ldo": "^0.0.0",
"@ldo/subscribable-dataset": "^0.0.0",
"@ldo/rdf-utils": "^0.0.0",
"cross-fetch": "^3.1.6"
},
"devDependencies": {
"@ldo/cli": "^0.0.0",
"@ldo/jsonld-dataset-proxy": "^0.0.0",
"@rdfjs/types": "^1.1.0",
"@types/jest": "^29.0.3",
"ts-jest": "^29.0.2"
}
@ -31269,7 +31262,6 @@
"@babel/preset-env": "^7.22.10",
"@babel/preset-react": "^7.22.5",
"@babel/preset-typescript": "^7.22.11",
"@rdfjs/types": "^1.1.0",
"@types/jest": "^29.0.3",
"@types/jsonld": "^1.5.8",
"@types/n3": "^1.10.4",
@ -33641,19 +33633,13 @@
"license": "MIT",
"dependencies": {
"@ldo/dataset": "^0.0.0",
"@rdfjs/data-model": "^1.2.0",
"@rdfjs/dataset": "^1.1.0",
"buffer": "^6.0.3",
"n3": "^1.10.0",
"readable-stream": "^4.2.0"
"@ldo/rdf-utils": "^0.0.0"
},
"devDependencies": {
"@rdfjs/types": "^1.0.1",
"@rdfjs/dataset": "^1.1.0",
"@types/jest": "^27.0.3",
"@types/jsonld": "^1.5.6",
"@types/n3": "^1.10.4",
"@types/rdfjs__dataset": "^1.0.4",
"@types/readable-stream": "^2.3.13",
"jest": "^27.4.5",
"ts-jest": "^27.1.2",
"ts-node": "^9.1.1"
@ -38032,9 +38018,9 @@
},
"dependencies": {
"@types/node": {
"version": "18.17.12",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.12.tgz",
"integrity": "sha512-d6xjC9fJ/nSnfDeU0AMDsaJyb1iHsqCSOdi84w4u+SlN/UgQdY5tRhpMzaFYsI4mnpvgTivEaQd0yOUhAtOnEQ=="
"version": "18.17.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.14.tgz",
"integrity": "sha512-ZE/5aB73CyGqgQULkLG87N9GnyGe5TcQjv34pwS8tfBs1IkCh0ASM69mydb2znqd6v0eX+9Ytvk6oQRqu8T1Vw=="
}
}
},
@ -39037,9 +39023,8 @@
"version": "file:packages/jsonld-dataset-proxy",
"requires": {
"@ldo/dataset": "^0.0.0",
"@ldo/rdf-utils": "^0.0.0",
"@ldo/subscribable-dataset": "^0.0.0",
"@rdfjs/data-model": "^1.2.0",
"@rdfjs/types": "^1.0.1",
"@types/jest": "^27.0.3",
"@types/jsonld": "^1.5.6",
"@types/n3": "^1.10.4",
@ -39083,9 +39068,8 @@
"requires": {
"@ldo/dataset": "^0.0.0",
"@ldo/jsonld-dataset-proxy": "^0.0.0",
"@ldo/rdf-utils": "^0.0.0",
"@ldo/subscribable-dataset": "^0.0.0",
"@rdfjs/data-model": "^1.2.0",
"@rdfjs/types": "^1.1.0",
"@types/jest": "^27.0.3",
"@types/jsonld": "^1.5.6",
"@types/n3": "^1.10.4",
@ -39094,7 +39078,6 @@
"buffer": "^6.0.3",
"cross-fetch": "^3.1.5",
"jest": "^27.4.5",
"n3": "^1.16.2",
"readable-stream": "^4.3.0",
"ts-jest": "^27.1.2",
"ts-node": "^10.4.0"
@ -39128,18 +39111,11 @@
"@ldo/rdf-utils": {
"version": "file:packages/rdf-utils",
"requires": {
"@rdfjs/data-model": "^2.0.1",
"@rdfjs/types": "^1.1.0",
"@rdfjs/data-model": "^1.2.0",
"@rdfjs/types": "^1.0.1",
"@types/jsonld": "^1.5.9",
"n3": "^1.17.1",
"rdf-string": "^1.6.3"
},
"dependencies": {
"@rdfjs/data-model": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/@rdfjs/data-model/-/data-model-2.0.1.tgz",
"integrity": "sha512-oRDYpy7/fJ9NNjS+M7m+dbnhi4lOWYGbBiM/A+u9bBExnN6ifXUF5mUsFxwZaQulmwTDaMhKERdV6iKTBUMgtw=="
}
}
},
"@ldo/schema-converter-shex": {
@ -39218,13 +39194,10 @@
"@ldo/solid": {
"version": "file:packages/solid",
"requires": {
"@inrupt/solid-client": "^1.29.0",
"@ldo/cli": "^0.0.0",
"@ldo/dataset": "^0.0.0",
"@ldo/jsonld-dataset-proxy": "^0.0.0",
"@ldo/ldo": "^0.0.0",
"@ldo/subscribable-dataset": "^0.0.0",
"@rdfjs/types": "^1.1.0",
"@ldo/rdf-utils": "^0.0.0",
"@types/jest": "^29.0.3",
"cross-fetch": "^3.1.6",
"ts-jest": "^29.0.2"
@ -40152,7 +40125,6 @@
"@ldo/ldo": "^0.0.0",
"@ldo/solid": "^0.0.0",
"@ldo/subscribable-dataset": "^0.0.0",
"@rdfjs/types": "^1.1.0",
"@types/jest": "^29.0.3",
"@types/jsonld": "^1.5.8",
"@types/n3": "^1.10.4",
@ -41077,18 +41049,12 @@
"version": "file:packages/subscribable-dataset",
"requires": {
"@ldo/dataset": "^0.0.0",
"@rdfjs/data-model": "^1.2.0",
"@ldo/rdf-utils": "^0.0.0",
"@rdfjs/dataset": "^1.1.0",
"@rdfjs/types": "^1.0.1",
"@types/jest": "^27.0.3",
"@types/jsonld": "^1.5.6",
"@types/n3": "^1.10.4",
"@types/rdfjs__dataset": "^1.0.4",
"@types/readable-stream": "^2.3.13",
"buffer": "^6.0.3",
"jest": "^27.4.5",
"n3": "^1.10.0",
"readable-stream": "^4.2.0",
"ts-jest": "^27.1.2",
"ts-node": "^9.1.1"
},
@ -43935,9 +43901,9 @@
}
},
"@types/node": {
"version": "20.5.7",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.7.tgz",
"integrity": "sha512-dP7f3LdZIysZnmvP3ANJYTSwg+wLLl8p7RqniVlV7j+oXSXAbt9h0WIBFmJy5inWZoX9wZN6eXx+YXd9Rh3RBA=="
"version": "20.5.9",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.5.9.tgz",
"integrity": "sha512-PcGNd//40kHAS3sTlzKB9C9XL4K0sTup8nbG5lC14kzEteTNuAFh9u5nA0o5TWnSG2r/JNPRXFVcHJIIeRlmqQ=="
},
"@types/normalize-package-data": {
"version": "2.4.1",
@ -46498,14 +46464,14 @@
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"cosmiconfig": {
"version": "8.2.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.2.0.tgz",
"integrity": "sha512-3rTMnFJA1tCOPwRxtgF4wd7Ab2qvDbL8jX+3smjIbS4HlZBagTlpERbdN7iAbWlrfxE3M8c27kTwTawQ7st+OQ==",
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.2.tgz",
"integrity": "sha512-/PvU3MjSLVKJMRHsL6GW+wHQ9RaJuMW6fnn56sXNy+kP1L8nI/SHk9F9giIA+dnfzjKNJAulRjOR/fi9kzGuNA==",
"dev": true,
"requires": {
"import-fresh": "^3.2.1",
"import-fresh": "^3.3.0",
"js-yaml": "^4.1.0",
"parse-json": "^5.0.0",
"parse-json": "^5.2.0",
"path-type": "^4.0.0"
}
},
@ -48450,9 +48416,9 @@
}
},
"expo": {
"version": "49.0.8",
"resolved": "https://registry.npmjs.org/expo/-/expo-49.0.8.tgz",
"integrity": "sha512-lkTRwMvJP8j7KAHJB+aZqI9dH1hw7j2QE1X9Okpcf+t0deGqH36XqkjUCcU6KYgCOjSnt8fvRm89TJR5Oq0ElA==",
"version": "49.0.9",
"resolved": "https://registry.npmjs.org/expo/-/expo-49.0.9.tgz",
"integrity": "sha512-x68r9sJ3HP5AedtGFZ5ufEYLWWrbWN9LN/jKavFMe22vRRyTGDMyIhKcoLCikqRDpYHFtIEuLh1P8H85Oz800Q==",
"peer": true,
"requires": {
"@babel/runtime": "^7.20.0",
@ -48464,11 +48430,11 @@
"expo-application": "~5.3.0",
"expo-asset": "~8.10.1",
"expo-constants": "~14.4.2",
"expo-file-system": "~15.4.3",
"expo-file-system": "~15.4.4",
"expo-font": "~11.4.0",
"expo-keep-awake": "~12.3.0",
"expo-modules-autolinking": "1.5.1",
"expo-modules-core": "1.5.10",
"expo-modules-core": "1.5.11",
"fbemitter": "^3.0.0",
"invariant": "^2.2.4",
"md5-file": "^3.2.3",
@ -48560,9 +48526,9 @@
}
},
"expo-file-system": {
"version": "15.4.3",
"resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-15.4.3.tgz",
"integrity": "sha512-HaaCBTUATs2+i7T4jxIvoU9rViAHMvOD2eBaJ1H7xPHlwZlMORjQs7bsNKonR/TQoduxZBJLVZGawvaAJNCH8g==",
"version": "15.4.4",
"resolved": "https://registry.npmjs.org/expo-file-system/-/expo-file-system-15.4.4.tgz",
"integrity": "sha512-F0xS88D85F7qVQ61r0qBnzh6VW/s6iIl+VaQEEi2nAIOQHw1JIEj4yCXPLTtbyn5VmArbe2dSL3KYz1V+BLkKA==",
"peer": true,
"requires": {
"uuid": "^3.4.0"
@ -48627,9 +48593,9 @@
}
},
"expo-modules-core": {
"version": "1.5.10",
"resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-1.5.10.tgz",
"integrity": "sha512-+m+poHkhjAhRZmngSLUpJJoxhjoExYKSr4J5luy4N+YMlowK31Zewztg4xsPrNRoPvGK/B5uCm0UEzIQvLsNGg==",
"version": "1.5.11",
"resolved": "https://registry.npmjs.org/expo-modules-core/-/expo-modules-core-1.5.11.tgz",
"integrity": "sha512-1Dj2t74nVjxq6xEQf2b9WFfAMhPzVnR0thY0PfRFgob4STyj3sq1U4PIHVWvKQBtDKIa227DrNRb+Hu+LqKWQg==",
"peer": true,
"requires": {
"compare-versions": "^3.4.0",
@ -51613,9 +51579,9 @@
"peer": true
},
"jose": {
"version": "4.14.4",
"resolved": "https://registry.npmjs.org/jose/-/jose-4.14.4.tgz",
"integrity": "sha512-j8GhLiKmUAh+dsFXlX1aJCbt5KMibuKb+d7j1JaOJG6s2UjX1PQlW+OKB/sD4a/5ZYF4RcmYmLSndOoU3Lt/3g=="
"version": "4.14.5",
"resolved": "https://registry.npmjs.org/jose/-/jose-4.14.5.tgz",
"integrity": "sha512-56ns1XlSI8d5V0t7hilPu8dMbE4YIwrTJU6e7bV1Abyu6oel4tSc4YmD742MoWV3U+vn7O0WlKpinzu2DP0HWw=="
},
"js-tokens": {
"version": "4.0.0",
@ -51849,9 +51815,9 @@
},
"dependencies": {
"@types/node": {
"version": "18.17.12",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.12.tgz",
"integrity": "sha512-d6xjC9fJ/nSnfDeU0AMDsaJyb1iHsqCSOdi84w4u+SlN/UgQdY5tRhpMzaFYsI4mnpvgTivEaQd0yOUhAtOnEQ=="
"version": "18.17.14",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.14.tgz",
"integrity": "sha512-ZE/5aB73CyGqgQULkLG87N9GnyGe5TcQjv34pwS8tfBs1IkCh0ASM69mydb2znqd6v0eX+9Ytvk6oQRqu8T1Vw=="
}
}
},

@ -25,8 +25,8 @@
"@types/jsonld": "^1.5.9"
},
"dependencies": {
"@rdfjs/data-model": "^2.0.1",
"@rdfjs/types": "^1.1.0",
"@rdfjs/data-model": "^1.2.0",
"@rdfjs/types": "^1.0.1",
"n3": "^1.17.1",
"rdf-string": "^1.6.3"
}

@ -234,7 +234,7 @@ export function stringToQuad(input: string) {
* @param input String Inupt
* @returns QuadMatch
*/
export function stringToQuadMatch(input: string) {
export function stringToQuadMatch(input: string): QuadMatch {
const jsonRep = JSON.parse(input);
return [
jsonRep.subject ? stringToSubjectNode(jsonRep.subject) : undefined,

@ -1,5 +1,5 @@
import { EventEmitter } from "events";
import { namedNode, blankNode, defaultGraph } from "@ldo/rdf-utils";
import { quadMatchToString, stringToQuadMatch } from "@ldo/rdf-utils";
import type {
DatasetChanges,
Dataset,
@ -7,9 +7,12 @@ import type {
Stream,
Term,
DatasetFactory,
QuadMatch,
SubjectNode,
PredicateNode,
ObjectNode,
} from "@ldo/rdf-utils";
import type {
SubscribableTerms,
nodeEventListener,
SubscribableDataset,
TransactionalDataset,
@ -36,6 +39,10 @@ export default class WrapperSubscribableDataset<
* The underlying event emitter
*/
private eventEmitter: EventEmitter;
/**
* EventNames as a Set for O(1) lookup
*/
private eventNamesSet: Set<string>;
/**
*
@ -49,6 +56,7 @@ export default class WrapperSubscribableDataset<
this.datasetFactory = datasetFactory;
this.dataset = initialDataset || this.datasetFactory.dataset();
this.eventEmitter = new EventEmitter();
this.eventNamesSet = new Set();
}
/**
@ -345,42 +353,6 @@ export default class WrapperSubscribableDataset<
* EVENTEMITTER METHODS
* ==================================================================
*/
private NAMED_NODE_KEY_PREFIX = "NamedNode";
private BLANK_NODE_KEY_PREFIX = "BlankNode";
private DEFAULT_GRAPH_KEY_PREFIX = "DefaultGraph";
private SUBSCRIBABLE_TERMS = [
this.NAMED_NODE_KEY_PREFIX,
this.BLANK_NODE_KEY_PREFIX,
this.DEFAULT_GRAPH_KEY_PREFIX,
];
/**
* Given a term, returns the string key to be used in an event emitter
*/
private getKeyFromNode(term: SubscribableTerms): string {
if (term.termType === "NamedNode") {
return `${this.NAMED_NODE_KEY_PREFIX}${term.value}`;
} else if (term.termType === "BlankNode") {
return `${this.BLANK_NODE_KEY_PREFIX}${term.value}`;
} else if (term.termType === "DefaultGraph") {
return `${this.DEFAULT_GRAPH_KEY_PREFIX}${term.value}`;
}
throw new Error("Invalid term type for subscription");
}
/**
* Given a key, returns the node
*/
private getNodeFromKey(key: string): SubscribableTerms {
if (key.startsWith(this.NAMED_NODE_KEY_PREFIX)) {
return namedNode(key.slice(this.NAMED_NODE_KEY_PREFIX.length));
} else if (key.startsWith(this.BLANK_NODE_KEY_PREFIX)) {
return blankNode(key.slice(this.BLANK_NODE_KEY_PREFIX.length));
} else if (key.startsWith(this.DEFAULT_GRAPH_KEY_PREFIX)) {
return defaultGraph();
}
throw Error("Invalid Subscription Key");
}
/**
* Triggers all subscriptions based on an updated quads
@ -389,82 +361,62 @@ export default class WrapperSubscribableDataset<
private triggerSubscriptionForQuads(
changed: DatasetChanges<InAndOutQuad>,
): void {
const triggeredTermsMap: Record<string, SubscribableTerms> = {};
const forEachQuad = (quad: BaseQuad) => {
const subject = quad.subject;
const predicate = quad.predicate;
const object = quad.object;
const graph = quad.graph;
const quadTerms = [subject, predicate, object, graph];
quadTerms.forEach((quadTerm) => {
if (this.SUBSCRIBABLE_TERMS.includes(quadTerm.termType)) {
triggeredTermsMap[`${quadTerm.termType}${quadTerm.value}`] =
quadTerm as SubscribableTerms;
// A mapping of serialized QuadMatches to the changed quads
const matchingDatasetChanges: Record<
string,
DatasetChanges<InAndOutQuad>
> = {};
// Population MatchingDatasetChanges
const populateMatchingDatasetChanges = (
changeType: "added" | "removed",
) => {
const changedQuads = changed[changeType];
changedQuads?.forEach((changedQuad) => {
// Cast the input because RDFJS types assume RDF 1.2 where a Subject can
// be a Quad
const quad = changedQuad as {
subject: SubjectNode;
predicate: PredicateNode;
object: ObjectNode;
};
// All possible matches that could match with this triple
const quadMatches: QuadMatch[] = [
[null, null, null, null],
[quad.subject, null, null, null],
[quad.subject, quad.predicate, null, null],
[quad.subject, null, quad.object, null],
[null, quad.predicate, null, null],
[null, quad.predicate, quad.object, null],
[null, null, quad.object, null],
[quad.subject, quad.predicate, quad.object, null],
];
quadMatches.forEach((quadMatch) => {
const eventName = quadMatchToString(quadMatch);
// Only add to the map if there's actually a listener for this
if (this.eventEmitter.listenerCount(eventName) > 0) {
// Set matchingDatasetChanges to include data to emit
if (!matchingDatasetChanges[eventName]) {
matchingDatasetChanges[eventName] = {};
}
if (!matchingDatasetChanges[eventName][changeType]) {
matchingDatasetChanges[eventName][changeType] =
this.datasetFactory.dataset();
}
matchingDatasetChanges[eventName][changeType]?.add(changedQuad);
}
});
};
changed.added?.forEach(forEachQuad);
changed.removed?.forEach(forEachQuad);
const triggeredTerms = Object.values(triggeredTermsMap);
triggeredTerms.forEach((triggeredTerm) => {
this.triggerSubscriptionForNode(triggeredTerm, changed);
});
}
/**
* Triggers all subscriptions for a given term
* @param term The term that should be triggered
* @param changed The changed triples of a certain transaction
*/
private triggerSubscriptionForNode(
term: SubscribableTerms,
changed: DatasetChanges<InAndOutQuad>,
): void {
if (this.listenerCount(term) > 0) {
let allQuads: Dataset<InAndOutQuad, InAndOutQuad> =
this.datasetFactory.dataset();
if (term.termType !== "DefaultGraph") {
allQuads = allQuads.union(this.match(term, null, null, null));
allQuads = allQuads.union(this.match(null, null, term, null));
if (term.termType !== "BlankNode") {
allQuads = allQuads.union(this.match(null, term, null, null));
allQuads = allQuads.union(this.match(null, null, null, term));
}
} else {
allQuads = allQuads.union(this.match(null, null, null, term));
}
let changedForThisNode: DatasetChanges<InAndOutQuad> = {
added: changed.added
? changed.added.filter(
(addedQuad) =>
addedQuad.subject.equals(term) ||
addedQuad.predicate.equals(term) ||
addedQuad.object.equals(term) ||
addedQuad.graph.equals(term),
)
: undefined,
removed: changed.removed
? changed.removed.filter(
(removedQuad) =>
removedQuad.subject.equals(term) ||
removedQuad.predicate.equals(term) ||
removedQuad.object.equals(term) ||
removedQuad.graph.equals(term),
)
: undefined,
};
changedForThisNode = {
added:
changedForThisNode.added && changedForThisNode.added.size > 0
? changedForThisNode.added
: undefined,
removed:
changedForThisNode.removed && changedForThisNode.removed.size > 0
? changedForThisNode.removed
: undefined,
};
this.emit(term, allQuads, changedForThisNode);
}
populateMatchingDatasetChanges("added");
populateMatchingDatasetChanges("removed");
// Alert all listeners
Object.entries(matchingDatasetChanges).forEach(
([quadMatchString, changes]) => {
this.eventEmitter.emit(quadMatchString, changes);
},
);
}
/**
@ -474,7 +426,7 @@ export default class WrapperSubscribableDataset<
* @returns
*/
public addListener(
eventName: SubscribableTerms,
eventName: QuadMatch,
listener: nodeEventListener<InAndOutQuad>,
): this {
return this.on(eventName, listener);
@ -488,24 +440,19 @@ export default class WrapperSubscribableDataset<
* @returns true if the event had listeners, false otherwise.
*/
public emit(
eventName: SubscribableTerms,
dataset: Dataset<InAndOutQuad, InAndOutQuad>,
datasetChanges: DatasetChanges<InAndOutQuad>,
eventName: QuadMatch,
changes: DatasetChanges<InAndOutQuad>,
): boolean {
return this.eventEmitter.emit(
this.getKeyFromNode(eventName),
dataset,
datasetChanges,
);
return this.eventEmitter.emit(quadMatchToString(eventName), changes);
}
/**
* Returns an array listing the events for which the emitter has registered listeners. The values in the array are strings or Symbols.
*/
public eventNames(): SubscribableTerms[] {
public eventNames(): QuadMatch[] {
return this.eventEmitter
.eventNames()
.map((eventName) => this.getNodeFromKey(eventName as string));
.map((eventName) => stringToQuadMatch(eventName as string));
}
/**
@ -518,18 +465,16 @@ export default class WrapperSubscribableDataset<
/**
* Returns the number of listeners listening to the event named eventName.
*/
public listenerCount(eventName: SubscribableTerms): number {
return this.eventEmitter.listenerCount(this.getKeyFromNode(eventName));
public listenerCount(eventName: QuadMatch): number {
return this.eventEmitter.listenerCount(quadMatchToString(eventName));
}
/**
* Returns a copy of the array of listeners for the event named eventName.
*/
public listeners(
eventName: SubscribableTerms,
): nodeEventListener<InAndOutQuad>[] {
public listeners(eventName: QuadMatch): nodeEventListener<InAndOutQuad>[] {
return this.eventEmitter.listeners(
this.getKeyFromNode(eventName),
quadMatchToString(eventName),
) as nodeEventListener<InAndOutQuad>[];
}
@ -537,7 +482,7 @@ export default class WrapperSubscribableDataset<
* Alias for emitter.removeListener()
*/
public off(
eventName: SubscribableTerms,
eventName: QuadMatch,
listener: nodeEventListener<InAndOutQuad>,
): void {
this.removeListener(eventName, listener);
@ -547,10 +492,10 @@ export default class WrapperSubscribableDataset<
* Adds the listener function to the end of the listeners array for the event named eventName. No checks are made to see if the listener has already been added. Multiple calls passing the same combination of eventName and listener will result in the listener being added, and called, multiple times.
*/
public on(
eventName: SubscribableTerms,
eventName: QuadMatch,
listener: nodeEventListener<InAndOutQuad>,
): this {
this.eventEmitter.on(this.getKeyFromNode(eventName), listener);
this.eventEmitter.on(quadMatchToString(eventName), listener);
return this;
}
@ -558,10 +503,10 @@ export default class WrapperSubscribableDataset<
* Adds a one-time listener function for the event named eventName. The next time eventName is triggered, this listener is removed and then invoked.
*/
public once(
eventName: SubscribableTerms,
eventName: QuadMatch,
listener: nodeEventListener<InAndOutQuad>,
): this {
this.eventEmitter.once(this.getKeyFromNode(eventName), listener);
this.eventEmitter.once(quadMatchToString(eventName), listener);
return this;
}
@ -569,10 +514,10 @@ export default class WrapperSubscribableDataset<
* Adds the listener function to the beginning of the listeners array for the event named eventName. No checks are made to see if the listener has already been added. Multiple calls passing the same combination of eventName and listener will result in the listener being added, and called, multiple times.
*/
public prependListener(
eventName: SubscribableTerms,
eventName: QuadMatch,
listener: nodeEventListener<InAndOutQuad>,
): this {
this.eventEmitter.prependListener(this.getKeyFromNode(eventName), listener);
this.eventEmitter.prependListener(quadMatchToString(eventName), listener);
return this;
}
@ -580,11 +525,11 @@ export default class WrapperSubscribableDataset<
* Adds a one-time listener function for the event named eventName to the beginning of the listeners array. The next time eventName is triggered, this listener is removed, and then invoked.
*/
public prependOnceListener(
eventName: SubscribableTerms,
eventName: QuadMatch,
listener: nodeEventListener<InAndOutQuad>,
): this {
this.eventEmitter.prependOnceListener(
this.getKeyFromNode(eventName),
quadMatchToString(eventName),
listener,
);
return this;
@ -593,8 +538,8 @@ export default class WrapperSubscribableDataset<
/**
* Removes all listeners, or those of the specified eventName.
*/
public removeAllListeners(eventName: SubscribableTerms): this {
this.eventEmitter.removeAllListeners(this.getKeyFromNode(eventName));
public removeAllListeners(eventName: QuadMatch): this {
this.eventEmitter.removeAllListeners(quadMatchToString(eventName));
return this;
}
@ -602,10 +547,10 @@ export default class WrapperSubscribableDataset<
* Removes the specified listener from the listener array for the event named eventName.
*/
public removeListener(
eventName: SubscribableTerms,
eventName: QuadMatch,
listener: nodeEventListener<InAndOutQuad>,
): this {
this.eventEmitter.removeListener(this.getKeyFromNode(eventName), listener);
this.eventEmitter.removeListener(quadMatchToString(eventName), listener);
return this;
}
@ -620,11 +565,9 @@ export default class WrapperSubscribableDataset<
/**
* Returns a copy of the array of listeners for the event named eventName, including any wrappers (such as those created by .once()).
*/
public rawListeners(
eventName: SubscribableTerms,
): nodeEventListener<InAndOutQuad>[] {
public rawListeners(eventName: QuadMatch): nodeEventListener<InAndOutQuad>[] {
return this.eventEmitter.rawListeners(
this.getKeyFromNode(eventName),
quadMatchToString(eventName),
) as nodeEventListener[];
}
@ -638,9 +581,6 @@ export default class WrapperSubscribableDataset<
* Returns a transactional dataset that will update this dataset when its transaction is committed.
*/
public startTransaction(): TransactionalDataset<InAndOutQuad> {
// Type problem again
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return new ProxyTransactionalDataset(this, this.datasetFactory);
}
}

@ -9,7 +9,6 @@ import type {
* An event listeners for nodes
*/
export type nodeEventListener<InAndOutQuad extends BaseQuad = BaseQuad> = (
dataset: Dataset<InAndOutQuad, InAndOutQuad>,
changes: DatasetChanges<InAndOutQuad>,
) => void;
@ -52,15 +51,10 @@ export interface SubscribableDataset<InAndOutQuad extends BaseQuad = BaseQuad>
/**
* Synchronously calls each of the listeners registered for the event named eventName, in the order they were registered, passing the supplied arguments to each.
* @param eventName
* @param dataset
* @param datasetChanges
* @param changes
* @returns true if the event had listeners, false otherwise.
*/
emit(
eventName: QuadMatch,
dataset: Dataset<InAndOutQuad, InAndOutQuad>,
datasetChanges: DatasetChanges<InAndOutQuad>,
): boolean;
emit(eventName: QuadMatch, changes: DatasetChanges<InAndOutQuad>): boolean;
/**
* Returns an array listing the events for which the emitter has registered listeners. The values in the array are strings or Symbols.

@ -55,53 +55,44 @@ describe("WrapperSubscribableDataset", () => {
it("Alerts when a node is added", () => {
const callbackFunc = jest.fn();
subscribableDatastet.addListener(
namedNode("http://example.org/cartoons#Tom"),
[namedNode("http://example.org/cartoons#Tom"), null, null, null],
callbackFunc,
);
subscribableDatastet.add(tomColorQuad);
expect(callbackFunc).toBeCalledTimes(1);
expect(callbackFunc.mock.calls[0][0].size).toBe(3);
expect(callbackFunc.mock.calls[0][0].has(tomNameQuad)).toBe(true);
expect(callbackFunc.mock.calls[0][0].has(tomTypeQuad)).toBe(true);
expect(callbackFunc.mock.calls[0][0].has(tomColorQuad)).toBe(true);
expect(callbackFunc.mock.calls[0][1].added.size).toBe(1);
expect(callbackFunc.mock.calls[0][1].added.has(tomColorQuad)).toBe(true);
expect(callbackFunc.mock.calls[0][0].added.size).toBe(1);
expect(callbackFunc.mock.calls[0][0].added.has(tomColorQuad)).toBe(true);
});
it("Alerts when a node is removed", () => {
const callbackFunc = jest.fn();
subscribableDatastet.on(
namedNode("http://example.org/cartoons#Tom"),
[namedNode("http://example.org/cartoons#Tom"), null, null, null],
callbackFunc,
);
subscribableDatastet.delete(tomTypeQuad);
expect(callbackFunc).toBeCalledTimes(1);
expect(callbackFunc.mock.calls[0][0].size).toBe(1);
expect(callbackFunc.mock.calls[0][0].has(tomNameQuad)).toBe(true);
expect(callbackFunc.mock.calls[0][1].removed.size).toBe(1);
expect(callbackFunc.mock.calls[0][1].removed.has(tomTypeQuad)).toBe(true);
expect(callbackFunc.mock.calls[0][0].removed.size).toBe(1);
expect(callbackFunc.mock.calls[0][0].removed.has(tomTypeQuad)).toBe(true);
});
it("Alerts when multiple quads are added", () => {
const callbackFunc = jest.fn();
subscribableDatastet.on(
namedNode("http://example.org/cartoons#Licky"),
[namedNode("http://example.org/cartoons#Licky"), null, null, null],
callbackFunc,
);
subscribableDatastet.addAll([lickyNameQuad, lickyTypeQuad]);
expect(callbackFunc).toBeCalledTimes(1);
expect(callbackFunc.mock.calls[0][0].size).toBe(2);
expect(callbackFunc.mock.calls[0][0].has(lickyTypeQuad)).toBe(true);
expect(callbackFunc.mock.calls[0][0].has(lickyNameQuad)).toBe(true);
expect(callbackFunc.mock.calls[0][1].added.size).toBe(2);
expect(callbackFunc.mock.calls[0][1].added.has(lickyNameQuad)).toBe(true);
expect(callbackFunc.mock.calls[0][1].added.has(lickyTypeQuad)).toBe(true);
expect(callbackFunc.mock.calls[0][0].added.size).toBe(2);
expect(callbackFunc.mock.calls[0][0].added.has(lickyNameQuad)).toBe(true);
expect(callbackFunc.mock.calls[0][0].added.has(lickyTypeQuad)).toBe(true);
});
it("Alerts when bulk updated by only adding", () => {
const callbackFuncLicky = jest.fn();
subscribableDatastet.on(
namedNode("http://example.org/cartoons#Licky"),
[namedNode("http://example.org/cartoons#Licky"), null, null, null],
callbackFuncLicky,
);
subscribableDatastet.bulk({
@ -109,20 +100,17 @@ describe("WrapperSubscribableDataset", () => {
});
expect(callbackFuncLicky).toBeCalledTimes(1);
expect(
callbackFuncLicky.mock.calls[0][0].equals(createDataset([lickyTypeQuad])),
).toBe(true);
expect(
callbackFuncLicky.mock.calls[0][1].added.equals(
callbackFuncLicky.mock.calls[0][0].added.equals(
createDataset([lickyTypeQuad]),
),
).toBe(true);
expect(callbackFuncLicky.mock.calls[0][1].removed).toBe(undefined);
expect(callbackFuncLicky.mock.calls[0][0].removed).toBe(undefined);
});
it("Alerts when bulk updated by only removing", () => {
const callbackFuncTom = jest.fn();
subscribableDatastet.on(
namedNode("http://example.org/cartoons#Tom"),
[namedNode("http://example.org/cartoons#Tom"), null, null, null],
callbackFuncTom,
);
subscribableDatastet.bulk({
@ -130,25 +118,22 @@ describe("WrapperSubscribableDataset", () => {
});
expect(callbackFuncTom).toBeCalledTimes(1);
expect(
callbackFuncTom.mock.calls[0][0].equals(createDataset([tomNameQuad])),
).toBe(true);
expect(
callbackFuncTom.mock.calls[0][1].removed.equals(
callbackFuncTom.mock.calls[0][0].removed.equals(
createDataset([tomTypeQuad]),
),
).toBe(true);
expect(callbackFuncTom.mock.calls[0][1].added).toBe(undefined);
expect(callbackFuncTom.mock.calls[0][0].added).toBe(undefined);
});
it("Alerts when bulk updated", () => {
const callbackFuncLicky = jest.fn();
const callbackFuncTom = jest.fn();
subscribableDatastet.on(
namedNode("http://example.org/cartoons#Tom"),
[namedNode("http://example.org/cartoons#Tom"), null, null, null],
callbackFuncTom,
);
subscribableDatastet.on(
namedNode("http://example.org/cartoons#Licky"),
[namedNode("http://example.org/cartoons#Licky"), null, null, null],
callbackFuncLicky,
);
subscribableDatastet.bulk({
@ -158,28 +143,22 @@ describe("WrapperSubscribableDataset", () => {
expect(callbackFuncLicky).toBeCalledTimes(1);
expect(callbackFuncTom).toBeCalledTimes(1);
expect(
callbackFuncLicky.mock.calls[0][0].equals(createDataset([lickyTypeQuad])),
).toBe(true);
expect(
callbackFuncTom.mock.calls[0][0].equals(createDataset([tomNameQuad])),
).toBe(true);
expect(
callbackFuncLicky.mock.calls[0][1].added.equals(
callbackFuncLicky.mock.calls[0][0].added.equals(
createDataset([lickyTypeQuad]),
),
).toBe(true);
expect(callbackFuncLicky.mock.calls[0][1].removed).toBe(undefined);
expect(callbackFuncLicky.mock.calls[0][0].removed).toBe(undefined);
expect(
callbackFuncTom.mock.calls[0][1].removed.equals(
callbackFuncTom.mock.calls[0][0].removed.equals(
createDataset([tomTypeQuad]),
),
).toBe(true);
expect(callbackFuncTom.mock.calls[0][1].added).toBe(undefined);
expect(callbackFuncTom.mock.calls[0][0].added).toBe(undefined);
});
it("Alerts when the default graph is updated but not when another graph is", () => {
const callbackFunc = jest.fn();
subscribableDatastet.on(defaultGraph(), callbackFunc);
subscribableDatastet.on([null, null, null, defaultGraph()], callbackFunc);
subscribableDatastet.add(lickyNameQuad);
subscribableDatastet.add(
quad(
@ -191,15 +170,18 @@ describe("WrapperSubscribableDataset", () => {
);
expect(callbackFunc).toHaveBeenCalledTimes(1);
expect(
callbackFunc.mock.calls[0][0].equals(
createDataset([tomNameQuad, lickyNameQuad, tomTypeQuad]),
callbackFunc.mock.calls[0][0].added.equals(
createDataset([lickyNameQuad]),
),
).toBe(true);
});
it("Alerts when a named graph is updated", () => {
const callbackFunc = jest.fn();
subscribableDatastet.on(namedNode("https://coolgraphs.com"), callbackFunc);
subscribableDatastet.on(
[null, null, null, namedNode("https://coolgraphs.com")],
callbackFunc,
);
const quadWithGraph = quad(
namedNode("https://example.com/books#Dumbledoor"),
namedNode("http://example.org/books#name"),
@ -209,7 +191,9 @@ describe("WrapperSubscribableDataset", () => {
subscribableDatastet.add(quadWithGraph);
expect(callbackFunc).toHaveBeenCalledTimes(1);
expect(
callbackFunc.mock.calls[0][0].equals(createDataset([quadWithGraph])),
callbackFunc.mock.calls[0][0].added.equals(
createDataset([quadWithGraph]),
),
).toBe(true);
});
@ -226,7 +210,10 @@ describe("WrapperSubscribableDataset", () => {
);
subscribableDatastet.addAll([blankNodeQuadA, blankNodeQuadB]);
const callbackFunc = jest.fn();
subscribableDatastet.on(blankNodeQuadA.object as BlankNode, callbackFunc);
subscribableDatastet.on(
[blankNodeQuadA.object as BlankNode, null, null, null],
callbackFunc,
);
const blankNodeAdditionA = quad(
blankNodeQuadA.object as BlankNode,
namedNode("http://example.org/cartoons#StreetNumber"),
@ -241,46 +228,43 @@ describe("WrapperSubscribableDataset", () => {
subscribableDatastet.add(blankNodeAdditionB);
expect(callbackFunc).toBeCalledTimes(1);
expect(
callbackFunc.mock.calls[0][0].equals(
callbackFunc.mock.calls[0][0].added.equals(
createDataset([blankNodeQuadA, blankNodeAdditionA]),
),
).toBe(true);
});
it("Throws an error if you try to subscribe to an invalid node type", () => {
expect(() =>
// Used incorrect parameter for test
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
subscribableDatastet.on(literal("YOLO"), () => {
/* Do nothing */
}),
).toThrowError("Invalid term type for subscription");
});
it("Provides event names", () => {
const sampleBlankNode = blankNode();
subscribableDatastet.on(namedNode("https://example.com"), () => {
subscribableDatastet.on(
[namedNode("https://example.com"), null, null, null],
() => {
/* Do nothing */
});
subscribableDatastet.on(sampleBlankNode, () => {
},
);
subscribableDatastet.on([null, null, sampleBlankNode, null], () => {
/* Do nothing */
});
subscribableDatastet.on(defaultGraph(), () => {
subscribableDatastet.on([null, null, null, defaultGraph()], () => {
/* Do nothing */
});
const subscribableTerms = subscribableDatastet.eventNames();
expect(subscribableTerms.length).toBe(3);
expect(
subscribableTerms.some((curTerm) =>
curTerm.equals(namedNode("https://example.com")),
subscribableTerms.some(
(curQuadMatch) =>
curQuadMatch[0]?.equals(namedNode("https://example.com")),
),
).toBe(true);
expect(
subscribableTerms.some((curTerm) => curTerm.equals(sampleBlankNode)),
subscribableTerms.some(
(curQuadMatch) => curQuadMatch[2]?.equals(sampleBlankNode),
),
).toBe(true);
expect(
subscribableTerms.some((curTerm) => curTerm.equals(defaultGraph())),
subscribableTerms.some(
(curQuadMatch) => curQuadMatch[3]?.equals(defaultGraph()),
),
).toBe(true);
});
@ -308,16 +292,19 @@ describe("WrapperSubscribableDataset", () => {
/* Do Nothing */
};
subscribableDatastet.on(
namedNode("http://example.org/cartoons#Tom"),
[namedNode("http://example.org/cartoons#Tom"), null, null, null],
dummyListener1,
);
subscribableDatastet.on(
namedNode("http://example.org/cartoons#Licky"),
[namedNode("http://example.org/cartoons#Licky"), null, null, null],
dummyListener2,
);
const listeners = subscribableDatastet.listeners(
const listeners = subscribableDatastet.listeners([
namedNode("http://example.org/cartoons#Tom"),
);
null,
null,
null,
]);
expect(listeners.length).toBe(1);
expect(listeners[0]).toBe(dummyListener1);
});
@ -325,11 +312,11 @@ describe("WrapperSubscribableDataset", () => {
it("Unsubscribes from a listener", () => {
const callbackFunc = jest.fn();
subscribableDatastet.on(
namedNode("http://example.org/cartoons#Tom"),
[namedNode("http://example.org/cartoons#Tom"), null, null, null],
callbackFunc,
);
subscribableDatastet.off(
namedNode("http://example.org/cartoons#Tom"),
[namedNode("http://example.org/cartoons#Tom"), null, null, null],
callbackFunc,
);
subscribableDatastet.add(tomColorQuad);
@ -339,7 +326,7 @@ describe("WrapperSubscribableDataset", () => {
it("Runs 'once' without erroring", () => {
expect(
subscribableDatastet.once(
namedNode("http://example.org/cartoons#Tom"),
[namedNode("http://example.org/cartoons#Tom"), null, null, null],
() => {
/* Do Nothing */
},
@ -350,7 +337,7 @@ describe("WrapperSubscribableDataset", () => {
it("Runs 'prependListener' without erroring", () => {
expect(
subscribableDatastet.prependListener(
namedNode("http://example.org/cartoons#Tom"),
[namedNode("http://example.org/cartoons#Tom"), null, null, null],
() => {
/* Do Nothing */
},
@ -361,7 +348,7 @@ describe("WrapperSubscribableDataset", () => {
it("Runs the 'prependOnceListener' without erroring", () => {
expect(
subscribableDatastet.prependOnceListener(
namedNode("http://example.org/cartoons#Tom"),
[namedNode("http://example.org/cartoons#Tom"), null, null, null],
() => {
/* Do Nothing */
},
@ -377,25 +364,34 @@ describe("WrapperSubscribableDataset", () => {
/* Do Nothing */
};
subscribableDatastet.on(
namedNode("http://example.org/cartoons#Tom"),
[namedNode("http://example.org/cartoons#Tom"), null, null, null],
dummyListener1,
);
subscribableDatastet.on(
namedNode("http://example.org/cartoons#Licky"),
[namedNode("http://example.org/cartoons#Licky"), null, null, null],
dummyListener2,
);
subscribableDatastet.removeAllListeners(
subscribableDatastet.removeAllListeners([
namedNode("http://example.org/cartoons#Tom"),
);
null,
null,
null,
]);
expect(
subscribableDatastet.listenerCount(
subscribableDatastet.listenerCount([
namedNode("http://example.org/cartoons#Tom"),
),
null,
null,
null,
]),
).toBe(0);
expect(
subscribableDatastet.listenerCount(
subscribableDatastet.listenerCount([
namedNode("http://example.org/cartoons#Licky"),
),
null,
null,
null,
]),
).toBe(1);
});
@ -409,12 +405,15 @@ describe("WrapperSubscribableDataset", () => {
/* Do Nothing */
};
subscribableDatastet.on(
namedNode("http://example.org/cartoons#Tom"),
[namedNode("http://example.org/cartoons#Tom"), null, null, null],
dummyListener1,
);
const rawListeners = subscribableDatastet.rawListeners(
const rawListeners = subscribableDatastet.rawListeners([
namedNode("http://example.org/cartoons#Tom"),
);
null,
null,
null,
]);
expect(rawListeners.length).toBe(1);
expect(rawListeners[0]).toBe(dummyListener1);
});

Loading…
Cancel
Save