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

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

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

@ -1,5 +1,5 @@
import { EventEmitter } from "events"; import { EventEmitter } from "events";
import { namedNode, blankNode, defaultGraph } from "@ldo/rdf-utils"; import { quadMatchToString, stringToQuadMatch } from "@ldo/rdf-utils";
import type { import type {
DatasetChanges, DatasetChanges,
Dataset, Dataset,
@ -7,9 +7,12 @@ import type {
Stream, Stream,
Term, Term,
DatasetFactory, DatasetFactory,
QuadMatch,
SubjectNode,
PredicateNode,
ObjectNode,
} from "@ldo/rdf-utils"; } from "@ldo/rdf-utils";
import type { import type {
SubscribableTerms,
nodeEventListener, nodeEventListener,
SubscribableDataset, SubscribableDataset,
TransactionalDataset, TransactionalDataset,
@ -36,6 +39,10 @@ export default class WrapperSubscribableDataset<
* The underlying event emitter * The underlying event emitter
*/ */
private eventEmitter: EventEmitter; 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.datasetFactory = datasetFactory;
this.dataset = initialDataset || this.datasetFactory.dataset(); this.dataset = initialDataset || this.datasetFactory.dataset();
this.eventEmitter = new EventEmitter(); this.eventEmitter = new EventEmitter();
this.eventNamesSet = new Set();
} }
/** /**
@ -345,42 +353,6 @@ export default class WrapperSubscribableDataset<
* EVENTEMITTER METHODS * 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 * Triggers all subscriptions based on an updated quads
@ -389,82 +361,62 @@ export default class WrapperSubscribableDataset<
private triggerSubscriptionForQuads( private triggerSubscriptionForQuads(
changed: DatasetChanges<InAndOutQuad>, changed: DatasetChanges<InAndOutQuad>,
): void { ): void {
const triggeredTermsMap: Record<string, SubscribableTerms> = {}; // A mapping of serialized QuadMatches to the changed quads
const forEachQuad = (quad: BaseQuad) => { const matchingDatasetChanges: Record<
const subject = quad.subject; string,
const predicate = quad.predicate; DatasetChanges<InAndOutQuad>
const object = quad.object; > = {};
const graph = quad.graph;
const quadTerms = [subject, predicate, object, graph]; // Population MatchingDatasetChanges
quadTerms.forEach((quadTerm) => { const populateMatchingDatasetChanges = (
if (this.SUBSCRIBABLE_TERMS.includes(quadTerm.termType)) { changeType: "added" | "removed",
triggeredTermsMap[`${quadTerm.termType}${quadTerm.value}`] = ) => {
quadTerm as SubscribableTerms; 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); populateMatchingDatasetChanges("added");
changed.removed?.forEach(forEachQuad); populateMatchingDatasetChanges("removed");
const triggeredTerms = Object.values(triggeredTermsMap);
triggeredTerms.forEach((triggeredTerm) => { // Alert all listeners
this.triggerSubscriptionForNode(triggeredTerm, changed); Object.entries(matchingDatasetChanges).forEach(
}); ([quadMatchString, changes]) => {
} this.eventEmitter.emit(quadMatchString, changes);
},
/** );
* 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);
}
} }
/** /**
@ -474,7 +426,7 @@ export default class WrapperSubscribableDataset<
* @returns * @returns
*/ */
public addListener( public addListener(
eventName: SubscribableTerms, eventName: QuadMatch,
listener: nodeEventListener<InAndOutQuad>, listener: nodeEventListener<InAndOutQuad>,
): this { ): this {
return this.on(eventName, listener); return this.on(eventName, listener);
@ -488,24 +440,19 @@ export default class WrapperSubscribableDataset<
* @returns true if the event had listeners, false otherwise. * @returns true if the event had listeners, false otherwise.
*/ */
public emit( public emit(
eventName: SubscribableTerms, eventName: QuadMatch,
dataset: Dataset<InAndOutQuad, InAndOutQuad>, changes: DatasetChanges<InAndOutQuad>,
datasetChanges: DatasetChanges<InAndOutQuad>,
): boolean { ): boolean {
return this.eventEmitter.emit( return this.eventEmitter.emit(quadMatchToString(eventName), changes);
this.getKeyFromNode(eventName),
dataset,
datasetChanges,
);
} }
/** /**
* Returns an array listing the events for which the emitter has registered listeners. The values in the array are strings or Symbols. * 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 return this.eventEmitter
.eventNames() .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. * Returns the number of listeners listening to the event named eventName.
*/ */
public listenerCount(eventName: SubscribableTerms): number { public listenerCount(eventName: QuadMatch): number {
return this.eventEmitter.listenerCount(this.getKeyFromNode(eventName)); return this.eventEmitter.listenerCount(quadMatchToString(eventName));
} }
/** /**
* Returns a copy of the array of listeners for the event named eventName. * Returns a copy of the array of listeners for the event named eventName.
*/ */
public listeners( public listeners(eventName: QuadMatch): nodeEventListener<InAndOutQuad>[] {
eventName: SubscribableTerms,
): nodeEventListener<InAndOutQuad>[] {
return this.eventEmitter.listeners( return this.eventEmitter.listeners(
this.getKeyFromNode(eventName), quadMatchToString(eventName),
) as nodeEventListener<InAndOutQuad>[]; ) as nodeEventListener<InAndOutQuad>[];
} }
@ -537,7 +482,7 @@ export default class WrapperSubscribableDataset<
* Alias for emitter.removeListener() * Alias for emitter.removeListener()
*/ */
public off( public off(
eventName: SubscribableTerms, eventName: QuadMatch,
listener: nodeEventListener<InAndOutQuad>, listener: nodeEventListener<InAndOutQuad>,
): void { ): void {
this.removeListener(eventName, listener); 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. * 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( public on(
eventName: SubscribableTerms, eventName: QuadMatch,
listener: nodeEventListener<InAndOutQuad>, listener: nodeEventListener<InAndOutQuad>,
): this { ): this {
this.eventEmitter.on(this.getKeyFromNode(eventName), listener); this.eventEmitter.on(quadMatchToString(eventName), listener);
return this; 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. * 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( public once(
eventName: SubscribableTerms, eventName: QuadMatch,
listener: nodeEventListener<InAndOutQuad>, listener: nodeEventListener<InAndOutQuad>,
): this { ): this {
this.eventEmitter.once(this.getKeyFromNode(eventName), listener); this.eventEmitter.once(quadMatchToString(eventName), listener);
return this; 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. * 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( public prependListener(
eventName: SubscribableTerms, eventName: QuadMatch,
listener: nodeEventListener<InAndOutQuad>, listener: nodeEventListener<InAndOutQuad>,
): this { ): this {
this.eventEmitter.prependListener(this.getKeyFromNode(eventName), listener); this.eventEmitter.prependListener(quadMatchToString(eventName), listener);
return this; 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. * 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( public prependOnceListener(
eventName: SubscribableTerms, eventName: QuadMatch,
listener: nodeEventListener<InAndOutQuad>, listener: nodeEventListener<InAndOutQuad>,
): this { ): this {
this.eventEmitter.prependOnceListener( this.eventEmitter.prependOnceListener(
this.getKeyFromNode(eventName), quadMatchToString(eventName),
listener, listener,
); );
return this; return this;
@ -593,8 +538,8 @@ export default class WrapperSubscribableDataset<
/** /**
* Removes all listeners, or those of the specified eventName. * Removes all listeners, or those of the specified eventName.
*/ */
public removeAllListeners(eventName: SubscribableTerms): this { public removeAllListeners(eventName: QuadMatch): this {
this.eventEmitter.removeAllListeners(this.getKeyFromNode(eventName)); this.eventEmitter.removeAllListeners(quadMatchToString(eventName));
return this; return this;
} }
@ -602,10 +547,10 @@ export default class WrapperSubscribableDataset<
* Removes the specified listener from the listener array for the event named eventName. * Removes the specified listener from the listener array for the event named eventName.
*/ */
public removeListener( public removeListener(
eventName: SubscribableTerms, eventName: QuadMatch,
listener: nodeEventListener<InAndOutQuad>, listener: nodeEventListener<InAndOutQuad>,
): this { ): this {
this.eventEmitter.removeListener(this.getKeyFromNode(eventName), listener); this.eventEmitter.removeListener(quadMatchToString(eventName), listener);
return this; 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()). * Returns a copy of the array of listeners for the event named eventName, including any wrappers (such as those created by .once()).
*/ */
public rawListeners( public rawListeners(eventName: QuadMatch): nodeEventListener<InAndOutQuad>[] {
eventName: SubscribableTerms,
): nodeEventListener<InAndOutQuad>[] {
return this.eventEmitter.rawListeners( return this.eventEmitter.rawListeners(
this.getKeyFromNode(eventName), quadMatchToString(eventName),
) as nodeEventListener[]; ) as nodeEventListener[];
} }
@ -638,9 +581,6 @@ export default class WrapperSubscribableDataset<
* Returns a transactional dataset that will update this dataset when its transaction is committed. * Returns a transactional dataset that will update this dataset when its transaction is committed.
*/ */
public startTransaction(): TransactionalDataset<InAndOutQuad> { public startTransaction(): TransactionalDataset<InAndOutQuad> {
// Type problem again
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
return new ProxyTransactionalDataset(this, this.datasetFactory); return new ProxyTransactionalDataset(this, this.datasetFactory);
} }
} }

@ -9,7 +9,6 @@ import type {
* An event listeners for nodes * An event listeners for nodes
*/ */
export type nodeEventListener<InAndOutQuad extends BaseQuad = BaseQuad> = ( export type nodeEventListener<InAndOutQuad extends BaseQuad = BaseQuad> = (
dataset: Dataset<InAndOutQuad, InAndOutQuad>,
changes: DatasetChanges<InAndOutQuad>, changes: DatasetChanges<InAndOutQuad>,
) => void; ) => 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. * 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 eventName
* @param dataset * @param changes
* @param datasetChanges
* @returns true if the event had listeners, false otherwise. * @returns true if the event had listeners, false otherwise.
*/ */
emit( emit(eventName: QuadMatch, changes: DatasetChanges<InAndOutQuad>): boolean;
eventName: QuadMatch,
dataset: Dataset<InAndOutQuad, InAndOutQuad>,
datasetChanges: 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. * 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", () => { it("Alerts when a node is added", () => {
const callbackFunc = jest.fn(); const callbackFunc = jest.fn();
subscribableDatastet.addListener( subscribableDatastet.addListener(
namedNode("http://example.org/cartoons#Tom"), [namedNode("http://example.org/cartoons#Tom"), null, null, null],
callbackFunc, callbackFunc,
); );
subscribableDatastet.add(tomColorQuad); subscribableDatastet.add(tomColorQuad);
expect(callbackFunc).toBeCalledTimes(1); expect(callbackFunc).toBeCalledTimes(1);
expect(callbackFunc.mock.calls[0][0].size).toBe(3); expect(callbackFunc.mock.calls[0][0].added.size).toBe(1);
expect(callbackFunc.mock.calls[0][0].has(tomNameQuad)).toBe(true); expect(callbackFunc.mock.calls[0][0].added.has(tomColorQuad)).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);
}); });
it("Alerts when a node is removed", () => { it("Alerts when a node is removed", () => {
const callbackFunc = jest.fn(); const callbackFunc = jest.fn();
subscribableDatastet.on( subscribableDatastet.on(
namedNode("http://example.org/cartoons#Tom"), [namedNode("http://example.org/cartoons#Tom"), null, null, null],
callbackFunc, callbackFunc,
); );
subscribableDatastet.delete(tomTypeQuad); subscribableDatastet.delete(tomTypeQuad);
expect(callbackFunc).toBeCalledTimes(1); expect(callbackFunc).toBeCalledTimes(1);
expect(callbackFunc.mock.calls[0][0].size).toBe(1); expect(callbackFunc.mock.calls[0][0].removed.size).toBe(1);
expect(callbackFunc.mock.calls[0][0].has(tomNameQuad)).toBe(true); expect(callbackFunc.mock.calls[0][0].removed.has(tomTypeQuad)).toBe(true);
expect(callbackFunc.mock.calls[0][1].removed.size).toBe(1);
expect(callbackFunc.mock.calls[0][1].removed.has(tomTypeQuad)).toBe(true);
}); });
it("Alerts when multiple quads are added", () => { it("Alerts when multiple quads are added", () => {
const callbackFunc = jest.fn(); const callbackFunc = jest.fn();
subscribableDatastet.on( subscribableDatastet.on(
namedNode("http://example.org/cartoons#Licky"), [namedNode("http://example.org/cartoons#Licky"), null, null, null],
callbackFunc, callbackFunc,
); );
subscribableDatastet.addAll([lickyNameQuad, lickyTypeQuad]); subscribableDatastet.addAll([lickyNameQuad, lickyTypeQuad]);
expect(callbackFunc).toBeCalledTimes(1); expect(callbackFunc).toBeCalledTimes(1);
expect(callbackFunc.mock.calls[0][0].size).toBe(2); expect(callbackFunc.mock.calls[0][0].added.size).toBe(2);
expect(callbackFunc.mock.calls[0][0].has(lickyTypeQuad)).toBe(true); expect(callbackFunc.mock.calls[0][0].added.has(lickyNameQuad)).toBe(true);
expect(callbackFunc.mock.calls[0][0].has(lickyNameQuad)).toBe(true); expect(callbackFunc.mock.calls[0][0].added.has(lickyTypeQuad)).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);
}); });
it("Alerts when bulk updated by only adding", () => { it("Alerts when bulk updated by only adding", () => {
const callbackFuncLicky = jest.fn(); const callbackFuncLicky = jest.fn();
subscribableDatastet.on( subscribableDatastet.on(
namedNode("http://example.org/cartoons#Licky"), [namedNode("http://example.org/cartoons#Licky"), null, null, null],
callbackFuncLicky, callbackFuncLicky,
); );
subscribableDatastet.bulk({ subscribableDatastet.bulk({
@ -109,20 +100,17 @@ describe("WrapperSubscribableDataset", () => {
}); });
expect(callbackFuncLicky).toBeCalledTimes(1); expect(callbackFuncLicky).toBeCalledTimes(1);
expect( expect(
callbackFuncLicky.mock.calls[0][0].equals(createDataset([lickyTypeQuad])), callbackFuncLicky.mock.calls[0][0].added.equals(
).toBe(true);
expect(
callbackFuncLicky.mock.calls[0][1].added.equals(
createDataset([lickyTypeQuad]), createDataset([lickyTypeQuad]),
), ),
).toBe(true); ).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", () => { it("Alerts when bulk updated by only removing", () => {
const callbackFuncTom = jest.fn(); const callbackFuncTom = jest.fn();
subscribableDatastet.on( subscribableDatastet.on(
namedNode("http://example.org/cartoons#Tom"), [namedNode("http://example.org/cartoons#Tom"), null, null, null],
callbackFuncTom, callbackFuncTom,
); );
subscribableDatastet.bulk({ subscribableDatastet.bulk({
@ -130,25 +118,22 @@ describe("WrapperSubscribableDataset", () => {
}); });
expect(callbackFuncTom).toBeCalledTimes(1); expect(callbackFuncTom).toBeCalledTimes(1);
expect( expect(
callbackFuncTom.mock.calls[0][0].equals(createDataset([tomNameQuad])), callbackFuncTom.mock.calls[0][0].removed.equals(
).toBe(true);
expect(
callbackFuncTom.mock.calls[0][1].removed.equals(
createDataset([tomTypeQuad]), createDataset([tomTypeQuad]),
), ),
).toBe(true); ).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", () => { it("Alerts when bulk updated", () => {
const callbackFuncLicky = jest.fn(); const callbackFuncLicky = jest.fn();
const callbackFuncTom = jest.fn(); const callbackFuncTom = jest.fn();
subscribableDatastet.on( subscribableDatastet.on(
namedNode("http://example.org/cartoons#Tom"), [namedNode("http://example.org/cartoons#Tom"), null, null, null],
callbackFuncTom, callbackFuncTom,
); );
subscribableDatastet.on( subscribableDatastet.on(
namedNode("http://example.org/cartoons#Licky"), [namedNode("http://example.org/cartoons#Licky"), null, null, null],
callbackFuncLicky, callbackFuncLicky,
); );
subscribableDatastet.bulk({ subscribableDatastet.bulk({
@ -158,28 +143,22 @@ describe("WrapperSubscribableDataset", () => {
expect(callbackFuncLicky).toBeCalledTimes(1); expect(callbackFuncLicky).toBeCalledTimes(1);
expect(callbackFuncTom).toBeCalledTimes(1); expect(callbackFuncTom).toBeCalledTimes(1);
expect( expect(
callbackFuncLicky.mock.calls[0][0].equals(createDataset([lickyTypeQuad])), callbackFuncLicky.mock.calls[0][0].added.equals(
).toBe(true);
expect(
callbackFuncTom.mock.calls[0][0].equals(createDataset([tomNameQuad])),
).toBe(true);
expect(
callbackFuncLicky.mock.calls[0][1].added.equals(
createDataset([lickyTypeQuad]), createDataset([lickyTypeQuad]),
), ),
).toBe(true); ).toBe(true);
expect(callbackFuncLicky.mock.calls[0][1].removed).toBe(undefined); expect(callbackFuncLicky.mock.calls[0][0].removed).toBe(undefined);
expect( expect(
callbackFuncTom.mock.calls[0][1].removed.equals( callbackFuncTom.mock.calls[0][0].removed.equals(
createDataset([tomTypeQuad]), createDataset([tomTypeQuad]),
), ),
).toBe(true); ).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", () => { it("Alerts when the default graph is updated but not when another graph is", () => {
const callbackFunc = jest.fn(); const callbackFunc = jest.fn();
subscribableDatastet.on(defaultGraph(), callbackFunc); subscribableDatastet.on([null, null, null, defaultGraph()], callbackFunc);
subscribableDatastet.add(lickyNameQuad); subscribableDatastet.add(lickyNameQuad);
subscribableDatastet.add( subscribableDatastet.add(
quad( quad(
@ -191,15 +170,18 @@ describe("WrapperSubscribableDataset", () => {
); );
expect(callbackFunc).toHaveBeenCalledTimes(1); expect(callbackFunc).toHaveBeenCalledTimes(1);
expect( expect(
callbackFunc.mock.calls[0][0].equals( callbackFunc.mock.calls[0][0].added.equals(
createDataset([tomNameQuad, lickyNameQuad, tomTypeQuad]), createDataset([lickyNameQuad]),
), ),
).toBe(true); ).toBe(true);
}); });
it("Alerts when a named graph is updated", () => { it("Alerts when a named graph is updated", () => {
const callbackFunc = jest.fn(); const callbackFunc = jest.fn();
subscribableDatastet.on(namedNode("https://coolgraphs.com"), callbackFunc); subscribableDatastet.on(
[null, null, null, namedNode("https://coolgraphs.com")],
callbackFunc,
);
const quadWithGraph = quad( const quadWithGraph = quad(
namedNode("https://example.com/books#Dumbledoor"), namedNode("https://example.com/books#Dumbledoor"),
namedNode("http://example.org/books#name"), namedNode("http://example.org/books#name"),
@ -209,7 +191,9 @@ describe("WrapperSubscribableDataset", () => {
subscribableDatastet.add(quadWithGraph); subscribableDatastet.add(quadWithGraph);
expect(callbackFunc).toHaveBeenCalledTimes(1); expect(callbackFunc).toHaveBeenCalledTimes(1);
expect( expect(
callbackFunc.mock.calls[0][0].equals(createDataset([quadWithGraph])), callbackFunc.mock.calls[0][0].added.equals(
createDataset([quadWithGraph]),
),
).toBe(true); ).toBe(true);
}); });
@ -226,7 +210,10 @@ describe("WrapperSubscribableDataset", () => {
); );
subscribableDatastet.addAll([blankNodeQuadA, blankNodeQuadB]); subscribableDatastet.addAll([blankNodeQuadA, blankNodeQuadB]);
const callbackFunc = jest.fn(); const callbackFunc = jest.fn();
subscribableDatastet.on(blankNodeQuadA.object as BlankNode, callbackFunc); subscribableDatastet.on(
[blankNodeQuadA.object as BlankNode, null, null, null],
callbackFunc,
);
const blankNodeAdditionA = quad( const blankNodeAdditionA = quad(
blankNodeQuadA.object as BlankNode, blankNodeQuadA.object as BlankNode,
namedNode("http://example.org/cartoons#StreetNumber"), namedNode("http://example.org/cartoons#StreetNumber"),
@ -241,46 +228,43 @@ describe("WrapperSubscribableDataset", () => {
subscribableDatastet.add(blankNodeAdditionB); subscribableDatastet.add(blankNodeAdditionB);
expect(callbackFunc).toBeCalledTimes(1); expect(callbackFunc).toBeCalledTimes(1);
expect( expect(
callbackFunc.mock.calls[0][0].equals( callbackFunc.mock.calls[0][0].added.equals(
createDataset([blankNodeQuadA, blankNodeAdditionA]), createDataset([blankNodeQuadA, blankNodeAdditionA]),
), ),
).toBe(true); ).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", () => { it("Provides event names", () => {
const sampleBlankNode = blankNode(); const sampleBlankNode = blankNode();
subscribableDatastet.on(namedNode("https://example.com"), () => { subscribableDatastet.on(
/* Do nothing */ [namedNode("https://example.com"), null, null, null],
}); () => {
subscribableDatastet.on(sampleBlankNode, () => { /* Do nothing */
},
);
subscribableDatastet.on([null, null, sampleBlankNode, null], () => {
/* Do nothing */ /* Do nothing */
}); });
subscribableDatastet.on(defaultGraph(), () => { subscribableDatastet.on([null, null, null, defaultGraph()], () => {
/* Do nothing */ /* Do nothing */
}); });
const subscribableTerms = subscribableDatastet.eventNames(); const subscribableTerms = subscribableDatastet.eventNames();
expect(subscribableTerms.length).toBe(3); expect(subscribableTerms.length).toBe(3);
expect( expect(
subscribableTerms.some((curTerm) => subscribableTerms.some(
curTerm.equals(namedNode("https://example.com")), (curQuadMatch) =>
curQuadMatch[0]?.equals(namedNode("https://example.com")),
), ),
).toBe(true); ).toBe(true);
expect( expect(
subscribableTerms.some((curTerm) => curTerm.equals(sampleBlankNode)), subscribableTerms.some(
(curQuadMatch) => curQuadMatch[2]?.equals(sampleBlankNode),
),
).toBe(true); ).toBe(true);
expect( expect(
subscribableTerms.some((curTerm) => curTerm.equals(defaultGraph())), subscribableTerms.some(
(curQuadMatch) => curQuadMatch[3]?.equals(defaultGraph()),
),
).toBe(true); ).toBe(true);
}); });
@ -308,16 +292,19 @@ describe("WrapperSubscribableDataset", () => {
/* Do Nothing */ /* Do Nothing */
}; };
subscribableDatastet.on( subscribableDatastet.on(
namedNode("http://example.org/cartoons#Tom"), [namedNode("http://example.org/cartoons#Tom"), null, null, null],
dummyListener1, dummyListener1,
); );
subscribableDatastet.on( subscribableDatastet.on(
namedNode("http://example.org/cartoons#Licky"), [namedNode("http://example.org/cartoons#Licky"), null, null, null],
dummyListener2, dummyListener2,
); );
const listeners = subscribableDatastet.listeners( const listeners = subscribableDatastet.listeners([
namedNode("http://example.org/cartoons#Tom"), namedNode("http://example.org/cartoons#Tom"),
); null,
null,
null,
]);
expect(listeners.length).toBe(1); expect(listeners.length).toBe(1);
expect(listeners[0]).toBe(dummyListener1); expect(listeners[0]).toBe(dummyListener1);
}); });
@ -325,11 +312,11 @@ describe("WrapperSubscribableDataset", () => {
it("Unsubscribes from a listener", () => { it("Unsubscribes from a listener", () => {
const callbackFunc = jest.fn(); const callbackFunc = jest.fn();
subscribableDatastet.on( subscribableDatastet.on(
namedNode("http://example.org/cartoons#Tom"), [namedNode("http://example.org/cartoons#Tom"), null, null, null],
callbackFunc, callbackFunc,
); );
subscribableDatastet.off( subscribableDatastet.off(
namedNode("http://example.org/cartoons#Tom"), [namedNode("http://example.org/cartoons#Tom"), null, null, null],
callbackFunc, callbackFunc,
); );
subscribableDatastet.add(tomColorQuad); subscribableDatastet.add(tomColorQuad);
@ -339,7 +326,7 @@ describe("WrapperSubscribableDataset", () => {
it("Runs 'once' without erroring", () => { it("Runs 'once' without erroring", () => {
expect( expect(
subscribableDatastet.once( subscribableDatastet.once(
namedNode("http://example.org/cartoons#Tom"), [namedNode("http://example.org/cartoons#Tom"), null, null, null],
() => { () => {
/* Do Nothing */ /* Do Nothing */
}, },
@ -350,7 +337,7 @@ describe("WrapperSubscribableDataset", () => {
it("Runs 'prependListener' without erroring", () => { it("Runs 'prependListener' without erroring", () => {
expect( expect(
subscribableDatastet.prependListener( subscribableDatastet.prependListener(
namedNode("http://example.org/cartoons#Tom"), [namedNode("http://example.org/cartoons#Tom"), null, null, null],
() => { () => {
/* Do Nothing */ /* Do Nothing */
}, },
@ -361,7 +348,7 @@ describe("WrapperSubscribableDataset", () => {
it("Runs the 'prependOnceListener' without erroring", () => { it("Runs the 'prependOnceListener' without erroring", () => {
expect( expect(
subscribableDatastet.prependOnceListener( subscribableDatastet.prependOnceListener(
namedNode("http://example.org/cartoons#Tom"), [namedNode("http://example.org/cartoons#Tom"), null, null, null],
() => { () => {
/* Do Nothing */ /* Do Nothing */
}, },
@ -377,25 +364,34 @@ describe("WrapperSubscribableDataset", () => {
/* Do Nothing */ /* Do Nothing */
}; };
subscribableDatastet.on( subscribableDatastet.on(
namedNode("http://example.org/cartoons#Tom"), [namedNode("http://example.org/cartoons#Tom"), null, null, null],
dummyListener1, dummyListener1,
); );
subscribableDatastet.on( subscribableDatastet.on(
namedNode("http://example.org/cartoons#Licky"), [namedNode("http://example.org/cartoons#Licky"), null, null, null],
dummyListener2, dummyListener2,
); );
subscribableDatastet.removeAllListeners( subscribableDatastet.removeAllListeners([
namedNode("http://example.org/cartoons#Tom"), namedNode("http://example.org/cartoons#Tom"),
); null,
null,
null,
]);
expect( expect(
subscribableDatastet.listenerCount( subscribableDatastet.listenerCount([
namedNode("http://example.org/cartoons#Tom"), namedNode("http://example.org/cartoons#Tom"),
), null,
null,
null,
]),
).toBe(0); ).toBe(0);
expect( expect(
subscribableDatastet.listenerCount( subscribableDatastet.listenerCount([
namedNode("http://example.org/cartoons#Licky"), namedNode("http://example.org/cartoons#Licky"),
), null,
null,
null,
]),
).toBe(1); ).toBe(1);
}); });
@ -409,12 +405,15 @@ describe("WrapperSubscribableDataset", () => {
/* Do Nothing */ /* Do Nothing */
}; };
subscribableDatastet.on( subscribableDatastet.on(
namedNode("http://example.org/cartoons#Tom"), [namedNode("http://example.org/cartoons#Tom"), null, null, null],
dummyListener1, dummyListener1,
); );
const rawListeners = subscribableDatastet.rawListeners( const rawListeners = subscribableDatastet.rawListeners([
namedNode("http://example.org/cartoons#Tom"), namedNode("http://example.org/cartoons#Tom"),
); null,
null,
null,
]);
expect(rawListeners.length).toBe(1); expect(rawListeners.length).toBe(1);
expect(rawListeners[0]).toBe(dummyListener1); expect(rawListeners[0]).toBe(dummyListener1);
}); });

Loading…
Cancel
Save