Skip to content

Nested Doc() in update_document produces incorrect WOQL JSON structure #346

@hoijnet

Description

@hoijnet

Describe the bug

When using new Doc() inside another Doc() to construct a document with a list of subdocuments, the resulting WOQL JSON appears to be double-converted. The nested Doc() result gets wrapped again by the parent conversion, producing a deeply nested structure that the server rejects.

This seems to happen because convert() in woqlDoc.js doesn't recognize when an object is already a converted WOQL Value structure.

To Reproduce

// Schema:
// UpdateList has a 'list' field of type List<Structure>
// Structure is a subdocument with a 'string' field

const query = WOQL.update_document(
  new Doc({
    '@type': 'UpdateList',
    '@id': 'UpdateList/list',
    list: [new Doc({ '@type': 'Structure', string: '3' })],
  }),
);

console.log(JSON.stringify(query.json(), null, 2));

The output shows the subdocument being converted multiple times, with WOQL constructs like Value, DictionaryTemplate, and FieldValuePair appearing as data inside the document rather than as the structural wrapper.

Expected behavior

The WOQL JSON should have a flat structure where each subdocument in the list is a single DictionaryTemplate:

{
  "@type": "UpdateDocument",
  "document": {
    "@type": "Value",
    "dictionary": {
      "@type": "DictionaryTemplate",
      "data": [
        {
          "@type": "FieldValuePair",
          "field": "@type",
          "value": { "@type": "Value", "data": { "@type": "xsd:string", "@value": "UpdateList" } }
        },
        {
          "@type": "FieldValuePair",
          "field": "@id",
          "value": { "@type": "Value", "data": { "@type": "xsd:string", "@value": "UpdateList/list" } }
        },
        {
          "@type": "FieldValuePair",
          "field": "list",
          "value": {
            "@type": "Value",
            "list": [
              {
                "@type": "Value",
                "dictionary": {
                  "@type": "DictionaryTemplate",
                  "data": [
                    {
                      "@type": "FieldValuePair",
                      "field": "@type",
                      "value": { "@type": "Value", "data": { "@type": "xsd:string", "@value": "Structure" } }
                    },
                    {
                      "@type": "FieldValuePair",
                      "field": "string",
                      "value": { "@type": "Value", "data": { "@type": "xsd:string", "@value": "3" } }
                    }
                  ]
                }
              }
            ]
          }
        }
      ]
    }
  }
}

Error logs

When sending the incorrectly structured query to the server:

{
  "@type": "api:WoqlErrorResponse",
  "api:error": {
    "@type": "api:WOQLSchemaCheckFailure",
    "api:witnesses": [...]
  },
  "api:message": "There was an error when schema checking",
  "api:status": "api:failure"
}

Workaround

Using plain objects instead of nested Doc() works correctly:

const query = WOQL.update_document(
  new Doc({
    '@type': 'UpdateList',
    '@id': 'UpdateList/list',
    list: [{ '@type': 'Structure', string: '3' }],  // plain object, not new Doc()
  }),
);

Additional context

The issue appears to be in lib/query/woqlDoc.js. The convert() function processes the return value of new Doc() (which is already converted) as if it were a regular object, iterating over its keys and wrapping them in additional FieldValuePair structures.

A possible fix would be to check if an object is already a converted Value structure (has @type: 'Value' with dictionary, list, data, node, or variable properties) and return it as-is.

System information (please complete the following information):

  • OS: [e.g. Ubuntu 18.04]
  • Browser/NodeJS version [e.g. chrome, safari]
  • terminus-client version

Additional context
Add any other context about the problem here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingjavascriptPull requests that update javascript codetriageissue to be triage

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions