shex.js icon indicating copy to clipboard operation
shex.js copied to clipboard

Object is not a constructor when trying to instantiate a ShExVisitor

Open constraintAutomaton opened this issue 4 months ago • 3 comments

What broken?

shexjs in node

Version

@shexjs/[email protected]

What happened (e.g., it crashed)?

When trying to run the example for shex visitor, I am getting this error. It also seems like the typing is not consistent with the implementation, for instance ShExVisitor is a class in the implementation whereas it is a function in the typing

// export function index (schema: ShExJ.Schema): SchemaIndex
export function ShExVisitor (... x: any): ShExVisitorIface

Example from docs

console.log(JSON.stringify(new (require("@shexjs/visitor"))()
  .visitSchema(
    {
      "type": "Schema",
      "shapes": [
        {
          "id": "http://a.example/S1",
          "type": "Shape",
          "expression": {
            "type": "TripleConstraint",
            "predicate": "http://a.example/p1",
            "valueExpr": {
              "type": "NodeConstraint",
              "values": [
                {
                  "value": "1",
                  "type": "http://www.w3.org/2001/XMLSchema#integer"
                },
                {
                  "value": "2",
                  "type": "http://www.w3.org/2001/XMLSchema#integer"
                }
              ]
            }
          }
        }
      ]
    }), null, 2))

Error

1 | console.log(JSON.stringify(new (require("@shexjs/visitor"))()
                               ^
TypeError: Object is not a constructor (evaluating 'new (require("@shexjs/visitor"))()')

Can someone please fix this? The example should work out of the box. I was a not able to find a way to make the visitor work.

What should have happened instead (e.g., it shouldn't crash)?

No response

How can we reproduce this error?

run this code with typescript

console.log(JSON.stringify(new (require("@shexjs/visitor"))()
  .visitSchema(
    {
      "type": "Schema",
      "shapes": [
        {
          "id": "http://a.example/S1",
          "type": "Shape",
          "expression": {
            "type": "TripleConstraint",
            "predicate": "http://a.example/p1",
            "valueExpr": {
              "type": "NodeConstraint",
              "values": [
                {
                  "value": "1",
                  "type": "http://www.w3.org/2001/XMLSchema#integer"
                },
                {
                  "value": "2",
                  "type": "http://www.w3.org/2001/XMLSchema#integer"
                }
              ]
            }
          }
        }
      ]
    }), null, 2))

constraintAutomaton avatar Sep 19 '25 14:09 constraintAutomaton

This version of the code also causes errors

import * as SHEX_VISITOR from "@shexjs/visitor"

const Visitor = SHEX_VISITOR.ShExVisitor();

const res = Visitor.visitSchema(
    {
      "type": "Schema",
      "shapes": [
        {
          "id": "http://a.example/S1",
          "type": "Shape",
          "expression": {
            "type": "TripleConstraint",
            "predicate": "http://a.example/p1",
            "valueExpr": {
              "type": "NodeConstraint",
              "values": [
                {
                  "value": "1",
                  "type": "http://www.w3.org/2001/XMLSchema#integer"
                },
                {
                  "value": "2",
                  "type": "http://www.w3.org/2001/XMLSchema#integer"
                }
              ]
            }
          }
        }
      ]
    });
console.log(res);
1 | 
2 | class ShExVisitor {
3 |   constructor (...ctor_args) {
                  ^
TypeError: Cannot call a class constructor without |new|

But in the typing ShExVisitor is a function.

constraintAutomaton avatar Sep 19 '25 14:09 constraintAutomaton

Is generate my own typing (using TypeScript tooling) from the code source JavaScript file I am still getting an error.

284 |       if (member in obj) {
285 |         const f = this[methodName];
286 |         if (typeof f !== "function") {
287 |           throw Error(methodName + " not found in Visitor");
288 |         }
289 |         const t = f.call(this, obj[member], ...args);
                ^
error: unknown property: "expression" in ShapeDecl: {"id":"http://a.example/S1","type":"Shape","expression":{"type":"TripleConstraint","predicate":"http://a.example/p1","valueExpr":{"type":"NodeConstraint","values":[{"value":"1","type":"http://www.w3.org/2001/XMLSchema#integer"},{"value":"2","type":"http://www.w3.org/2001/XMLSchema#integer"}]}}}

constraintAutomaton avatar Sep 19 '25 14:09 constraintAutomaton

I believe there's an issue with the example shape syntax. When I modify the shape this way

{
  "type": "Schema",
  "@context": "http://www.w3.org/ns/shex.jsonld",
  "shapes": [
    {
      "type": "ShapeDecl",
      "id": "http://a.example/S1",
      "shapeExpr": {
        "type": "Shape",
        "expression": {
          "type": "TripleConstraint",
          "predicate": "http://a.example/p1",
          "valueExpr": {
            "type": "NodeConstraint",
            "values": [
              {
                "value": "1",
                "type": "http://www.w3.org/2001/XMLSchema#integer"
              },
              {
                "value": "2", 
                "type": "http://www.w3.org/2001/XMLSchema#integer"
              }
            ]
          }
        }
      }
    }
  ]
}

And generate my own typings, it works correctly.

Proposed changes:

  • Fix the example syntax
  • Add more comprehensive documentation (it was difficult for me to figure out how to actually traverse the shex tree)
  • Update/improve TypeScript definitions (potentially with auto-generation workflow)

I'm happy to submit a PR if maintainers are interested in these potential improvements.

constraintAutomaton avatar Sep 22 '25 08:09 constraintAutomaton