{"id":17875827,"url":"https://github.com/constraintautomaton/query-shape-detection","last_synced_at":"2025-04-03T00:23:42.670Z","repository":{"id":246742984,"uuid":"697189482","full_name":"constraintAutomaton/query-shape-detection","owner":"constraintAutomaton","description":null,"archived":false,"fork":false,"pushed_at":"2025-03-13T06:57:21.000Z","size":675,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-13T07:39:10.469Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/constraintAutomaton.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-27T08:29:48.000Z","updated_at":"2025-03-13T06:57:24.000Z","dependencies_parsed_at":"2024-07-21T06:43:33.886Z","dependency_job_id":"34e7cb5f-34e7-4931-a257-3e0649876919","html_url":"https://github.com/constraintAutomaton/query-shape-detection","commit_stats":null,"previous_names":["constraintautomaton/query-shape-detection"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/constraintAutomaton%2Fquery-shape-detection","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/constraintAutomaton%2Fquery-shape-detection/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/constraintAutomaton%2Fquery-shape-detection/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/constraintAutomaton%2Fquery-shape-detection/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/constraintAutomaton","download_url":"https://codeload.github.com/constraintAutomaton/query-shape-detection/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":246912866,"owners_count":20853938,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-10-28T11:25:28.749Z","updated_at":"2025-04-03T00:23:42.654Z","avatar_url":"https://github.com/constraintAutomaton.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Query Shape Detection\n[![npm version](https://badge.fury.io/js/query-shape-detection.svg)](https://www.npmjs.com/package/query-shape-detection)\n\n\nA nodejs library to calculate the subsumption between [SPARQL queries](https://www.w3.org/TR/sparql11-query/) and [RDF data shapes](https://www.w3.org/groups/wg/data-shapes/) at the star pattern level.\n\n## Installation\n```sh\nyarn add query-shape-detection\n```\n\n## Dependencies\nNode v20 or higher\n\n## Example code\n\n```ts\nimport {\n  ContainmentResult,\n  generateQuery,\n  shapeFromQuads,\n  solveShapeQueryContainment,\n} from 'query-shape-detection';\n\nimport type {\n  IResult,\n  IQuery,\n  IShape,\n} from 'query-shape-detection';\nimport { translate } from 'sparqlalgebrajs';\nimport * as ShexParser from '@shexjs/parser';\nimport { JsonLdParser } from 'jsonld-streaming-parser';\nimport * as SHEX_CONTEXT from './shex_context.json'; // you need to provide this JSON from https://www.w3.org/ns/shex.jsonld\n\nconst rawQuery = `\nPREFIX rdf: \u003chttp://www.w3.org/1999/02/22-rdf-syntax-ns#\u003e\n      PREFIX snvoc: \u003chttp://localhost:3000/www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/\u003e\n      SELECT ?personId ?personFirstName ?personLastName ?commentCreationDate ?commentId ?commentContent WHERE {\n        VALUES ?type {\n          snvoc:Comment\n          snvoc:Post\n        }\n        \u003chttp://localhost:3000/pods/00000002199023256816/profile/card#me\u003e rdf:type snvoc:Person.\n        ?message snvoc:hasCreator \u003chttp://localhost:3000/pods/00000002199023256816/profile/card#me\u003e;\n          rdf:type ?type.\n        ?comment rdf:type snvoc:Comment;\n          snvoc:replyOf ?message;\n          snvoc:creationDate ?commentCreationDate;\n          snvoc:id ?commentId;\n          snvoc:content ?commentContent;\n          snvoc:hasCreator ?person.\n        ?person snvoc:id ?personId;\n          snvoc:firstName ?personFirstName;\n          snvoc:lastName ?personLastName.\n      }\n      ORDER BY DESC (?commentCreationDate) (?commentId)\n      LIMIT 20\n`;\n\nconst query = generateQuery(translate(rawQuery));\n\n// The shape may come already as an array of quad or a quad stream. I am presenting a contained example.\nconst shapeShexc = `\nPREFIX xsd: \u003chttp://www.w3.org/2001/XMLSchema#\u003e\nPREFIX ldbcvoc: \u003chttp://localhost:3000/www.ldbc.eu/ldbc_socialnet/1.0/vocabulary/\u003e\nPREFIX schema: \u003chttp://www.w3.org/2000/01/rdf-schema#\u003e\n\n\u003chttp://localhost:3000/pods/00000000000000000065/comments_shape#Comment\u003e CLOSED {\n    a ldbcvoc:Comment?;\n    ldbcvoc:id xsd:long ;\n    ldbcvoc:creationDate xsd:dateTime ;\n    ldbcvoc:locationIP xsd:string  ;\n    ldbcvoc:browserUsed xsd:string ;\n    ldbcvoc:content xsd:string?;\n    ldbcvoc:lenght xsd:int ;\n    ldbcvoc:hasTag IRI *;\n    (\n        ldbcvoc:replyOf @\u003chttp://localhost:3000/pods/00000000000000000065/comments_shape#Post\u003e *;\n        |\n        ldbcvoc:replyOf @\u003chttp://localhost:3000/pods/00000000000000000065/comments_shape#Comment\u003e *;\n    );\n    ldbcvoc:isLocatedIn IRI ;\n    ldbcvoc:hasCreator @\u003chttp://localhost:3000/pods/00000000000000000065/comments_shape#Profile\u003e ;\n}\n`;\nconst shapeIRI = \"http://localhost:3000/pods/00000000000000000065/comments_shape#Comment\";\nconst shexParser = ShexParser.construct(shapeIRI);\n\nconst shapeJSONLD = shexParser.parse(shapeShexc);\nconst stringShapeJsonLD = JSON.stringify(shapeJSONLD);\nconst quads: RDF.Quad[] = [];\n\nconst shapeQuadPromise = new Promise((resolve, reject) =\u003e {\n      // The jsonLD is not valid without the context field and the library doesn't include it\n      // because a ShExJ MAY contain a @context field\n      // https://shex.io/shex-semantics/#shexj\n      const jsonldParser = new JsonLdParser({\n        streamingProfile: false,\n        context: SHEX_CONTEXT // you have to provide a JSON of the context,\n        skipContextValidation: true,\n      });\n      jsonldParser\n        .on('data', async(quad: RDF.Quad) =\u003e {\n          quads.push(quad);\n        })\n        .on('error',(error: any) =\u003e {\n          reject(error);\n        })\n        .on('end', async() =\u003e {\n          resolve(quads);\n        });\n\n      jsonldParser.write(stringShapeJsonLD);\n      jsonldParser.end();\n    });\n// shapeQuadPromise can be a quad stream or a array of quad \nconst commentShape = await shapeFromQuads(await shapeQuadPromise, shapeIRI);\n\n\nconst resultsReport: IResult = solveShapeQueryContainment({\n        query: query,\n        shapes,\n      });\n\n// resultsReport provide an object with information about the containement.\n// The containement is calculated by star patterns.\n\n\n/**\nexport interface IResult {\n  // URL from the object of triples (s, p, o) that are not bound by a shape\n  conditionalLink: IConditionalLink[];\n  // The documents associated with a shape that can be followed\n  visitShapeBoundedResource: Map\u003cShapeName, boolean\u003e;\n  // The type of containment of each star patterns with there associated shapes\n  // This is the general information about the containment\n  starPatternsContainment: Map\u003cStarPatternName, IContainmentResult\u003e;\n}\n*/\n\n/**\nexport type IContainmentResult = Readonly\u003c{\n  // The type of containement\n  result: ContainmentResult;\n  \n   // The shape iri associated with the containement\n   // Will be undefined if the the star pattern has no alignment with any shape\n   // The size of the array will be greater than one if it is contained by dependence\n  target?: string[];\n  \n   // If the result is an alignment then we record the shape\n   // that have a binding with RDF class\n  bindingByRdfClass?: string[];\n}\u003e;\n\nexport enum ContainmentResult {\n  // Is contained\n  CONTAIN,\n  // Has at least one binding\n  ALIGNED,\n  // Is a dependency of a contained star pattern\n  DEPEND,\n  // Has no binding\n  REJECTED,\n}\n \n*/\n```\n\n## Current limitation\n- Support only ShEx\n- Known bug for some complex property path\n- No support for MINUS statement\n- No support for filter expression\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconstraintautomaton%2Fquery-shape-detection","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fconstraintautomaton%2Fquery-shape-detection","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fconstraintautomaton%2Fquery-shape-detection/lists"}