[
  {
    "__docId__": 1,
    "kind": "external",
    "name": "Infinity",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Infinity",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Infinity",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 2,
    "kind": "external",
    "name": "NaN",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/NaN",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~NaN",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 3,
    "kind": "external",
    "name": "undefined",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~undefined",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 4,
    "kind": "external",
    "name": "null",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/null",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~null",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 5,
    "kind": "external",
    "name": "Object",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Object",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 6,
    "kind": "external",
    "name": "object",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~object",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 7,
    "kind": "external",
    "name": "Function",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Function",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 8,
    "kind": "external",
    "name": "function",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~function",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 9,
    "kind": "external",
    "name": "Boolean",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Boolean",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 10,
    "kind": "external",
    "name": "boolean",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~boolean",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 11,
    "kind": "external",
    "name": "Symbol",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Symbol",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 12,
    "kind": "external",
    "name": "Error",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Error",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 13,
    "kind": "external",
    "name": "EvalError",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/EvalError",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~EvalError",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 14,
    "kind": "external",
    "name": "InternalError",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/InternalError",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~InternalError",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 15,
    "kind": "external",
    "name": "RangeError",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RangeError",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~RangeError",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 16,
    "kind": "external",
    "name": "ReferenceError",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ReferenceError",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~ReferenceError",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 17,
    "kind": "external",
    "name": "SyntaxError",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SyntaxError",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~SyntaxError",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 18,
    "kind": "external",
    "name": "TypeError",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypeError",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~TypeError",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 19,
    "kind": "external",
    "name": "URIError",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/URIError",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~URIError",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 20,
    "kind": "external",
    "name": "Number",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Number",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 21,
    "kind": "external",
    "name": "number",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~number",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 22,
    "kind": "external",
    "name": "Date",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Date",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 23,
    "kind": "external",
    "name": "String",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~String",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 24,
    "kind": "external",
    "name": "string",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~string",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 25,
    "kind": "external",
    "name": "RegExp",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~RegExp",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 26,
    "kind": "external",
    "name": "Array",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Array",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 27,
    "kind": "external",
    "name": "Int8Array",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int8Array",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Int8Array",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 28,
    "kind": "external",
    "name": "Uint8Array",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Uint8Array",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 29,
    "kind": "external",
    "name": "Uint8ClampedArray",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8ClampedArray",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Uint8ClampedArray",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 30,
    "kind": "external",
    "name": "Int16Array",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int16Array",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Int16Array",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 31,
    "kind": "external",
    "name": "Uint16Array",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint16Array",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Uint16Array",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 32,
    "kind": "external",
    "name": "Int32Array",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Int32Array",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Int32Array",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 33,
    "kind": "external",
    "name": "Uint32Array",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint32Array",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Uint32Array",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 34,
    "kind": "external",
    "name": "Float32Array",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float32Array",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Float32Array",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 35,
    "kind": "external",
    "name": "Float64Array",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Float64Array",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Float64Array",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 36,
    "kind": "external",
    "name": "Map",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Map",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 37,
    "kind": "external",
    "name": "Set",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Set",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 38,
    "kind": "external",
    "name": "WeakMap",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~WeakMap",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 39,
    "kind": "external",
    "name": "WeakSet",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~WeakSet",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 40,
    "kind": "external",
    "name": "ArrayBuffer",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~ArrayBuffer",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 41,
    "kind": "external",
    "name": "DataView",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~DataView",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 42,
    "kind": "external",
    "name": "JSON",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/JSON",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~JSON",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 43,
    "kind": "external",
    "name": "Promise",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Promise",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 44,
    "kind": "external",
    "name": "Generator",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Generator",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Generator",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 45,
    "kind": "external",
    "name": "GeneratorFunction",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/GeneratorFunction",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~GeneratorFunction",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 46,
    "kind": "external",
    "name": "Reflect",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Reflect",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Reflect",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 47,
    "kind": "external",
    "name": "Proxy",
    "externalLink": "https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Proxy",
    "memberof": "src/.external-ecmascript.js",
    "static": true,
    "longname": "src/.external-ecmascript.js~Proxy",
    "access": "public",
    "description": "",
    "builtinExternal": true
  },
  {
    "__docId__": 48,
    "kind": "file",
    "name": "src/Gulpfile.js",
    "content": "import cleanup from 'node-cleanup';\nimport cleanupHandler from './util/cleanup';\n\n// Register tasks\nexport { default as pull } from './tasks/pull';\nexport { default as push } from './tasks/push';\nexport { default as watch } from './tasks/watch';\nexport { default as import } from './tasks/import';\n\n// Register cleanup\n/* istanbul ignore if */\nif (process.env.NODE_ENV !== 'test') {\n  // Prevent node-opcua logging\n  console.log = () => {}; // eslint-disable-line no-console\n\n  cleanup((code, signal) => cleanupHandler(code, signal, cleanup.uninstall), {\n    ctrl_C: '',\n    unhandledRejection: '',\n  });\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/Gulpfile.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 49,
    "kind": "file",
    "name": "src/api.js",
    "content": "import { NodeClass } from 'node-opcua/lib/datamodel/nodeclass';\nimport { DataType, VariantArrayType } from 'node-opcua/lib/datamodel/variant';\nimport { StatusCodes } from 'node-opcua/lib/datamodel/opcua_status_code';\nimport Session from './lib/server/Session';\nimport NodeId from './lib/model/opcua/NodeId';\n\n// Helpers\n/**\n * Creates a callback that calls `resolve` on success and `reject` on error.\n * @param {function(result: any): void} resolve The resolve callback.\n * @param {function(error: Error): void} reject The reject callback.\n * @example\n * // `aCallbackFn` is a function that accepts a node-style callback as the last argument\n * const promise = new Promise(\n *   (resolve, reject) => aCallbackFn('other', 'args', promisifiedCallback(resolve, reject)\n * );\n */\nfunction promisifiedCallback(resolve, reject) {\n  return (err, result) => {\n    if (err) {\n      return reject(err);\n    }\n    return resolve(result);\n  };\n}\n\n/**\n * Promisifies a async function that would otherwise require a callback.\n * @param {function(cb: function(error: Error, result: any)):Promise<any>} call A function that\n * accepts a callback and performs the async action to wrap.\n */\nfunction promisified(call) {\n  return new Promise((resolve, reject) => call(promisifiedCallback(resolve, reject)));\n}\n\n/**\n * Creates a session, runs `action` and closes the session.\n * @param {function(session: Session): Promise<any>} action The action to run a session.\n */\nasync function withSession(action) {\n  const session = await Session.create();\n  let result = null;\n  let error = null;\n  try {\n    result = await action(session);\n  } catch (e) {\n    error = e;\n  }\n\n  await Session.close(session);\n\n  if (error) {\n    throw error;\n  }\n\n  return result;\n}\n\n// Reading/Writing\n\n/**\n * Reads a single node's value.\n * @param {NodeId} nodeId The node to read.\n * @return {Promise<any>} The read value.\n */\nexport async function readNode(nodeId) {\n  return withSession((session) => promisified((cb) => session.readVariableValue(nodeId, cb))).then(\n    ({ value, statusCode }) => {\n      if (statusCode !== StatusCodes.Good) {\n        throw Object.assign(new Error(statusCode.description), { nodeId, statusCode });\n      }\n\n      return value;\n    }\n  );\n}\n\n/**\n * Writes a single node's value.\n * @param {NodeId} nodeId The node to write.\n * @param {Variant} value The value to write.\n * @return {Promise<node-opcua~StatusCodes} The operation status result.\n */\nexport function writeNode(nodeId, value) {\n  return withSession((session) =>\n    promisified((cb) => session.writeSingleNode(nodeId, value, cb))\n  ).then((statusCode) => {\n    if (statusCode !== StatusCodes.Good) {\n      throw Object.assign(new Error(statusCode.description), { nodeId, statusCode });\n    }\n\n    return statusCode;\n  });\n}\n\n// Methods / Scripts\n\n/**\n * Calls an OPC-UA method on the server.\n * @param {NodeId} methodId The method's id.\n * @param {Array<Variant>} args The arguments to pass.\n */\nexport function callMethod(methodId, args = []) {\n  return withSession((session) =>\n    promisified((cb) =>\n      session.call(\n        [\n          {\n            objectId: methodId.parent,\n            methodId,\n            inputArguments: args,\n          },\n        ],\n        cb\n      )\n    )\n  ).then(([result] = []) => {\n    if (result.statusCode.value) {\n      throw Object.assign(new Error(result.statusCode.description), {\n        methodId,\n        inputArguments: args,\n      });\n    }\n\n    return result;\n  });\n}\n\n/**\n * Calls a server script on the server.\n * @param {NodeId} scriptId The script's id.\n * @param {Object} parameters The parameters to pass, given as a map of Variants, like\n * `{ name: { ... } }`.\n */\nexport function callScript(scriptId, parameters = {}) {\n  return callMethod(new NodeId('AGENT.SCRIPT.METHODS.callScript'), [\n    {\n      dataType: DataType.NodeId,\n      value: scriptId,\n    },\n    {\n      dataType: DataType.NodeId,\n      value: scriptId.parent,\n    },\n    {\n      dataType: DataType.String,\n      arrayType: VariantArrayType.Array,\n      value: Object.keys(parameters),\n    },\n    {\n      dataType: DataType.Variant,\n      arrayType: VariantArrayType.Array,\n      value: Object.values(parameters),\n    },\n  ]).then((result) => {\n    const statusCode = result.outputArguments[0].value;\n\n    if (statusCode.value) {\n      throw Object.assign(\n        new Error(`Script failed: ${statusCode.description}\n${result.outputArguments[1].value}`),\n        {\n          scriptId,\n          parameters,\n        }\n      );\n    }\n\n    return result;\n  });\n}\n\n/**\n * Creates a new Node on the server.\n * @param {NodeId} nodeId The new node's id.\n * @param {Object} options The options to use.\n * @param {string} options.name The node's name.\n * @param {NodeId} [options.parentNodeId] The node's parent, defaults to the calculated parent\n * (`Test` for `Test.Child`).\n * @param {node-opcua~NodeClass} [options.nodeClass] The node's class, defaults so\n * `node-opcua~NodeClass.Variable`.\n * @param {NodeId} [options.typeDefinition] The node's type definition, must be provided for\n * non-variable nodes.\n * @param {NodeId} [options.modellingRule] The node's modelling rule.\n * @param {string} [options.reference] Name of the type of the node's reference to it's parent.\n * @param {node-opcua~Variant} [options.value] The node's value, required for all variable nodes.\n */\nexport function createNode(\n  nodeId,\n  {\n    name,\n    parentNodeId = nodeId.parent,\n    nodeClass = NodeClass.Variable,\n    typeDefinition = new NodeId('ns=0;i=62'),\n    modellingRule,\n    reference,\n    value,\n  }\n) {\n  const variableOptions =\n    nodeClass.value === NodeClass.Variable.value\n      ? {\n          dataType: value.dataType.value,\n          valueRank: value.arrayType ? value.arrayType.value : VariantArrayType.Scalar.value,\n          value:\n            value.arrayType && value.arrayType.value !== VariantArrayType.Scalar.value\n              ? Array.from(value.value)\n              : value.value,\n        }\n      : {};\n\n  const is64Bit = value.dataType === DataType.Int64 || value.dataType === DataType.UInt64;\n  if (is64Bit) {\n    variableOptions.value = 0;\n  }\n\n  return callScript(new NodeId('SYSTEM.LIBRARY.ATVISE.SERVERSCRIPTS.atscm.CreateNode'), {\n    paramObjString: {\n      dataType: DataType.String,\n      value: JSON.stringify(\n        Object.assign(\n          {\n            nodeId,\n            browseName: name,\n            parentNodeId: parentNodeId || nodeId.parent,\n            nodeClass: nodeClass.value,\n            typeDefinition,\n            modellingRule,\n            reference,\n          },\n          variableOptions\n        )\n      ),\n    },\n  }).then(async (result) => {\n    const [{ value: createdNode }] = result.outputArguments[3].value;\n\n    if (createdNode && is64Bit) {\n      await writeNode(nodeId, value);\n    }\n\n    return result;\n  });\n}\n\n/**\n * Adds references to a node.\n * @param {NodeId} nodeId The node to add the references to.\n * @param {Object} references The references to add.\n * @return {Promise} Resolved once the references were added.\n * @example <caption>Add a simple reference</caption>\n * import { ReferenceTypeIds } from 'node-opcua/lib/opcua_node_ids';\n *\n * addReferences('AGENT.DISPLAYS.Main', {\n *   [47]: ['VariableTypes.ATVISE.Display'],\n *   // equals:\n *   [ReferenceTypeIds.HasTypeDefinition]: ['VariableTypes.ATVISE.Display'],\n * })\n *   .then(() => console.log('Done!'))\n *   .catch(console.error);\n */\nexport function addReferences(nodeId, references) {\n  return callScript(new NodeId('SYSTEM.LIBRARY.ATVISE.SERVERSCRIPTS.atscm.AddReferences'), {\n    paramObjString: {\n      dataType: DataType.String,\n      value: JSON.stringify({\n        nodeId,\n        references: Object.entries(references).map(([type, items]) => ({\n          referenceIdValue: parseInt(type, 10),\n          items,\n        })),\n      }),\n    },\n  });\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/api.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 50,
    "kind": "function",
    "name": "promisifiedCallback",
    "memberof": "src/api.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/api.js~promisifiedCallback",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/api.js",
    "importStyle": null,
    "description": "Creates a callback that calls `resolve` on success and `reject` on error.",
    "examples": [
      "// `aCallbackFn` is a function that accepts a node-style callback as the last argument\nconst promise = new Promise(\n  (resolve, reject) => aCallbackFn('other', 'args', promisifiedCallback(resolve, reject)\n);"
    ],
    "lineNumber": 18,
    "params": [
      {
        "nullable": null,
        "types": [
          "function(result: any): void"
        ],
        "spread": false,
        "optional": false,
        "name": "resolve",
        "description": "The resolve callback."
      },
      {
        "nullable": null,
        "types": [
          "function(error: Error): void"
        ],
        "spread": false,
        "optional": false,
        "name": "reject",
        "description": "The reject callback."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    },
    "ignore": true
  },
  {
    "__docId__": 51,
    "kind": "function",
    "name": "promisified",
    "memberof": "src/api.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/api.js~promisified",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/api.js",
    "importStyle": null,
    "description": "Promisifies a async function that would otherwise require a callback.",
    "lineNumber": 32,
    "params": [
      {
        "nullable": null,
        "types": [
          "function(cb: function(error: Error, result: any)):Promise<any>"
        ],
        "spread": false,
        "optional": false,
        "name": "call",
        "description": "A function that\naccepts a callback and performs the async action to wrap."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    },
    "ignore": true
  },
  {
    "__docId__": 52,
    "kind": "function",
    "name": "withSession",
    "memberof": "src/api.js",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/api.js~withSession",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/api.js",
    "importStyle": null,
    "description": "Creates a session, runs `action` and closes the session.",
    "lineNumber": 40,
    "params": [
      {
        "nullable": null,
        "types": [
          "function(session: Session): Promise<any>"
        ],
        "spread": false,
        "optional": false,
        "name": "action",
        "description": "The action to run a session."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    },
    "ignore": true
  },
  {
    "__docId__": 53,
    "kind": "function",
    "name": "readNode",
    "memberof": "src/api.js",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/api.js~readNode",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/api.js",
    "importStyle": "{readNode}",
    "description": "Reads a single node's value.",
    "lineNumber": 66,
    "params": [
      {
        "nullable": null,
        "types": [
          "NodeId"
        ],
        "spread": false,
        "optional": false,
        "name": "nodeId",
        "description": "The node to read."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise<any>"
      ],
      "spread": false,
      "description": "The read value."
    }
  },
  {
    "__docId__": 54,
    "kind": "function",
    "name": "writeNode",
    "memberof": "src/api.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/api.js~writeNode",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/api.js",
    "importStyle": "{writeNode}",
    "description": "Writes a single node's value.",
    "lineNumber": 84,
    "params": [
      {
        "nullable": null,
        "types": [
          "NodeId"
        ],
        "spread": false,
        "optional": false,
        "name": "nodeId",
        "description": "The node to write."
      },
      {
        "nullable": null,
        "types": [
          "Variant"
        ],
        "spread": false,
        "optional": false,
        "name": "value",
        "description": "The value to write."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise<node-opcua~StatusCodes"
      ],
      "spread": false,
      "description": "The operation status result."
    }
  },
  {
    "__docId__": 55,
    "kind": "function",
    "name": "callMethod",
    "memberof": "src/api.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/api.js~callMethod",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/api.js",
    "importStyle": "{callMethod}",
    "description": "Calls an OPC-UA method on the server.",
    "lineNumber": 103,
    "params": [
      {
        "nullable": null,
        "types": [
          "NodeId"
        ],
        "spread": false,
        "optional": false,
        "name": "methodId",
        "description": "The method's id."
      },
      {
        "nullable": null,
        "types": [
          "Array<Variant>"
        ],
        "spread": false,
        "optional": false,
        "name": "args",
        "description": "The arguments to pass."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 56,
    "kind": "function",
    "name": "callScript",
    "memberof": "src/api.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/api.js~callScript",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/api.js",
    "importStyle": "{callScript}",
    "description": "Calls a server script on the server.",
    "lineNumber": 135,
    "params": [
      {
        "nullable": null,
        "types": [
          "NodeId"
        ],
        "spread": false,
        "optional": false,
        "name": "scriptId",
        "description": "The script's id."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "parameters",
        "description": "The parameters to pass, given as a map of Variants, like\n`{ name: { ... } }`."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 57,
    "kind": "function",
    "name": "createNode",
    "memberof": "src/api.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/api.js~createNode",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/api.js",
    "importStyle": "{createNode}",
    "description": "Creates a new Node on the server.",
    "lineNumber": 188,
    "params": [
      {
        "nullable": null,
        "types": [
          "NodeId"
        ],
        "spread": false,
        "optional": false,
        "name": "nodeId",
        "description": "The new node's id."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "The options to use."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "options.name",
        "description": "The node's name."
      },
      {
        "nullable": null,
        "types": [
          "NodeId"
        ],
        "spread": false,
        "optional": true,
        "name": "options.parentNodeId",
        "description": "The node's parent, defaults to the calculated parent\n(`Test` for `Test.Child`)."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~NodeClass"
        ],
        "spread": false,
        "optional": true,
        "name": "options.nodeClass",
        "description": "The node's class, defaults so\n`node-opcua~NodeClass.Variable`."
      },
      {
        "nullable": null,
        "types": [
          "NodeId"
        ],
        "spread": false,
        "optional": true,
        "name": "options.typeDefinition",
        "description": "The node's type definition, must be provided for\nnon-variable nodes."
      },
      {
        "nullable": null,
        "types": [
          "NodeId"
        ],
        "spread": false,
        "optional": true,
        "name": "options.modellingRule",
        "description": "The node's modelling rule."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": true,
        "name": "options.reference",
        "description": "Name of the type of the node's reference to it's parent."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~Variant"
        ],
        "spread": false,
        "optional": true,
        "name": "options.value",
        "description": "The node's value, required for all variable nodes."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 58,
    "kind": "function",
    "name": "addReferences",
    "memberof": "src/api.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/api.js~addReferences",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/api.js",
    "importStyle": "{addReferences}",
    "description": "Adds references to a node.",
    "examples": [
      "<caption>Add a simple reference</caption>\nimport { ReferenceTypeIds } from 'node-opcua/lib/opcua_node_ids';\n\naddReferences('AGENT.DISPLAYS.Main', {\n  [47]: ['VariableTypes.ATVISE.Display'],\n  // equals:\n  [ReferenceTypeIds.HasTypeDefinition]: ['VariableTypes.ATVISE.Display'],\n})\n  .then(() => console.log('Done!'))\n  .catch(console.error);"
    ],
    "lineNumber": 262,
    "params": [
      {
        "nullable": null,
        "types": [
          "NodeId"
        ],
        "spread": false,
        "optional": false,
        "name": "nodeId",
        "description": "The node to add the references to."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "references",
        "description": "The references to add."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": "Resolved once the references were added."
    }
  },
  {
    "__docId__": 59,
    "kind": "file",
    "name": "src/config/ProjectConfig.js",
    "content": "/**\n * The path to the project's configuration file.\n * @type {string}\n */\nexport const path = process.env.ATSCM_CONFIG_PATH;\n\n/**\n * The current project's configuration.\n * @type {Atviseproject}\n */\nconst Config = require(path).default;\n\n/**\n * The current project's configuration, with overrides (through `ATSCM_PROJECT__` env vars) already\n * handled.\n */\nexport default class ProjectConfig extends Config {\n  /**\n   * Return the project configuration override for the given name if available.\n   * @param {string} name The variable to return.\n   * @type {string|undefined} The variables's value or `undefined`.\n   */\n  static _env(name) {\n    return process.env[`ATSCM_PROJECT__${name}`];\n  }\n\n  /**\n   * The atvise server's host. Can be overridden with the `ATSCM_PROJECT__HOST` env variable.\n   * @type {string}\n   */\n  static get host() {\n    return this._env('HOST') || super.host;\n  }\n\n  /**\n   * The atvise server ports to use.\n   * @type {Object}\n   * @property {number} opc The OPC-UA port the atvise server runs on. Can be overridden with the\n   * `ATSCM_PROJECT__PORT__OPC` env variable.\n   * @property {number} http The HTTP port the atvise server can be reached at. Can be overridden\n   * with the `ATSCM_PROJECT__PORT__HTTP` env variable.\n   */\n  static get port() {\n    return {\n      opc: parseInt(this._env('PORT__OPC'), 10) || super.port.opc,\n      http: parseInt(this._env('PORT__HTTP'), 10) || super.port.http,\n    };\n  }\n\n  /**\n   * The login to use. Return false if no login is required (default).\n   * @type {Object}\n   * @property {string} username The username to log in with. Can be overridden with the\n   * `ATSCM_PROJECT__LOGIN__USERNAME` env variable.\n   * @property {string} password The password to log in with. Can be overridden with the\n   * `ATSCM_PROJECT__LOGIN__PASSWORD` env variable.\n   */\n  static get login() {\n    if (this._env('LOGIN__USERNAME') || this._env('LOGIN__PASSWORD')) {\n      return {\n        username: this._env('LOGIN__USERNAME') || super.login.username,\n        password: this._env('LOGIN__PASSWORD') || super.login.password,\n      };\n    }\n\n    return super.login;\n  }\n\n  /**\n   * A regular expression matching all source nodes.\n   * @type {RegExp};\n   */\n  static get sourceNodeRegExp() {\n    if (!this._sourceNodeRegExp) {\n      this._sourceNodesRegExp = new RegExp(\n        `^(${this.nodes.map(({ value }) => `${value.replace(/\\./g, '\\\\.')}`).join('|')})`\n      );\n    }\n\n    return this._sourceNodesRegExp;\n  }\n\n  /**\n   * A regular expression matching all ignored nodes.\n   * @type {RegExp};\n   */\n  static get ignoredNodesRegExp() {\n    if (!this._ignoredNodesRegExp) {\n      this._ignoredNodesRegExp = new RegExp(\n        `^(${this.ignoreNodes.map(({ value }) => `${value.replace(/\\./g, '\\\\.')}`).join('|')})`\n      );\n    }\n\n    return this._ignoredNodesRegExp;\n  }\n\n  /**\n   * Returns `true` for all external (not in {@link Atviseproject.nodes} or ignored by\n   * {@link Atviseproject.ignoreNodes}).\n   * @param {string} id The node id to check.\n   * @return {boolean} If the node is external.\n   */\n  static isExternal(id) {\n    return !id.match(this.sourceNodeRegExp) || !!id.match(this.ignoredNodesRegExp);\n  }\n\n  /**\n   * The connection timeout, in milliseconds. Can be overridden with the `ATSCM_PROJECT__TIMEOUT`\n   * env variable.\n   * @type {number}\n   */\n  static get timeout() {\n    const env = this._env('TIMEOUT');\n    return env ? parseInt(env, 10) : super.timeout;\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/config/ProjectConfig.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 60,
    "kind": "variable",
    "name": "path",
    "memberof": "src/config/ProjectConfig.js",
    "static": true,
    "longname": "src/config/ProjectConfig.js~path",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/config/ProjectConfig.js",
    "importStyle": "{path}",
    "description": "The path to the project's configuration file.",
    "lineNumber": 5,
    "type": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 61,
    "kind": "variable",
    "name": "Config",
    "memberof": "src/config/ProjectConfig.js",
    "static": true,
    "longname": "src/config/ProjectConfig.js~Config",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/config/ProjectConfig.js",
    "importStyle": null,
    "description": "The current project's configuration.",
    "lineNumber": 11,
    "type": {
      "nullable": null,
      "types": [
        "Atviseproject"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 62,
    "kind": "class",
    "name": "ProjectConfig",
    "memberof": "src/config/ProjectConfig.js",
    "static": true,
    "longname": "src/config/ProjectConfig.js~ProjectConfig",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/config/ProjectConfig.js",
    "importStyle": "ProjectConfig",
    "description": "The current project's configuration, with overrides (through `ATSCM_PROJECT__` env vars) already\nhandled.",
    "lineNumber": 17,
    "interface": false,
    "extends": [
      "Config"
    ]
  },
  {
    "__docId__": 63,
    "kind": "method",
    "name": "_env",
    "memberof": "src/config/ProjectConfig.js~ProjectConfig",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/config/ProjectConfig.js~ProjectConfig._env",
    "access": "private",
    "description": "Return the project configuration override for the given name if available.",
    "lineNumber": 23,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "name",
        "description": "The variable to return."
      }
    ],
    "type": {
      "nullable": null,
      "types": [
        "string",
        "undefined"
      ],
      "spread": false,
      "description": null
    },
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 64,
    "kind": "get",
    "name": "host",
    "memberof": "src/config/ProjectConfig.js~ProjectConfig",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/config/ProjectConfig.js~ProjectConfig.host",
    "access": "public",
    "description": "The atvise server's host. Can be overridden with the `ATSCM_PROJECT__HOST` env variable.",
    "lineNumber": 31,
    "type": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 65,
    "kind": "get",
    "name": "port",
    "memberof": "src/config/ProjectConfig.js~ProjectConfig",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/config/ProjectConfig.js~ProjectConfig.port",
    "access": "public",
    "description": "The atvise server ports to use.",
    "lineNumber": 43,
    "properties": [
      {
        "nullable": null,
        "types": [
          "number"
        ],
        "spread": false,
        "optional": false,
        "name": "opc",
        "description": "The OPC-UA port the atvise server runs on. Can be overridden with the\n`ATSCM_PROJECT__PORT__OPC` env variable."
      },
      {
        "nullable": null,
        "types": [
          "number"
        ],
        "spread": false,
        "optional": false,
        "name": "http",
        "description": "The HTTP port the atvise server can be reached at. Can be overridden\nwith the `ATSCM_PROJECT__PORT__HTTP` env variable."
      }
    ],
    "type": {
      "nullable": null,
      "types": [
        "Object"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 66,
    "kind": "get",
    "name": "login",
    "memberof": "src/config/ProjectConfig.js~ProjectConfig",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/config/ProjectConfig.js~ProjectConfig.login",
    "access": "public",
    "description": "The login to use. Return false if no login is required (default).",
    "lineNumber": 58,
    "properties": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "username",
        "description": "The username to log in with. Can be overridden with the\n`ATSCM_PROJECT__LOGIN__USERNAME` env variable."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "password",
        "description": "The password to log in with. Can be overridden with the\n`ATSCM_PROJECT__LOGIN__PASSWORD` env variable."
      }
    ],
    "type": {
      "nullable": null,
      "types": [
        "Object"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 67,
    "kind": "get",
    "name": "sourceNodeRegExp",
    "memberof": "src/config/ProjectConfig.js~ProjectConfig",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/config/ProjectConfig.js~ProjectConfig.sourceNodeRegExp",
    "access": "public",
    "description": "A regular expression matching all source nodes.",
    "lineNumber": 73,
    "type": {
      "nullable": null,
      "types": [
        "*"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 68,
    "kind": "member",
    "name": "_sourceNodesRegExp",
    "memberof": "src/config/ProjectConfig.js~ProjectConfig",
    "static": true,
    "longname": "src/config/ProjectConfig.js~ProjectConfig._sourceNodesRegExp",
    "access": "private",
    "description": null,
    "lineNumber": 75,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 69,
    "kind": "get",
    "name": "ignoredNodesRegExp",
    "memberof": "src/config/ProjectConfig.js~ProjectConfig",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/config/ProjectConfig.js~ProjectConfig.ignoredNodesRegExp",
    "access": "public",
    "description": "A regular expression matching all ignored nodes.",
    "lineNumber": 87,
    "type": {
      "nullable": null,
      "types": [
        "*"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 70,
    "kind": "member",
    "name": "_ignoredNodesRegExp",
    "memberof": "src/config/ProjectConfig.js~ProjectConfig",
    "static": true,
    "longname": "src/config/ProjectConfig.js~ProjectConfig._ignoredNodesRegExp",
    "access": "private",
    "description": null,
    "lineNumber": 89,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 71,
    "kind": "method",
    "name": "isExternal",
    "memberof": "src/config/ProjectConfig.js~ProjectConfig",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/config/ProjectConfig.js~ProjectConfig.isExternal",
    "access": "public",
    "description": "Returns `true` for all external (not in {@link Atviseproject.nodes} or ignored by\n{@link Atviseproject.ignoreNodes}).",
    "lineNumber": 103,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "id",
        "description": "The node id to check."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": "If the node is external."
    }
  },
  {
    "__docId__": 72,
    "kind": "get",
    "name": "timeout",
    "memberof": "src/config/ProjectConfig.js~ProjectConfig",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/config/ProjectConfig.js~ProjectConfig.timeout",
    "access": "public",
    "description": "The connection timeout, in milliseconds. Can be overridden with the `ATSCM_PROJECT__TIMEOUT`\nenv variable.",
    "lineNumber": 112,
    "type": {
      "nullable": null,
      "types": [
        "number"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 73,
    "kind": "file",
    "name": "src/hooks/check-atserver.ts",
    "content": "import { VariableIds } from 'node-opcua/lib/opcua_node_ids';\nimport { readJson } from 'fs-extra';\nimport { coerce, satisfies, gtr, minVersion } from 'semver';\nimport Logger from 'gulplog';\nimport prompts from 'prompts';\nimport { red, yellow } from 'chalk';\nimport { readNode } from '../api';\nimport { engines } from '../../package.json';\nimport { updateJson } from '../lib/helpers/fs';\nimport NodeId from '../lib/model/opcua/NodeId';\nimport { HookContext } from './hooks';\n\nconst atserverVersionNodeId = new NodeId(\n  `ns=0;i=${VariableIds.Server_ServerStatus_BuildInfo_SoftwareVersion}`\n);\n\nexport async function loadProjectRequirement(): Promise<string> {\n  const packageManifest = await readJson('./package.json');\n\n  return packageManifest.engines && packageManifest.engines.atserver;\n}\n\nexport async function loadRemoteVersion(): Promise<string> {\n  const raw = (await readNode(atserverVersionNodeId)).value;\n\n  return coerce(raw).version;\n}\n\nexport async function askForConfirmation({\n  onAsk,\n  ...options\n}: {\n  message: string;\n  onAsk?: () => void;\n}): Promise<boolean> {\n  if (!process.stdin.isTTY) return false;\n\n  if (onAsk) onAsk();\n\n  return (\n    await prompts({\n      type: 'confirm',\n      name: 'confirmed',\n      ...options,\n    })\n  ).confirmed;\n}\n\nexport async function approveToContinue(\n  { log, continueOnError }: HookContext,\n  error: Error\n): Promise<void> {\n  if (continueOnError) {\n    log.warn(red(error.message));\n    log.warn(`Using --continue, skipping...`);\n    return;\n  }\n\n  const shouldContinue = await askForConfirmation({\n    onAsk: () => Logger.error(red(error.message)),\n    message: 'Do you want to continue anyway?',\n  });\n\n  if (!shouldContinue) {\n    throw error;\n  }\n}\n\nexport default async function checkAtserver(context: HookContext): Promise<{ version: string }> {\n  const { log } = context;\n\n  log.debug('Checking atserver version');\n\n  const atscmRequirement = engines.atserver;\n\n  const [projectRequirement, remoteVersion] = await Promise.all([\n    loadProjectRequirement(),\n    loadRemoteVersion(),\n  ]);\n\n  if (!satisfies(remoteVersion, atscmRequirement)) {\n    log.debug(`Version ${remoteVersion} does not satisfy requirement ${atscmRequirement}`);\n    log.warn(\n      yellow(\n        `Your atvise server version (${remoteVersion}) is not supported, it may or may not work.`\n      )\n    );\n\n    if (gtr(remoteVersion, atscmRequirement)) {\n      log.info(\n        `You're running a newer version of atvise server. Please run 'atscm update' to check for updates.`\n      );\n    } else {\n      log.info(`Please upgrade to atserver ${minVersion(atscmRequirement)} or above.`);\n    }\n  }\n\n  let updatePackage = false;\n  if (!projectRequirement) {\n    log.info(`Your package.json file doesn't specify an atserver version, adding it...`);\n\n    updatePackage = true;\n  } else if (!satisfies(remoteVersion, projectRequirement)) {\n    await approveToContinue(\n      context,\n      new Error(\n        `Your project is setup with atserver ${projectRequirement} but you're using ${remoteVersion}`\n      )\n    );\n\n    updatePackage = await askForConfirmation({\n      message: `Use atvise server ${remoteVersion} as new default?`,\n    });\n  } else {\n    log.debug(`Running against atserver ${remoteVersion}`);\n  }\n\n  if (updatePackage) {\n    await updateJson<{ engines?: { atserver?: string } }>('./package.json', (current) => {\n      /* eslint-disable no-param-reassign */\n      if (!current.engines) current.engines = {};\n      current.engines.atserver = remoteVersion;\n      /* eslint-enable no-param-reassign */\n\n      return current;\n    });\n  }\n\n  return { version: remoteVersion };\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/hooks/check-atserver.ts",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 74,
    "kind": "variable",
    "name": "atserverVersionNodeId",
    "memberof": "src/hooks/check-atserver.ts",
    "static": true,
    "longname": "src/hooks/check-atserver.ts~atserverVersionNodeId",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/hooks/check-atserver.ts",
    "importStyle": null,
    "description": null,
    "lineNumber": 11,
    "undocument": true,
    "type": {
      "types": [
        "src/lib/model/opcua/NodeId.js~NodeId"
      ]
    },
    "ignore": true
  },
  {
    "__docId__": 75,
    "kind": "function",
    "name": "loadProjectRequirement",
    "memberof": "src/hooks/check-atserver.ts",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/hooks/check-atserver.ts~loadProjectRequirement",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/hooks/check-atserver.ts",
    "importStyle": "{loadProjectRequirement}",
    "description": "",
    "lineNumber": 17,
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": ""
    },
    "params": []
  },
  {
    "__docId__": 76,
    "kind": "function",
    "name": "loadRemoteVersion",
    "memberof": "src/hooks/check-atserver.ts",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/hooks/check-atserver.ts~loadRemoteVersion",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/hooks/check-atserver.ts",
    "importStyle": "{loadRemoteVersion}",
    "description": "",
    "lineNumber": 23,
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": ""
    },
    "params": []
  },
  {
    "__docId__": 77,
    "kind": "function",
    "name": "askForConfirmation",
    "memberof": "src/hooks/check-atserver.ts",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/hooks/check-atserver.ts~askForConfirmation",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/hooks/check-atserver.ts",
    "importStyle": "{askForConfirmation}",
    "description": "",
    "lineNumber": 29,
    "params": [
      {
        "nullable": null,
        "types": [
          "undefined"
        ],
        "spread": false,
        "optional": false,
        "name": "undefined",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 78,
    "kind": "function",
    "name": "approveToContinue",
    "memberof": "src/hooks/check-atserver.ts",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/hooks/check-atserver.ts~approveToContinue",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/hooks/check-atserver.ts",
    "importStyle": "{approveToContinue}",
    "description": "",
    "lineNumber": 49,
    "params": [
      {
        "nullable": null,
        "types": [
          "HookContext"
        ],
        "spread": false,
        "optional": false,
        "name": "undefined",
        "description": ""
      },
      {
        "nullable": null,
        "types": [
          "Error"
        ],
        "spread": false,
        "optional": false,
        "name": "error",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 79,
    "kind": "function",
    "name": "checkAtserver",
    "memberof": "src/hooks/check-atserver.ts",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/hooks/check-atserver.ts~checkAtserver",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/hooks/check-atserver.ts",
    "importStyle": "checkAtserver",
    "description": "",
    "lineNumber": 69,
    "params": [
      {
        "nullable": null,
        "types": [
          "HookContext"
        ],
        "spread": false,
        "optional": false,
        "name": "context",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 80,
    "kind": "file",
    "name": "src/hooks/check-serverscripts.ts",
    "content": "import { satisfies as validVersion } from 'semver';\nimport { readNode } from '../api';\nimport { versionNode } from '../lib/server/scripts/version';\nimport { dependencies } from '../../package.json';\nimport { HookContext } from './hooks';\n\nexport default async function checkServerscripts({ log }: HookContext): Promise<void> {\n  log.debug('Checking installed serverscripts');\n\n  const required = dependencies['@atscm/server-scripts'];\n  let version;\n\n  try {\n    version = (await readNode(versionNode)).value;\n\n    const [release] = version.split('-beta');\n    const valid = validVersion(release, required);\n\n    if (!valid) throw new Error('Invalid version');\n\n    log.debug(`Serverscripts ${version} installed (${required} required)`);\n  } catch (error) {\n    throw Object.assign(\n      new Error(`Invalid server script version: ${version || 'not installed'} (${required} required)\n- Please run 'atscm import' again to update`),\n      { originalError: error }\n    );\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/hooks/check-serverscripts.ts",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 81,
    "kind": "function",
    "name": "checkServerscripts",
    "memberof": "src/hooks/check-serverscripts.ts",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/hooks/check-serverscripts.ts~checkServerscripts",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/hooks/check-serverscripts.ts",
    "importStyle": "checkServerscripts",
    "description": "",
    "lineNumber": 7,
    "params": [
      {
        "nullable": null,
        "types": [
          "HookContext"
        ],
        "spread": false,
        "optional": false,
        "name": "undefined",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 82,
    "kind": "file",
    "name": "src/hooks/hooks.ts",
    "content": "/* eslint-disable import/prefer-default-export */\n\nimport Logger from 'gulplog';\n\nexport interface HookContext {\n  continueOnError: boolean;\n  log: typeof Logger;\n}\n\nexport function setupContext({ log, continueOnError }: Partial<HookContext> = {}): HookContext {\n  return {\n    log: log || Logger,\n    continueOnError:\n      continueOnError === undefined ? process.env.CONTINUE_ON_FAILURE === 'true' : continueOnError,\n  };\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/hooks/hooks.ts",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 83,
    "kind": "function",
    "name": "setupContext",
    "memberof": "src/hooks/hooks.ts",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/hooks/hooks.ts~setupContext",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/hooks/hooks.ts",
    "importStyle": "{setupContext}",
    "description": "",
    "lineNumber": 10,
    "params": [
      {
        "nullable": null,
        "types": [
          "Partial"
        ],
        "spread": false,
        "optional": false,
        "name": "undefined",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "HookContext"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 84,
    "kind": "file",
    "name": "src/index.js",
    "content": "export { default as Atviseproject } from './lib/config/Atviseproject';\nexport { default as ProjectConfig } from './config/ProjectConfig';\nexport { default as NodeId } from './lib/model/opcua/NodeId';\nexport { default as Transformer, TransformDirection } from './lib/transform/Transformer';\nexport { default as PartialTransformer } from './lib/transform/PartialTransformer';\nexport { default as SplittingTransformer } from './lib/transform/SplittingTransformer';\nexport { default as DisplayTransformer } from './transform/DisplayTransformer';\nexport * from './transform/ScriptTransformer';\nexport { default as NewlinesTransformer } from './transform/Newlines';\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/index.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 85,
    "kind": "file",
    "name": "src/init/InitTask.js",
    "content": "import { join } from 'path';\nimport { src, dest } from 'gulp';\nimport handlebars from 'gulp-compile-handlebars';\nimport replace from 'gulp-replace';\nimport helpers from 'handlebars-helpers';\nimport streamToPromise from 'stream-to-promise';\nimport through from 'through2';\nimport camelCase from 'camelcase';\nimport deps from '../../res/init/templates/dependencies.json';\n\n/**\n * Converts a string to pascal case.\n * @param {string} str The string to convert.\n */\nconst pascalCase = (str) => camelCase(str, { pascalCase: true });\n\n/**\n * Converts a value to a valid JavaScript literal.\n * @param {any} value The value to convert.\n */\nconst toLiteral = (value) =>\n  ({\n    string: `'${value}'`,\n  }[typeof value] || JSON.stringify(value));\n\n/**\n * The action run when running \"atscm init\".\n */\nexport default class InitTask {\n  /**\n   * Returns the globs of the processed files for the given config lanugage.\n   * @param {string} langId The configuration language used.\n   * @return {string[]} Globs of the files to handle.\n   */\n  static filesToHandle(langId) {\n    return [\n      './general/**/*',\n      './general/**/.*',\n      `./lang/${langId}/**/*.*`,\n      `./lang/${langId}/**/.*`,\n    ].map((p) => join(__dirname, '../../res/init/templates', p));\n  }\n\n  /**\n   * Runs the task with the given options.\n   * @param {Object} options The options to use.\n   * @return {Promise<{ install: string[] }, Error>} Resolved with information on further actions\n   * to run or rejected if the task failed.\n   */\n  static async run(options) {\n    const langId = options.configLang;\n\n    const install = deps.lang[langId];\n\n    const renameGitignore = through.obj((file, _, callback) => {\n      if (file.basename === 'gitignore') {\n        // eslint-disable-next-line no-param-reassign\n        file.basename = '.gitignore';\n      }\n\n      callback(null, file);\n    });\n\n    const stream = src(this.filesToHandle(langId), { dot: true })\n      .pipe(replace(/[\\s\\S]*\\/\\/\\* start output\\s*/, ''))\n      .pipe(replace('__CONFIG_CLASS_NAME__', pascalCase(options.name)))\n      .pipe(replace(/\\/\\/\\*\\s?/g, ''))\n      .pipe(replace(/__INIT__.([a-z]+)/gi, (_, name) => toLiteral(options[name])))\n      .pipe(renameGitignore)\n      .pipe(\n        handlebars(options, {\n          helpers: helpers(),\n        })\n      )\n      .pipe(dest('./'));\n\n    await streamToPromise(stream);\n\n    return { install };\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/init/InitTask.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 86,
    "kind": "function",
    "name": "pascalCase",
    "memberof": "src/init/InitTask.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/init/InitTask.js~pascalCase",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/init/InitTask.js",
    "importStyle": null,
    "description": "Converts a string to pascal case.",
    "lineNumber": 15,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "str",
        "description": "The string to convert."
      }
    ],
    "return": null,
    "ignore": true
  },
  {
    "__docId__": 87,
    "kind": "function",
    "name": "toLiteral",
    "memberof": "src/init/InitTask.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/init/InitTask.js~toLiteral",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/init/InitTask.js",
    "importStyle": null,
    "description": "Converts a value to a valid JavaScript literal.",
    "lineNumber": 21,
    "params": [
      {
        "nullable": null,
        "types": [
          "any"
        ],
        "spread": false,
        "optional": false,
        "name": "value",
        "description": "The value to convert."
      }
    ],
    "return": null,
    "ignore": true
  },
  {
    "__docId__": 88,
    "kind": "class",
    "name": "InitTask",
    "memberof": "src/init/InitTask.js",
    "static": true,
    "longname": "src/init/InitTask.js~InitTask",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/init/InitTask.js",
    "importStyle": "InitTask",
    "description": "The action run when running \"atscm init\".",
    "lineNumber": 29,
    "interface": false
  },
  {
    "__docId__": 89,
    "kind": "method",
    "name": "filesToHandle",
    "memberof": "src/init/InitTask.js~InitTask",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/init/InitTask.js~InitTask.filesToHandle",
    "access": "public",
    "description": "Returns the globs of the processed files for the given config lanugage.",
    "lineNumber": 35,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "langId",
        "description": "The configuration language used."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "string[]"
      ],
      "spread": false,
      "description": "Globs of the files to handle."
    }
  },
  {
    "__docId__": 90,
    "kind": "method",
    "name": "run",
    "memberof": "src/init/InitTask.js~InitTask",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/init/InitTask.js~InitTask.run",
    "access": "public",
    "description": "Runs the task with the given options.",
    "lineNumber": 50,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "The options to use."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise<{ install: string[] }, Error>"
      ],
      "spread": false,
      "description": "Resolved with information on further actions\nto run or rejected if the task failed."
    }
  },
  {
    "__docId__": 91,
    "kind": "file",
    "name": "src/init/Options.js",
    "content": "import { basename } from 'path';\nimport InitOption from '../lib/init/Option';\nimport Atviseproject from '../lib/config/Atviseproject';\nimport Validator from './OptionsValidator';\n\n/**\n * A map providing dirnames for config langs\n * @type {Map<String, String>}\n */\nexport const ConfigLangs = {\n  'ES2015 JavaScript': 'es2015',\n  'Regular JavaScript': 'es5',\n  TypeScript: 'ts',\n};\n\n/**\n * Suggests a project name based on the name of the directory 'atscm init' was called in.\n * @param {string} dirname The current working directory's name.\n * @return {string} The suggested name.\n */\nfunction projectName(dirname) {\n  if (dirname === 'atscm') {\n    return 'atscm-project';\n  }\n\n  return dirname;\n}\n\n/**\n * Options available for the \"atscm init\" command.\n * @type {Object}\n * @property {InitOption<input>} name The new project's name.\n * @property {InitOption<input>} description The new project's description.\n * @property {InitOption<input>} author The new project's author.\n * @property {InitOption<input>} atviseHost The new project's atvise server host.\n * @property {InitOption<input>} atvisePortOpc The new project's atvise server OPC port.\n * @property {InitOption<input>} atvisePortHttp The new project's atvise server HTTP port.\n * @property {InitOption<confirm>} useLogin If the new porject's atvise server requires login.\n * @property {InitOption<input>} atviseUsername The new project's atvise server login name.\n * @property {InitOption<input>} atvisePassword The new project's atvise server login password.\n * @property {InitOption<list>} configLang The language to use for the new project's configuration.\n */\nexport const InitOptions = {\n  name: new InitOption({\n    message: 'Project name',\n    default: projectName(basename(process.cwd())),\n    validate: Validator.name,\n  }),\n  description: new InitOption('Project description'),\n  author: new InitOption('Project author'),\n  atviseHost: new InitOption('Atvise server host', Atviseproject.host),\n  atvisePortOpc: new InitOption('Atvise OPC port', Atviseproject.port.opc),\n  atvisePortHttp: new InitOption('Atvise HTTP port', Atviseproject.port.http),\n  useLogin: new InitOption({\n    message: 'Does your atvise server require login',\n    type: 'confirm',\n    default: false,\n  }),\n  atviseUser: new InitOption({\n    message: ' - Username',\n    when: (answers) => answers.useLogin,\n  }),\n  atvisePassword: new InitOption({\n    message: ' - Password',\n    when: (answers) => answers.useLogin,\n  }),\n  configLang: new InitOption({\n    type: 'list',\n    message: 'Configuration language to use',\n    choices: Object.keys(ConfigLangs).map((name) => ({ name, value: ConfigLangs[name] })),\n  }),\n};\n\n/**\n * {@link InitOptions}, exported as an array. Required to run {@link Inquirer}.\n * @type {InitOption[]}\n */\nconst InitOptionsAsArray = Object.keys(InitOptions).map((name) =>\n  Object.assign({ name }, InitOptions[name])\n);\n\nexport default InitOptionsAsArray;\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/init/Options.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 92,
    "kind": "variable",
    "name": "ConfigLangs",
    "memberof": "src/init/Options.js",
    "static": true,
    "longname": "src/init/Options.js~ConfigLangs",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/init/Options.js",
    "importStyle": "{ConfigLangs}",
    "description": "A map providing dirnames for config langs",
    "lineNumber": 10,
    "type": {
      "nullable": null,
      "types": [
        "Map<String, String>"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 93,
    "kind": "function",
    "name": "projectName",
    "memberof": "src/init/Options.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/init/Options.js~projectName",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/init/Options.js",
    "importStyle": null,
    "description": "Suggests a project name based on the name of the directory 'atscm init' was called in.",
    "lineNumber": 21,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "dirname",
        "description": "The current working directory's name."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": "The suggested name."
    },
    "ignore": true
  },
  {
    "__docId__": 94,
    "kind": "variable",
    "name": "InitOptions",
    "memberof": "src/init/Options.js",
    "static": true,
    "longname": "src/init/Options.js~InitOptions",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/init/Options.js",
    "importStyle": "{InitOptions}",
    "description": "Options available for the \"atscm init\" command.",
    "lineNumber": 43,
    "properties": [
      {
        "nullable": null,
        "types": [
          "InitOption<input>"
        ],
        "spread": false,
        "optional": false,
        "name": "name",
        "description": "The new project's name."
      },
      {
        "nullable": null,
        "types": [
          "InitOption<input>"
        ],
        "spread": false,
        "optional": false,
        "name": "description",
        "description": "The new project's description."
      },
      {
        "nullable": null,
        "types": [
          "InitOption<input>"
        ],
        "spread": false,
        "optional": false,
        "name": "author",
        "description": "The new project's author."
      },
      {
        "nullable": null,
        "types": [
          "InitOption<input>"
        ],
        "spread": false,
        "optional": false,
        "name": "atviseHost",
        "description": "The new project's atvise server host."
      },
      {
        "nullable": null,
        "types": [
          "InitOption<input>"
        ],
        "spread": false,
        "optional": false,
        "name": "atvisePortOpc",
        "description": "The new project's atvise server OPC port."
      },
      {
        "nullable": null,
        "types": [
          "InitOption<input>"
        ],
        "spread": false,
        "optional": false,
        "name": "atvisePortHttp",
        "description": "The new project's atvise server HTTP port."
      },
      {
        "nullable": null,
        "types": [
          "InitOption<confirm>"
        ],
        "spread": false,
        "optional": false,
        "name": "useLogin",
        "description": "If the new porject's atvise server requires login."
      },
      {
        "nullable": null,
        "types": [
          "InitOption<input>"
        ],
        "spread": false,
        "optional": false,
        "name": "atviseUsername",
        "description": "The new project's atvise server login name."
      },
      {
        "nullable": null,
        "types": [
          "InitOption<input>"
        ],
        "spread": false,
        "optional": false,
        "name": "atvisePassword",
        "description": "The new project's atvise server login password."
      },
      {
        "nullable": null,
        "types": [
          "InitOption<list>"
        ],
        "spread": false,
        "optional": false,
        "name": "configLang",
        "description": "The language to use for the new project's configuration."
      }
    ],
    "type": {
      "nullable": null,
      "types": [
        "Object"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 95,
    "kind": "variable",
    "name": "InitOptionsAsArray",
    "memberof": "src/init/Options.js",
    "static": true,
    "longname": "src/init/Options.js~InitOptionsAsArray",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/init/Options.js",
    "importStyle": "InitOptionsAsArray",
    "description": "{@link InitOptions}, exported as an array. Required to run {@link Inquirer}.",
    "lineNumber": 78,
    "type": {
      "nullable": null,
      "types": [
        "InitOption[]"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 96,
    "kind": "file",
    "name": "src/init/OptionsValidator.js",
    "content": "import validatePackageName from 'validate-npm-package-name';\n\n/**\n * A static class containing validators for the options used when running \"atscm init\".\n */\nexport default class InitOptionsValidator {\n  /**\n   * Validates a project name to be a valid npm package name.\n   * @param {string} value The name to validate.\n   * @return {boolean|string} Returns true if `value` is a valid npm package name, or an error\n   * message otherwise.\n   */\n  static name(value) {\n    const result = validatePackageName(value);\n\n    if (result.errors) {\n      return result.errors[0];\n    }\n\n    // First letter must be a letter\n    if (value.match(/^@?[a-z]+/i) === null) {\n      return 'name must start with a letter';\n    }\n\n    if (value === 'atscm') {\n      return \"'atscm' is not allowed\";\n    }\n\n    return result.validForNewPackages ? true : result.warnings[0];\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/init/OptionsValidator.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 97,
    "kind": "class",
    "name": "InitOptionsValidator",
    "memberof": "src/init/OptionsValidator.js",
    "static": true,
    "longname": "src/init/OptionsValidator.js~InitOptionsValidator",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/init/OptionsValidator.js",
    "importStyle": "InitOptionsValidator",
    "description": "A static class containing validators for the options used when running \"atscm init\".",
    "lineNumber": 6,
    "interface": false
  },
  {
    "__docId__": 98,
    "kind": "method",
    "name": "name",
    "memberof": "src/init/OptionsValidator.js~InitOptionsValidator",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/init/OptionsValidator.js~InitOptionsValidator.name",
    "access": "public",
    "description": "Validates a project name to be a valid npm package name.",
    "lineNumber": 13,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "value",
        "description": "The name to validate."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "boolean",
        "string"
      ],
      "spread": false,
      "description": "Returns true if `value` is a valid npm package name, or an error\nmessage otherwise."
    }
  },
  {
    "__docId__": 99,
    "kind": "file",
    "name": "src/init/init.js",
    "content": "import InitTask from './InitTask';\n\nexport default InitTask.run.bind(InitTask);\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/init/init.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 100,
    "kind": "file",
    "name": "src/lib/coding.js",
    "content": "import { DataType, VariantArrayType, Variant } from 'node-opcua/lib/datamodel/variant';\nimport { resolveNodeId } from 'node-opcua/lib/datamodel/nodeid';\nimport { LocalizedText } from 'node-opcua/lib/datamodel/localized_text';\nimport { StatusCodes } from 'node-opcua/lib/datamodel/opcua_status_code';\nimport { QualifiedName } from 'node-opcua/lib/datamodel/qualified_name';\nimport { DataValue } from 'node-opcua/lib/datamodel/datavalue';\nimport { ExpandedNodeId } from 'node-opcua/lib/datamodel/expanded_nodeid';\nimport { DiagnosticInfo } from 'node-opcua/lib/datamodel/diagnostic_info';\nimport { pick } from './helpers/Object';\n\n/**\n * Function that returns the passed argument as is.\n * @param {*} b The input argument.\n * @return {*} The value passed.\n */\nconst asIs = (b) => b;\n\n/**\n * Maps a single property of an object using the the mapper defined in *map* for the given\n * *dataType*.\n * @param {Map<node-opcua~DataType, function} map The mappings to use.\n * @param {Object} obj The object to process.\n * @param {string} key Name of the property to map.\n * @param {node-opcua~DataType} dataType The data type to map the property to.\n */\nconst mapPropertyAs = (map, obj, key, dataType) => {\n  if (obj[key]) {\n    return Object.assign(obj, {\n      [key]: map[dataType](obj[key]),\n    });\n  }\n\n  return obj;\n};\n\n/**\n * A set of functions that return raw values from {@link node-opcua~Variant} for specific\n * {@link node-opcua~DataType}s.\n * @type {Map<node-opcua~DataType, function(value: any): any>}\n */\nconst toRawValue = {\n  [DataType.Null]: () => null,\n  [DataType.StatusCode]: ({ name }) => name,\n  [DataType.QualifiedName]: ({ namespaceIndex, name }) => ({ namespaceIndex, name }),\n  [DataType.LocalizedText]: ({ text, locale }) => ({ text: text || null, locale }),\n  [DataType.DataValue]: (value) => {\n    const options = pick(value, [\n      'value',\n      'statusCode',\n      'sourceTimestamp',\n      'sourcePicoseconds',\n      'serverTimestamp',\n      'serverPicoseconds',\n    ]);\n\n    mapPropertyAs(toRawValue, options, 'value', DataType.Variant);\n    mapPropertyAs(toRawValue, options, 'statusCode', DataType.StatusCode);\n    // NOTE: server- and sourceTimstamps get mapped as dates\n\n    return options;\n  },\n  [DataType.Variant]: ({ dataType, arrayType, value, dimensions }) => ({\n    dataType,\n    arrayType,\n    // eslint-disable-next-line no-use-before-define\n    value: getRawValue({ value, dataType, arrayType }),\n    dimensions,\n  }),\n  [DataType.DiagnosticInfo]: (info) => {\n    const options = pick(info, [\n      'namespaceUri',\n      'symbolicId',\n      'locale',\n      'localizedText',\n      'additionalInfo',\n      'innerStatusCode',\n      'innerDiagnosticInfo',\n    ]);\n\n    mapPropertyAs(toRawValue, options, 'innerStatusCode', DataType.StatusCode);\n    mapPropertyAs(toRawValue, options, 'innerDiagnosticInfo', DataType.DiagnosticInfo);\n\n    return options;\n  },\n};\n\n/**\n * Returns the raw value for a {@link node-opcua~Variant}.\n * @param {node-opcua~Variant} variant The variant to convert.\n */\nfunction getRawValue({ value, dataType, arrayType }) {\n  if (arrayType !== VariantArrayType.Scalar) {\n    return (Array.isArray(value) ? value : Array.from(value)).map((val) =>\n      getRawValue({\n        value: val,\n        dataType,\n        arrayType: VariantArrayType[arrayType.value - 1],\n      })\n    );\n  }\n\n  return (toRawValue[dataType] || asIs)(value);\n}\n\n/**\n * Returns a buffer containing a {@link node-opcua~Variant}s encoded value.\n * @param {node-opcua~Variant} variant The variant to encode.\n * @return {Buffer} A buffer containing the encoded value.\n */\nexport function encodeVariant({ value, dataType, arrayType }) {\n  if (value === null) {\n    return Buffer.from([]);\n  }\n\n  const rawValue = getRawValue({ value, dataType, arrayType });\n\n  if (rawValue instanceof Buffer) {\n    return rawValue;\n  }\n\n  const stringify = (a) => (a.toJSON ? a.toJSON() : JSON.stringify(a, null, '  '));\n\n  const stringified =\n    typeof rawValue === 'object' ? stringify(rawValue) : rawValue.toString().trim();\n\n  return Buffer.from(stringified);\n}\n\n/**\n * Decodes a buffer to a string.\n * @param {Buffer} b The buffer to decode from.\n * @return {string} The buffer's string representation.\n */\nconst decodeAsString = (b) => b.toString().trim();\n\n/**\n * Decodes a buffer to an integer value.\n * @param {Buffer} b The buffer to decode from.\n * @return {number} The decoded integer.\n */\nconst decodeAsInt = (b) => parseInt(decodeAsString(b), 10);\n\n/**\n * Decodes a buffer to a float value.\n * @param {Buffer} b The buffer to decode from.\n * @return {number} The decoded float.\n */\nconst decodeAsFloat = (b) => parseFloat(decodeAsString(b));\n\n/**\n * Decodes a buffer using JSON.\n * @param {Buffer} b The buffer to decode from.\n * @return {*} The decoded value, most likely an Object.\n */\nconst decodeAsJson = (b) => JSON.parse(b.toString());\n\n/**\n * Mapping functions that return raw values for a stored value of the given type.\n * @type {Map<node-opcua~DataType, function>}\n */\nconst decodeRawValue = {\n  [DataType.Null]: () => null,\n  [DataType.Boolean]: (b) => decodeAsString(b) === 'true',\n  [DataType.SByte]: decodeAsInt,\n  [DataType.Byte]: decodeAsInt,\n  [DataType.Int16]: decodeAsInt,\n  [DataType.UInt16]: decodeAsInt,\n  [DataType.Int32]: decodeAsInt,\n  [DataType.UInt32]: decodeAsInt,\n  [DataType.Int64]: decodeAsJson,\n  [DataType.UInt64]: decodeAsJson,\n  [DataType.Float]: decodeAsFloat,\n  [DataType.Double]: decodeAsFloat,\n  [DataType.String]: decodeAsString,\n  [DataType.DateTime]: decodeAsString,\n  [DataType.Guid]: decodeAsString,\n  // ByteString maps to Buffer\n  [DataType.XmlElement]: decodeAsString,\n  [DataType.NodeId]: decodeAsString,\n  [DataType.ExpandedNodeId]: decodeAsString,\n  [DataType.StatusCode]: decodeAsString,\n  [DataType.QualifiedName]: decodeAsJson,\n  [DataType.LocalizedText]: decodeAsJson,\n  // FIXME: Add ExtensionObject\n  [DataType.DataValue]: decodeAsJson,\n  [DataType.Variant]: decodeAsJson,\n  [DataType.DiagnosticInfo]: decodeAsJson,\n};\n\n/**\n * Mapping functions that return OPC-UA node values for raw values.\n * @type {Map<node-opcua~DataType, function>}\n */\nconst toNodeValue = {\n  [DataType.DateTime]: (s) => new Date(s),\n  [DataType.ByteString]: (b) => {\n    if (b instanceof Buffer) {\n      return b;\n    }\n\n    return Buffer.from(b.data, 'binary');\n  },\n  [DataType.NodeId]: (s) => resolveNodeId(s),\n\n  // Jep, node-opcua does not provide a resolve function for expanded nodeids\n  [DataType.ExpandedNodeId]: (s) => {\n    const nodeId = resolveNodeId(s);\n    const [value, ...defs] = nodeId.value.split(';');\n\n    const { identifierType, namespace, namespaceUri, serverIndex } = defs.reduce((opts, def) => {\n      const match = def.match(/^([^:]+):(.*)/);\n      if (!match) {\n        return opts;\n      }\n\n      let [key, val] = match.slice(1); // eslint-disable-line prefer-const\n\n      if (key === 'serverIndex') {\n        val = parseInt(val, 10);\n      }\n\n      return Object.assign(opts, { [key]: val });\n    }, Object.assign({}, nodeId));\n\n    return new ExpandedNodeId(identifierType, value, namespace, namespaceUri, serverIndex);\n  },\n\n  [DataType.StatusCode]: (name) => StatusCodes[name],\n  [DataType.QualifiedName]: (options) => new QualifiedName(options),\n  [DataType.LocalizedText]: (options) => new LocalizedText(options),\n  [DataType.DataValue]: (options) => {\n    const opts = options;\n\n    mapPropertyAs(toNodeValue, opts, 'value', DataType.Variant);\n    mapPropertyAs(toNodeValue, opts, 'statusCode', DataType.StatusCode);\n    mapPropertyAs(toNodeValue, opts, 'sourceTimestamp', DataType.DateTime);\n    mapPropertyAs(toNodeValue, opts, 'serverTimestamp', DataType.DateTime);\n\n    return new DataValue(opts);\n  },\n  [DataType.Variant]: ({ dataType, arrayType, value, dimensions }) =>\n    new Variant({\n      dataType,\n      arrayType: VariantArrayType[arrayType],\n      value,\n      dimensions,\n    }),\n  [DataType.DiagnosticInfo]: (options) => {\n    const opts = options;\n\n    mapPropertyAs(toNodeValue, opts, 'innerStatusCode', DataType.StatusCode);\n    mapPropertyAs(toNodeValue, opts, 'innerDiagnosticInfo', DataType.DiagnosticInfo);\n\n    return new DiagnosticInfo(opts);\n  },\n};\n\n/**\n * Returns a node's OPC-UA value based on it's raw value and type.\n * @param {*} rawValue A node's raw value.\n * @param {node-opcua~DataType} dataType A node's data type.\n * @param {node-opcua~VariantArrayType} arrayType A node's array type.\n */\nconst getNodeValue = (rawValue, dataType, arrayType) => {\n  if (arrayType.value !== VariantArrayType.Scalar.value) {\n    if (!Array.isArray(rawValue)) {\n      throw new Error('Value is not an array');\n    }\n\n    return rawValue.map((raw) =>\n      getNodeValue(raw, dataType, VariantArrayType[arrayType.value - 1])\n    );\n  }\n\n  return (toNodeValue[dataType] || asIs)(rawValue);\n};\n\n/**\n * Returns a {@link node-opcua~Variant} from a Buffer with the given *dataType* and *arrayType*.\n * @param {Buffer} buffer The buffer to decode from.\n * @param {Object} options The options to use.\n * @param {node-opcua~DataType} options.dataType The data type to decode to.\n * @param {node-opcua~VariantArrayType} options.arrayType The array type to decode to.\n */\nexport function decodeVariant(buffer, { dataType, arrayType }) {\n  if (buffer === null || buffer.length === 0) {\n    return null;\n  }\n\n  if (dataType === DataType.ByteString && arrayType === VariantArrayType.Scalar) {\n    return buffer;\n  }\n\n  const rawValue =\n    arrayType === VariantArrayType.Scalar\n      ? (decodeRawValue[dataType] || asIs)(buffer)\n      : JSON.parse(buffer.toString());\n\n  return getNodeValue(rawValue, dataType, arrayType);\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/coding.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 101,
    "kind": "function",
    "name": "asIs",
    "memberof": "src/lib/coding.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/coding.js~asIs",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/coding.js",
    "importStyle": null,
    "description": "Function that returns the passed argument as is.",
    "lineNumber": 16,
    "params": [
      {
        "nullable": null,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "b",
        "description": "The input argument."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "*"
      ],
      "spread": false,
      "description": "The value passed."
    },
    "ignore": true
  },
  {
    "__docId__": 102,
    "kind": "function",
    "name": "mapPropertyAs",
    "memberof": "src/lib/coding.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/coding.js~mapPropertyAs",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/coding.js",
    "importStyle": null,
    "description": "Maps a single property of an object using the the mapper defined in *map* for the given\n*dataType*.",
    "lineNumber": 26,
    "params": [
      {
        "nullable": null,
        "types": [
          "Map<node-opcua~DataType, function"
        ],
        "spread": false,
        "optional": false,
        "name": "map",
        "description": "The mappings to use."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "obj",
        "description": "The object to process."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "key",
        "description": "Name of the property to map."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~DataType"
        ],
        "spread": false,
        "optional": false,
        "name": "dataType",
        "description": "The data type to map the property to."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    },
    "ignore": true
  },
  {
    "__docId__": 103,
    "kind": "variable",
    "name": "toRawValue",
    "memberof": "src/lib/coding.js",
    "static": true,
    "longname": "src/lib/coding.js~toRawValue",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/coding.js",
    "importStyle": null,
    "description": "A set of functions that return raw values from {@link node-opcua~Variant} for specific\n{@link node-opcua~DataType}s.",
    "lineNumber": 41,
    "type": {
      "nullable": null,
      "types": [
        "Map<node-opcua~DataType, function(value: any): any>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 104,
    "kind": "function",
    "name": "getRawValue",
    "memberof": "src/lib/coding.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/coding.js~getRawValue",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/coding.js",
    "importStyle": null,
    "description": "Returns the raw value for a {@link node-opcua~Variant}.",
    "lineNumber": 91,
    "params": [
      {
        "nullable": null,
        "types": [
          "node-opcua~Variant"
        ],
        "spread": false,
        "optional": false,
        "name": "variant",
        "description": "The variant to convert."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    },
    "ignore": true
  },
  {
    "__docId__": 105,
    "kind": "function",
    "name": "encodeVariant",
    "memberof": "src/lib/coding.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/coding.js~encodeVariant",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/coding.js",
    "importStyle": "{encodeVariant}",
    "description": "Returns a buffer containing a {@link node-opcua~Variant}s encoded value.",
    "lineNumber": 110,
    "params": [
      {
        "nullable": null,
        "types": [
          "node-opcua~Variant"
        ],
        "spread": false,
        "optional": false,
        "name": "variant",
        "description": "The variant to encode."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Buffer"
      ],
      "spread": false,
      "description": "A buffer containing the encoded value."
    }
  },
  {
    "__docId__": 106,
    "kind": "function",
    "name": "decodeAsString",
    "memberof": "src/lib/coding.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/coding.js~decodeAsString",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/coding.js",
    "importStyle": null,
    "description": "Decodes a buffer to a string.",
    "lineNumber": 134,
    "params": [
      {
        "nullable": null,
        "types": [
          "Buffer"
        ],
        "spread": false,
        "optional": false,
        "name": "b",
        "description": "The buffer to decode from."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": "The buffer's string representation."
    },
    "ignore": true
  },
  {
    "__docId__": 107,
    "kind": "function",
    "name": "decodeAsInt",
    "memberof": "src/lib/coding.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/coding.js~decodeAsInt",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/coding.js",
    "importStyle": null,
    "description": "Decodes a buffer to an integer value.",
    "lineNumber": 141,
    "params": [
      {
        "nullable": null,
        "types": [
          "Buffer"
        ],
        "spread": false,
        "optional": false,
        "name": "b",
        "description": "The buffer to decode from."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "number"
      ],
      "spread": false,
      "description": "The decoded integer."
    },
    "ignore": true
  },
  {
    "__docId__": 108,
    "kind": "function",
    "name": "decodeAsFloat",
    "memberof": "src/lib/coding.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/coding.js~decodeAsFloat",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/coding.js",
    "importStyle": null,
    "description": "Decodes a buffer to a float value.",
    "lineNumber": 148,
    "params": [
      {
        "nullable": null,
        "types": [
          "Buffer"
        ],
        "spread": false,
        "optional": false,
        "name": "b",
        "description": "The buffer to decode from."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "number"
      ],
      "spread": false,
      "description": "The decoded float."
    },
    "ignore": true
  },
  {
    "__docId__": 109,
    "kind": "function",
    "name": "decodeAsJson",
    "memberof": "src/lib/coding.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/coding.js~decodeAsJson",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/coding.js",
    "importStyle": null,
    "description": "Decodes a buffer using JSON.",
    "lineNumber": 155,
    "params": [
      {
        "nullable": null,
        "types": [
          "Buffer"
        ],
        "spread": false,
        "optional": false,
        "name": "b",
        "description": "The buffer to decode from."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "*"
      ],
      "spread": false,
      "description": "The decoded value, most likely an Object."
    },
    "ignore": true
  },
  {
    "__docId__": 110,
    "kind": "variable",
    "name": "decodeRawValue",
    "memberof": "src/lib/coding.js",
    "static": true,
    "longname": "src/lib/coding.js~decodeRawValue",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/coding.js",
    "importStyle": null,
    "description": "Mapping functions that return raw values for a stored value of the given type.",
    "lineNumber": 161,
    "type": {
      "nullable": null,
      "types": [
        "Map<node-opcua~DataType, function>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 111,
    "kind": "variable",
    "name": "toNodeValue",
    "memberof": "src/lib/coding.js",
    "static": true,
    "longname": "src/lib/coding.js~toNodeValue",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/coding.js",
    "importStyle": null,
    "description": "Mapping functions that return OPC-UA node values for raw values.",
    "lineNumber": 194,
    "type": {
      "nullable": null,
      "types": [
        "Map<node-opcua~DataType, function>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 112,
    "kind": "function",
    "name": "getNodeValue",
    "memberof": "src/lib/coding.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/coding.js~getNodeValue",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/coding.js",
    "importStyle": null,
    "description": "Returns a node's OPC-UA value based on it's raw value and type.",
    "lineNumber": 264,
    "params": [
      {
        "nullable": null,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "rawValue",
        "description": "A node's raw value."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~DataType"
        ],
        "spread": false,
        "optional": false,
        "name": "dataType",
        "description": "A node's data type."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~VariantArrayType"
        ],
        "spread": false,
        "optional": false,
        "name": "arrayType",
        "description": "A node's array type."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    },
    "ignore": true
  },
  {
    "__docId__": 113,
    "kind": "function",
    "name": "decodeVariant",
    "memberof": "src/lib/coding.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/coding.js~decodeVariant",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/coding.js",
    "importStyle": "{decodeVariant}",
    "description": "Returns a {@link node-opcua~Variant} from a Buffer with the given *dataType* and *arrayType*.",
    "lineNumber": 285,
    "params": [
      {
        "nullable": null,
        "types": [
          "Buffer"
        ],
        "spread": false,
        "optional": false,
        "name": "buffer",
        "description": "The buffer to decode from."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "The options to use."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~DataType"
        ],
        "spread": false,
        "optional": false,
        "name": "options.dataType",
        "description": "The data type to decode to."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~VariantArrayType"
        ],
        "spread": false,
        "optional": false,
        "name": "options.arrayType",
        "description": "The array type to decode to."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 114,
    "kind": "file",
    "name": "src/lib/config/Atviseproject.ts",
    "content": "/* eslint-disable no-useless-escape */\n\nimport NodeId from '../model/opcua/NodeId';\nimport DisplayTransformer from '../../transform/DisplayTransformer';\nimport {\n  ServerscriptTransformer,\n  QuickDynamicTransformer,\n  DisplayScriptTransformer,\n} from '../../transform/ScriptTransformer';\nimport MappingTransformer from '../../transform/Mapping';\nimport AlarmConfigTransformer from '../../transform/AlarmConfigTransformer';\nimport { Transformer } from '../..';\n\ninterface AtserverPortConfiguration {\n  /** The OPC-UA port the atvise-server runs on. */\n  opc: number;\n  /** The HTTP port the atvise-server can be reached at. */\n  http: number;\n}\n\ninterface AtserverCredentials {\n  /** The username to log in with. */\n  username: string;\n  /** The password to log in with. */\n  password: string;\n}\n\ntype NodesConfiguration = Array<string | NodeId>;\n\n/**\n * An *atscm* project's configuration.\n * @abstract\n */\nexport default class Atviseproject {\n  /**\n   * The atvise-server's host. Defaults to *localhost*.\n   */\n  static get host(): string {\n    return 'localhost';\n  }\n\n  /**\n   * The atvise-server ports to use.\n   */\n  static get port(): AtserverPortConfiguration {\n    return {\n      opc: 4840,\n      http: 80,\n    };\n  }\n\n  /**\n   * The login to use. Return `false` if no login is required (default).\n   */\n  static get login(): false | AtserverCredentials {\n    return false;\n  }\n\n  private static get xmlTransformerOptions() {\n    return {\n      sortXMLAttributes: this.sortXMLAttributes,\n      removeBuilderRefs: this.removeBuilderRefs,\n    };\n  }\n\n  /**\n   * The transformers to use in this project. Returns a {@link DisplayTransformer}, a\n   * {@link ScriptTransformer} and a {@link NewlinesTransformer} by default.\n   */\n  static get useTransformers(): Transformer[] {\n    return [\n      new AlarmConfigTransformer(),\n      new DisplayTransformer(this.xmlTransformerOptions),\n      new ServerscriptTransformer(this.xmlTransformerOptions),\n      new QuickDynamicTransformer(this.xmlTransformerOptions),\n      new DisplayScriptTransformer(this.xmlTransformerOptions),\n      new MappingTransformer() as any,\n    ];\n  }\n\n  /**\n   * The atvise-server nodes that atscm should sync. Defaults to the nodes *AGENT*, *SYSTEM*,\n   * *ObjectTypes.PROJECT* and *VariableTypes.PROJECT*.\n   */\n  static get nodes(): NodesConfiguration {\n    return [\n      new NodeId('AGENT'),\n      new NodeId('SYSTEM'),\n      new NodeId('ObjectTypes.PROJECT'),\n      new NodeId('VariableTypes.PROJECT'),\n    ];\n  }\n\n  /**\n   * The atvise-server nodes to watch in the corresponding tasks. Defaults to all nodes containing\n   * displays.\n   */\n  static get nodesToWatch(): NodesConfiguration {\n    return [new NodeId('AGENT.DISPLAYS'), new NodeId('SYSTEM.LIBRARY.PROJECT.OBJECTDISPLAYS')];\n  }\n\n  /**\n   * An array of editor related node ids. They should be ignored in a atscm project.\n   */\n  static get EditorRelatedNodes(): NodesConfiguration {\n    return [new NodeId('SYSTEM.JOURNALS.ProjectHistory')];\n  }\n\n  /**\n   * An array of server related node ids. They should be ignored in a atscm project\n   * as they are read-only.\n   */\n  static get ServerRelatedNodes(): NodesConfiguration {\n    return [\n      new NodeId('AGENT.OPCUA.server_url'),\n      new NodeId('AGENT.WEBACCESS.https?[^.]+.(state)'),\n      new NodeId('SYSTEM.INFORMATION.LOGS.'),\n      new NodeId('AGENT.GENERATOR.METHODS'),\n      new NodeId('AGENT.MIRROR.METHODS'),\n      new NodeId('AGENT.HISTORY.METHODS'),\n      new NodeId('AGENT.SCRIPT.METHODS'),\n      new NodeId('AGENT.OPCUA.METHODS'),\n      new NodeId('AGENT.ALARMING.METHODS'),\n    ];\n  }\n\n  /**\n   * Server nodes atscm manages itself. These include the serverscripts used during pull/push for\n   * example.\n   */\n  static get AtscmRelatedNodes(): NodesConfiguration {\n    return [new NodeId('SYSTEM.LIBRARY.ATVISE.SERVERSCRIPTS.atscm')];\n  }\n\n  /**\n   * These nodes (and their subnodes, if any) will be ignored by atscm. Defaults to\n   * {@link Atviseproject.EditorRelatedNodes} combined with\n   * {@link Atviseproject.ServerRelatedNodes}.\n   */\n  static get ignoreNodes(): NodesConfiguration {\n    return [...this.EditorRelatedNodes, ...this.ServerRelatedNodes, ...this.AtscmRelatedNodes];\n  }\n\n  /**\n   * Returns an object containing the properties to inspect.\n   * @see https://nodejs.org/api/util.html#util_util_inspect_object_options\n   */\n  static inspect() {\n    return {\n      host: this.host,\n      port: this.port,\n      login: this.login,\n      useTransformers: this.useTransformers,\n      nodes: this.nodes,\n      nodesToWatch: this.nodesToWatch,\n      ignoreNodes: this.ignoreNodes,\n    };\n  }\n\n  /**\n   * The *version control system* to optimize tasks for.\n   * @since 1.0.0\n   */\n  static get vcs(): 'git' | 'svn' {\n    return 'git';\n  }\n\n  /**\n   * If atvise builder sort order nodes should be stored.\n   * @since 1.0.0\n   * @deprecated Mapping source order nodes leads to inconsistent results in many cases.\n   */\n  static get preserveSortOrderNodes(): boolean {\n    return false;\n  }\n\n  /**\n   * The connection timeout, in milliseconds.\n   */\n  static get timeout(): number {\n    return 10000;\n  }\n\n  /**\n   * Remove `atv:refpx` and `atv:refpy` attributes from XML to minimize diffs between pulls. This\n   * will eventually default to *true* in a future atscm version.\n   */\n  static get removeBuilderRefs(): boolean {\n    return false;\n  }\n\n  /**\n   * Sort XML attributes to minimize diffs between pulls. This will eventually default to *true* in\n   * a future atscm version.\n   */\n  static get sortXMLAttributes(): boolean {\n    return false;\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/config/Atviseproject.ts",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 115,
    "kind": "class",
    "name": "Atviseproject",
    "memberof": "src/lib/config/Atviseproject.ts",
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/config/Atviseproject.ts",
    "importStyle": "Atviseproject",
    "description": "An *atscm* project's configuration.",
    "lineNumber": 34,
    "interface": false
  },
  {
    "__docId__": 116,
    "kind": "get",
    "name": "host",
    "memberof": "src/lib/config/Atviseproject.ts~Atviseproject",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject.host",
    "access": "public",
    "description": "The atvise-server's host. Defaults to *localhost*.",
    "lineNumber": 38,
    "type": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 117,
    "kind": "get",
    "name": "port",
    "memberof": "src/lib/config/Atviseproject.ts~Atviseproject",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject.port",
    "access": "public",
    "description": "The atvise-server ports to use.",
    "lineNumber": 45,
    "type": {
      "nullable": null,
      "types": [
        "AtserverPortConfiguration"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 118,
    "kind": "get",
    "name": "login",
    "memberof": "src/lib/config/Atviseproject.ts~Atviseproject",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject.login",
    "access": "public",
    "description": "The login to use. Return `false` if no login is required (default).",
    "lineNumber": 55,
    "type": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 119,
    "kind": "get",
    "name": "xmlTransformerOptions",
    "memberof": "src/lib/config/Atviseproject.ts~Atviseproject",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject.xmlTransformerOptions",
    "access": "public",
    "description": "",
    "lineNumber": 59,
    "type": {
      "types": [
        "{\"sortXMLAttributes\": *, \"removeBuilderRefs\": *}"
      ]
    }
  },
  {
    "__docId__": 120,
    "kind": "get",
    "name": "useTransformers",
    "memberof": "src/lib/config/Atviseproject.ts~Atviseproject",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject.useTransformers",
    "access": "public",
    "description": "The transformers to use in this project. Returns a {@link DisplayTransformer}, a\n{@link ScriptTransformer} and a {@link NewlinesTransformer} by default.",
    "lineNumber": 70,
    "type": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 121,
    "kind": "get",
    "name": "nodes",
    "memberof": "src/lib/config/Atviseproject.ts~Atviseproject",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject.nodes",
    "access": "public",
    "description": "The atvise-server nodes that atscm should sync. Defaults to the nodes *AGENT*, *SYSTEM*,\nObjectTypes.PROJECT* and *VariableTypes.PROJECT*.",
    "lineNumber": 85,
    "type": {
      "nullable": null,
      "types": [
        "NodesConfiguration"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 122,
    "kind": "get",
    "name": "nodesToWatch",
    "memberof": "src/lib/config/Atviseproject.ts~Atviseproject",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject.nodesToWatch",
    "access": "public",
    "description": "The atvise-server nodes to watch in the corresponding tasks. Defaults to all nodes containing\ndisplays.",
    "lineNumber": 98,
    "type": {
      "nullable": null,
      "types": [
        "NodesConfiguration"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 123,
    "kind": "get",
    "name": "EditorRelatedNodes",
    "memberof": "src/lib/config/Atviseproject.ts~Atviseproject",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject.EditorRelatedNodes",
    "access": "public",
    "description": "An array of editor related node ids. They should be ignored in a atscm project.",
    "lineNumber": 105,
    "type": {
      "nullable": null,
      "types": [
        "NodesConfiguration"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 124,
    "kind": "get",
    "name": "ServerRelatedNodes",
    "memberof": "src/lib/config/Atviseproject.ts~Atviseproject",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject.ServerRelatedNodes",
    "access": "public",
    "description": "An array of server related node ids. They should be ignored in a atscm project\nas they are read-only.",
    "lineNumber": 113,
    "type": {
      "nullable": null,
      "types": [
        "NodesConfiguration"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 125,
    "kind": "get",
    "name": "AtscmRelatedNodes",
    "memberof": "src/lib/config/Atviseproject.ts~Atviseproject",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject.AtscmRelatedNodes",
    "access": "public",
    "description": "Server nodes atscm manages itself. These include the serverscripts used during pull/push for\nexample.",
    "lineNumber": 131,
    "type": {
      "nullable": null,
      "types": [
        "NodesConfiguration"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 126,
    "kind": "get",
    "name": "ignoreNodes",
    "memberof": "src/lib/config/Atviseproject.ts~Atviseproject",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject.ignoreNodes",
    "access": "public",
    "description": "These nodes (and their subnodes, if any) will be ignored by atscm. Defaults to\n{@link Atviseproject.EditorRelatedNodes} combined with\n{@link Atviseproject.ServerRelatedNodes}.",
    "lineNumber": 140,
    "type": {
      "nullable": null,
      "types": [
        "NodesConfiguration"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 127,
    "kind": "method",
    "name": "inspect",
    "memberof": "src/lib/config/Atviseproject.ts~Atviseproject",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject.inspect",
    "access": "public",
    "description": "Returns an object containing the properties to inspect.",
    "lineNumber": 148,
    "params": [],
    "return": {
      "types": [
        "{\"host\": *, \"port\": *, \"login\": *, \"useTransformers\": *, \"nodes\": *, \"nodesToWatch\": *, \"ignoreNodes\": *}"
      ]
    }
  },
  {
    "__docId__": 128,
    "kind": "get",
    "name": "vcs",
    "memberof": "src/lib/config/Atviseproject.ts~Atviseproject",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject.vcs",
    "access": "public",
    "description": "The *version control system* to optimize tasks for.",
    "lineNumber": 164,
    "type": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 129,
    "kind": "get",
    "name": "preserveSortOrderNodes",
    "memberof": "src/lib/config/Atviseproject.ts~Atviseproject",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject.preserveSortOrderNodes",
    "access": "public",
    "description": "If atvise builder sort order nodes should be stored.",
    "lineNumber": 173,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 130,
    "kind": "get",
    "name": "timeout",
    "memberof": "src/lib/config/Atviseproject.ts~Atviseproject",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject.timeout",
    "access": "public",
    "description": "The connection timeout, in milliseconds.",
    "lineNumber": 180,
    "type": {
      "nullable": null,
      "types": [
        "number"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 131,
    "kind": "get",
    "name": "removeBuilderRefs",
    "memberof": "src/lib/config/Atviseproject.ts~Atviseproject",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject.removeBuilderRefs",
    "access": "public",
    "description": "Remove `atv:refpx` and `atv:refpy` attributes from XML to minimize diffs between pulls. This\nwill eventually default to *true* in a future atscm version.",
    "lineNumber": 188,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 132,
    "kind": "get",
    "name": "sortXMLAttributes",
    "memberof": "src/lib/config/Atviseproject.ts~Atviseproject",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/config/Atviseproject.ts~Atviseproject.sortXMLAttributes",
    "access": "public",
    "description": "Sort XML attributes to minimize diffs between pulls. This will eventually default to *true* in\na future atscm version.",
    "lineNumber": 196,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 133,
    "kind": "file",
    "name": "src/lib/gulp/ImportStream.js",
    "content": "import { DataType } from 'node-opcua/lib/datamodel/variant';\nimport Logger from 'gulplog';\nimport NodeId from '../model/opcua/NodeId';\nimport CallMethodStream from '../server/scripts/CallMethodStream';\n\n/**\n * The import operation's scope, which is set to be *absolute*.\n * @type {NodeId}\n */\nconst scopeId = new NodeId(NodeId.NodeIdType.NUMERIC, 0, 0);\n\n/**\n * A stream that imports xml files in parallel.\n */\nexport default class ImportStream extends CallMethodStream {\n  /**\n   * Id of the `importNodes` OPC-UA method.\n   * @type {NodeId}\n   */\n  get methodId() {\n    return new NodeId('ns=1;s=AGENT.OPCUA.METHODS.importNodes');\n  }\n\n  /**\n   * Returns the arguments the `importNodes` needs to be called with for the given file.\n   * @param {vinyl~File} file The file being processed.\n   * @return {node-opcua~Variant[]} The arguments for the `importNodes` method:\n   *  - The import scope (which is set to be absolute)\n   *  - The XML code (read from *file*)\n   * .\n   */\n  inputArguments(file) {\n    return [\n      {\n        dataType: DataType.NodeId,\n        value: scopeId,\n      },\n      {\n        dataType: DataType.XmlElement,\n        value: file.contents,\n      },\n    ];\n  }\n\n  /**\n   * Returns an error message specifically for the given file.\n   * @param {vinyl~File} file The file to generate the error message for.\n   * @return {string} The specific error message.\n   */\n  processErrorMessage(file) {\n    return `Error importing file: ${file.relative}`;\n  }\n\n  /**\n   * Checks if the import succeeded and calls `callback` with an error otherwise.\n   * @param {vinyl~File} file The file that was processed.\n   * @param {?node-opcua~Variant[]} outputArguments The import status output arguments (Array with a\n   * single entry).\n   * @param {function(err: ?Error)} callback The callback called with an error if import failed.\n   */\n  handleOutputArguments(file, outputArguments, callback) {\n    const [importStatus] = outputArguments || [{}];\n\n    if (importStatus.value) {\n      Logger.debug(`Successfully imported file: ${file.relative}`);\n\n      callback(null);\n    } else {\n      callback(new Error('Import failed'));\n    }\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/gulp/ImportStream.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 134,
    "kind": "variable",
    "name": "scopeId",
    "memberof": "src/lib/gulp/ImportStream.js",
    "static": true,
    "longname": "src/lib/gulp/ImportStream.js~scopeId",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/gulp/ImportStream.js",
    "importStyle": null,
    "description": "The import operation's scope, which is set to be *absolute*.",
    "lineNumber": 10,
    "type": {
      "nullable": null,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 135,
    "kind": "class",
    "name": "ImportStream",
    "memberof": "src/lib/gulp/ImportStream.js",
    "static": true,
    "longname": "src/lib/gulp/ImportStream.js~ImportStream",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/gulp/ImportStream.js",
    "importStyle": "ImportStream",
    "description": "A stream that imports xml files in parallel.",
    "lineNumber": 15,
    "interface": false,
    "extends": [
      "src/lib/server/scripts/CallMethodStream.js~CallMethodStream"
    ]
  },
  {
    "__docId__": 136,
    "kind": "get",
    "name": "methodId",
    "memberof": "src/lib/gulp/ImportStream.js~ImportStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/ImportStream.js~ImportStream#methodId",
    "access": "public",
    "description": "Id of the `importNodes` OPC-UA method.",
    "lineNumber": 20,
    "type": {
      "nullable": null,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 137,
    "kind": "method",
    "name": "inputArguments",
    "memberof": "src/lib/gulp/ImportStream.js~ImportStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/ImportStream.js~ImportStream#inputArguments",
    "access": "public",
    "description": "Returns the arguments the `importNodes` needs to be called with for the given file.",
    "lineNumber": 32,
    "params": [
      {
        "nullable": null,
        "types": [
          "vinyl~File"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file being processed."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "node-opcua~Variant[]"
      ],
      "spread": false,
      "description": "The arguments for the `importNodes` method:\n - The import scope (which is set to be absolute)\n - The XML code (read from *file*)\n."
    }
  },
  {
    "__docId__": 138,
    "kind": "method",
    "name": "processErrorMessage",
    "memberof": "src/lib/gulp/ImportStream.js~ImportStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/ImportStream.js~ImportStream#processErrorMessage",
    "access": "public",
    "description": "Returns an error message specifically for the given file.",
    "lineNumber": 50,
    "params": [
      {
        "nullable": null,
        "types": [
          "vinyl~File"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file to generate the error message for."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": "The specific error message."
    }
  },
  {
    "__docId__": 139,
    "kind": "method",
    "name": "handleOutputArguments",
    "memberof": "src/lib/gulp/ImportStream.js~ImportStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/ImportStream.js~ImportStream#handleOutputArguments",
    "access": "public",
    "description": "Checks if the import succeeded and calls `callback` with an error otherwise.",
    "lineNumber": 61,
    "params": [
      {
        "nullable": null,
        "types": [
          "vinyl~File"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file that was processed."
      },
      {
        "nullable": true,
        "types": [
          "node-opcua~Variant[]"
        ],
        "spread": false,
        "optional": false,
        "name": "outputArguments",
        "description": "The import status output arguments (Array with a\nsingle entry)."
      },
      {
        "nullable": null,
        "types": [
          "function(err: ?Error)"
        ],
        "spread": false,
        "optional": false,
        "name": "callback",
        "description": "The callback called with an error if import failed."
      }
    ],
    "return": null
  },
  {
    "__docId__": 140,
    "kind": "file",
    "name": "src/lib/gulp/PullStream.js",
    "content": "import readline from 'readline';\nimport Logger from 'gulplog';\nimport ProjectConfig from '../../config/ProjectConfig';\nimport Transformer, { TransformDirection } from '../transform/Transformer';\nimport dest from './dest';\n\n/**\n * A stream that transforms read {@link ReadStream.ReadResult}s and stores the on the filesystem.\n */\nexport default class PullStream {\n  /**\n   * Creates a new PullStream based on a stream that writes {@link ReadStream.ReadResult} which may\n   * be an instance of {@link ReadStream}.\n   * @param {ReadStream} readStream The stream to read from.\n   */\n  constructor(readStream) {\n    const printProgress = setInterval(() => {\n      Logger.info(`Pulled: ${readStream.processed} (${readStream.opsPerSecond.toFixed(1)} ops/s)`);\n\n      if (Logger.listenerCount('info') > 0) {\n        readline.cursorTo(process.stdout, 0);\n        readline.moveCursor(process.stdout, 0, -1);\n      }\n    }, 1000);\n\n    return Transformer.applyTransformers(\n      readStream,\n      ProjectConfig.useTransformers,\n      TransformDirection.FromDB\n    )\n      .pipe(dest('./src')) // FIXME: Get from config file\n      .on('finish', () => {\n        if (Logger.listenerCount('info') > 0) {\n          readline.clearLine(process.stdout, 0);\n          readline.cursorTo(process.stdout, 0);\n        }\n\n        clearInterval(printProgress);\n      });\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/gulp/PullStream.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 141,
    "kind": "class",
    "name": "PullStream",
    "memberof": "src/lib/gulp/PullStream.js",
    "static": true,
    "longname": "src/lib/gulp/PullStream.js~PullStream",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/gulp/PullStream.js",
    "importStyle": "PullStream",
    "description": "A stream that transforms read {@link ReadStream.ReadResult}s and stores the on the filesystem.",
    "lineNumber": 10,
    "interface": false
  },
  {
    "__docId__": 142,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/gulp/PullStream.js~PullStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/PullStream.js~PullStream#constructor",
    "access": "public",
    "description": "Creates a new PullStream based on a stream that writes {@link ReadStream.ReadResult} which may\nbe an instance of {@link ReadStream}.",
    "lineNumber": 16,
    "params": [
      {
        "nullable": null,
        "types": [
          "ReadStream"
        ],
        "spread": false,
        "optional": false,
        "name": "readStream",
        "description": "The stream to read from."
      }
    ]
  },
  {
    "__docId__": 143,
    "kind": "file",
    "name": "src/lib/gulp/PushStream.js",
    "content": "import readline from 'readline';\nimport Logger from 'gulplog';\nimport ProjectConfig from '../../config/ProjectConfig';\nimport Transformer, { TransformDirection } from '../transform/Transformer';\nimport WriteStream from '../server/WriteStream';\nimport CreateNodeStream from '../server/CreateNodeStream';\nimport AddReferencesStream from '../server/AddReferencesStream';\n\n/**\n * A stream that transforms read {@link vinyl~File}s and pushes them to atvise server.\n */\nexport default class PushStream {\n  /**\n   * Creates a new PushSteam based on a source file stream.\n   * @param {Stream} srcStream The file stream to read from.\n   */\n  constructor(srcStream) {\n    const createStream = new CreateNodeStream();\n    const addReferencesStream = new AddReferencesStream();\n    const writeStream = new WriteStream(createStream, addReferencesStream);\n\n    const printProgress = setInterval(() => {\n      Logger.info(\n        `Pushed: ${writeStream._processed} (${writeStream.opsPerSecond.toFixed(1)} ops/s)`\n      );\n\n      if (Logger.listenerCount('info') > 0) {\n        readline.cursorTo(process.stdout, 0);\n        readline.moveCursor(process.stdout, 0, -1);\n      }\n    }, 1000);\n\n    return Transformer.applyTransformers(\n      srcStream,\n      ProjectConfig.useTransformers,\n      TransformDirection.FromFilesystem\n    )\n      .pipe(writeStream)\n      .pipe(createStream)\n      .pipe(addReferencesStream)\n      .on('finish', () => {\n        if (Logger.listenerCount('info') > 0) {\n          readline.cursorTo(process.stdout, 0);\n          readline.clearLine(process.stdout);\n        }\n\n        clearInterval(printProgress);\n      });\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/gulp/PushStream.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 144,
    "kind": "class",
    "name": "PushStream",
    "memberof": "src/lib/gulp/PushStream.js",
    "static": true,
    "longname": "src/lib/gulp/PushStream.js~PushStream",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/gulp/PushStream.js",
    "importStyle": "PushStream",
    "description": "A stream that transforms read {@link vinyl~File}s and pushes them to atvise server.",
    "lineNumber": 12,
    "interface": false
  },
  {
    "__docId__": 145,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/gulp/PushStream.js~PushStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/PushStream.js~PushStream#constructor",
    "access": "public",
    "description": "Creates a new PushSteam based on a source file stream.",
    "lineNumber": 17,
    "params": [
      {
        "nullable": null,
        "types": [
          "Stream"
        ],
        "spread": false,
        "optional": false,
        "name": "srcStream",
        "description": "The file stream to read from."
      }
    ]
  },
  {
    "__docId__": 146,
    "kind": "file",
    "name": "src/lib/gulp/dest.js",
    "content": "import { Writable } from 'stream';\nimport { join } from 'path';\nimport { EOL } from 'os';\nimport { NodeClass } from 'node-opcua/lib/datamodel/nodeclass';\nimport { outputFile, readJson } from 'fs-extra';\nimport hasha from 'hasha';\nimport Logger from 'gulplog';\nimport ProjectConfig from '../../config/ProjectConfig';\nimport { encodeVariant } from '../coding';\n\n/**\n * Relative path to the rename file.\n * @type {string}\n */\nexport const renameConfigPath = './atscm/rename.json';\n\n/**\n * The default name inserted into the rename file.\n * @type {string}\n */\nconst renameDefaultName = 'insert node name';\n\n/**\n * Options to pass to *hasha*.\n * @type {Object}\n */\nconst hashaOptions = { algorithm: 'md5' };\n\n/**\n * If checksums should be used to decide if writes are needed.\n * @type {boolean}\n */\nconst useChecksums = ProjectConfig.vcs === 'svn';\n\nconst escapePathComponent = (a) => a.replace(/\\//g, '%2F');\n\n/**\n * A stream that writes {@link Node}s to the file system.\n */\nexport class WriteStream extends Writable {\n  /**\n   * Creates a new WriteStream.\n   * @param {Object} options The options to use.\n   * @param {string} options.path The path to write to **(required)**.\n   * @param {string} options.base The base path to write to (defaults to *path*).\n   * @param {boolean} [options.cleanRenameConfig=false] If unused entries should be removed when\n   * rename config is written.\n   */\n  constructor(options) {\n    if (!options.path) {\n      throw new Error('Missing `path` option');\n    }\n\n    super(Object.assign({}, options, { objectMode: true, highWaterMark: 10000 }));\n\n    /**\n     * If the stream is destroyed.\n     * @type {boolean}\n     */\n    this._isDestroyed = false;\n\n    /**\n     * The number of processed nodes.\n     * @type {number}\n     */\n    this._processed = 0;\n\n    /**\n     * The number of written nodes.\n     * @type {number}\n     */\n    this._written = 0;\n\n    /**\n     * The base to output to.\n     * @type {string}\n     */\n    this._base = options.base || options.path;\n\n    /**\n     * The object stored in the *rename file* (usually at './atscm/rename.json')\n     */\n    this._renameConfig = {};\n    this._renamesUsed = {};\n    this._cleanRenameConfig = options.cleanRenameConfig || false;\n\n    /**\n     * A promise that resolves once the *rename file* is loaded.\n     * @type Promise<Object>\n     */\n    this._loadRenameConfig = readJson(renameConfigPath)\n      .then((config) => (this._renameConfig = config))\n      .catch(() => Logger.debug('No rename config file loaded'));\n\n    /**\n     * A map of ids used for renaming.\n     */\n    this._idMap = new Map();\n\n    /**\n     * If writes should actually be performed. Set to `false` once id conflicts were discovered.\n     */\n    this._performWrites = true;\n\n    /**\n     * The IDs that are affected by node id conflicts, lowercased.\n     * @type {Set<string>}\n     */\n    this._conflictingIds = new Set();\n\n    /**\n     * The number of id conflicts discovered.\n     * @type {number}\n     */\n    this._discoveredIdConflicts = 0;\n\n    if (useChecksums) {\n      Logger.info('Optimizing for SVN diffs');\n    }\n  }\n\n  /**\n   * If the stream is destroyed.\n   * @type {boolean}\n   */\n  get isDestroyed() {\n    return this._isDestroyed;\n  }\n\n  /**\n   * Transverses the node tree to see if any parent node has an id conflict.\n   * @param {ServerNode} node The processed node.\n   * @return {boolean} `true` if a parent node has an id conflict.\n   */\n  _parentHasIdConflict(node) {\n    let current = node.parent;\n\n    while (current) {\n      if (this._conflictingIds.has(current.nodeId.toLowerCase())) {\n        return true;\n      }\n      current = current.parent;\n    }\n\n    return false;\n  }\n\n  async _outputFile(path, content) {\n    if (useChecksums) {\n      const oldSum = await hasha.fromFile(path, hashaOptions).catch(() => null);\n\n      if (oldSum) {\n        if (oldSum === hasha(content, hashaOptions)) {\n          Logger.debug(`Content did not change at ${path}`);\n          return Promise.resolve();\n        }\n\n        Logger.debug(`Content changed at ${path}`);\n      } else {\n        Logger.debug(`No checksums for ${path}`);\n      }\n    }\n\n    return outputFile(path, content);\n  }\n\n  /**\n   * Writes a single node to disk.\n   * @param {ServerNode} node The processed node.\n   * @return {Promise<boolean>} Resolves once the node has been written, `true` indicates the node\n   * has actually been written.\n   */\n  async _writeNode(node) {\n    // TODO: Throw if node.name ends with '.inner'\n    const dirPath = node.filePath.map(escapePathComponent);\n\n    const writeOps = [];\n\n    // Rename nodes specified in the rename config\n    const rename = this._renameConfig[node.id.value];\n    if (rename && rename !== renameDefaultName) {\n      this._renamesUsed[node.id.value] = true;\n      node.renameTo(rename);\n      Logger.debug(`'${node.nodeId}' was renamed to '${rename}'`);\n\n      Object.assign(node, { _renamed: true });\n    }\n\n    // Resolve invalid ids\n    if (!node._renamed && node.nodeId !== node.id.value) {\n      Logger.debug(\n        `Resolved ID conflict: '${node.id.value}' should be renamed to '${node.nodeId}'`\n      );\n    }\n\n    Object.assign(node, { specialId: node.id.value });\n\n    if (node.name.match(/:/)) {\n      const before = node.name;\n      node.renameTo(node.name.replace(/:/g, '_'));\n      Logger.debug(`Resolved ID conflict: '${before}' was renamed to safe name '${node.name}'`);\n    }\n\n    // Detect \"duplicate\" ids (as file names are case insensitive)\n    const pathKey = dirPath.concat(node.fileName).join('/').toLowerCase();\n    if (this._idMap.has(pathKey)) {\n      if (this._parentHasIdConflict(node)) {\n        Logger.debug(`ID conflict: Skipping '${node.nodeId}'`);\n      } else {\n        Logger.error(`ID conflict: '${node.nodeId}' conflicts with '${this._idMap.get(pathKey)}'`);\n\n        this._discoveredIdConflicts++;\n\n        const existingRename = this._renameConfig[node.nodeId];\n        if (existingRename) {\n          if (existingRename === renameDefaultName) {\n            // eslint-disable-next-line max-len\n            Logger.error(\n              ` - '${node.nodeId}' is present inside the rename file at './atscm/rename.json', but no name has been inserted yet.`\n            );\n          } else {\n            // eslint-disable-next-line max-len\n            Logger.error(\n              ` - The name for '${node.nodeId}' inside './atscm/rename.json' is not unique.`\n            );\n          }\n\n          Logger.info(\" - Edit the node's name and run 'atscm pull' again\");\n        } else {\n          this._renameConfig[node.nodeId] = renameDefaultName;\n          Logger.info(` - '${node.nodeId}' was added to the rename file at './atscm/rename.json'`);\n          Logger.info(\"Edit it's name and run 'atscm pull' again.\");\n        }\n      }\n\n      this._conflictingIds.add(node.nodeId.toLowerCase());\n      this._performWrites = false;\n    } else {\n      this._idMap.set(pathKey, node.nodeId);\n    }\n\n    // Write definition file (if needed)\n    if (node.hasUnresolvedMetadata) {\n      const name =\n        node.nodeClass === NodeClass.Variable\n          ? `./.${escapePathComponent(node.fileName)}.json`\n          : `./${escapePathComponent(node.fileName)}/.${node.nodeClass.key}.json`;\n\n      if (this._performWrites) {\n        writeOps.push(\n          this._outputFile(\n            join(this._base, dirPath.join('/'), name),\n            JSON.stringify(node.metadata, null, '  ')\n          )\n        );\n      }\n    }\n\n    // Write value\n    if (node.nodeClass === NodeClass.Variable) {\n      if (node.value) {\n        if (!node.value.noWrite) {\n          if (this._performWrites) {\n            writeOps.push(\n              this._outputFile(\n                join(this._base, dirPath.join('/'), escapePathComponent(node.fileName)),\n                encodeVariant(node.value)\n              )\n            );\n          }\n\n          // Store child nodes as file.inner/...\n          node.renameTo(`${node.name}.inner`);\n        }\n      } else {\n        throw new Error('Missing value');\n      }\n    }\n\n    return Promise.all(writeOps)\n      .then(() => {\n        this._processed++;\n        this._written += writeOps.length;\n      })\n      .then(() => writeOps.length > 0);\n  }\n\n  /**\n   * Writes a single node to the file system.\n   * @param {Node} node The node to write.\n   * @param {string} enc The encoding used.\n   * @param {function(err: ?Error): void} callback Called once finished.\n   */\n  _write(node, enc, callback) {\n    this._loadRenameConfig\n      .then(() => this._writeNode(node))\n      .then(() => callback())\n      .catch((err) => callback(err));\n  }\n\n  writeAsync(node) {\n    return new Promise((resolve, reject) => {\n      this._write(node, null, (err) => (err ? reject(err) : resolve()));\n    });\n  }\n\n  /**\n   * Writes multiple nodes in parallel.\n   * @param {Node[]} nodes The nodes to write.\n   * @param {function(error: ?Error): void} callback Called once all nodes have been written.\n   */\n  _writev(nodes, callback) {\n    if (this.isDestroyed) {\n      return;\n    }\n\n    this._loadRenameConfig\n      .then(() => Promise.all(nodes.map(({ chunk }) => this._writeNode(chunk))))\n      .then(() => callback())\n      .catch((err) => callback(err));\n  }\n\n  /**\n   * Destroys the stream.\n   * @param {?Error} err The error that caused the destroy.\n   * @param {function(err: ?Error): void} callback Called once finished.\n   */\n  _destroy(err, callback) {\n    this._isDestroyed = true;\n    super._destroy(err, callback);\n  }\n\n  /**\n   * Writes the updated rename config to disk.\n   */\n  writeRenamefile() {\n    if (this._discoveredIdConflicts) {\n      Logger.error(\n        `Discovered ${this._discoveredIdConflicts} node id conflicts, results are incomplete.\n - Resolve all conflicts inside '${renameConfigPath}' and run 'atscm pull' again`\n      );\n      // FIXME: Insert link to node id conflict manual here once 1.0.0 is released.\n    }\n\n    let renameConfig = this._renameConfig;\n    if (!this._discoveredIdConflicts && this._cleanRenameConfig) {\n      renameConfig = Object.keys(this._renamesUsed)\n        .sort()\n        .reduce(\n          (result, key) =>\n            Object.assign(result, {\n              [key]: this._renameConfig[key],\n            }),\n          {}\n        );\n\n      const renamesRemoved =\n        Object.keys(this._renameConfig).length - Object.keys(renameConfig).length;\n\n      if (renamesRemoved > 0) {\n        Logger.info(`Removed ${renamesRemoved} unused renames from rename configuration.`);\n      }\n    }\n\n    return outputFile(renameConfigPath, `${JSON.stringify(renameConfig, null, '  ')}${EOL}`);\n  }\n}\n\n/**\n * Creates a new {@link WriteStream} to write to *path*.\n * @param {string} path The path to write to.\n * @param {Object} [options] The options to use. Passed to {@link WriteStream#constructor}.\n */\nexport default function dest(path, { cleanRenameConfig = false } = {}) {\n  return new WriteStream({ path, cleanRenameConfig });\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/gulp/dest.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 147,
    "kind": "variable",
    "name": "renameConfigPath",
    "memberof": "src/lib/gulp/dest.js",
    "static": true,
    "longname": "src/lib/gulp/dest.js~renameConfigPath",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/gulp/dest.js",
    "importStyle": "{renameConfigPath}",
    "description": "Relative path to the rename file.",
    "lineNumber": 15,
    "type": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 148,
    "kind": "variable",
    "name": "renameDefaultName",
    "memberof": "src/lib/gulp/dest.js",
    "static": true,
    "longname": "src/lib/gulp/dest.js~renameDefaultName",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/gulp/dest.js",
    "importStyle": null,
    "description": "The default name inserted into the rename file.",
    "lineNumber": 21,
    "type": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 149,
    "kind": "variable",
    "name": "hashaOptions",
    "memberof": "src/lib/gulp/dest.js",
    "static": true,
    "longname": "src/lib/gulp/dest.js~hashaOptions",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/gulp/dest.js",
    "importStyle": null,
    "description": "Options to pass to *hasha*.",
    "lineNumber": 27,
    "type": {
      "nullable": null,
      "types": [
        "Object"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 150,
    "kind": "variable",
    "name": "useChecksums",
    "memberof": "src/lib/gulp/dest.js",
    "static": true,
    "longname": "src/lib/gulp/dest.js~useChecksums",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/gulp/dest.js",
    "importStyle": null,
    "description": "If checksums should be used to decide if writes are needed.",
    "lineNumber": 33,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 151,
    "kind": "function",
    "name": "escapePathComponent",
    "memberof": "src/lib/gulp/dest.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/gulp/dest.js~escapePathComponent",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/gulp/dest.js",
    "importStyle": null,
    "description": null,
    "lineNumber": 35,
    "undocument": true,
    "params": [
      {
        "name": "a",
        "types": [
          "*"
        ]
      }
    ],
    "return": null,
    "ignore": true
  },
  {
    "__docId__": 152,
    "kind": "class",
    "name": "WriteStream",
    "memberof": "src/lib/gulp/dest.js",
    "static": true,
    "longname": "src/lib/gulp/dest.js~WriteStream",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/gulp/dest.js",
    "importStyle": "{WriteStream}",
    "description": "A stream that writes {@link Node}s to the file system.",
    "lineNumber": 40,
    "interface": false,
    "extends": [
      "stream~Writable"
    ]
  },
  {
    "__docId__": 153,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#constructor",
    "access": "public",
    "description": "Creates a new WriteStream.",
    "lineNumber": 49,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "The options to use."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "options.path",
        "description": "The path to write to **(required)**."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "options.base",
        "description": "The base path to write to (defaults to *path*)."
      },
      {
        "nullable": null,
        "types": [
          "boolean"
        ],
        "spread": false,
        "optional": true,
        "defaultValue": "false",
        "defaultRaw": false,
        "name": "options.cleanRenameConfig",
        "description": "If unused entries should be removed when\nrename config is written."
      }
    ]
  },
  {
    "__docId__": 154,
    "kind": "member",
    "name": "_isDestroyed",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_isDestroyed",
    "access": "private",
    "description": "If the stream is destroyed.",
    "lineNumber": 60,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 155,
    "kind": "member",
    "name": "_processed",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_processed",
    "access": "private",
    "description": "The number of processed nodes.",
    "lineNumber": 66,
    "type": {
      "nullable": null,
      "types": [
        "number"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 156,
    "kind": "member",
    "name": "_written",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_written",
    "access": "private",
    "description": "The number of written nodes.",
    "lineNumber": 72,
    "type": {
      "nullable": null,
      "types": [
        "number"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 157,
    "kind": "member",
    "name": "_base",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_base",
    "access": "private",
    "description": "The base to output to.",
    "lineNumber": 78,
    "type": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 158,
    "kind": "member",
    "name": "_renameConfig",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_renameConfig",
    "access": "private",
    "description": "The object stored in the *rename file* (usually at './atscm/rename.json')",
    "lineNumber": 83,
    "type": {
      "types": [
        "{}"
      ]
    }
  },
  {
    "__docId__": 159,
    "kind": "member",
    "name": "_renamesUsed",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_renamesUsed",
    "access": "private",
    "description": null,
    "lineNumber": 84,
    "undocument": true,
    "type": {
      "types": [
        "{}"
      ]
    }
  },
  {
    "__docId__": 160,
    "kind": "member",
    "name": "_cleanRenameConfig",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_cleanRenameConfig",
    "access": "private",
    "description": null,
    "lineNumber": 85,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 161,
    "kind": "member",
    "name": "_loadRenameConfig",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_loadRenameConfig",
    "access": "private",
    "description": "A promise that resolves once the *rename file* is loaded.",
    "lineNumber": 91,
    "type": {
      "nullable": null,
      "types": [
        "*"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 162,
    "kind": "member",
    "name": "_idMap",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_idMap",
    "access": "private",
    "description": "A map of ids used for renaming.",
    "lineNumber": 98,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 163,
    "kind": "member",
    "name": "_performWrites",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_performWrites",
    "access": "private",
    "description": "If writes should actually be performed. Set to `false` once id conflicts were discovered.",
    "lineNumber": 103,
    "type": {
      "types": [
        "boolean"
      ]
    }
  },
  {
    "__docId__": 164,
    "kind": "member",
    "name": "_conflictingIds",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_conflictingIds",
    "access": "private",
    "description": "The IDs that are affected by node id conflicts, lowercased.",
    "lineNumber": 109,
    "type": {
      "nullable": null,
      "types": [
        "Set<string>"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 165,
    "kind": "member",
    "name": "_discoveredIdConflicts",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_discoveredIdConflicts",
    "access": "private",
    "description": "The number of id conflicts discovered.",
    "lineNumber": 115,
    "type": {
      "nullable": null,
      "types": [
        "number"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 166,
    "kind": "get",
    "name": "isDestroyed",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#isDestroyed",
    "access": "public",
    "description": "If the stream is destroyed.",
    "lineNumber": 126,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 167,
    "kind": "method",
    "name": "_parentHasIdConflict",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_parentHasIdConflict",
    "access": "private",
    "description": "Transverses the node tree to see if any parent node has an id conflict.",
    "lineNumber": 135,
    "params": [
      {
        "nullable": null,
        "types": [
          "ServerNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The processed node."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": "`true` if a parent node has an id conflict."
    }
  },
  {
    "__docId__": 168,
    "kind": "method",
    "name": "_outputFile",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "generator": false,
    "async": true,
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_outputFile",
    "access": "private",
    "description": null,
    "lineNumber": 148,
    "undocument": true,
    "params": [
      {
        "name": "path",
        "types": [
          "*"
        ]
      },
      {
        "name": "content",
        "types": [
          "*"
        ]
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 169,
    "kind": "method",
    "name": "_writeNode",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "generator": false,
    "async": true,
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_writeNode",
    "access": "private",
    "description": "Writes a single node to disk.",
    "lineNumber": 173,
    "params": [
      {
        "nullable": null,
        "types": [
          "ServerNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The processed node."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise<boolean>"
      ],
      "spread": false,
      "description": "Resolves once the node has been written, `true` indicates the node\nhas actually been written."
    }
  },
  {
    "__docId__": 172,
    "kind": "method",
    "name": "_write",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_write",
    "access": "private",
    "description": "Writes a single node to the file system.",
    "lineNumber": 294,
    "params": [
      {
        "nullable": null,
        "types": [
          "Node"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The node to write."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "enc",
        "description": "The encoding used."
      },
      {
        "nullable": null,
        "types": [
          "function(err: ?Error): void"
        ],
        "spread": false,
        "optional": false,
        "name": "callback",
        "description": "Called once finished."
      }
    ],
    "return": null
  },
  {
    "__docId__": 173,
    "kind": "method",
    "name": "writeAsync",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#writeAsync",
    "access": "public",
    "description": null,
    "lineNumber": 301,
    "undocument": true,
    "params": [
      {
        "name": "node",
        "types": [
          "*"
        ]
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 174,
    "kind": "method",
    "name": "_writev",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_writev",
    "access": "private",
    "description": "Writes multiple nodes in parallel.",
    "lineNumber": 312,
    "params": [
      {
        "nullable": null,
        "types": [
          "Node[]"
        ],
        "spread": false,
        "optional": false,
        "name": "nodes",
        "description": "The nodes to write."
      },
      {
        "nullable": null,
        "types": [
          "function(error: ?Error): void"
        ],
        "spread": false,
        "optional": false,
        "name": "callback",
        "description": "Called once all nodes have been written."
      }
    ],
    "return": null
  },
  {
    "__docId__": 175,
    "kind": "method",
    "name": "_destroy",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#_destroy",
    "access": "private",
    "description": "Destroys the stream.",
    "lineNumber": 328,
    "params": [
      {
        "nullable": true,
        "types": [
          "Error"
        ],
        "spread": false,
        "optional": false,
        "name": "err",
        "description": "The error that caused the destroy."
      },
      {
        "nullable": null,
        "types": [
          "function(err: ?Error): void"
        ],
        "spread": false,
        "optional": false,
        "name": "callback",
        "description": "Called once finished."
      }
    ],
    "return": null
  },
  {
    "__docId__": 177,
    "kind": "method",
    "name": "writeRenamefile",
    "memberof": "src/lib/gulp/dest.js~WriteStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/dest.js~WriteStream#writeRenamefile",
    "access": "public",
    "description": "Writes the updated rename config to disk.",
    "lineNumber": 336,
    "params": [],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 178,
    "kind": "function",
    "name": "dest",
    "memberof": "src/lib/gulp/dest.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/gulp/dest.js~dest",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/gulp/dest.js",
    "importStyle": "dest",
    "description": "Creates a new {@link WriteStream} to write to *path*.",
    "lineNumber": 374,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "path",
        "description": "The path to write to."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": true,
        "name": "options",
        "description": "The options to use. Passed to {@link WriteStream#constructor}."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 179,
    "kind": "file",
    "name": "src/lib/gulp/src.ts",
    "content": "import { join, basename, dirname } from 'path';\nimport { readdir, stat, readFile, readJSON } from 'fs-extra';\nimport { NodeClass } from 'node-opcua/lib/datamodel/nodeclass';\nimport { DataType, VariantArrayType, Variant } from 'node-opcua/lib/datamodel/variant';\nimport { KeyOf } from 'node-opcua/lib/misc/enum.js';\nimport Logger from 'gulplog';\nimport PromiseQueue from 'p-queue';\nimport { SourceNode, ReferenceTypeIds, NodeOptions, NodeDefinition } from '../model/Node';\nimport ProjectConfig from '../../config/ProjectConfig';\nimport { decodeVariant } from '../coding';\nimport { Omit } from '../helpers/types';\n\ntype FileNodeOptions = Omit<NodeOptions, 'nodeClass'> & NodeDefinition;\n\n/**\n * A node returned by the {@link SourceStream}.\n */\nexport class FileNode extends SourceNode {\n  /**\n   * Creates a new node.\n   * @param options The options to use.\n   */\n  public constructor({\n    nodeClass,\n    dataType,\n    arrayType,\n    references,\n    nodeId,\n    ...options\n  }: FileNodeOptions) {\n    super({\n      ...options,\n      nodeClass: NodeClass[nodeClass || 'Variable'],\n    });\n\n    if (nodeId) {\n      /**\n       * The id stored in the definition file\n       * @type {NodeId}\n       */\n      this.specialId = nodeId;\n    }\n\n    if (references) {\n      (Object.entries(references) as [\n        keyof typeof ReferenceTypeIds,\n        (string | number)[]\n      ][]).forEach(([ref, ids]) => {\n        const type = ReferenceTypeIds[ref] || parseInt(ref, 10);\n\n        ids.forEach((id) => {\n          this.references.addReference(type, id);\n          this._resolvedReferences.addReference(type, id);\n        });\n      });\n    }\n\n    if (dataType) {\n      this.valueSoFar.dataType = DataType[dataType];\n    }\n\n    if (arrayType) {\n      this.valueSoFar.arrayType = VariantArrayType[arrayType];\n    }\n  }\n\n  protected _rawValue?: Buffer;\n\n  public setRawValue(value: Buffer): void {\n    this._rawValue = value;\n  }\n\n  private hasRawValue(): this is { _rawValue: Buffer } {\n    return !!this._rawValue;\n  }\n\n  /**\n   * A node's raw value, decoded into a string.\n   */\n  public get stringValue(): string {\n    if (!this.hasRawValue()) {\n      throw new Error('No value read yet. Ensure to call #setRawValue');\n    }\n\n    return this._rawValue.toString();\n  }\n\n  /** The node's value (may be incomplete, use {@link FileNode#value} to ensure). */\n  public valueSoFar: Partial<Variant> = {};\n\n  private valueIsComplete(): this is { valueSoFar: Variant } {\n    return this.valueSoFar.value !== undefined;\n  }\n\n  /**\n   * A node's {@link node-opcua~Variant} value.\n   */\n  public get variantValue(): Variant {\n    const value = this.valueSoFar;\n\n    if (!this.valueIsComplete()) {\n      if (!value.dataType) {\n        throw new Error(`${this.nodeId} has no data type`);\n      }\n      if (!value.arrayType) {\n        throw new Error(`${this.nodeId} has no array type`);\n      }\n      if (this.hasRawValue()) {\n        value.value = decodeVariant(this._rawValue, value);\n      }\n    }\n\n    return this.valueSoFar as Variant;\n  }\n\n  public get value(): Variant {\n    return this.variantValue;\n  }\n}\n\n// Helpers\n/**\n * Returns `true` for definition file paths.\n * @param path The path to check.\n * @return If the file at path is a definition file.\n */\nexport function isDefinitionFile(path: string): boolean {\n  return Boolean(basename(path).match(/^\\..*\\.json$/));\n}\n\n/**\n * Matches container files.\n */\nconst containerFileRegexp = /^\\.((Object|Variable)(Type)?|Method|View|(Reference|Data)Type)\\.json$/;\n\ntype NodeHandler<R = void> = (node: FileNode) => R;\n\ninterface SourceBrowserOptions {\n  handleNode: NodeHandler<Promise<void>>;\n  readNodeFile: NodeHandler<boolean>;\n  atserverVersion: string;\n}\n\n/**\n * Browses the local file system for nodes.\n */\nexport class SourceBrowser {\n  /** The queue processing incoming paths / nodes. @type {p-queue~PQueue} */\n  private _queue: PromiseQueue;\n\n  /** A callback called with every discovered node. */\n  private _nodeHandler: NodeHandler<Promise<void>>;\n  /** A callback deciding if a node file should be read. */\n  private _readNodeFile: NodeHandler<boolean>;\n\n  /** The pushed node's ids */\n  private _pushed = new Set<string>();\n  /** The pushed node's paths */\n  private _pushedPath = new Set<string>();\n  /** Stores how queued nodes depend on each other */\n  // eslint-disable-next-line no-spaced-func\n  private _dependingOn = new Map<string, (BrowsedFileNode & { waitingFor: Set<string> })[]>();\n\n  private _atserverVersion: string;\n\n  /**\n   * Sets up a new browser.\n   * @param options The options to apply.\n   * @param options.handleNode A callback called with every discovered node.\n   * @param options.readNodeFile A callback deciding if a node file should be read.\n   */\n  public constructor({ handleNode, readNodeFile, atserverVersion }: SourceBrowserOptions) {\n    this._queue = new PromiseQueue({\n      concurrency: 250,\n    });\n\n    this._nodeHandler = handleNode;\n    this._readNodeFile = readNodeFile;\n\n    // Setup context\n    this._atserverVersion = atserverVersion;\n  }\n\n  get atserverVersion(): string {\n    return this._atserverVersion;\n  }\n\n  /**\n   * A function to be called once an error occurres during parallel processing.\n   * @param error The error to exit with.\n   */\n  private _reject!: (error: Error) => void;\n\n  /**\n   * Starts the browser at the given path.\n   * @param path The path to start browsing at.\n   * @param options Passed directly to {@link SourceBrowser#processPath}.\n   * @return Fulfilled once browsing is complete.\n   */\n  public async browse(path: string, options = {}): Promise<void> {\n    let processError: Error;\n\n    const done = new Promise<void>((resolve, reject) => {\n      this._reject = (err) => {\n        if (processError) {\n          // Multiple errors occured. In most cases this means, that the server connection was\n          // closed after the first error.\n          Logger.debug('Additional error', err);\n          return;\n        }\n\n        processError = err;\n        this._queue.pause();\n        this._queue.clear();\n\n        reject(err);\n      };\n\n      // write initial path\n      this.processPath({ path, ...options });\n\n      this._queue.onIdle().then(() => {\n        if (processError) {\n          return;\n        }\n\n        if (this._dependingOn.size) {\n          reject(\n            new Error(`Some nodes are still waiting for dependencies\n  Missing nodes: ${Array.from(this._dependingOn.keys()).join(', ')}\n  - Pull these nodes or add them to the ignored ones`)\n          );\n        }\n\n        resolve();\n      });\n    });\n\n    return done;\n  }\n\n  /**\n   * Enqueues a {@link SourceBrowser#_processPath} call with the given options.\n   * @param options Passed directly to {@link SourceBrowser#_processPath}.\n   */\n  public processPath(options: ProcessPathOptions): Promise<FileNode | void> {\n    return this._queue.add(() => this._processPath(options).catch(this._reject));\n  }\n\n  /**\n   * Can be called by transformers to read this path before finishing it's parent nodes.\n   * @param {Object} options Passed directly to {@link SourceBrowser#_processPath}.\n   * @param {string} options.path The path to read.\n   */\n  public readNode({ path }: { path: string }): Promise<FileNode> {\n    return this._processPath({\n      path,\n      push: false,\n    }) as Promise<FileNode>; // NOTE: If `push` is true, the browser always returns a node.\n  }\n\n  /**\n   * Where the real browsing happens: Stats the given path, discovering new node definition files,\n   * if any and finally pushes discovered nodes to {@link SourceBrowser#_processNode}.\n   * @param {Object} options The options to use.\n   */\n  private async _processPath({\n    path,\n    parent,\n    children,\n    push = true,\n    singleNode = false,\n  }: ProcessPathOptions): Promise<void | FileNode> {\n    const s = await stat(path);\n\n    if (s.isDirectory()) {\n      let container;\n      const nextChildren = (await readdir(path)).reduce((nodes, p) => {\n        const node = {\n          name: p,\n          path: join(path, p),\n          push,\n        };\n\n        if (p.match(containerFileRegexp)) {\n          container = node;\n\n          return nodes;\n        }\n\n        let parts: string[];\n        const noProcessingNeeded = nodes.find((current) => {\n          const n = current.name;\n          if (n === `.${p}.json`) {\n            return true;\n          } // Skip files with definitions already present\n\n          const [raw, rest] = parts || (parts = p.split('.inner'));\n\n          if (rest === '' && (n === raw || n === `.${raw}.json`)) {\n            // Got an *.inner directory\n            // eslint-disable-next-line no-param-reassign\n            current.children = (current.children || []).concat(node);\n            return true;\n          }\n\n          return false;\n        });\n\n        return noProcessingNeeded ? nodes : nodes.concat(node);\n      }, [] as DiscoveredNodeFile[]);\n\n      if (container) {\n        return this._processPath(Object.assign(container, { children: nextChildren, parent }));\n      } else if (singleNode) {\n        Logger.debug(`Pushing parent at ${path}`);\n        return this._processPath({ path: join(path, '../'), parent, children, push });\n      }\n\n      const inheritParent = path.endsWith('.inner');\n      nextChildren.forEach((node) => {\n        if (inheritParent) {\n          // eslint-disable-next-line no-param-reassign\n          node.parent = parent;\n        }\n        this.processPath(node);\n      });\n    } else if (s.isFile()) {\n      if (!isDefinitionFile(path)) {\n        // FIXME: Browse parent here for watch task / Variable source node\n        // (e.g. AGENT/DISPLAYS/Default.display/Default.js changed)\n\n        if (singleNode) {\n          Logger.debug(`Pushing parent at ${path}`);\n          return this._processPath({ path: join(path, '../'), parent, children, push, singleNode });\n        }\n\n        Logger.warn(`Not a definition file at ${path}`);\n        return Promise.resolve();\n      }\n\n      let name = basename(path, '.json').slice(1);\n      if (name.length >= 4 && NodeClass[name as KeyOf<typeof NodeClass>]) {\n        name = basename(dirname(path));\n      }\n\n      if (this._pushedPath.has(path)) {\n        // throw new Error('Double-handled node ' + path);\n        return Promise.resolve();\n      }\n\n      const dir = dirname(path);\n      const rel = join(dir, name);\n      const node: BrowsedFileNode = Object.assign(\n        new FileNode({\n          name,\n          parent,\n          ...((await readJSON(path)) as NodeDefinition),\n        }),\n        {\n          push, // FIXME: Remove?\n          children,\n          relative: rel,\n          definitionPath: path,\n        }\n      );\n\n      return this._processNode(node);\n    }\n\n    return Promise.resolve();\n  }\n\n  /**\n   * Handles a node's dependencies and calls {@link SourceBrowser#_pushNode} once it's ready.\n   * @param node A discovered node.\n   */\n  private _processNode(node: BrowsedFileNode): Promise<void | FileNode> {\n    // Build dependency map\n    if (!node.waitingFor) {\n      const deps = Array.from(node.references).reduce(\n        (result, [, ids]) =>\n          result.concat(\n            Array.from(ids).filter((id) => {\n              if (typeof id === 'number') {\n                // OPC-UA node\n                return false;\n              }\n\n              return !this._pushed.has(id) && !ProjectConfig.isExternal(id);\n            }) as string[]\n          ),\n        [] as string[]\n      );\n      // eslint-disable-next-line no-param-reassign\n      node.waitingFor = new Set(deps);\n      deps.forEach((d) => {\n        this._dependingOn.set(\n          d,\n          (this._dependingOn.get(d) || []).concat(\n            node as BrowsedFileNode & {\n              waitingFor: Set<string>;\n            }\n          )\n        );\n      });\n    }\n\n    if (!node.waitingFor.size) {\n      return this._pushNode(node);\n    }\n\n    return Promise.resolve();\n  }\n\n  /**\n   * Reads a node's value file (if it's a variable) and calls {@link SourceBrowser#_nodeHandler}\n   * with it, finishing the node's processing and promoting it's dependents, if any.\n   * @param node A discovered node.\n   * @return The node, once it's fully processed.\n   */\n  private async _pushNode(node: BrowsedFileNode): Promise<FileNode> {\n    // Read node value\n    if (node.nodeClass === NodeClass.Variable && this._readNodeFile(node)) {\n      // eslint-disable-next-line no-param-reassign\n      await readFile(node.relative)\n        .then((value) => node.setRawValue(value))\n        .catch((err) => {\n          if (err.code === 'EISDIR') {\n            return;\n          }\n          throw new Error(`${err.code}: Error reading ${node.relative}`);\n        });\n    }\n\n    return this._nodeHandler(node).then(() => {\n      // Handle children\n      if (node.children) {\n        node.children.forEach((child) => {\n          // eslint-disable-next-line no-param-reassign\n          child.parent = node;\n          this.processPath(child);\n        });\n      }\n\n      // Handle dependencies\n      const depending = this._dependingOn.get(node.nodeId);\n      if (depending) {\n        depending.forEach((dep) => {\n          dep.waitingFor.delete(node.nodeId);\n\n          if (!dep.waitingFor.size) {\n            // All dependencies resolved\n            return this._pushNode(dep);\n          }\n\n          // Still waiting\n          return Logger.debug('Still waiting', dep.nodeId, Array.from(dep.waitingFor));\n        });\n      }\n\n      // eslint-disable-next-line no-param-reassign\n      delete node.waitingFor;\n      this._dependingOn.delete(node.nodeId);\n      this._pushed.add(node.nodeId);\n\n      // Mark as pushed\n      this._pushedPath.add(node.definitionPath);\n\n      return node;\n    });\n  }\n}\n\n/**\n * Starts a new source browser at the given path.\n * @param path The path to start browsing with.\n * @param options Passed directly to {@link SourceBrowser#constructor}.\n * @return A promise resolved once browsing is finished, with an addional *browser* property holding\n * the SourceBrowser instance created.\n */\nexport default function src(\n  path: string,\n  options: SourceBrowserOptions\n): Promise<void> & {\n  browser: SourceBrowser;\n} {\n  const browser = new SourceBrowser(options);\n\n  return Object.assign(browser.browse(path, options), { browser });\n}\n\n// Option types\n\n/** A file node while being processed by a source browser */\ntype BrowsedFileNode = FileNode & {\n  waitingFor?: Set<string>;\n  children?: DiscoveredNodeFile[];\n  relative: string;\n  definitionPath: string;\n};\n\ninterface DiscoveredNodeFile {\n  path: string;\n  name: string;\n  push: boolean;\n  parent?: FileNode;\n  children?: DiscoveredNodeFile[];\n}\n\ntype ProcessPathOptions = Partial<DiscoveredNodeFile> & {\n  path: string;\n  singleNode?: boolean;\n};\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/gulp/src.ts",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 180,
    "kind": "class",
    "name": "FileNode",
    "memberof": "src/lib/gulp/src.ts",
    "static": true,
    "longname": "src/lib/gulp/src.ts~FileNode",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/gulp/src.ts",
    "importStyle": "{FileNode}",
    "description": "A node returned by the {@link SourceStream}.",
    "lineNumber": 18,
    "interface": false,
    "extends": [
      "src/lib/model/Node.js~SourceNode"
    ]
  },
  {
    "__docId__": 181,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/gulp/src.ts~FileNode",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/src.ts~FileNode#constructor",
    "access": "public",
    "description": "Creates a new node.",
    "lineNumber": 21,
    "params": [
      {
        "nullable": null,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "The options to use."
      }
    ]
  },
  {
    "__docId__": 182,
    "kind": "member",
    "name": "valueSoFar",
    "memberof": "src/lib/gulp/src.ts~FileNode",
    "static": false,
    "longname": "src/lib/gulp/src.ts~FileNode#valueSoFar",
    "access": "public",
    "description": "The node's value (may be incomplete, use {@link FileNode#value} to ensure).",
    "lineNumber": 89,
    "type": {
      "nullable": null,
      "types": [
        "Partial"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 183,
    "kind": "member",
    "name": "specialId",
    "memberof": "src/lib/gulp/src.ts~FileNode",
    "static": false,
    "longname": "src/lib/gulp/src.ts~FileNode#specialId",
    "access": "public",
    "description": "The id stored in the definition file",
    "lineNumber": 40,
    "type": {
      "nullable": null,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 184,
    "kind": "method",
    "name": "setRawValue",
    "memberof": "src/lib/gulp/src.ts~FileNode",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/src.ts~FileNode#setRawValue",
    "access": "public",
    "description": "",
    "lineNumber": 69,
    "params": [
      {
        "nullable": null,
        "types": [
          "Buffer"
        ],
        "spread": false,
        "optional": false,
        "name": "value",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 185,
    "kind": "member",
    "name": "_rawValue",
    "memberof": "src/lib/gulp/src.ts~FileNode",
    "static": false,
    "longname": "src/lib/gulp/src.ts~FileNode#_rawValue",
    "access": "private",
    "description": null,
    "lineNumber": 69,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 186,
    "kind": "method",
    "name": "hasRawValue",
    "memberof": "src/lib/gulp/src.ts~FileNode",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/src.ts~FileNode#hasRawValue",
    "access": "public",
    "description": "",
    "lineNumber": 73,
    "return": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": ""
    },
    "params": []
  },
  {
    "__docId__": 187,
    "kind": "get",
    "name": "stringValue",
    "memberof": "src/lib/gulp/src.ts~FileNode",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/src.ts~FileNode#stringValue",
    "access": "public",
    "description": "A node's raw value, decoded into a string.",
    "lineNumber": 80,
    "type": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 188,
    "kind": "method",
    "name": "valueIsComplete",
    "memberof": "src/lib/gulp/src.ts~FileNode",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/src.ts~FileNode#valueIsComplete",
    "access": "public",
    "description": "",
    "lineNumber": 91,
    "return": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": ""
    },
    "params": []
  },
  {
    "__docId__": 189,
    "kind": "get",
    "name": "variantValue",
    "memberof": "src/lib/gulp/src.ts~FileNode",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/src.ts~FileNode#variantValue",
    "access": "public",
    "description": "A node's {@link node-opcua~Variant} value.",
    "lineNumber": 98,
    "type": {
      "nullable": null,
      "types": [
        "Variant"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 190,
    "kind": "get",
    "name": "value",
    "memberof": "src/lib/gulp/src.ts~FileNode",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/src.ts~FileNode#value",
    "access": "public",
    "description": "",
    "lineNumber": 116,
    "type": {
      "nullable": null,
      "types": [
        "Variant"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 191,
    "kind": "function",
    "name": "isDefinitionFile",
    "memberof": "src/lib/gulp/src.ts",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/gulp/src.ts~isDefinitionFile",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/gulp/src.ts",
    "importStyle": "{isDefinitionFile}",
    "description": "Returns `true` for definition file paths.",
    "lineNumber": 127,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "path",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 192,
    "kind": "variable",
    "name": "containerFileRegexp",
    "memberof": "src/lib/gulp/src.ts",
    "static": true,
    "longname": "src/lib/gulp/src.ts~containerFileRegexp",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/gulp/src.ts",
    "importStyle": null,
    "description": "Matches container files.",
    "lineNumber": 159,
    "type": {
      "types": [
        "undefined"
      ]
    },
    "ignore": true
  },
  {
    "__docId__": 193,
    "kind": "class",
    "name": "SourceBrowser",
    "memberof": "src/lib/gulp/src.ts",
    "static": true,
    "longname": "src/lib/gulp/src.ts~SourceBrowser",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/gulp/src.ts",
    "importStyle": "{SourceBrowser}",
    "description": "Browses the local file system for nodes.",
    "lineNumber": 147,
    "interface": false
  },
  {
    "__docId__": 194,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/gulp/src.ts~SourceBrowser",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/src.ts~SourceBrowser#constructor",
    "access": "public",
    "description": "Sets up a new browser.",
    "lineNumber": 173,
    "params": [
      {
        "nullable": null,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "The options to apply."
      },
      {
        "nullable": null,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "options.handleNode",
        "description": "A callback called with every discovered node."
      },
      {
        "nullable": null,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "options.readNodeFile",
        "description": "A callback deciding if a node file should be read."
      }
    ]
  },
  {
    "__docId__": 195,
    "kind": "member",
    "name": "_pushed",
    "memberof": "src/lib/gulp/src.ts~SourceBrowser",
    "static": false,
    "longname": "src/lib/gulp/src.ts~SourceBrowser#_pushed",
    "access": "private",
    "description": "The pushed node's ids",
    "lineNumber": 157,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 196,
    "kind": "member",
    "name": "_pushedPath",
    "memberof": "src/lib/gulp/src.ts~SourceBrowser",
    "static": false,
    "longname": "src/lib/gulp/src.ts~SourceBrowser#_pushedPath",
    "access": "private",
    "description": "The pushed node's paths",
    "lineNumber": 159,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 197,
    "kind": "member",
    "name": "_dependingOn",
    "memberof": "src/lib/gulp/src.ts~SourceBrowser",
    "static": false,
    "longname": "src/lib/gulp/src.ts~SourceBrowser#_dependingOn",
    "access": "private",
    "description": "Stores how queued nodes depend on each other",
    "lineNumber": 162,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 198,
    "kind": "member",
    "name": "_queue",
    "memberof": "src/lib/gulp/src.ts~SourceBrowser",
    "static": false,
    "longname": "src/lib/gulp/src.ts~SourceBrowser#_queue",
    "access": "private",
    "description": null,
    "lineNumber": 196,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 199,
    "kind": "member",
    "name": "_nodeHandler",
    "memberof": "src/lib/gulp/src.ts~SourceBrowser",
    "static": false,
    "longname": "src/lib/gulp/src.ts~SourceBrowser#_nodeHandler",
    "access": "private",
    "description": null,
    "lineNumber": 199,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 200,
    "kind": "member",
    "name": "_readNodeFile",
    "memberof": "src/lib/gulp/src.ts~SourceBrowser",
    "static": false,
    "longname": "src/lib/gulp/src.ts~SourceBrowser#_readNodeFile",
    "access": "private",
    "description": null,
    "lineNumber": 200,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 201,
    "kind": "member",
    "name": "_atserverVersion",
    "memberof": "src/lib/gulp/src.ts~SourceBrowser",
    "static": false,
    "longname": "src/lib/gulp/src.ts~SourceBrowser#_atserverVersion",
    "access": "private",
    "description": null,
    "lineNumber": 202,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 202,
    "kind": "get",
    "name": "atserverVersion",
    "memberof": "src/lib/gulp/src.ts~SourceBrowser",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/src.ts~SourceBrowser#atserverVersion",
    "access": "public",
    "description": "",
    "lineNumber": 184,
    "type": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 203,
    "kind": "method",
    "name": "browse",
    "memberof": "src/lib/gulp/src.ts~SourceBrowser",
    "generator": false,
    "async": true,
    "static": false,
    "longname": "src/lib/gulp/src.ts~SourceBrowser#browse",
    "access": "public",
    "description": "Starts the browser at the given path.",
    "lineNumber": 200,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "path",
        "description": ""
      },
      {
        "nullable": null,
        "types": [
          "undefined"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 204,
    "kind": "member",
    "name": "_reject",
    "memberof": "src/lib/gulp/src.ts~SourceBrowser",
    "static": false,
    "longname": "src/lib/gulp/src.ts~SourceBrowser#_reject",
    "access": "private",
    "description": null,
    "lineNumber": 230,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 205,
    "kind": "method",
    "name": "processPath",
    "memberof": "src/lib/gulp/src.ts~SourceBrowser",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/src.ts~SourceBrowser#processPath",
    "access": "public",
    "description": "Enqueues a {@link SourceBrowser#_processPath} call with the given options.",
    "lineNumber": 246,
    "params": [
      {
        "nullable": null,
        "types": [
          "ProcessPathOptions"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 206,
    "kind": "method",
    "name": "readNode",
    "memberof": "src/lib/gulp/src.ts~SourceBrowser",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/src.ts~SourceBrowser#readNode",
    "access": "public",
    "description": "Can be called by transformers to read this path before finishing it's parent nodes.",
    "lineNumber": 255,
    "params": [
      {
        "nullable": null,
        "types": [
          "undefined"
        ],
        "spread": false,
        "optional": false,
        "name": "undefined",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 207,
    "kind": "method",
    "name": "_processPath",
    "memberof": "src/lib/gulp/src.ts~SourceBrowser",
    "generator": false,
    "async": true,
    "static": false,
    "longname": "src/lib/gulp/src.ts~SourceBrowser#_processPath",
    "access": "private",
    "description": "Where the real browsing happens: Stats the given path, discovering new node definition files,\nif any and finally pushes discovered nodes to {@link SourceBrowser#_processNode}.",
    "lineNumber": 267,
    "params": [
      {
        "nullable": null,
        "types": [
          "ProcessPathOptions"
        ],
        "spread": false,
        "optional": false,
        "name": "undefined",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 208,
    "kind": "method",
    "name": "_processNode",
    "memberof": "src/lib/gulp/src.ts~SourceBrowser",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/gulp/src.ts~SourceBrowser#_processNode",
    "access": "private",
    "description": "Handles a node's dependencies and calls {@link SourceBrowser#_pushNode} once it's ready.",
    "lineNumber": 378,
    "params": [
      {
        "nullable": null,
        "types": [
          "BrowsedFileNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 209,
    "kind": "method",
    "name": "_pushNode",
    "memberof": "src/lib/gulp/src.ts~SourceBrowser",
    "generator": false,
    "async": true,
    "static": false,
    "longname": "src/lib/gulp/src.ts~SourceBrowser#_pushNode",
    "access": "private",
    "description": "Reads a node's value file (if it's a variable) and calls {@link SourceBrowser#_nodeHandler}\nwith it, finishing the node's processing and promoting it's dependents, if any.",
    "lineNumber": 422,
    "params": [
      {
        "nullable": null,
        "types": [
          "BrowsedFileNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 210,
    "kind": "function",
    "name": "src",
    "memberof": "src/lib/gulp/src.ts",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/gulp/src.ts~src",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/gulp/src.ts",
    "importStyle": "src",
    "description": "Starts a new source browser at the given path.",
    "lineNumber": 482,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "path",
        "description": ""
      },
      {
        "nullable": null,
        "types": [
          "SourceBrowserOptions"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 211,
    "kind": "file",
    "name": "src/lib/helpers/Object.js",
    "content": "/**\n * Switches keys and values in an object. E.G.: { \"a\": 1 } becomes { 1: \"a\" }.\n * @param {Object} obj The object to reverse.\n * @return {Object} The reversed object.\n */\nexport function reverse(obj) {\n  return Object.keys(obj).reduce(\n    (result, key) =>\n      Object.assign(result, {\n        [obj[key]]: key,\n      }),\n    {}\n  );\n}\n\n/**\n * Picks some properties from an object and returns a new object containing these.\n * @param {Object} obj The object to pick from.\n * @param {Array<string>} properties Names of the properties to pick.\n * @return {Object} The resulting object.\n */\nexport function pick(obj, properties) {\n  return properties.reduce((props, key) => Object.assign(props, { [key]: obj[key] }), {});\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/helpers/Object.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 212,
    "kind": "function",
    "name": "reverse",
    "memberof": "src/lib/helpers/Object.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/helpers/Object.js~reverse",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/helpers/Object.js",
    "importStyle": "{reverse}",
    "description": "Switches keys and values in an object. E.G.: { \"a\": 1 } becomes { 1: \"a\" }.",
    "lineNumber": 6,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "obj",
        "description": "The object to reverse."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Object"
      ],
      "spread": false,
      "description": "The reversed object."
    }
  },
  {
    "__docId__": 213,
    "kind": "function",
    "name": "pick",
    "memberof": "src/lib/helpers/Object.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/helpers/Object.js~pick",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/helpers/Object.js",
    "importStyle": "{pick}",
    "description": "Picks some properties from an object and returns a new object containing these.",
    "lineNumber": 22,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "obj",
        "description": "The object to pick from."
      },
      {
        "nullable": null,
        "types": [
          "Array<string>"
        ],
        "spread": false,
        "optional": false,
        "name": "properties",
        "description": "Names of the properties to pick."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Object"
      ],
      "spread": false,
      "description": "The resulting object."
    }
  },
  {
    "__docId__": 214,
    "kind": "file",
    "name": "src/lib/helpers/async.ts",
    "content": "/**\n * Returns a promise that resolves after the given duration.\n * @param ms Milliseconds to delay.\n * @return A promise resolved after the specified delay.\n */\nexport const delay = (ms: number): Promise<void> =>\n  new Promise((resolve) => setTimeout(() => resolve(), ms));\n\ntype AsyncCallback<R> = (error?: Error | null, result?: R) => void;\n\n/**\n * Wraps a function with an async callback in a promise.\n * @param fn The function to promisify.\n */\nexport const promisified = <R>(fn: (cb: AsyncCallback<R>) => R): Promise<R> =>\n  new Promise((resolve, reject) => {\n    fn((err, data) => (err ? reject(err) : resolve(data)));\n  });\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/helpers/async.ts",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 215,
    "kind": "function",
    "name": "delay",
    "memberof": "src/lib/helpers/async.ts",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/helpers/async.ts~delay",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/helpers/async.ts",
    "importStyle": "{delay}",
    "description": "Returns a promise that resolves after the given duration.",
    "lineNumber": 6,
    "params": [
      {
        "nullable": null,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "ms",
        "description": "Milliseconds to delay."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "*"
      ],
      "spread": false,
      "description": "A promise resolved after the specified delay."
    }
  },
  {
    "__docId__": 216,
    "kind": "function",
    "name": "promisified",
    "memberof": "src/lib/helpers/async.ts",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/helpers/async.ts~promisified",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/helpers/async.ts",
    "importStyle": "{promisified}",
    "description": "Wraps a function with an async callback in a promise.",
    "lineNumber": 11,
    "params": [
      {
        "nullable": null,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "fn",
        "description": "The function to promisify."
      }
    ],
    "return": null
  },
  {
    "__docId__": 217,
    "kind": "file",
    "name": "src/lib/helpers/fs.ts",
    "content": "import { readFile, writeFile } from 'fs-extra';\nimport detectIndent from 'detect-indent';\n\ntype UpdateFn<T = string> = (current: T) => T | Promise<T>;\n\nexport async function updateFile(path: string, update: UpdateFn, encoding = 'utf8'): Promise<void> {\n  const contents = await readFile(path, encoding);\n  const updated = await update(contents);\n\n  return writeFile(path, updated);\n}\n\nexport async function updateJson<T = {}>(path: string, update: UpdateFn<T>): Promise<void> {\n  return updateFile(path, async (contents) => {\n    const indent = detectIndent(contents).indent || '  ';\n    const current = JSON.parse(contents) as T;\n\n    const updated = await update(current);\n\n    return JSON.stringify(updated, null, indent);\n  });\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/helpers/fs.ts",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 218,
    "kind": "function",
    "name": "updateFile",
    "memberof": "src/lib/helpers/fs.ts",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/lib/helpers/fs.ts~updateFile",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/helpers/fs.ts",
    "importStyle": "{updateFile}",
    "description": "",
    "lineNumber": 6,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "path",
        "description": ""
      },
      {
        "nullable": null,
        "types": [
          "UpdateFn"
        ],
        "spread": false,
        "optional": false,
        "name": "update",
        "description": ""
      },
      {
        "nullable": null,
        "types": [
          "undefined"
        ],
        "spread": false,
        "optional": false,
        "name": "encoding",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 219,
    "kind": "function",
    "name": "updateJson",
    "memberof": "src/lib/helpers/fs.ts",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/lib/helpers/fs.ts~updateJson",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/helpers/fs.ts",
    "importStyle": "{updateJson}",
    "description": "",
    "lineNumber": 13,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "path",
        "description": ""
      },
      {
        "nullable": null,
        "types": [
          "UpdateFn"
        ],
        "spread": false,
        "optional": false,
        "name": "update",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 220,
    "kind": "file",
    "name": "src/lib/helpers/log.js",
    "content": "/* eslint-disable import/prefer-default-export */\n\nimport readline from 'readline';\nimport Logger from 'gulplog';\n\n/**\n * Prints the progress of a task.\n * @param {Promise<any>} task The task to print the progress for.\n * @param {Object} options The options used.\n * @param {function(): number} options.getter A function returning the current progress.\n * @param {function(value: number): string} options.formatter A function returning a log message for\n * the progress passed.\n * @param {string} [options.level='info'] The log level to use.\n * @param {boolean} [options.logResult=true] If the final progress should be printed.\n * @example <caption>A basic implementation</caption>\n * const task = doSomething(); // Returns a Promise\n *\n * reportProgress(task, {\n *   getter: () => getTaskProgress(), // returns a number, e.g. 13 if 13 files have been written\n *   formatter: value => `${value} files written`,\n * })\n *  .then(result => { // Results get passed directly from `task`\n *    console.log(`The result is: ${result}`);\n *  })\n *  .catch(console.error) // which means you need error handling as well!\n */\nexport function reportProgress(task, { getter, formatter, level = 'info', logResult = true } = {}) {\n  const start = Date.now();\n  const ops = (value) => (value / ((Date.now() - start) / 1000)).toFixed(1);\n  const message = () => {\n    const value = getter();\n    return `${formatter(value)} (${ops(value)}/s)`;\n  };\n\n  const interval = setInterval(() => {\n    if (Logger.listenerCount(level) > 0) {\n      Logger[level](message());\n\n      readline.cursorTo(process.stdout, 0);\n      readline.moveCursor(process.stdout, 0, -1);\n    }\n  }, 80);\n\n  const done = (err) => {\n    clearInterval(interval);\n\n    if (logResult && !err) {\n      Logger[level](message());\n    } else if (Logger.listenerCount(level) > 0) {\n      readline.cursorTo(process.stdout, 0);\n      readline.clearLine(process.stdout);\n    }\n\n    if (err) {\n      throw err;\n    }\n  };\n\n  return task.then(\n    () => done(),\n    (err) => done(err)\n  );\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/helpers/log.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 221,
    "kind": "function",
    "name": "reportProgress",
    "memberof": "src/lib/helpers/log.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/helpers/log.js~reportProgress",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/helpers/log.js",
    "importStyle": "{reportProgress}",
    "description": "Prints the progress of a task.",
    "examples": [
      "<caption>A basic implementation</caption>\nconst task = doSomething(); // Returns a Promise\n\nreportProgress(task, {\n  getter: () => getTaskProgress(), // returns a number, e.g. 13 if 13 files have been written\n  formatter: value => `${value} files written`,\n})\n .then(result => { // Results get passed directly from `task`\n   console.log(`The result is: ${result}`);\n })\n .catch(console.error) // which means you need error handling as well!"
    ],
    "lineNumber": 27,
    "params": [
      {
        "nullable": null,
        "types": [
          "Promise<any>"
        ],
        "spread": false,
        "optional": false,
        "name": "task",
        "description": "The task to print the progress for."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "The options used."
      },
      {
        "nullable": null,
        "types": [
          "function(): number"
        ],
        "spread": false,
        "optional": false,
        "name": "options.getter",
        "description": "A function returning the current progress."
      },
      {
        "nullable": null,
        "types": [
          "function(value: number): string"
        ],
        "spread": false,
        "optional": false,
        "name": "options.formatter",
        "description": "A function returning a log message for\nthe progress passed."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": true,
        "defaultValue": "'info'",
        "defaultRaw": "'info'",
        "name": "options.level",
        "description": "The log level to use."
      },
      {
        "nullable": null,
        "types": [
          "boolean"
        ],
        "spread": false,
        "optional": true,
        "defaultValue": "true",
        "defaultRaw": true,
        "name": "options.logResult",
        "description": "If the final progress should be printed."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 222,
    "kind": "file",
    "name": "src/lib/helpers/mapping.js",
    "content": "/* eslint-disable import/prefer-default-export */\n\n/**\n * Sorts the given references before they are persisted to disk.\n * @param {Object} references The references to be sorted.\n */\nexport function sortReferences(references) {\n  return Object.keys(references)\n    .sort()\n    .reduce(\n      (sorted, key) =>\n        Object.assign(sorted, {\n          [key]: Array.isArray(references[key]) ? references[key].sort() : references[key],\n        }),\n      {}\n    );\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/helpers/mapping.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 223,
    "kind": "function",
    "name": "sortReferences",
    "memberof": "src/lib/helpers/mapping.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/helpers/mapping.js~sortReferences",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/helpers/mapping.js",
    "importStyle": "{sortReferences}",
    "description": "Sorts the given references before they are persisted to disk.",
    "lineNumber": 7,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "references",
        "description": "The references to be sorted."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 224,
    "kind": "file",
    "name": "src/lib/helpers/tasks.js",
    "content": "import { codeFrameColumns } from '@babel/code-frame';\nimport Session from '../server/Session';\n\n/**\n * Adds additional infomation to the error's message and rethows it.\n * @param {Error} error The error that occured.\n * @throws {Error} The extended error.\n */\nexport function handleTaskError(error) {\n  if (error.location && error.rawLines) {\n    error.originalStack = error.stack; // eslint-disable-line no-param-reassign\n    // eslint-disable-next-line no-param-reassign\n    error.stack = `${error.message}\n${codeFrameColumns(error.rawLines, error.location, { message: error.message })}`;\n  }\n\n  const additionalMessage = error.node\n    ? `\n - Node: ${error.node.nodeId}`\n    : '';\n\n  Object.assign(error, {\n    message: `${error.message}${additionalMessage}`,\n    stack: `${error.stack}${additionalMessage}`,\n  });\n\n  throw error;\n}\n\n/**\n * Closes open sessions once a task is complete.\n * @return {Promise<void>} Resolved once cleanup is complete.\n */\nexport function finishTask() {\n  return Session.closeOpen();\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/helpers/tasks.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 225,
    "kind": "function",
    "name": "handleTaskError",
    "memberof": "src/lib/helpers/tasks.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/helpers/tasks.js~handleTaskError",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/helpers/tasks.js",
    "importStyle": "{handleTaskError}",
    "description": "Adds additional infomation to the error's message and rethows it.",
    "lineNumber": 9,
    "params": [
      {
        "nullable": null,
        "types": [
          "Error"
        ],
        "spread": false,
        "optional": false,
        "name": "error",
        "description": "The error that occured."
      }
    ],
    "throws": [
      {
        "types": [
          "Error"
        ],
        "description": "The extended error."
      }
    ],
    "return": null
  },
  {
    "__docId__": 226,
    "kind": "function",
    "name": "finishTask",
    "memberof": "src/lib/helpers/tasks.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/helpers/tasks.js~finishTask",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/helpers/tasks.js",
    "importStyle": "{finishTask}",
    "description": "Closes open sessions once a task is complete.",
    "lineNumber": 34,
    "return": {
      "nullable": null,
      "types": [
        "Promise<void>"
      ],
      "spread": false,
      "description": "Resolved once cleanup is complete."
    },
    "params": []
  },
  {
    "__docId__": 227,
    "kind": "file",
    "name": "src/lib/helpers/types.ts",
    "content": "export type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;\nexport type ValueOf<T> = T[keyof T];\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/helpers/types.ts",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 228,
    "kind": "file",
    "name": "src/lib/init/Option.js",
    "content": "/**\n * An option the \"atscm init\" command handles.\n * TODO: Support function values for name, message, default, choices...\n */\nexport default class InitOption {\n  /**\n   * Creates a new option based either on a message and (optionally) a default value or some\n   * options.\n   * @param {string|Object} messageOrOptions The message or options to use.\n   * @param {inquirer~PromptType} [messageOrOptions.type] The option's type.\n   * @param {string} messageOrOptions.message The option's message. Required if `messageOrOptions`\n   * is an object.\n   * @param {string|number} [messageOrOptions.default] The options's default value.\n   * @param {inquirer~Validator} [messageOrOptions.validate] A function that validates user input.\n   * @param {string[]|number[]} [messageOrOptions.choices] The options's choices. Applies to to list\n   * types only.\n   * @param {boolean|function(answers: Object): boolean} [messageOrOptions.when] Weather or not to\n   * prompt this option.\n   * @param {string|number} [defaultOrUndefined] The default value to use.\n   */\n  constructor(messageOrOptions, defaultOrUndefined) {\n    if (messageOrOptions === undefined) {\n      throw new Error('message or options required');\n    }\n\n    if (typeof messageOrOptions === 'string') {\n      if (messageOrOptions.length === 0) {\n        throw new Error('message is required');\n      }\n\n      /**\n       * The option's {@link inquirer~PromptType}. Defaults to 'input'.\n       * @type {inquirer~PromptType}\n       */\n      this.type = InitOption.DefaultType;\n\n      /**\n       * The option's message. A '?' sign is added automatically.\n       * @type {String}\n       */\n      this.message = `${messageOrOptions}?`;\n\n      /**\n       * The default value to use.\n       * @type {String|Number|undefined}\n       */\n      this.default = defaultOrUndefined;\n    } else {\n      if (!messageOrOptions.message || messageOrOptions.length === 0) {\n        throw new Error('message is required');\n      }\n\n      this.type = messageOrOptions.type || InitOption.DefaultType;\n      this.message = `${messageOrOptions.message}?`;\n      this.default = messageOrOptions.default;\n\n      /**\n       * The choices available. Applies to list types only.\n       * @type {String[]|Number[]|undefined}\n       */\n      this.choices = messageOrOptions.choices;\n\n      /**\n       * Validates the user input for this option.\n       * @type {inquirer~Validator}\n       */\n      this.validate = messageOrOptions.validate;\n\n      /**\n       * A function or boolean that indicates weather or not to prompt this option.\n       * @type {Boolean|function(answers: Object): Boolean|undefined}\n       */\n      this.when = messageOrOptions.when;\n    }\n  }\n\n  /**\n   * The default {@link inquirer~PromptType} to use. Equals 'input'.\n   * @return {inquirer~PromptType} The default {@link inquirer~PromptType} to use.\n   */\n  static get DefaultType() {\n    return 'input';\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/init/Option.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 229,
    "kind": "class",
    "name": "InitOption",
    "memberof": "src/lib/init/Option.js",
    "static": true,
    "longname": "src/lib/init/Option.js~InitOption",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/init/Option.js",
    "importStyle": "InitOption",
    "description": "An option the \"atscm init\" command handles.\nTODO: Support function values for name, message, default, choices...",
    "lineNumber": 5,
    "interface": false
  },
  {
    "__docId__": 230,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/init/Option.js~InitOption",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/init/Option.js~InitOption#constructor",
    "access": "public",
    "description": "Creates a new option based either on a message and (optionally) a default value or some\noptions.",
    "lineNumber": 21,
    "params": [
      {
        "nullable": null,
        "types": [
          "string",
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "messageOrOptions",
        "description": "The message or options to use."
      },
      {
        "nullable": null,
        "types": [
          "inquirer~PromptType"
        ],
        "spread": false,
        "optional": true,
        "name": "messageOrOptions.type",
        "description": "The option's type."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "messageOrOptions.message",
        "description": "The option's message. Required if `messageOrOptions`\nis an object."
      },
      {
        "nullable": null,
        "types": [
          "string",
          "number"
        ],
        "spread": false,
        "optional": true,
        "name": "messageOrOptions.default",
        "description": "The options's default value."
      },
      {
        "nullable": null,
        "types": [
          "inquirer~Validator"
        ],
        "spread": false,
        "optional": true,
        "name": "messageOrOptions.validate",
        "description": "A function that validates user input."
      },
      {
        "nullable": null,
        "types": [
          "string[]",
          "number[]"
        ],
        "spread": false,
        "optional": true,
        "name": "messageOrOptions.choices",
        "description": "The options's choices. Applies to to list\ntypes only."
      },
      {
        "nullable": null,
        "types": [
          "boolean",
          "function(answers: Object): boolean"
        ],
        "spread": false,
        "optional": true,
        "name": "messageOrOptions.when",
        "description": "Weather or not to\nprompt this option."
      },
      {
        "nullable": null,
        "types": [
          "string",
          "number"
        ],
        "spread": false,
        "optional": true,
        "name": "defaultOrUndefined",
        "description": "The default value to use."
      }
    ]
  },
  {
    "__docId__": 231,
    "kind": "member",
    "name": "type",
    "memberof": "src/lib/init/Option.js~InitOption",
    "static": false,
    "longname": "src/lib/init/Option.js~InitOption#type",
    "access": "public",
    "description": "The option's {@link inquirer~PromptType}. Defaults to 'input'.",
    "lineNumber": 35,
    "type": {
      "nullable": null,
      "types": [
        "inquirer~PromptType"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 232,
    "kind": "member",
    "name": "message",
    "memberof": "src/lib/init/Option.js~InitOption",
    "static": false,
    "longname": "src/lib/init/Option.js~InitOption#message",
    "access": "public",
    "description": "The option's message. A '?' sign is added automatically.",
    "lineNumber": 41,
    "type": {
      "nullable": null,
      "types": [
        "String"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 233,
    "kind": "member",
    "name": "default",
    "memberof": "src/lib/init/Option.js~InitOption",
    "static": false,
    "longname": "src/lib/init/Option.js~InitOption#default",
    "access": "public",
    "description": "The default value to use.",
    "lineNumber": 47,
    "type": {
      "nullable": null,
      "types": [
        "String",
        "Number",
        "undefined"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 237,
    "kind": "member",
    "name": "choices",
    "memberof": "src/lib/init/Option.js~InitOption",
    "static": false,
    "longname": "src/lib/init/Option.js~InitOption#choices",
    "access": "public",
    "description": "The choices available. Applies to list types only.",
    "lineNumber": 61,
    "type": {
      "nullable": null,
      "types": [
        "String[]",
        "Number[]",
        "undefined"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 238,
    "kind": "member",
    "name": "validate",
    "memberof": "src/lib/init/Option.js~InitOption",
    "static": false,
    "longname": "src/lib/init/Option.js~InitOption#validate",
    "access": "public",
    "description": "Validates the user input for this option.",
    "lineNumber": 67,
    "type": {
      "nullable": null,
      "types": [
        "inquirer~Validator"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 239,
    "kind": "member",
    "name": "when",
    "memberof": "src/lib/init/Option.js~InitOption",
    "static": false,
    "longname": "src/lib/init/Option.js~InitOption#when",
    "access": "public",
    "description": "A function or boolean that indicates weather or not to prompt this option.",
    "lineNumber": 73,
    "type": {
      "nullable": null,
      "types": [
        "Boolean",
        "function(answers: Object): Boolean",
        "undefined"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 240,
    "kind": "get",
    "name": "DefaultType",
    "memberof": "src/lib/init/Option.js~InitOption",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/init/Option.js~InitOption.DefaultType",
    "access": "public",
    "description": "The default {@link inquirer~PromptType} to use. Equals 'input'.",
    "lineNumber": 81,
    "return": {
      "nullable": null,
      "types": [
        "inquirer~PromptType"
      ],
      "spread": false,
      "description": "The default {@link inquirer~PromptType} to use."
    },
    "type": {
      "types": [
        "string"
      ]
    }
  },
  {
    "__docId__": 241,
    "kind": "file",
    "name": "src/lib/model/Node.ts",
    "content": "import { ReferenceTypeIds as OpcReferenceTypeIds } from 'node-opcua/lib/opcua_node_ids';\nimport { NodeClass } from 'node-opcua/lib/datamodel/nodeclass';\nimport { VariantArrayType, DataType, Variant } from 'node-opcua/lib/datamodel/variant';\nimport { ItemOf, KeyOf } from 'node-opcua/lib/misc/enum.js';\nimport { reverse } from '../helpers/Object';\nimport { sortReferences } from '../helpers/mapping';\nimport { ValueOf } from '../helpers/types';\n\n/**\n * References type ids.\n */\nexport const ReferenceTypeIds = {\n  ...OpcReferenceTypeIds,\n  toParent: -1,\n};\n\n/** A reference type name */\ntype ReferenceTypeName = keyof typeof ReferenceTypeIds;\n\n/** A raw (number) reference type */\ntype ReferenceType = ValueOf<typeof ReferenceTypeIds>;\n\n/** Node references stored in definition files */\nexport type ReferenceDefinitions = {\n  [type in ReferenceTypeName]?: (number | string)[];\n};\n\n/** Node definition stored in definition file */\nexport interface NodeDefinition {\n  nodeId?: string;\n  nodeClass?: KeyOf<typeof NodeClass>; // Defaults to 'Variable'\n  dataType?: KeyOf<typeof DataType>;\n  arrayType?: KeyOf<typeof VariantArrayType>;\n  references?: ReferenceDefinitions;\n}\n\n/**\n * Names for references.\n */\nexport const ReferenceTypeNames = reverse(ReferenceTypeIds) as { [key: number]: string };\n\n/**\n * A map specialized for holding references.\n */\nclass ReferenceMap extends Map<ReferenceType, Set<number | string>> {\n  /**\n   * Adds a new reference.\n   * @param {number} type The reference id.\n   * @param {string} nodeId The reference target node's id.\n   */\n  public addReference(type: ReferenceType, nodeId: number | string): void {\n    const set = this.get(type);\n    if (set) {\n      set.add(nodeId);\n    } else {\n      this.set(type, new Set([nodeId]));\n    }\n  }\n\n  /**\n   * Removes the given reference.\n   * @param {number} type The reference id.\n   * @param {string} nodeId The reference target node's id.\n   */\n  public deleteReference(type: ReferenceType, nodeId: number | string): number | string {\n    const set = this.get(type);\n    if (set) {\n      const ref = set.delete(nodeId);\n\n      if (ref) {\n        if (set.size === 0) {\n          this.delete(type);\n        }\n\n        return nodeId;\n      }\n    }\n\n    throw new Error(`No ${ReferenceTypeNames[type] || type} reference to ${nodeId}`);\n  }\n\n  /**\n   * Returns the first entry of a specific type.\n   * @param type The reference type id to look for.\n   * @return The first reference found or undefined.\n   */\n  public getSingle(type: ReferenceType): number | string | undefined {\n    const set = this.get(type);\n    return set && Array.from(set)[0];\n  }\n\n  /**\n   * Returns a plain object of refernces.\n   * @return A string describing the reference map.\n   */\n  public toJSON(): ReferenceDefinitions {\n    return [...this].reduce(\n      (result, [key, value]) =>\n        Object.assign(result, {\n          [ReferenceTypeNames[key] || key]: [...value],\n        }),\n      {}\n    );\n  }\n}\n\ninterface WithValue {\n  value: Variant;\n}\n\nexport interface NodeOptions {\n  name: string;\n  parent?: Node;\n  nodeClass: ItemOf<typeof NodeClass>;\n}\n\ntype NodeResolveKey = 'nodeClass' | 'dataType' | 'arrayType';\n\n/**\n * The main model class.\n */\nexport default abstract class Node {\n  /** The node's name when stored to a file. */\n  protected fileName: string;\n  /** The node's name when written to the server. */\n  protected idName: string;\n  /** The id stored in the definition file. */\n  protected specialId?: string;\n\n  /** The node's parent node. */\n  public readonly parent?: Node;\n  /** The node's class. */\n  public readonly nodeClass: ItemOf<typeof NodeClass>;\n\n  /** A set of resolved properties. */\n  protected _resolved = new Set<NodeResolveKey>();\n  /** A set of unresolved properties. */\n  protected _unresolved: Set<NodeResolveKey>;\n  /** The node's references. */\n  public references = new ReferenceMap();\n  /** The node's unresolved refernces. */\n  protected _resolvedReferences = new ReferenceMap();\n  /** The node's resolved refernces. */\n  protected _unresolvedReferences = new ReferenceMap();\n  /** If the parent node resolves metadata. */\n  protected _parentResolvesMetadata = false;\n\n  /**\n   * Creates a new node.\n   * @param {Object} options The options to use.\n   * @param {string} options.name The node's name.\n   * @param {Node} options.parent The node's parent node.\n   * @param {node-opcua~NodeClass} options.nodeClass The node's class.\n   */\n  public constructor({ name, parent, nodeClass /* , referenceToParent */ }: NodeOptions) {\n    this.fileName = name;\n    this.idName = name;\n    this.parent = parent;\n    this.nodeClass = nodeClass;\n\n    this._unresolved = new Set([\n      'nodeClass',\n      // Only for variables\n      'dataType',\n      'arrayType',\n    ]);\n  }\n\n  /**\n   * If the parent resolves metadata (for example: split transformer source files).\n   */\n  public get parentResolvesMetadata(): boolean {\n    return this._parentResolvesMetadata;\n  }\n\n  public markAsResolved(key: NodeResolveKey): void {\n    const value = this._unresolved.delete(key);\n\n    // FIXME: Only test if debug / test\n    if (value === false) {\n      throw new Error(`'${key}' is already resolved`);\n    }\n\n    this._resolved.add(key);\n  }\n\n  public isResolved(key: NodeResolveKey): boolean {\n    return this._resolved.has(key);\n  }\n\n  /**\n   * Adds a new reference.\n   * @param {number} type The reference type's id.\n   * @param {string} id The reference target node's id.\n   */\n  public addReference(type: ReferenceType, id: string): void {\n    this.references.addReference(type, id);\n    this._unresolvedReferences.addReference(type, id);\n  }\n\n  public setReferences(type: ReferenceType, ids: string[]): void {\n    this.references.set(type, new Set(ids));\n    this._unresolvedReferences.set(type, new Set(ids));\n  }\n\n  public markReferenceAsResolved(name: ReferenceTypeName, value: string): void {\n    const type = ReferenceTypeIds[name];\n    const ref = this._unresolvedReferences.deleteReference(type, value);\n    this._resolvedReferences.addReference(type, ref);\n  }\n\n  public markAllReferencesAsResolved(name: ReferenceTypeName): void {\n    const type = ReferenceTypeIds[name];\n    this._unresolvedReferences.delete(type);\n  }\n\n  public hasUnresolvedReference(name: ReferenceTypeName): boolean {\n    const type = ReferenceTypeIds[name];\n    return this._unresolvedReferences.has(type);\n  }\n\n  /**\n   * The node's file path, used to compute {@link Node#filePath}.\n   */\n  private get _filePath(): string[] {\n    if (!this.parent) {\n      return [this.fileName];\n    }\n    return this.parent._filePath.concat(this.fileName);\n  }\n\n  /**\n   * The node's file path.\n   */\n  public get filePath(): string[] {\n    if (!this.parent) {\n      return [];\n    }\n    return this.parent._filePath;\n  }\n\n  /**\n   * The node's id, used to compute {@link Node#nodeId}.\n   */\n  private get _nodeId(): { id: string; separator: '/' | '.' } {\n    if (this.specialId) {\n      return {\n        id: this.specialId,\n        separator: this.specialId.match(/\\.RESOURCES\\/?/) ? '/' : '.',\n      };\n    }\n\n    if (!this.parent) {\n      return {\n        id: this.idName,\n        separator: '.',\n      };\n    }\n\n    const { separator, id } = this.parent._nodeId;\n\n    if (this._parentResolvesMetadata) {\n      return { separator, id };\n    }\n\n    return {\n      separator: this.idName === 'RESOURCES' ? '/' : separator,\n      id: `${id}${separator}${this.idName}`,\n    };\n  }\n\n  /**\n   * The node's id.\n   */\n  public get nodeId(): string {\n    return this._nodeId.id;\n  }\n\n  /**\n   * The node's type definition if given.\n   */\n  public get typeDefinition(): number | string | undefined {\n    return this.references.getSingle(ReferenceTypeIds.HasTypeDefinition);\n  }\n\n  /**\n   * The node's modellingRule if given.\n   * @type {?number}\n   */\n  public get modellingRule(): number | string | undefined {\n    return this.references.getSingle(ReferenceTypeIds.HasModellingRule);\n  }\n\n  /**\n   * Returns `true` if the node has the given type definition.\n   * @param typeDefName - The type definition to check.\n   * @return If the node has the given type definition.\n   */\n  public hasTypeDefinition(typeDefName: number | string): boolean {\n    const def = this.typeDefinition;\n\n    return def ? def === typeDefName : false;\n  }\n\n  /**\n   * `true` at the moment.\n   */\n  public get hasUnresolvedMetadata(): boolean {\n    return true;\n    /* FIXME: Once plugin mapping is implemented\n    const value = !this._parentResolvesMetadata && (Boolean(this._unresolved.size) ||\n      Boolean(this._unresolvedReferences.size) || this.specialId);\n\n    // FIXME: If debug / test\n    if (!value && Object.keys(this.metadata).length > 0) {\n      throw new Error(`#hasUnresolvedMetadata did return invalid result ${\n        value\n      } for ${\n        JSON.stringify(Object.assign(this, {parent: undefined, value: undefined }), null, '  ')\n      }`);\n    } else if (value && Object.keys(this.metadata).length === 0) {\n      throw new Error('#metadata did return invalid result');\n    }\n\n    return value; */\n  }\n\n  /**\n   * The metadata to store in the node's definition file.\n   * @type {Object}\n   */\n  public get metadata(): NodeDefinition {\n    if (this._parentResolvesMetadata) {\n      return {};\n    }\n\n    const meta: Partial<NodeDefinition> = {};\n\n    if (this.specialId) {\n      meta.nodeId = this.specialId;\n    }\n\n    if (this.isVariableNode()) {\n      meta.dataType = this.value.dataType.key;\n      meta.arrayType = this.value.arrayType.key;\n    } else {\n      meta.nodeClass = this.nodeClass.key;\n    }\n\n    meta.references = sortReferences(this.references.toJSON());\n\n    /* FIXME: Once plugin mapping is implemented\n    for (const unresolved of this._unresolved) {\n      let value = this[unresolved];\n\n      if (unresolved === 'dataType') {\n        value = this.value.dataType ? this.value.dataType.key : 'UNKNOWN';\n      } else if (unresolved === 'arrayType') {\n        value = this.value.arrayType ? this.value.arrayType.key : 'UNKNOWN';\n      }\n\n      meta[unresolved] = value;\n    }\n\n\n    if (this._unresolvedReferences.size) {\n      meta.references = sortReferences(this._unresolvedReferences.toJSON());\n    }\n    */\n\n    return meta;\n  }\n\n  // Manipulation\n\n  /**\n   * Creates a new child node.\n   * @param {Object} options The options to use.\n   * @param {string} options.extension The extension to append to the node's name.\n   */\n  public createChild({ extension }: { extension: string }): Node {\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    const node: Node = new (this.constructor as any)({\n      name: this.idName,\n      parent: this,\n      nodeClass: this.nodeClass,\n    });\n\n    node.fileName = `${this.fileName}${extension}`;\n\n    node.references = this.references;\n    node._parentResolvesMetadata = true;\n\n    return node;\n  }\n\n  // Convenience getters\n\n  /**\n   * The node's data type.\n   */\n  public get dataType(): ItemOf<typeof DataType> {\n    if (!this.isVariableNode()) {\n      throw new TypeError('Not a variable node');\n    }\n\n    return this.value.dataType;\n  }\n\n  /**\n   * The node's array type.\n   */\n  public get arrayType(): ItemOf<typeof VariantArrayType> {\n    if (!this.isVariableNode()) {\n      throw new TypeError('Not a variable node');\n    }\n\n    return this.value.arrayType;\n  }\n\n  /**\n   * If the node is a variable.\n   * @deprecated Use TypeScript compatible {@link Node#isVariableNode} instead.\n   */\n  public get isVariable(): boolean {\n    return this.nodeClass === NodeClass.Variable;\n  }\n\n  public isVariableNode(): this is WithValue {\n    return this.isVariable;\n  }\n\n  // FIXME: Move to display / script transformers\n\n  /**\n   * If the node is an object display.\n   */\n  public get isDisplay(): boolean {\n    return this.hasTypeDefinition('VariableTypes.ATVISE.Display');\n  }\n\n  /**\n   * If the node is a serverside script.\n   */\n  public get isScript(): boolean {\n    return this.hasTypeDefinition('VariableTypes.ATVISE.ScriptCode');\n  }\n\n  /**\n   * If the node is a quickdynamic.\n   */\n  public get isQuickDynamic(): boolean {\n    return this.hasTypeDefinition('VariableTypes.ATVISE.QuickDynamic');\n  }\n\n  /**\n   * If the node is a display script.\n   */\n  public get isDisplayScript(): boolean {\n    return this.hasTypeDefinition('VariableTypes.ATVISE.DisplayScript');\n  }\n}\n\n/**\n * A node during a *pull*.\n */\nexport abstract class ServerNode extends Node {\n  /**\n   * The node's name.\n   */\n  public get name(): string {\n    return this.fileName;\n  }\n\n  /**\n   * Renames a node.\n   * @param name The name to set.\n   */\n  public renameTo(name: string): void {\n    this.fileName = name;\n  }\n}\n\n/**\n * A node during a *push*.\n */\nexport abstract class SourceNode extends Node {\n  /**\n   * The node's name.\n   */\n  public get name(): string {\n    return this.idName;\n  }\n\n  /**\n   * Renames a node.\n   * @param name The name to set.\n   */\n  public renameTo(name: string): void {\n    this.idName = name;\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/model/Node.ts",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 242,
    "kind": "variable",
    "name": "ReferenceTypeIds",
    "memberof": "src/lib/model/Node.ts",
    "static": true,
    "longname": "src/lib/model/Node.ts~ReferenceTypeIds",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/model/Node.ts",
    "importStyle": "{ReferenceTypeIds}",
    "description": "References type ids.",
    "lineNumber": 8,
    "type": {
      "types": [
        "{...OpcReferenceTypeIds: Object, \"toParent\": *}"
      ]
    }
  },
  {
    "__docId__": 243,
    "kind": "variable",
    "name": "ReferenceTypeNames",
    "memberof": "src/lib/model/Node.ts",
    "static": true,
    "longname": "src/lib/model/Node.ts~ReferenceTypeNames",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/model/Node.ts",
    "importStyle": "{ReferenceTypeNames}",
    "description": "Names for references.",
    "lineNumber": 15,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 244,
    "kind": "class",
    "name": "ReferenceMap",
    "memberof": "src/lib/model/Node.ts",
    "static": true,
    "longname": "src/lib/model/Node.ts~ReferenceMap",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/model/Node.ts",
    "importStyle": null,
    "description": "A map specialized for holding references.",
    "lineNumber": 45,
    "interface": false,
    "extends": [
      "Map"
    ],
    "ignore": true
  },
  {
    "__docId__": 245,
    "kind": "method",
    "name": "addReference",
    "memberof": "src/lib/model/Node.ts~ReferenceMap",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~ReferenceMap#addReference",
    "access": "public",
    "description": "Adds a new reference.",
    "lineNumber": 51,
    "params": [
      {
        "nullable": null,
        "types": [
          "ReferenceType"
        ],
        "spread": false,
        "optional": false,
        "name": "type",
        "description": ""
      },
      {
        "nullable": null,
        "types": [
          "undefined"
        ],
        "spread": false,
        "optional": false,
        "name": "nodeId",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 246,
    "kind": "method",
    "name": "deleteReference",
    "memberof": "src/lib/model/Node.ts~ReferenceMap",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~ReferenceMap#deleteReference",
    "access": "public",
    "description": "Removes the given reference.",
    "lineNumber": 65,
    "params": [
      {
        "nullable": null,
        "types": [
          "ReferenceType"
        ],
        "spread": false,
        "optional": false,
        "name": "type",
        "description": ""
      },
      {
        "nullable": null,
        "types": [
          "undefined"
        ],
        "spread": false,
        "optional": false,
        "name": "nodeId",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 247,
    "kind": "method",
    "name": "getSingle",
    "memberof": "src/lib/model/Node.ts~ReferenceMap",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~ReferenceMap#getSingle",
    "access": "public",
    "description": "Returns the first entry of a specific type.",
    "lineNumber": 87,
    "params": [
      {
        "nullable": null,
        "types": [
          "ReferenceType"
        ],
        "spread": false,
        "optional": false,
        "name": "type",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 248,
    "kind": "method",
    "name": "toJSON",
    "memberof": "src/lib/model/Node.ts~ReferenceMap",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~ReferenceMap#toJSON",
    "access": "public",
    "description": "Returns a plain object of refernces.",
    "lineNumber": 96,
    "return": {
      "nullable": null,
      "types": [
        "ReferenceDefinitions"
      ],
      "spread": false,
      "description": ""
    },
    "params": []
  },
  {
    "__docId__": 249,
    "kind": "class",
    "name": "Node",
    "memberof": "src/lib/model/Node.ts",
    "static": true,
    "longname": "src/lib/model/Node.ts~Node",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/model/Node.ts",
    "importStyle": "Node",
    "description": "The main model class.",
    "lineNumber": 122,
    "interface": false
  },
  {
    "__docId__": 250,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#constructor",
    "access": "public",
    "description": "Creates a new node.",
    "lineNumber": 111,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "The options to use."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "options.name",
        "description": "The node's name."
      },
      {
        "nullable": null,
        "types": [
          "Node"
        ],
        "spread": false,
        "optional": false,
        "name": "options.parent",
        "description": "The node's parent node."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~NodeClass"
        ],
        "spread": false,
        "optional": false,
        "name": "options.nodeClass",
        "description": "The node's class."
      }
    ]
  },
  {
    "__docId__": 251,
    "kind": "member",
    "name": "_resolved",
    "memberof": "src/lib/model/Node.ts~Node",
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#_resolved",
    "access": "private",
    "description": "A set of resolved properties.",
    "lineNumber": 136,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 252,
    "kind": "member",
    "name": "references",
    "memberof": "src/lib/model/Node.ts~Node",
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#references",
    "access": "public",
    "description": "The node's references.",
    "lineNumber": 140,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 253,
    "kind": "member",
    "name": "_resolvedReferences",
    "memberof": "src/lib/model/Node.ts~Node",
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#_resolvedReferences",
    "access": "private",
    "description": "The node's unresolved refernces.",
    "lineNumber": 142,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 254,
    "kind": "member",
    "name": "_unresolvedReferences",
    "memberof": "src/lib/model/Node.ts~Node",
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#_unresolvedReferences",
    "access": "private",
    "description": "The node's resolved refernces.",
    "lineNumber": 144,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 255,
    "kind": "member",
    "name": "_parentResolvesMetadata",
    "memberof": "src/lib/model/Node.ts~Node",
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#_parentResolvesMetadata",
    "access": "private",
    "description": "If the parent node resolves metadata.",
    "lineNumber": 146,
    "type": {
      "types": [
        "boolean"
      ]
    }
  },
  {
    "__docId__": 256,
    "kind": "member",
    "name": "fileName",
    "memberof": "src/lib/model/Node.ts~Node",
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#fileName",
    "access": "public",
    "description": null,
    "lineNumber": 147,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 257,
    "kind": "member",
    "name": "idName",
    "memberof": "src/lib/model/Node.ts~Node",
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#idName",
    "access": "public",
    "description": null,
    "lineNumber": 148,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 258,
    "kind": "member",
    "name": "parent",
    "memberof": "src/lib/model/Node.ts~Node",
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#parent",
    "access": "public",
    "description": null,
    "lineNumber": 149,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 259,
    "kind": "member",
    "name": "nodeClass",
    "memberof": "src/lib/model/Node.ts~Node",
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#nodeClass",
    "access": "public",
    "description": null,
    "lineNumber": 150,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 260,
    "kind": "member",
    "name": "_unresolved",
    "memberof": "src/lib/model/Node.ts~Node",
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#_unresolved",
    "access": "private",
    "description": null,
    "lineNumber": 151,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 261,
    "kind": "get",
    "name": "parentResolvesMetadata",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#parentResolvesMetadata",
    "access": "public",
    "description": "If the parent resolves metadata (for example: split transformer source files).",
    "lineNumber": 172,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 262,
    "kind": "method",
    "name": "markAsResolved",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#markAsResolved",
    "access": "public",
    "description": "",
    "lineNumber": 176,
    "params": [
      {
        "nullable": null,
        "types": [
          "NodeResolveKey"
        ],
        "spread": false,
        "optional": false,
        "name": "key",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 263,
    "kind": "method",
    "name": "isResolved",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#isResolved",
    "access": "public",
    "description": "",
    "lineNumber": 187,
    "params": [
      {
        "nullable": null,
        "types": [
          "NodeResolveKey"
        ],
        "spread": false,
        "optional": false,
        "name": "key",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 264,
    "kind": "method",
    "name": "addReference",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#addReference",
    "access": "public",
    "description": "Adds a new reference.",
    "lineNumber": 196,
    "params": [
      {
        "nullable": null,
        "types": [
          "ReferenceType"
        ],
        "spread": false,
        "optional": false,
        "name": "type",
        "description": ""
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "id",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 265,
    "kind": "method",
    "name": "setReferences",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#setReferences",
    "access": "public",
    "description": "",
    "lineNumber": 201,
    "params": [
      {
        "nullable": null,
        "types": [
          "ReferenceType"
        ],
        "spread": false,
        "optional": false,
        "name": "type",
        "description": ""
      },
      {
        "nullable": null,
        "types": [
          "undefined"
        ],
        "spread": false,
        "optional": false,
        "name": "ids",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 266,
    "kind": "method",
    "name": "markReferenceAsResolved",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#markReferenceAsResolved",
    "access": "public",
    "description": "",
    "lineNumber": 206,
    "params": [
      {
        "nullable": null,
        "types": [
          "ReferenceTypeName"
        ],
        "spread": false,
        "optional": false,
        "name": "name",
        "description": ""
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "value",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 267,
    "kind": "method",
    "name": "markAllReferencesAsResolved",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#markAllReferencesAsResolved",
    "access": "public",
    "description": "",
    "lineNumber": 212,
    "params": [
      {
        "nullable": null,
        "types": [
          "ReferenceTypeName"
        ],
        "spread": false,
        "optional": false,
        "name": "name",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 268,
    "kind": "method",
    "name": "hasUnresolvedReference",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#hasUnresolvedReference",
    "access": "public",
    "description": "",
    "lineNumber": 217,
    "params": [
      {
        "nullable": null,
        "types": [
          "ReferenceTypeName"
        ],
        "spread": false,
        "optional": false,
        "name": "name",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 269,
    "kind": "get",
    "name": "_filePath",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#_filePath",
    "access": "private",
    "description": "The node's file path, used to compute {@link Node#filePath}.",
    "lineNumber": 225,
    "type": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 270,
    "kind": "get",
    "name": "filePath",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#filePath",
    "access": "public",
    "description": "The node's file path.",
    "lineNumber": 235,
    "type": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 271,
    "kind": "get",
    "name": "_nodeId",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#_nodeId",
    "access": "private",
    "description": "The node's id, used to compute {@link Node#nodeId}.",
    "lineNumber": 245,
    "type": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 272,
    "kind": "get",
    "name": "nodeId",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#nodeId",
    "access": "public",
    "description": "The node's id.",
    "lineNumber": 275,
    "type": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 273,
    "kind": "get",
    "name": "typeDefinition",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#typeDefinition",
    "access": "public",
    "description": "The node's type definition if given.",
    "lineNumber": 282,
    "type": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 274,
    "kind": "get",
    "name": "modellingRule",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#modellingRule",
    "access": "public",
    "description": "The node's modellingRule if given.",
    "lineNumber": 290,
    "type": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 275,
    "kind": "method",
    "name": "hasTypeDefinition",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#hasTypeDefinition",
    "access": "public",
    "description": "Returns `true` if the node has the given type definition.",
    "lineNumber": 299,
    "params": [
      {
        "nullable": null,
        "types": [
          "undefined"
        ],
        "spread": false,
        "optional": false,
        "name": "typeDefName",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 276,
    "kind": "get",
    "name": "hasUnresolvedMetadata",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#hasUnresolvedMetadata",
    "access": "public",
    "description": "`true` at the moment.",
    "lineNumber": 308,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 277,
    "kind": "get",
    "name": "metadata",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#metadata",
    "access": "public",
    "description": "The metadata to store in the node's definition file.",
    "lineNumber": 332,
    "type": {
      "nullable": null,
      "types": [
        "NodeDefinition"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 278,
    "kind": "method",
    "name": "createChild",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#createChild",
    "access": "public",
    "description": "Creates a new child node.",
    "lineNumber": 381,
    "params": [
      {
        "nullable": null,
        "types": [
          "undefined"
        ],
        "spread": false,
        "optional": false,
        "name": "undefined",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Node"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 279,
    "kind": "get",
    "name": "dataType",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#dataType",
    "access": "public",
    "description": "The node's data type.",
    "lineNumber": 402,
    "type": {
      "nullable": null,
      "types": [
        "ItemOf"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 280,
    "kind": "get",
    "name": "arrayType",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#arrayType",
    "access": "public",
    "description": "The node's array type.",
    "lineNumber": 413,
    "type": {
      "nullable": null,
      "types": [
        "ItemOf"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 281,
    "kind": "get",
    "name": "isVariable",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#isVariable",
    "access": "public",
    "description": "If the node is a variable.",
    "lineNumber": 425,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 282,
    "kind": "method",
    "name": "isVariableNode",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#isVariableNode",
    "access": "public",
    "description": "",
    "lineNumber": 429,
    "return": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": ""
    },
    "params": []
  },
  {
    "__docId__": 283,
    "kind": "get",
    "name": "isDisplay",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#isDisplay",
    "access": "public",
    "description": "If the node is an object display.",
    "lineNumber": 438,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 284,
    "kind": "get",
    "name": "isScript",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#isScript",
    "access": "public",
    "description": "If the node is a serverside script.",
    "lineNumber": 445,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 285,
    "kind": "get",
    "name": "isQuickDynamic",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#isQuickDynamic",
    "access": "public",
    "description": "If the node is a quickdynamic.",
    "lineNumber": 452,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 286,
    "kind": "get",
    "name": "isDisplayScript",
    "memberof": "src/lib/model/Node.ts~Node",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~Node#isDisplayScript",
    "access": "public",
    "description": "If the node is a display script.",
    "lineNumber": 459,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 287,
    "kind": "class",
    "name": "ServerNode",
    "memberof": "src/lib/model/Node.ts",
    "static": true,
    "longname": "src/lib/model/Node.ts~ServerNode",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/model/Node.ts",
    "importStyle": "{ServerNode}",
    "description": "A node during a *pull*.",
    "lineNumber": 467,
    "interface": false,
    "extends": [
      "Node"
    ]
  },
  {
    "__docId__": 288,
    "kind": "get",
    "name": "name",
    "memberof": "src/lib/model/Node.ts~ServerNode",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~ServerNode#name",
    "access": "public",
    "description": "The node's name.",
    "lineNumber": 471,
    "type": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 289,
    "kind": "method",
    "name": "renameTo",
    "memberof": "src/lib/model/Node.ts~ServerNode",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~ServerNode#renameTo",
    "access": "public",
    "description": "Renames a node.",
    "lineNumber": 479,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "name",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 290,
    "kind": "member",
    "name": "fileName",
    "memberof": "src/lib/model/Node.ts~ServerNode",
    "static": false,
    "longname": "src/lib/model/Node.ts~ServerNode#fileName",
    "access": "public",
    "description": null,
    "lineNumber": 602,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 291,
    "kind": "class",
    "name": "SourceNode",
    "memberof": "src/lib/model/Node.ts",
    "static": true,
    "longname": "src/lib/model/Node.ts~SourceNode",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/model/Node.ts",
    "importStyle": "{SourceNode}",
    "description": "A node during a *push*.",
    "lineNumber": 487,
    "interface": false,
    "extends": [
      "Node"
    ]
  },
  {
    "__docId__": 292,
    "kind": "get",
    "name": "name",
    "memberof": "src/lib/model/Node.ts~SourceNode",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~SourceNode#name",
    "access": "public",
    "description": "The node's name.",
    "lineNumber": 491,
    "type": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 293,
    "kind": "method",
    "name": "renameTo",
    "memberof": "src/lib/model/Node.ts~SourceNode",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/Node.ts~SourceNode#renameTo",
    "access": "public",
    "description": "Renames a node.",
    "lineNumber": 499,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "name",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 294,
    "kind": "member",
    "name": "idName",
    "memberof": "src/lib/model/Node.ts~SourceNode",
    "static": false,
    "longname": "src/lib/model/Node.ts~SourceNode#idName",
    "access": "public",
    "description": null,
    "lineNumber": 634,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 295,
    "kind": "file",
    "name": "src/lib/model/opcua/NodeId.js",
    "content": "import { sep } from 'path';\nimport { NodeId as OpcNodeId } from 'node-opcua/lib/datamodel/nodeid';\n\n/**\n * OPC-UA node id types.\n * @type {Map<String, node-opcua~NodeIdType>}\n */\nconst Type = OpcNodeId.NodeIdType;\n\n/**\n * OPC-UA node id types mapped against node-id identifiers (e.g. i, s ...).\n * @type {Map<String, node-opcua~NodeIdType>}\n */\nconst TypeForIdentifier = {\n  i: Type.NUMERIC,\n  s: Type.STRING,\n  g: Type.GUID,\n  b: Type.BYTESTRING,\n};\n\n/**\n * Resource nodes are only allowed to have these child nodes.\n * @type {Set<string>}\n */\nconst possibleResourceChildNodes = new Set(['Translate', 'Compress']);\n\n/**\n * A wrapper around {@link node-opcua~NodeId}.\n */\nexport default class NodeId extends OpcNodeId {\n  /**\n   * Creates a new NodeId. Can be called in multiple ways:\n   *  - with a {@link node-opcua~NodeIdType}, a value and a namespace (defaults to 0),\n   *  - with a value only (type will be taken from it, namespace defaults to 1) or\n   *  - with a {@link NodeId}s string representation (for example `ns=1;s=AGENT.DISPLAYS`).\n   * @param {node-opcua~NodeIdType|string|number} typeOrValue The type or value to use.\n   * @param {(number|string)} [value] The value to use.\n   * @param {number} [namespace=1] The namespace to use.\n   */\n  constructor(typeOrValue, value, namespace = 1) {\n    if (!Type.get(typeOrValue)) {\n      let m = null;\n\n      if (typeof typeOrValue === 'string') {\n        m = typeOrValue.match(/^ns=([0-9]+);(i|s|g|b)=(.*)$/);\n      }\n\n      if (m === null) {\n        super(\n          Number.isNaN(Number.parseInt(typeOrValue, 10)) ? Type.STRING : Type.NUMERIC,\n          typeOrValue,\n          1\n        );\n      } else {\n        const n = Number.parseInt(m[1], 10);\n        const t = TypeForIdentifier[m[2]];\n        const v = t === Type.NUMERIC ? Number.parseInt(m[3], 10) : m[3];\n\n        super(t, v, n);\n      }\n    } else {\n      super(typeOrValue, value, namespace);\n    }\n  }\n\n  /**\n   * Creates a new NodeId based on a file path.\n   * @param {string} path The file path to use.\n   * @return {NodeId} The resulting NodeId.\n   */\n  static fromFilePath(path) {\n    let separator = '.';\n\n    const value = path.split(sep).reduce((result, current, index, components) => {\n      const next = `${result ? `${result}${separator}` : ''}${current.replace('%2F', '/')}`;\n\n      if (current === 'RESOURCES') {\n        separator = '/';\n      } else if (separator === '/' && possibleResourceChildNodes.has(components[index + 1])) {\n        separator = '.';\n      }\n\n      return next;\n    }, '');\n\n    return new NodeId(NodeId.NodeIdType.STRING, value, 1);\n  }\n\n  /**\n   * The node id's value, encoded to a file path.\n   * @type {string}\n   */\n  get filePath() {\n    const parts = this.value.split('RESOURCES');\n    parts[0] = parts[0].replace('/', '%2F').split('.').join('/');\n\n    return parts.join('RESOURCES');\n  }\n\n  // eslint-disable-next-line jsdoc/require-description-complete-sentence\n  /**\n   * Returns the last separator in a string node id's path, e.g.:\n   * - `'/'` for `ns=1;SYSTEM.LIBRARY.RESOURCES/index.htm`,\n   * - `'.'` for `ns=1;AGENT.DISPLAYS.Main`.\n   * @type {?string} `null` for non-string node ids, `'/'` for resource paths, `'.'` for regular\n   * string node ids.\n   */\n  get _lastSeparator() {\n    if (this.identifierType !== NodeId.NodeIdType.STRING) {\n      return null;\n    }\n\n    return ~this.value.indexOf('/') ? '/' : '.';\n  }\n\n  /**\n   * The parent node id, or `null`.\n   * @type {?NodeId}\n   * @deprecated Doesn't work properly in some edge cases. Use AtviseFile#parentNodeId instead\n   * whenever possible.\n   */\n  get parent() {\n    if (this.identifierType !== NodeId.NodeIdType.STRING) {\n      return null;\n    }\n\n    /*\n      Known aliases:\n        - AGENT and SYSTEM are children of \"Objects\"\n        - ObjectTypes.PROJECT and VariableTypes.PROJECT are children of their base Types\n    */\n    // FIXME: Should be in mapping transformer\n    if (this.value === 'AGENT' || this.value === 'SYSTEM') {\n      return new NodeId(NodeId.NodeIdType.NUMERIC, 85, 0); // \"Objects\"\n    } else if (this.value === 'ObjectTypes.PROJECT') {\n      return new NodeId(NodeId.NodeIdType.NUMERIC, 58, 0); // \"BaseObjectType\"\n    } else if (this.value === 'VariableTypes.PROJECT') {\n      return new NodeId(NodeId.NodeIdType.NUMERIC, 62, 0); // \"BaseVariableType\"\n    }\n\n    const parentValue = this.value.substr(0, this.value.lastIndexOf(this._lastSeparator));\n\n    if (!parentValue) {\n      // Root node -> 'Objects' is parent\n      return new NodeId(NodeId.NodeIdType.NUMERIC, 85, 0);\n    }\n\n    return new NodeId(NodeId.NodeIdType.STRING, parentValue, this.namespace);\n  }\n\n  /**\n   * Checks if the node is a child of another.\n   * @param {NodeId} parent The possible parent to check.\n   * @return {boolean} `true` if *this* is a child node of *parent*.\n   */\n  isChildOf(parent) {\n    if (\n      this.identifierType !== NodeId.NodeIdType.STRING ||\n      parent.identifierType !== NodeId.NodeIdType.STRING\n    ) {\n      return false;\n    }\n\n    if (this.namespace !== parent.namespace || this.value === parent.value) {\n      return false;\n    }\n\n    const [prefix, postfix] = this.value.split(parent.value);\n\n    return (\n      prefix === '' &&\n      postfix &&\n      (postfix[0] === this._lastSeparator ||\n        (this._lastSeparator === '/' && postfix[0] === '.' && postfix.split('.').length === 2))\n    );\n  }\n\n  /**\n   * The node id's browsename as string.\n   * @type {string}\n   */\n  get browseName() {\n    if (this.identifierType !== NodeId.NodeIdType.STRING) {\n      return null;\n    }\n\n    return this.value.substr(this.value.lastIndexOf(this._lastSeparator) + 1);\n  }\n\n  /**\n   * Returns a string in the format \"namespace value\" that is printed when inspecting the NodeId\n   * using {@link util~inspect}.\n   * @see https://nodejs.org/api/util.html#util_util_inspect_object_options\n   * @param {number} depth The depth to inspect.\n   * @param {Object} options The options to use.\n   * @return {string} A string in the format \"namespace value\".\n   */\n  inspect(depth, options) {\n    return [\n      options.stylize(this.namespace, 'number'),\n      options.stylize(this.value, this.identifierType === Type.NUMERIC ? 'number' : 'string'),\n    ].join(' ');\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/model/opcua/NodeId.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 296,
    "kind": "variable",
    "name": "Type",
    "memberof": "src/lib/model/opcua/NodeId.js",
    "static": true,
    "longname": "src/lib/model/opcua/NodeId.js~Type",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/model/opcua/NodeId.js",
    "importStyle": null,
    "description": "OPC-UA node id types.",
    "lineNumber": 8,
    "type": {
      "nullable": null,
      "types": [
        "Map<String, node-opcua~NodeIdType>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 297,
    "kind": "variable",
    "name": "TypeForIdentifier",
    "memberof": "src/lib/model/opcua/NodeId.js",
    "static": true,
    "longname": "src/lib/model/opcua/NodeId.js~TypeForIdentifier",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/model/opcua/NodeId.js",
    "importStyle": null,
    "description": "OPC-UA node id types mapped against node-id identifiers (e.g. i, s ...).",
    "lineNumber": 14,
    "type": {
      "nullable": null,
      "types": [
        "Map<String, node-opcua~NodeIdType>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 298,
    "kind": "variable",
    "name": "possibleResourceChildNodes",
    "memberof": "src/lib/model/opcua/NodeId.js",
    "static": true,
    "longname": "src/lib/model/opcua/NodeId.js~possibleResourceChildNodes",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/model/opcua/NodeId.js",
    "importStyle": null,
    "description": "Resource nodes are only allowed to have these child nodes.",
    "lineNumber": 25,
    "type": {
      "nullable": null,
      "types": [
        "Set<string>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 299,
    "kind": "class",
    "name": "NodeId",
    "memberof": "src/lib/model/opcua/NodeId.js",
    "static": true,
    "longname": "src/lib/model/opcua/NodeId.js~NodeId",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/model/opcua/NodeId.js",
    "importStyle": "NodeId",
    "description": "A wrapper around {@link node-opcua~NodeId}.",
    "lineNumber": 30,
    "interface": false,
    "extends": [
      "node-opcua/lib/datamodel/nodeid~OpcNodeId"
    ]
  },
  {
    "__docId__": 300,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/model/opcua/NodeId.js~NodeId",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/opcua/NodeId.js~NodeId#constructor",
    "access": "public",
    "description": "Creates a new NodeId. Can be called in multiple ways:\n - with a {@link node-opcua~NodeIdType}, a value and a namespace (defaults to 0),\n - with a value only (type will be taken from it, namespace defaults to 1) or\n - with a {@link NodeId}s string representation (for example `ns=1;s=AGENT.DISPLAYS`).",
    "lineNumber": 40,
    "params": [
      {
        "nullable": null,
        "types": [
          "node-opcua~NodeIdType",
          "string",
          "number"
        ],
        "spread": false,
        "optional": false,
        "name": "typeOrValue",
        "description": "The type or value to use."
      },
      {
        "nullable": null,
        "types": [
          "number",
          "string"
        ],
        "spread": false,
        "optional": true,
        "name": "value",
        "description": "The value to use."
      },
      {
        "nullable": null,
        "types": [
          "number"
        ],
        "spread": false,
        "optional": true,
        "defaultValue": "1",
        "defaultRaw": 1,
        "name": "namespace",
        "description": "The namespace to use."
      }
    ]
  },
  {
    "__docId__": 301,
    "kind": "method",
    "name": "fromFilePath",
    "memberof": "src/lib/model/opcua/NodeId.js~NodeId",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/model/opcua/NodeId.js~NodeId.fromFilePath",
    "access": "public",
    "description": "Creates a new NodeId based on a file path.",
    "lineNumber": 71,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "path",
        "description": "The file path to use."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": "The resulting NodeId."
    }
  },
  {
    "__docId__": 302,
    "kind": "get",
    "name": "filePath",
    "memberof": "src/lib/model/opcua/NodeId.js~NodeId",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/opcua/NodeId.js~NodeId#filePath",
    "access": "public",
    "description": "The node id's value, encoded to a file path.",
    "lineNumber": 93,
    "type": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 303,
    "kind": "get",
    "name": "_lastSeparator",
    "memberof": "src/lib/model/opcua/NodeId.js~NodeId",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/opcua/NodeId.js~NodeId#_lastSeparator",
    "access": "private",
    "description": "Returns the last separator in a string node id's path, e.g.:\n- `'/'` for `ns=1;SYSTEM.LIBRARY.RESOURCES/index.htm`,\n- `'.'` for `ns=1;AGENT.DISPLAYS.Main`.",
    "lineNumber": 108,
    "type": {
      "nullable": true,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 304,
    "kind": "get",
    "name": "parent",
    "memberof": "src/lib/model/opcua/NodeId.js~NodeId",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/opcua/NodeId.js~NodeId#parent",
    "access": "public",
    "description": "The parent node id, or `null`.",
    "lineNumber": 122,
    "deprecated": "Doesn't work properly in some edge cases. Use AtviseFile#parentNodeId instead\nwhenever possible.",
    "type": {
      "nullable": true,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 305,
    "kind": "method",
    "name": "isChildOf",
    "memberof": "src/lib/model/opcua/NodeId.js~NodeId",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/opcua/NodeId.js~NodeId#isChildOf",
    "access": "public",
    "description": "Checks if the node is a child of another.",
    "lineNumber": 156,
    "params": [
      {
        "nullable": null,
        "types": [
          "NodeId"
        ],
        "spread": false,
        "optional": false,
        "name": "parent",
        "description": "The possible parent to check."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": "`true` if *this* is a child node of *parent*."
    }
  },
  {
    "__docId__": 306,
    "kind": "get",
    "name": "browseName",
    "memberof": "src/lib/model/opcua/NodeId.js~NodeId",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/opcua/NodeId.js~NodeId#browseName",
    "access": "public",
    "description": "The node id's browsename as string.",
    "lineNumber": 182,
    "type": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 307,
    "kind": "method",
    "name": "inspect",
    "memberof": "src/lib/model/opcua/NodeId.js~NodeId",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/model/opcua/NodeId.js~NodeId#inspect",
    "access": "public",
    "description": "Returns a string in the format \"namespace value\" that is printed when inspecting the NodeId\nusing {@link util~inspect}.",
    "see": [
      "https://nodejs.org/api/util.html#util_util_inspect_object_options"
    ],
    "lineNumber": 198,
    "params": [
      {
        "nullable": null,
        "types": [
          "number"
        ],
        "spread": false,
        "optional": false,
        "name": "depth",
        "description": "The depth to inspect."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "The options to use."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": "A string in the format \"namespace value\"."
    }
  },
  {
    "__docId__": 308,
    "kind": "file",
    "name": "src/lib/model/opcua/ReverseReferenceTypeIds.js",
    "content": "import { ReferenceTypeIds } from 'node-opcua/lib/opcua_node_ids';\nimport { reverse } from '../../helpers/Object';\n\n/**\n * Reverse map of {@link node-opcua~ReferenceTypeId}s.\n * @type {Map<number, node-opcua~ReferenceTypeId}\n */\nconst ReverseReferenceTypeIds = reverse(ReferenceTypeIds);\n\nexport default ReverseReferenceTypeIds;\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/model/opcua/ReverseReferenceTypeIds.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 309,
    "kind": "variable",
    "name": "ReverseReferenceTypeIds",
    "memberof": "src/lib/model/opcua/ReverseReferenceTypeIds.js",
    "static": true,
    "longname": "src/lib/model/opcua/ReverseReferenceTypeIds.js~ReverseReferenceTypeIds",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/model/opcua/ReverseReferenceTypeIds.js",
    "importStyle": "ReverseReferenceTypeIds",
    "description": "Reverse map of {@link node-opcua~ReferenceTypeId}s.",
    "lineNumber": 8,
    "type": {
      "nullable": null,
      "types": [
        "Map<number, node-opcua~ReferenceTypeId"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 310,
    "kind": "file",
    "name": "src/lib/regexp.ts",
    "content": "/** Special characters in regular expressions. */\nexport const specialChars = ['[', '\\\\', '^', '$', '.', '|', '?', '*', '+', '(', ')', ']'];\n\n/** A regular expression that matches all special characters in regular expressions. */\nexport const specialCharsRegExp = new RegExp(\n  `(${specialChars.map((c) => `\\\\${c}`).join('|')})`,\n  'g'\n);\n\n/**\n * Returns a string with all special regular expression characters escaped.\n * @param source The string to escape.\n */\nexport function escapeForRegExp(source: string) {\n  return source.replace(specialCharsRegExp, '\\\\$1');\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/regexp.ts",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 311,
    "kind": "variable",
    "name": "specialChars",
    "memberof": "src/lib/regexp.ts",
    "static": true,
    "longname": "src/lib/regexp.ts~specialChars",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/regexp.ts",
    "importStyle": "{specialChars}",
    "description": "Special characters in regular expressions.",
    "lineNumber": 2,
    "type": {
      "types": [
        "string[]"
      ]
    }
  },
  {
    "__docId__": 312,
    "kind": "variable",
    "name": "specialCharsRegExp",
    "memberof": "src/lib/regexp.ts",
    "static": true,
    "longname": "src/lib/regexp.ts~specialCharsRegExp",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/regexp.ts",
    "importStyle": "{specialCharsRegExp}",
    "description": "A regular expression that matches all special characters in regular expressions.",
    "lineNumber": 4,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 313,
    "kind": "function",
    "name": "escapeForRegExp",
    "memberof": "src/lib/regexp.ts",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/regexp.ts~escapeForRegExp",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/regexp.ts",
    "importStyle": "{escapeForRegExp}",
    "description": "Returns a string with all special regular expression characters escaped.",
    "lineNumber": 14,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "source",
        "description": ""
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 314,
    "kind": "file",
    "name": "src/lib/server/AddReferencesStream.js",
    "content": "import { DataType } from 'node-opcua/lib/datamodel/variant';\nimport { StatusCodes } from 'node-opcua/lib/datamodel/opcua_status_code';\nimport NodeId from '../model/opcua/NodeId';\nimport { ReferenceTypeIds } from '../model/Node';\nimport Atviseproject from '../config/Atviseproject';\nimport CallScriptStream from './scripts/CallScriptStream';\nimport { waitForDependencies } from './WaitingStream';\n\nconst serverNodes = new Set(Atviseproject.ServerRelatedNodes.map((id) => id.value));\n\nconst ignoredReferences = new Set([\n  ReferenceTypeIds.toParent,\n  ReferenceTypeIds.HasTypeDefinition,\n  ReferenceTypeIds.HasModellingRule,\n]);\n\n/**\n * A stream that adds non-standard references to nodes when pushed.\n */\nexport default class AddReferencesStream extends waitForDependencies(CallScriptStream) {\n  /**\n   * Creates a new stream for adding references to pushed nodes.\n   * @param {Object} options The options to pass to the {@link CallScriptStream}.\n   */\n  constructor(options) {\n    super(options);\n\n    /**\n     * A stack of {@link NodeId#value}s to be retried afterwards.\n     * @type {Set<string>}\n     */\n    this._retry = new Set();\n  }\n\n  /**\n   * Returns the references that need to be set for a file.\n   * @param {AtviseFile} file The file to check.\n   * @return {Object} The files's references.\n   */\n  referencesToAdd(file) {\n    const additionalReferences = Object.assign({}, file.references);\n    delete additionalReferences.toParent;\n    delete additionalReferences.HasTypeDefinition;\n    delete additionalReferences.HasModellingRule;\n\n    return additionalReferences;\n  }\n\n  /**\n   * Returns the referenced nodes that should be processed before the given file.\n   * @param {AtviseFile} file The file to check.\n   * @return {NodeId[]} The files dependencies.\n   */\n  dependenciesFor(file) {\n    const refs = this.referencesToAdd(file);\n\n    return Object.values(refs)\n      .reduce((deps, nodes) => deps.concat(nodes), [])\n      .filter(({ value }) => !serverNodes.has(value));\n  }\n\n  /**\n   * Id of the *CreateNode* script added with `atscm import`.\n   * @type {NodeId}\n   */\n  get scriptId() {\n    return new NodeId(\n      NodeId.NodeIdType.STRING,\n      'SYSTEM.LIBRARY.ATVISE.SERVERSCRIPTS.atscm.AddReferences',\n      1\n    );\n  }\n\n  /**\n   * The options required to add references to the node for the given file.\n   * @param {AtviseFile} file The processed file.\n   * @return {Object} The options passed to the *AddReferences* script.\n   */\n  scriptParameters(file) {\n    const references = [...file.references].reduce((result, [key, value]) => {\n      if (ignoredReferences.has(key)) {\n        return result;\n      }\n\n      return Object.assign(result, {\n        [key]: [...value].map((s) => (typeof s === 'string' ? `ns=1;s=${s}` : s)),\n      });\n    }, {});\n\n    const referenceKeys = Object.keys(references);\n\n    if (referenceKeys.length > 0) {\n      return {\n        paramObjString: {\n          dataType: DataType.String,\n          value: JSON.stringify({\n            nodeId: file.nodeId,\n            references: referenceKeys.map((type) => ({\n              referenceIdValue: parseInt(type, 10),\n              items: references[type],\n            })),\n          }),\n        },\n      };\n    }\n\n    // No need to add references\n    return null;\n  }\n\n  /**\n   * Prints an error message telling that adding one or more references failed.\n   * @param {AtviseFile} file The file who's node could not be created.\n   * @return {string} The resulting error message.\n   */\n  processErrorMessage(file) {\n    return `Error adding references to node ${file.nodeId}`;\n  }\n\n  /**\n   * Handles the results of a script call.\n   * @param {AtviseFile} file The file the script was called with.\n   * @param {node-opcua~Variant[]} outArgs The raw method results.\n   * @param {function(err: Error)} callback Called once finished.\n   */\n  handleOutputArguments(file, outArgs, callback) {\n    if (outArgs[0].value !== StatusCodes.Good) {\n      callback(new Error(outArgs[1].value));\n    } else {\n      const [{ value: failures }] = outArgs[3].value;\n\n      if (failures && failures.length) {\n        const retryKey = file.nodeId.value;\n\n        if (this._retry.has(retryKey)) {\n          this._retry.delete(retryKey);\n          callback(new Error(`Failed to create references to ${failures.join(', ')}`));\n        } else {\n          this._retry.add(retryKey);\n          callback(null);\n\n          this.once('drained', () => {\n            this.write(file);\n          });\n        }\n\n        return;\n      }\n\n      callback(null);\n    }\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/server/AddReferencesStream.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 315,
    "kind": "variable",
    "name": "serverNodes",
    "memberof": "src/lib/server/AddReferencesStream.js",
    "static": true,
    "longname": "src/lib/server/AddReferencesStream.js~serverNodes",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AddReferencesStream.js",
    "importStyle": null,
    "description": null,
    "lineNumber": 9,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    },
    "ignore": true
  },
  {
    "__docId__": 316,
    "kind": "variable",
    "name": "ignoredReferences",
    "memberof": "src/lib/server/AddReferencesStream.js",
    "static": true,
    "longname": "src/lib/server/AddReferencesStream.js~ignoredReferences",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AddReferencesStream.js",
    "importStyle": null,
    "description": null,
    "lineNumber": 11,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    },
    "ignore": true
  },
  {
    "__docId__": 317,
    "kind": "class",
    "name": "AddReferencesStream",
    "memberof": "src/lib/server/AddReferencesStream.js",
    "static": true,
    "longname": "src/lib/server/AddReferencesStream.js~AddReferencesStream",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/AddReferencesStream.js",
    "importStyle": "AddReferencesStream",
    "description": "A stream that adds non-standard references to nodes when pushed.",
    "lineNumber": 20,
    "interface": false,
    "expressionExtends": "waitForDependencies(CallScriptStream)"
  },
  {
    "__docId__": 318,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/server/AddReferencesStream.js~AddReferencesStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AddReferencesStream.js~AddReferencesStream#constructor",
    "access": "public",
    "description": "Creates a new stream for adding references to pushed nodes.",
    "lineNumber": 25,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "The options to pass to the {@link CallScriptStream}."
      }
    ]
  },
  {
    "__docId__": 319,
    "kind": "member",
    "name": "_retry",
    "memberof": "src/lib/server/AddReferencesStream.js~AddReferencesStream",
    "static": false,
    "longname": "src/lib/server/AddReferencesStream.js~AddReferencesStream#_retry",
    "access": "private",
    "description": "A stack of {@link NodeId#value}s to be retried afterwards.",
    "lineNumber": 32,
    "type": {
      "nullable": null,
      "types": [
        "Set<string>"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 320,
    "kind": "method",
    "name": "referencesToAdd",
    "memberof": "src/lib/server/AddReferencesStream.js~AddReferencesStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AddReferencesStream.js~AddReferencesStream#referencesToAdd",
    "access": "public",
    "description": "Returns the references that need to be set for a file.",
    "lineNumber": 40,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file to check."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Object"
      ],
      "spread": false,
      "description": "The files's references."
    }
  },
  {
    "__docId__": 321,
    "kind": "method",
    "name": "dependenciesFor",
    "memberof": "src/lib/server/AddReferencesStream.js~AddReferencesStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AddReferencesStream.js~AddReferencesStream#dependenciesFor",
    "access": "public",
    "description": "Returns the referenced nodes that should be processed before the given file.",
    "lineNumber": 54,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file to check."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "NodeId[]"
      ],
      "spread": false,
      "description": "The files dependencies."
    }
  },
  {
    "__docId__": 322,
    "kind": "get",
    "name": "scriptId",
    "memberof": "src/lib/server/AddReferencesStream.js~AddReferencesStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AddReferencesStream.js~AddReferencesStream#scriptId",
    "access": "public",
    "description": "Id of the *CreateNode* script added with `atscm import`.",
    "lineNumber": 66,
    "type": {
      "nullable": null,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 323,
    "kind": "method",
    "name": "scriptParameters",
    "memberof": "src/lib/server/AddReferencesStream.js~AddReferencesStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AddReferencesStream.js~AddReferencesStream#scriptParameters",
    "access": "public",
    "description": "The options required to add references to the node for the given file.",
    "lineNumber": 79,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The processed file."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Object"
      ],
      "spread": false,
      "description": "The options passed to the *AddReferences* script."
    }
  },
  {
    "__docId__": 324,
    "kind": "method",
    "name": "processErrorMessage",
    "memberof": "src/lib/server/AddReferencesStream.js~AddReferencesStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AddReferencesStream.js~AddReferencesStream#processErrorMessage",
    "access": "public",
    "description": "Prints an error message telling that adding one or more references failed.",
    "lineNumber": 116,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file who's node could not be created."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": "The resulting error message."
    }
  },
  {
    "__docId__": 325,
    "kind": "method",
    "name": "handleOutputArguments",
    "memberof": "src/lib/server/AddReferencesStream.js~AddReferencesStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AddReferencesStream.js~AddReferencesStream#handleOutputArguments",
    "access": "public",
    "description": "Handles the results of a script call.",
    "lineNumber": 126,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file the script was called with."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~Variant[]"
        ],
        "spread": false,
        "optional": false,
        "name": "outArgs",
        "description": "The raw method results."
      },
      {
        "nullable": null,
        "types": [
          "function(err: Error)"
        ],
        "spread": false,
        "optional": false,
        "name": "callback",
        "description": "Called once finished."
      }
    ],
    "return": null
  },
  {
    "__docId__": 326,
    "kind": "file",
    "name": "src/lib/server/AtviseFile.js",
    "content": "import { readFile } from 'fs';\nimport { dirname } from 'path';\nimport { NodeClass } from 'node-opcua/lib/datamodel/nodeclass';\nimport { DataType, VariantArrayType, Variant } from 'node-opcua/lib/datamodel/variant';\nimport { resolveNodeId } from 'node-opcua/lib/datamodel/nodeid';\nimport { LocalizedText } from 'node-opcua/lib/datamodel/localized_text';\nimport { StatusCodes } from 'node-opcua/lib/datamodel/opcua_status_code';\nimport { QualifiedName } from 'node-opcua/lib/datamodel/qualified_name';\nimport { DataValue } from 'node-opcua/lib/datamodel/datavalue';\nimport { ReferenceTypeIds } from 'node-opcua/lib/opcua_node_ids';\nimport { ExpandedNodeId } from 'node-opcua/lib/datamodel/expanded_nodeid';\nimport { DiagnosticInfo } from 'node-opcua/lib/datamodel/diagnostic_info';\nimport File from 'vinyl';\nimport NodeId from '../model/opcua/NodeId';\nimport { reverse, pick } from '../helpers/Object';\nimport { sortReferences } from '../helpers/mapping';\nimport AtviseTypes, { AtviseResourceType } from './Types';\n\n/**\n * A map of AtviseTypes against their definition id's value.\n * @type {Map<String, AtivseType>}\n */\nconst AtviseTypesByValue = AtviseTypes.reduce(\n  (result, type) =>\n    Object.assign(result, {\n      [type.typeDefinition.value]: type,\n    }),\n  {}\n);\n\n/**\n * A map of AtviseTypes against their identifiers.\n * @type {Map<String, AtivseType>}\n */\nconst AtviseTypesByIdentifier = AtviseTypes.reduce(\n  (result, type) =>\n    Object.assign(result, {\n      [type.identifier]: type,\n    }),\n  {}\n);\n\n/**\n * A map providing shorter extensions for data types\n * @type {Map<node-opcua~DataType, String>}\n */\nexport const ExtensionForDataType = {\n  [DataType.Boolean]: 'bool',\n  [DataType.XmlElement]: 'xml',\n};\n\n/**\n * A map providing data types for shorter extensions (Reverse of {@link DataTypeForExtension}).\n * * @type {Map<String, node-opcua~DataType>}\n */\nexport const DataTypeForExtension = reverse(ExtensionForDataType);\n\n// Cache DataType\n/**\n * OPC-UA data type names.\n * @type {String[]}\n */\nconst types = Object.keys(DataType);\n\n/**\n * OPC-UA data type extensions.\n * @type {String[]}\n */\nconst typeExtensions = types.map((t) => t.toLowerCase());\n\n// Cache TypeDefinitions\n/**\n * Variable data type definition node id.\n * @type {NodeId}\n */\nconst VariableTypeDefinition = new NodeId(NodeId.NodeIdType.NUMERIC, 62, 0);\n/**\n * Property data type definition node id.\n * @type {NodeId}\n */\nconst PropertyTypeDefinition = new NodeId(NodeId.NodeIdType.NUMERIC, 68, 0);\n\n// Cache Regular expressions\n/**\n * A regular expression picking file extensions from file names.\n * @type {RegExp}\n */\nconst ExtensionRegExp = /\\.([^/\\\\]*)$/;\n\n/**\n * Function that returns the passed argument as is.\n * @param {*} b The input argument.\n * @return {*} The value passed.\n */\nconst asIs = (b) => b;\n\n/**\n * Maps a single property of an object using the the mapper defined in *map* for the given\n * *dataType*.\n * @param {Map<node-opcua~DataType, function} map The mappings to use.\n * @param {Object} obj The object to process.\n * @param {string} key Name of the property to map.\n * @param {node-opcua~DataType} dataType The data type to map the property to.\n */\nconst mapPropertyAs = (map, obj, key, dataType) => {\n  if (obj[key]) {\n    return Object.assign(obj, {\n      [key]: map[dataType](obj[key]),\n    });\n  }\n\n  return obj;\n};\n\n/**\n * Mapping functions that return serializable values for a node of the given\n * {@link node-opcua~DataType}.\n * @type {Map<node-opcua~DataType, function>}\n */\nconst toRawValue = {\n  [DataType.Null]: () => null,\n  [DataType.StatusCode]: ({ name }) => name,\n  [DataType.QualifiedName]: ({ namespaceIndex, name }) => ({ namespaceIndex, name }),\n  [DataType.LocalizedText]: ({ text, locale }) => ({ text, locale }),\n  [DataType.DataValue]: (value) => {\n    const options = pick(value, [\n      'value',\n      'statusCode',\n      'sourceTimestamp',\n      'sourcePicoseconds',\n      'serverTimestamp',\n      'serverPicoseconds',\n    ]);\n\n    mapPropertyAs(toRawValue, options, 'value', DataType.Variant);\n    mapPropertyAs(toRawValue, options, 'statusCode', DataType.StatusCode);\n    // NOTE: server- and sourceTimstamps get mapped as dates\n\n    return options;\n  },\n  [DataType.Variant]: ({ dataType, arrayType, value, dimensions }) => ({\n    dataType,\n    arrayType,\n    // eslint-disable-next-line no-use-before-define\n    value: getRawValue(value, dataType, arrayType),\n    dimensions,\n  }),\n  [DataType.DiagnosticInfo]: (info) => {\n    const options = pick(info, [\n      'namespaceUri',\n      'symbolicId',\n      'locale',\n      'localizedText',\n      'additionalInfo',\n      'innerStatusCode',\n      'innerDiagnosticInfo',\n    ]);\n\n    mapPropertyAs(toRawValue, options, 'innerStatusCode', DataType.StatusCode);\n    mapPropertyAs(toRawValue, options, 'innerDiagnosticInfo', DataType.DiagnosticInfo);\n\n    return options;\n  },\n};\n\n/**\n * Decodes a buffer to a string.\n * @param {Buffer} b The buffer to decode from.\n * @return {string} The buffer's string representation.\n */\nconst decodeAsString = (b) => b.toString().trim();\n\n/**\n * Decodes a buffer to an integer value.\n * @param {Buffer} b The buffer to decode from.\n * @return {number} The decoded integer.\n */\nconst decodeAsInt = (b) => parseInt(decodeAsString(b), 10);\n\n/**\n * Decodes a buffer to a float value.\n * @param {Buffer} b The buffer to decode from.\n * @return {number} The decoded float.\n */\nconst decodeAsFloat = (b) => parseFloat(decodeAsString(b));\n\n/**\n * Decodes a buffer using JSON.\n * @param {Buffer} b The buffer to decode from.\n * @return {*} The decoded value, most likely an Object.\n */\nconst decodeAsJson = (b) => JSON.parse(b.toString());\n\n/**\n * Mapping functions that return raw values for a stored value of the given type.\n * @type {Map<node-opcua~DataType, function>}\n */\nconst decodeRawValue = {\n  [DataType.Null]: () => null,\n  [DataType.Boolean]: (b) => decodeAsString(b) === 'true',\n  [DataType.SByte]: decodeAsInt,\n  [DataType.Byte]: decodeAsInt,\n  [DataType.Int16]: decodeAsInt,\n  [DataType.UInt16]: decodeAsInt,\n  [DataType.Int32]: decodeAsInt,\n  [DataType.UInt32]: decodeAsInt,\n  [DataType.Int64]: decodeAsJson,\n  [DataType.UInt64]: decodeAsJson,\n  [DataType.Float]: decodeAsFloat,\n  [DataType.Double]: decodeAsFloat,\n  [DataType.String]: decodeAsString,\n  [DataType.DateTime]: decodeAsString,\n  [DataType.Guid]: decodeAsString,\n  // ByteString maps to Buffer\n  [DataType.XmlElement]: decodeAsString,\n  [DataType.NodeId]: decodeAsString,\n  [DataType.ExpandedNodeId]: decodeAsString,\n  [DataType.StatusCode]: decodeAsString,\n  [DataType.QualifiedName]: decodeAsJson,\n  [DataType.LocalizedText]: decodeAsJson,\n  // FIXME: Add ExtensionObject\n  [DataType.DataValue]: decodeAsJson,\n  [DataType.Variant]: decodeAsJson,\n  [DataType.DiagnosticInfo]: decodeAsJson,\n};\n\n/**\n * Mapping functions that return OPC-UA node values for raw values.\n * @type {Map<node-opcua~DataType, function>}\n */\nconst toNodeValue = {\n  [DataType.DateTime]: (s) => new Date(s),\n  [DataType.ByteString]: (b) => {\n    if (b instanceof Buffer) {\n      return b;\n    }\n\n    return Buffer.from(b.data, 'binary');\n  },\n  [DataType.NodeId]: (s) => resolveNodeId(s),\n\n  // Jep, node-opcua does not provide a resolve function for expanded nodeids\n  [DataType.ExpandedNodeId]: (s) => {\n    const nodeId = resolveNodeId(s);\n    const [value, ...defs] = nodeId.value.split(';');\n\n    const { identifierType, namespace, namespaceUri, serverIndex } = defs.reduce((opts, def) => {\n      const match = def.match(/^([^:]+):(.*)/);\n      if (!match) {\n        return opts;\n      }\n\n      let [key, val] = match.slice(1); // eslint-disable-line prefer-const\n\n      if (key === 'serverIndex') {\n        val = parseInt(val, 10);\n      }\n\n      return Object.assign(opts, { [key]: val });\n    }, Object.assign({}, nodeId));\n\n    return new ExpandedNodeId(identifierType, value, namespace, namespaceUri, serverIndex);\n  },\n\n  [DataType.StatusCode]: (name) => StatusCodes[name],\n  [DataType.QualifiedName]: (options) => new QualifiedName(options),\n  [DataType.LocalizedText]: (options) => new LocalizedText(options),\n  [DataType.DataValue]: (options) => {\n    const opts = options;\n\n    mapPropertyAs(toNodeValue, opts, 'value', DataType.Variant);\n    mapPropertyAs(toNodeValue, opts, 'statusCode', DataType.StatusCode);\n    mapPropertyAs(toNodeValue, opts, 'sourceTimestamp', DataType.DateTime);\n    mapPropertyAs(toNodeValue, opts, 'serverTimestamp', DataType.DateTime);\n\n    return new DataValue(opts);\n  },\n  [DataType.Variant]: ({ dataType, arrayType, value, dimensions }) =>\n    new Variant({\n      dataType,\n      arrayType: VariantArrayType[arrayType],\n      value,\n      dimensions,\n    }),\n  [DataType.DiagnosticInfo]: (options) => {\n    const opts = options;\n\n    mapPropertyAs(toNodeValue, opts, 'innerStatusCode', DataType.StatusCode);\n    mapPropertyAs(toNodeValue, opts, 'innerDiagnosticInfo', DataType.DiagnosticInfo);\n\n    return new DiagnosticInfo(opts);\n  },\n};\n\n/**\n * Returns a node's raw value based on it's OPC-UA value and type.\n * @param {*} value A node's OPC-UA value.\n * @param {node-opcua~DataType} dataType The node's data type.\n * @param {node-opcua~VariantArrayType} arrayType The node's array type.\n * @return {*} The raw value of the given node.\n */\nconst getRawValue = (value, dataType, arrayType) => {\n  if (arrayType.value !== VariantArrayType.Scalar.value) {\n    const array = Array.isArray(value) ? value : Array.from(value);\n\n    return array.map((val) => getRawValue(val, dataType, VariantArrayType[arrayType.value - 1]));\n  }\n\n  return (toRawValue[dataType] || asIs)(value);\n};\n\n/**\n * Returns a node's OPC-UA value based on it's raw value and type.\n * @param {*} rawValue A node's raw value.\n * @param {node-opcua~DataType} dataType A node's data type.\n * @param {node-opcua~VariantArrayType} arrayType A node's array type.\n */\nconst getNodeValue = (rawValue, dataType, arrayType) => {\n  if (arrayType.value !== VariantArrayType.Scalar.value) {\n    if (!Array.isArray(rawValue)) {\n      throw new Error('Value is not an array');\n    }\n\n    return rawValue.map((raw) =>\n      getNodeValue(raw, dataType, VariantArrayType[arrayType.value - 1])\n    );\n  }\n\n  return (toNodeValue[dataType] || asIs)(rawValue);\n};\n\n/**\n * Returns the extension for a specific {@link node-opcua~DataType}.\n * Algorithm:\n *   - if the type has a shortened extension defined in {@link ExtensionForDataType}, return it.\n *   - else return the DataType's name, in lowercase letters.\n * @param {node-opcua~DataType} dataType The datatype to get the extension for.\n * @return {string} The resulting extension.\n */\nfunction extensionForDataType(dataType) {\n  return ExtensionForDataType[dataType] || dataType.toString().toLowerCase();\n}\n\n/**\n * A regular expression that maches all reference definition files.\n * @type {RegExp}\n */\nconst ConfigFileRegexp = /^\\.((Object|Variable)(Type)?|Method|View|(Reference|Data)Type)\\.json$/;\n\n/**\n * An extension to {@link vinyl~File} providing some additional, atvise-related properties.\n * @property {node-opcua~DataType} AtviseFile#dataType The {@link node-opcua~DataType} the node is\n * stored against on atvise server.\n * @property {NodeId} typeDefinition The file's type definition on atvise server.\n * FIXME: Additional properties not showing in API docs.\n */\nexport default class AtviseFile extends File {\n  /**\n   * Returns a storage path for a {@link ReadStream.ReadResult}.\n   * @param {ReadStream.ReadResult} readResult The read result to get a path for.\n   */\n  static pathForReadResult(readResult) {\n    let path = readResult.nodeId.filePath;\n\n    if (readResult.nodeClass.value !== NodeClass.Variable.value) {\n      return `${path}/.${readResult.nodeClass.key}.json`;\n    }\n\n    const dataType = readResult.value.$dataType;\n    const arrayType = readResult.value.$arrayType;\n    const typeDefinition = readResult.references.HasTypeDefinition[0];\n\n    if (typeDefinition.value === VariableTypeDefinition.value) {\n      // Variable nodes are stored with their lowercase datatype as an extension\n      path += `.${extensionForDataType(dataType)}`;\n    } else if (typeDefinition.value === PropertyTypeDefinition.value) {\n      // Property nodes are stored with \".prop\" and their lowercase datatype as an extension\n      path += `.prop.${extensionForDataType(dataType)}`;\n    } else {\n      // Handle custom types\n      let identifier = 'var';\n      let fileExtension = false;\n      let keepExtension = false;\n\n      const atType = AtviseTypesByValue[typeDefinition.value];\n      if (atType) {\n        identifier = atType.identifier;\n        fileExtension = atType.fileExtension;\n        keepExtension = atType.keepExtension;\n      }\n\n      if (!keepExtension) {\n        path += `.${identifier}.${fileExtension || extensionForDataType(dataType)}`;\n      }\n    }\n\n    // Add \"array\" or \"matrix\" extensions for corresponding array types\n    if (arrayType.value !== VariantArrayType.Scalar.value) {\n      path += `.${arrayType === VariantArrayType.Array ? 'array' : 'matrix'}`;\n    }\n\n    return path;\n  }\n\n  /**\n   * Encodes a node's value to file contents.\n   * @param {*} value The value to encode.\n   * @param {node-opcua~DataType} dataType The {@link node-opcua~DataType} to encode the value for.\n   * @param {node-opcua~VariantArrayType} arrayType The files array type.\n   * @return {?Buffer} The encoded file contents or null.\n   */\n  static encodeValue(value, dataType, arrayType) {\n    if (value.value === null) {\n      return Buffer.from('');\n    }\n\n    const rawValue = getRawValue(value.value, dataType, arrayType);\n\n    if (rawValue instanceof Buffer) {\n      return rawValue;\n    }\n\n    const stringify = (a) => (a.toJSON ? a.toJSON() : JSON.stringify(a, null, '  '));\n    const stringified =\n      typeof rawValue === 'object' ? stringify(rawValue) : rawValue.toString().trim();\n\n    return Buffer.from(stringified);\n  }\n\n  /**\n   * Decodes a file's contents to a node's value.\n   * @param {Buffer} buffer The file contents to decode.\n   * @param {node-opcua~DataType} dataType The {@link node-opcua~DataType} to decode the contents.\n   * @param {node-opcua~VariantArrayType} arrayType The files array type.\n   * @return {?*} The decoded node value or null.\n   */\n  static decodeValue(buffer, dataType, arrayType) {\n    if (buffer === null || buffer.length === 0) {\n      return null;\n    }\n\n    if (dataType === DataType.ByteString && arrayType === VariantArrayType.Scalar) {\n      return buffer;\n    }\n\n    const rawValue =\n      arrayType === VariantArrayType.Scalar\n        ? (decodeRawValue[dataType] || asIs)(buffer)\n        : JSON.parse(buffer.toString());\n\n    return getNodeValue(rawValue, dataType, arrayType);\n  }\n\n  /**\n   * As file mtimes do not support millisecond resolution these must be removed before storing\n   * files.\n   * @param {Date} date The original mtime.\n   * @return {Date} The normalized mtime.\n   */\n  static normalizeMtime(date) {\n    date.setMilliseconds(0);\n\n    return date;\n  }\n\n  /**\n   * Creates a new {@link AtviseFile} for the given {@link ReadStream.ReadResult}.\n   * @param {ReadStream.ReadResult} readResult The read result to create the file for.\n   * @return {AtviseFile} The resulting file.\n   */\n  static fromReadResult(readResult) {\n    const { nodeClass, references, value, mtime } = readResult;\n\n    if (nodeClass.value === NodeClass.Variable.value && !value) {\n      throw new Error('no value');\n    }\n\n    return new AtviseFile({\n      path: AtviseFile.pathForReadResult(readResult),\n      contents: value\n        ? AtviseFile.encodeValue(value, value.$dataType, value.$arrayType) // Variables\n        : Buffer.from(\n            JSON.stringify(\n              {\n                references: sortReferences(references),\n              },\n              null,\n              '  '\n            )\n          ), // Objects, types, ...\n      _nodeClass: nodeClass,\n      _dataType: value && value.$dataType,\n      _arrayType: value && value.$arrayType,\n      _references: references,\n      stat: { mtime: mtime ? this.normalizeMtime(mtime) : undefined },\n    });\n  }\n\n  /**\n   * Recalculates {@link AtviseFile#dataType}, {@link AtviseFile#arrayType} and\n   * {@link AtviseFile#typeDefinition}. **Never call this method directly.**.\n   */\n  _getMetadata() {\n    if (this.stem[0] === '.') {\n      // Got non-variable node\n      /**\n       * The node's class.\n       * @type {node-opcua~NodeClass}\n       */\n      this._nodeClass = NodeClass[this.stem.split('.')[1]];\n\n      const { references = {} } = JSON.parse(this.contents.toString());\n\n      /**\n       * References the node holds: In most cases this will be a single entry for\n       * `'HasTypeDefinition'`.\n       * @type {Map<String, NodeId[]>}\n       */\n      this._references = Object.entries(references).reduce(\n        (result, [type, refs]) =>\n          Object.assign(result, {\n            [type]: Array.isArray(refs) ? refs.map((v) => new NodeId(v)) : new NodeId(refs),\n          }),\n        {}\n      );\n\n      return;\n    }\n\n    this._nodeClass = NodeClass.Variable;\n\n    // Set default metadata\n    /**\n     * The node's stored {@link node-opcua~VariantArrayType}.\n     * @type {?node-opcua~VariantArrayType}\n     */\n    this._arrayType = VariantArrayType.Scalar;\n\n    this._references = {};\n\n    /**\n     * A node's browse- and display name.\n     * @type {?string}\n     */\n    this._name = this.stem.split('.')[0];\n\n    let extensions = [];\n    const m = this.relative.match(ExtensionRegExp);\n    if (m) {\n      extensions = m[1].split('.');\n    }\n\n    // For split files, add the directory name extension\n    const dirnameExts = this.dirname.split('.');\n    if (dirnameExts.length > 1) {\n      extensions.unshift(dirnameExts[dirnameExts.length - 1]);\n    }\n\n    function ifLastExtensionMatches(matches, fn) {\n      if (matches(extensions[extensions.length - 1])) {\n        fn(extensions.pop());\n      }\n    }\n\n    const complete = () =>\n      this._dataType !== undefined && this._references.HasTypeDefinition !== undefined;\n\n    // Handle array types\n    ifLastExtensionMatches(\n      (ext) => ext === 'array',\n      () => {\n        this._arrayType = VariantArrayType.Array;\n      }\n    );\n\n    ifLastExtensionMatches(\n      (ext) => ext === 'matrix',\n      () => {\n        this._arrayType = VariantArrayType.Matrix;\n      }\n    );\n\n    ifLastExtensionMatches(\n      (ext) => typeExtensions.includes(ext),\n      (ext) => {\n        /**\n         * The node's stored {@link node-opcua~DataType}.\n         * @type {?node-opcua~DataType}\n         */\n        this._dataType = DataType[types[typeExtensions.indexOf(ext)]];\n      }\n    );\n\n    // Handle wrapped data types (e.g. \"bool\" for DataType.Boolean)\n    ifLastExtensionMatches(\n      (ext) => DataTypeForExtension[ext],\n      (ext) => {\n        this._dataType = DataType[DataTypeForExtension[ext]];\n      }\n    );\n\n    if (extensions.length === 0) {\n      // Got variable\n      /**\n       * The node's stored type definition.\n       * @type {?node-opcua~NodeId}\n       */\n      this._references.HasTypeDefinition = [new NodeId(NodeId.NodeIdType.NUMERIC, 62, 0)];\n    }\n\n    ifLastExtensionMatches(\n      (ext) => ext === 'prop',\n      () => {\n        this._references.HasTypeDefinition = [new NodeId(NodeId.NodeIdType.NUMERIC, 68, 0)];\n        this._references.toParent = ReferenceTypeIds.HasProperty;\n      }\n    );\n\n    ifLastExtensionMatches(\n      (ext) => ext === 'var',\n      () => {\n        this._references.HasTypeDefinition = [new NodeId('Custom.VarResourceType')];\n      }\n    );\n\n    if (!complete()) {\n      // Handle atvise types\n      let foundAtType = false;\n\n      Object.entries(AtviseTypesByIdentifier).forEach(([identifier, type]) => {\n        if (!foundAtType && extensions.includes(identifier)) {\n          foundAtType = true;\n\n          if (!(type instanceof AtviseResourceType)) {\n            extensions = extensions.filter((e) => e !== identifier);\n          }\n\n          this._references.HasTypeDefinition = [type.typeDefinition];\n          this._dataType = type.dataType;\n        }\n      });\n    }\n\n    if (!complete()) {\n      this._references.HasTypeDefinition = [\n        new NodeId('VariableTypes.ATVISE.Resource.OctetStream'),\n      ];\n      this._dataType = DataType.ByteString;\n    }\n\n    this._name = [this._name, ...extensions.filter((e) => !dirnameExts.includes(e))].join('.');\n  }\n\n  /**\n   * Computes a file's metadata if needed.\n   * @return {AtviseFile} The file.\n   */\n  getMetadata() {\n    if (!this._nodeClass) {\n      this._getMetadata();\n    }\n\n    return this;\n  }\n\n  /**\n   * The node's class.\n   * @type {node-opcua~NodeClass}\n   */\n  get nodeClass() {\n    if (!this._nodeClass) {\n      this._getMetadata();\n    }\n\n    return this._nodeClass;\n  }\n\n  /**\n   * The file's {@link node-opcua~DataType}.\n   * @type {node-opcua~DataType}\n   */\n  get dataType() {\n    if (!this._dataType) {\n      this._getMetadata();\n    }\n\n    return this._dataType;\n  }\n\n  /**\n   * The file's {@link node-opcua~VariantArrayType}.\n   * @type {node-opcua~VariantArrayType}\n   */\n  get arrayType() {\n    if (!this._arrayType) {\n      this._getMetadata();\n    }\n\n    return this._arrayType;\n  }\n\n  /**\n   * The files's references.\n   * @type {Map<string, NodeId|NodeId[]>}\n   */\n  get references() {\n    if (!this._references) {\n      this._getMetadata();\n    }\n\n    return this._references;\n  }\n\n  /**\n   * The file's type definition.\n   * @type {node-opcua~NodeId}\n   */\n  get typeDefinition() {\n    const refs = this.references;\n\n    if (refs && refs.HasTypeDefinition) {\n      return refs.HasTypeDefinition[0];\n    }\n\n    return new NodeId(NodeId.NodeIdType.NUMERIC, 0, 0);\n  }\n\n  // eslint-disable-next-line jsdoc/require-description-complete-sentence\n  /**\n   * `true` for reference config files (for example `.index.htm.json`).\n   * @type {boolean}\n   */\n  get isReferenceConfig() {\n    return this.stem[0] === '.' && !this.stem.match(ConfigFileRegexp);\n  }\n\n  /**\n   * `true` for files containing atvise displays.\n   * @type {boolean}\n   */\n  get isDisplay() {\n    return this.typeDefinition.value === 'VariableTypes.ATVISE.Display';\n  }\n\n  /**\n   * `true` for files containing atvise scripts.\n   * @type {boolean}\n   */\n  get isScript() {\n    return this.typeDefinition.value === 'VariableTypes.ATVISE.ScriptCode';\n  }\n\n  /**\n   * `true` for files containing atvise quick dynamics.\n   * @type {boolean}\n   */\n  get isQuickDynamic() {\n    return this.typeDefinition.value === 'VariableTypes.ATVISE.QuickDynamic';\n  }\n\n  /**\n   * Sets the node value for the file.\n   * @param {?*} newValue The value to set.\n   */\n  set value(newValue) {\n    /**\n     * The file's contents.\n     * @type {?Buffer}\n     */\n    this.contents = AtviseFile.encodeValue(newValue, this.dataType, this.arrayType);\n  }\n\n  /**\n   * Returns the decoded node value for the file.\n   * @type {?*} The file's decoded value.\n   */\n  get value() {\n    return AtviseFile.decodeValue(this.contents, this.dataType, this.arrayType);\n  }\n\n  /**\n   * Returns the decoded node value for create node serverscript.\n   * @type {?*} The file's decoded value.\n   */\n  get createNodeValue() {\n    const value = this.value;\n\n    if (this.dataType === DataType.DateTime) {\n      return value.valueOf();\n    }\n\n    if (value instanceof Buffer) {\n      return value.toString();\n    }\n\n    return value;\n  }\n\n  /**\n   * Returns the node id associated with the file.\n   * @type {NodeId} The file's node id.\n   */\n  get nodeId() {\n    if (this.nodeClass.value !== NodeClass.Variable.value) {\n      return NodeId.fromFilePath(dirname(this.relative));\n    }\n    const atType = AtviseTypesByValue[this.typeDefinition.value];\n    let idPath = this.relative;\n\n    if (!atType || !atType.keepExtension) {\n      const exts = idPath.match(ExtensionRegExp)[1];\n      idPath = idPath.split(`.${exts}`)[0];\n    }\n\n    return NodeId.fromFilePath(idPath);\n  }\n\n  /**\n   * A file's browse and display name.\n   * @type {string}\n   */\n  get name() {\n    if (!this._name) {\n      this._getMetadata();\n    }\n\n    return this._name;\n  }\n\n  /**\n   * A file's parent's node id.\n   * @type {NodeId}\n   */\n  get parentNodeId() {\n    const name = this.name;\n    const id = this.nodeId;\n\n    if (name) {\n      const parts = this.nodeId.value.split(name);\n\n      if (parts.length > 1) {\n        return new NodeId(id.identifierType, parts[0].slice(0, -1), id.namespaceIndex);\n      }\n    }\n\n    return this.nodeId.parent;\n  }\n\n  /**\n   * Returns a new file with all attributes of the current file.\n   * @param {Object} options See the {@link vinyl~File} docs for all options available.\n   * @return {AtviseFile} The cloned file.\n   * @see https://github.com/gulpjs/vinyl#filecloneoptions\n   */\n  clone(options) {\n    const clonedFile = super.clone(options);\n\n    clonedFile._nodeClass = this._nodeClass;\n    clonedFile._dataType = this._dataType;\n    clonedFile._arrayType = this._arrayType;\n    clonedFile._references = this._references;\n\n    return clonedFile;\n  }\n\n  /**\n   * Creates a new AtviseFile and reads it's contents.\n   * @param {Object} options See {@link vinyl~File} for available options.\n   * @return {Promise} Resolved with the new file of rejected with the error that occured while\n   * trying to read it's path.\n   */\n  static read(options = {}) {\n    return new Promise((resolve, reject) => {\n      if (!options.path) {\n        reject(new Error('options.path is required'));\n      } else {\n        readFile(options.path, (err, contents) => {\n          if (err) {\n            reject(err);\n          } else {\n            resolve(new AtviseFile(Object.assign(options, { contents })));\n          }\n        });\n      }\n    });\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/server/AtviseFile.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 327,
    "kind": "variable",
    "name": "AtviseTypesByValue",
    "memberof": "src/lib/server/AtviseFile.js",
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~AtviseTypesByValue",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "A map of AtviseTypes against their definition id's value.",
    "lineNumber": 23,
    "type": {
      "nullable": null,
      "types": [
        "Map<String, AtivseType>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 328,
    "kind": "variable",
    "name": "AtviseTypesByIdentifier",
    "memberof": "src/lib/server/AtviseFile.js",
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~AtviseTypesByIdentifier",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "A map of AtviseTypes against their identifiers.",
    "lineNumber": 35,
    "type": {
      "nullable": null,
      "types": [
        "Map<String, AtivseType>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 329,
    "kind": "variable",
    "name": "ExtensionForDataType",
    "memberof": "src/lib/server/AtviseFile.js",
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~ExtensionForDataType",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": "{ExtensionForDataType}",
    "description": "A map providing shorter extensions for data types",
    "lineNumber": 47,
    "type": {
      "nullable": null,
      "types": [
        "Map<node-opcua~DataType, String>"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 330,
    "kind": "variable",
    "name": "DataTypeForExtension",
    "memberof": "src/lib/server/AtviseFile.js",
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~DataTypeForExtension",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": "{DataTypeForExtension}",
    "description": "A map providing data types for shorter extensions (Reverse of {@link DataTypeForExtension}).\n* @type {Map<String, node-opcua~DataType>}",
    "lineNumber": 56,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 331,
    "kind": "variable",
    "name": "types",
    "memberof": "src/lib/server/AtviseFile.js",
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~types",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "OPC-UA data type names.",
    "lineNumber": 63,
    "type": {
      "nullable": null,
      "types": [
        "String[]"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 332,
    "kind": "variable",
    "name": "typeExtensions",
    "memberof": "src/lib/server/AtviseFile.js",
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~typeExtensions",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "OPC-UA data type extensions.",
    "lineNumber": 69,
    "type": {
      "nullable": null,
      "types": [
        "String[]"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 333,
    "kind": "variable",
    "name": "VariableTypeDefinition",
    "memberof": "src/lib/server/AtviseFile.js",
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~VariableTypeDefinition",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "Variable data type definition node id.",
    "lineNumber": 76,
    "type": {
      "nullable": null,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 334,
    "kind": "variable",
    "name": "PropertyTypeDefinition",
    "memberof": "src/lib/server/AtviseFile.js",
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~PropertyTypeDefinition",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "Property data type definition node id.",
    "lineNumber": 81,
    "type": {
      "nullable": null,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 335,
    "kind": "variable",
    "name": "ExtensionRegExp",
    "memberof": "src/lib/server/AtviseFile.js",
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~ExtensionRegExp",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "A regular expression picking file extensions from file names.",
    "lineNumber": 88,
    "type": {
      "nullable": null,
      "types": [
        "RegExp"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 336,
    "kind": "function",
    "name": "asIs",
    "memberof": "src/lib/server/AtviseFile.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~asIs",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "Function that returns the passed argument as is.",
    "lineNumber": 95,
    "params": [
      {
        "nullable": null,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "b",
        "description": "The input argument."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "*"
      ],
      "spread": false,
      "description": "The value passed."
    },
    "ignore": true
  },
  {
    "__docId__": 337,
    "kind": "function",
    "name": "mapPropertyAs",
    "memberof": "src/lib/server/AtviseFile.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~mapPropertyAs",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "Maps a single property of an object using the the mapper defined in *map* for the given\n*dataType*.",
    "lineNumber": 105,
    "params": [
      {
        "nullable": null,
        "types": [
          "Map<node-opcua~DataType, function"
        ],
        "spread": false,
        "optional": false,
        "name": "map",
        "description": "The mappings to use."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "obj",
        "description": "The object to process."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "key",
        "description": "Name of the property to map."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~DataType"
        ],
        "spread": false,
        "optional": false,
        "name": "dataType",
        "description": "The data type to map the property to."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    },
    "ignore": true
  },
  {
    "__docId__": 338,
    "kind": "variable",
    "name": "toRawValue",
    "memberof": "src/lib/server/AtviseFile.js",
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~toRawValue",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "Mapping functions that return serializable values for a node of the given\n{@link node-opcua~DataType}.",
    "lineNumber": 120,
    "type": {
      "nullable": null,
      "types": [
        "Map<node-opcua~DataType, function>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 339,
    "kind": "function",
    "name": "decodeAsString",
    "memberof": "src/lib/server/AtviseFile.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~decodeAsString",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "Decodes a buffer to a string.",
    "lineNumber": 171,
    "params": [
      {
        "nullable": null,
        "types": [
          "Buffer"
        ],
        "spread": false,
        "optional": false,
        "name": "b",
        "description": "The buffer to decode from."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": "The buffer's string representation."
    },
    "ignore": true
  },
  {
    "__docId__": 340,
    "kind": "function",
    "name": "decodeAsInt",
    "memberof": "src/lib/server/AtviseFile.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~decodeAsInt",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "Decodes a buffer to an integer value.",
    "lineNumber": 178,
    "params": [
      {
        "nullable": null,
        "types": [
          "Buffer"
        ],
        "spread": false,
        "optional": false,
        "name": "b",
        "description": "The buffer to decode from."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "number"
      ],
      "spread": false,
      "description": "The decoded integer."
    },
    "ignore": true
  },
  {
    "__docId__": 341,
    "kind": "function",
    "name": "decodeAsFloat",
    "memberof": "src/lib/server/AtviseFile.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~decodeAsFloat",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "Decodes a buffer to a float value.",
    "lineNumber": 185,
    "params": [
      {
        "nullable": null,
        "types": [
          "Buffer"
        ],
        "spread": false,
        "optional": false,
        "name": "b",
        "description": "The buffer to decode from."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "number"
      ],
      "spread": false,
      "description": "The decoded float."
    },
    "ignore": true
  },
  {
    "__docId__": 342,
    "kind": "function",
    "name": "decodeAsJson",
    "memberof": "src/lib/server/AtviseFile.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~decodeAsJson",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "Decodes a buffer using JSON.",
    "lineNumber": 192,
    "params": [
      {
        "nullable": null,
        "types": [
          "Buffer"
        ],
        "spread": false,
        "optional": false,
        "name": "b",
        "description": "The buffer to decode from."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "*"
      ],
      "spread": false,
      "description": "The decoded value, most likely an Object."
    },
    "ignore": true
  },
  {
    "__docId__": 343,
    "kind": "variable",
    "name": "decodeRawValue",
    "memberof": "src/lib/server/AtviseFile.js",
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~decodeRawValue",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "Mapping functions that return raw values for a stored value of the given type.",
    "lineNumber": 198,
    "type": {
      "nullable": null,
      "types": [
        "Map<node-opcua~DataType, function>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 344,
    "kind": "variable",
    "name": "toNodeValue",
    "memberof": "src/lib/server/AtviseFile.js",
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~toNodeValue",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "Mapping functions that return OPC-UA node values for raw values.",
    "lineNumber": 231,
    "type": {
      "nullable": null,
      "types": [
        "Map<node-opcua~DataType, function>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 345,
    "kind": "function",
    "name": "getRawValue",
    "memberof": "src/lib/server/AtviseFile.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~getRawValue",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "Returns a node's raw value based on it's OPC-UA value and type.",
    "lineNumber": 302,
    "params": [
      {
        "nullable": null,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "value",
        "description": "A node's OPC-UA value."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~DataType"
        ],
        "spread": false,
        "optional": false,
        "name": "dataType",
        "description": "The node's data type."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~VariantArrayType"
        ],
        "spread": false,
        "optional": false,
        "name": "arrayType",
        "description": "The node's array type."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "*"
      ],
      "spread": false,
      "description": "The raw value of the given node."
    },
    "ignore": true
  },
  {
    "__docId__": 346,
    "kind": "function",
    "name": "getNodeValue",
    "memberof": "src/lib/server/AtviseFile.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~getNodeValue",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "Returns a node's OPC-UA value based on it's raw value and type.",
    "lineNumber": 318,
    "params": [
      {
        "nullable": null,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "rawValue",
        "description": "A node's raw value."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~DataType"
        ],
        "spread": false,
        "optional": false,
        "name": "dataType",
        "description": "A node's data type."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~VariantArrayType"
        ],
        "spread": false,
        "optional": false,
        "name": "arrayType",
        "description": "A node's array type."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    },
    "ignore": true
  },
  {
    "__docId__": 347,
    "kind": "function",
    "name": "extensionForDataType",
    "memberof": "src/lib/server/AtviseFile.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~extensionForDataType",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "Returns the extension for a specific {@link node-opcua~DataType}.\nAlgorithm:\n  - if the type has a shortened extension defined in {@link ExtensionForDataType}, return it.\n  - else return the DataType's name, in lowercase letters.",
    "lineNumber": 340,
    "params": [
      {
        "nullable": null,
        "types": [
          "node-opcua~DataType"
        ],
        "spread": false,
        "optional": false,
        "name": "dataType",
        "description": "The datatype to get the extension for."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": "The resulting extension."
    },
    "ignore": true
  },
  {
    "__docId__": 348,
    "kind": "variable",
    "name": "ConfigFileRegexp",
    "memberof": "src/lib/server/AtviseFile.js",
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~ConfigFileRegexp",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": null,
    "description": "A regular expression that maches all reference definition files.",
    "lineNumber": 348,
    "type": {
      "nullable": null,
      "types": [
        "RegExp"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 349,
    "kind": "class",
    "name": "AtviseFile",
    "memberof": "src/lib/server/AtviseFile.js",
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/AtviseFile.js",
    "importStyle": "AtviseFile",
    "description": "An extension to {@link vinyl~File} providing some additional, atvise-related properties.",
    "lineNumber": 357,
    "properties": [
      {
        "nullable": null,
        "types": [
          "node-opcua~DataType"
        ],
        "spread": false,
        "optional": false,
        "name": "AtviseFile#dataType",
        "description": "The {@link node-opcua~DataType} the node is\nstored against on atvise server."
      },
      {
        "nullable": null,
        "types": [
          "NodeId"
        ],
        "spread": false,
        "optional": false,
        "name": "typeDefinition",
        "description": "The file's type definition on atvise server.\nFIXME: Additional properties not showing in API docs."
      }
    ],
    "interface": false,
    "extends": [
      "vinyl~File"
    ]
  },
  {
    "__docId__": 350,
    "kind": "method",
    "name": "pathForReadResult",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile.pathForReadResult",
    "access": "public",
    "description": "Returns a storage path for a {@link ReadStream.ReadResult}.",
    "lineNumber": 362,
    "params": [
      {
        "nullable": null,
        "types": [
          "ReadStream.ReadResult"
        ],
        "spread": false,
        "optional": false,
        "name": "readResult",
        "description": "The read result to get a path for."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 351,
    "kind": "method",
    "name": "encodeValue",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile.encodeValue",
    "access": "public",
    "description": "Encodes a node's value to file contents.",
    "lineNumber": 412,
    "params": [
      {
        "nullable": null,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "value",
        "description": "The value to encode."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~DataType"
        ],
        "spread": false,
        "optional": false,
        "name": "dataType",
        "description": "The {@link node-opcua~DataType} to encode the value for."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~VariantArrayType"
        ],
        "spread": false,
        "optional": false,
        "name": "arrayType",
        "description": "The files array type."
      }
    ],
    "return": {
      "nullable": true,
      "types": [
        "Buffer"
      ],
      "spread": false,
      "description": "The encoded file contents or null."
    }
  },
  {
    "__docId__": 352,
    "kind": "method",
    "name": "decodeValue",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile.decodeValue",
    "access": "public",
    "description": "Decodes a file's contents to a node's value.",
    "lineNumber": 437,
    "params": [
      {
        "nullable": null,
        "types": [
          "Buffer"
        ],
        "spread": false,
        "optional": false,
        "name": "buffer",
        "description": "The file contents to decode."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~DataType"
        ],
        "spread": false,
        "optional": false,
        "name": "dataType",
        "description": "The {@link node-opcua~DataType} to decode the contents."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~VariantArrayType"
        ],
        "spread": false,
        "optional": false,
        "name": "arrayType",
        "description": "The files array type."
      }
    ],
    "return": {
      "nullable": true,
      "types": [
        "*"
      ],
      "spread": false,
      "description": "The decoded node value or null."
    }
  },
  {
    "__docId__": 353,
    "kind": "method",
    "name": "normalizeMtime",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile.normalizeMtime",
    "access": "public",
    "description": "As file mtimes do not support millisecond resolution these must be removed before storing\nfiles.",
    "lineNumber": 460,
    "params": [
      {
        "nullable": null,
        "types": [
          "Date"
        ],
        "spread": false,
        "optional": false,
        "name": "date",
        "description": "The original mtime."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Date"
      ],
      "spread": false,
      "description": "The normalized mtime."
    }
  },
  {
    "__docId__": 354,
    "kind": "method",
    "name": "fromReadResult",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile.fromReadResult",
    "access": "public",
    "description": "Creates a new {@link AtviseFile} for the given {@link ReadStream.ReadResult}.",
    "lineNumber": 471,
    "params": [
      {
        "nullable": null,
        "types": [
          "ReadStream.ReadResult"
        ],
        "spread": false,
        "optional": false,
        "name": "readResult",
        "description": "The read result to create the file for."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "AtviseFile"
      ],
      "spread": false,
      "description": "The resulting file."
    }
  },
  {
    "__docId__": 355,
    "kind": "method",
    "name": "_getMetadata",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#_getMetadata",
    "access": "private",
    "description": "Recalculates {@link AtviseFile#dataType}, {@link AtviseFile#arrayType} and\n{@link AtviseFile#typeDefinition}. **Never call this method directly.**.",
    "lineNumber": 503,
    "params": [],
    "return": null
  },
  {
    "__docId__": 356,
    "kind": "member",
    "name": "_nodeClass",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#_nodeClass",
    "access": "private",
    "description": "The node's class.",
    "lineNumber": 510,
    "type": {
      "nullable": null,
      "types": [
        "node-opcua~NodeClass"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 357,
    "kind": "member",
    "name": "_references",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#_references",
    "access": "private",
    "description": "References the node holds: In most cases this will be a single entry for\n`'HasTypeDefinition'`.",
    "lineNumber": 519,
    "type": {
      "nullable": null,
      "types": [
        "Map<String, NodeId[]>"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 359,
    "kind": "member",
    "name": "_arrayType",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#_arrayType",
    "access": "private",
    "description": "The node's stored {@link node-opcua~VariantArrayType}.",
    "lineNumber": 537,
    "type": {
      "nullable": true,
      "types": [
        "node-opcua~VariantArrayType"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 361,
    "kind": "member",
    "name": "_name",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#_name",
    "access": "private",
    "description": "A node's browse- and display name.",
    "lineNumber": 545,
    "type": {
      "nullable": true,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 364,
    "kind": "member",
    "name": "_dataType",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#_dataType",
    "access": "private",
    "description": "The node's stored {@link node-opcua~DataType}.",
    "lineNumber": 590,
    "type": {
      "nullable": true,
      "types": [
        "node-opcua~DataType"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 369,
    "kind": "method",
    "name": "getMetadata",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#getMetadata",
    "access": "public",
    "description": "Computes a file's metadata if needed.",
    "lineNumber": 658,
    "return": {
      "nullable": null,
      "types": [
        "AtviseFile"
      ],
      "spread": false,
      "description": "The file."
    },
    "params": []
  },
  {
    "__docId__": 370,
    "kind": "get",
    "name": "nodeClass",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#nodeClass",
    "access": "public",
    "description": "The node's class.",
    "lineNumber": 670,
    "type": {
      "nullable": null,
      "types": [
        "node-opcua~NodeClass"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 371,
    "kind": "get",
    "name": "dataType",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#dataType",
    "access": "public",
    "description": "The file's {@link node-opcua~DataType}.",
    "lineNumber": 682,
    "type": {
      "nullable": null,
      "types": [
        "node-opcua~DataType"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 372,
    "kind": "get",
    "name": "arrayType",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#arrayType",
    "access": "public",
    "description": "The file's {@link node-opcua~VariantArrayType}.",
    "lineNumber": 694,
    "type": {
      "nullable": null,
      "types": [
        "node-opcua~VariantArrayType"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 373,
    "kind": "get",
    "name": "references",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#references",
    "access": "public",
    "description": "The files's references.",
    "lineNumber": 706,
    "type": {
      "nullable": null,
      "types": [
        "Map<string, NodeId|NodeId[]>"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 374,
    "kind": "get",
    "name": "typeDefinition",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#typeDefinition",
    "access": "public",
    "description": "The file's type definition.",
    "lineNumber": 718,
    "type": {
      "nullable": null,
      "types": [
        "node-opcua~NodeId"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 375,
    "kind": "get",
    "name": "isReferenceConfig",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#isReferenceConfig",
    "access": "public",
    "description": "`true` for reference config files (for example `.index.htm.json`).",
    "lineNumber": 733,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 376,
    "kind": "get",
    "name": "isDisplay",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#isDisplay",
    "access": "public",
    "description": "`true` for files containing atvise displays.",
    "lineNumber": 741,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 377,
    "kind": "get",
    "name": "isScript",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#isScript",
    "access": "public",
    "description": "`true` for files containing atvise scripts.",
    "lineNumber": 749,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 378,
    "kind": "get",
    "name": "isQuickDynamic",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#isQuickDynamic",
    "access": "public",
    "description": "`true` for files containing atvise quick dynamics.",
    "lineNumber": 757,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 379,
    "kind": "set",
    "name": "value",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#value",
    "access": "public",
    "description": "Sets the node value for the file.",
    "lineNumber": 765,
    "params": [
      {
        "nullable": true,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "newValue",
        "description": "The value to set."
      }
    ]
  },
  {
    "__docId__": 380,
    "kind": "member",
    "name": "contents",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#contents",
    "access": "public",
    "description": "The file's contents.",
    "lineNumber": 770,
    "type": {
      "nullable": true,
      "types": [
        "Buffer"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 381,
    "kind": "get",
    "name": "value",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#value",
    "access": "public",
    "description": "Returns the decoded node value for the file.",
    "lineNumber": 777,
    "type": {
      "nullable": true,
      "types": [
        "*"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 382,
    "kind": "get",
    "name": "createNodeValue",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#createNodeValue",
    "access": "public",
    "description": "Returns the decoded node value for create node serverscript.",
    "lineNumber": 785,
    "type": {
      "nullable": true,
      "types": [
        "*"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 383,
    "kind": "get",
    "name": "nodeId",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#nodeId",
    "access": "public",
    "description": "Returns the node id associated with the file.",
    "lineNumber": 803,
    "type": {
      "nullable": null,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 384,
    "kind": "get",
    "name": "name",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#name",
    "access": "public",
    "description": "A file's browse and display name.",
    "lineNumber": 822,
    "type": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 385,
    "kind": "get",
    "name": "parentNodeId",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#parentNodeId",
    "access": "public",
    "description": "A file's parent's node id.",
    "lineNumber": 834,
    "type": {
      "nullable": null,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 386,
    "kind": "method",
    "name": "clone",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile#clone",
    "access": "public",
    "description": "Returns a new file with all attributes of the current file.",
    "see": [
      "https://github.com/gulpjs/vinyl#filecloneoptions"
    ],
    "lineNumber": 855,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "See the {@link vinyl~File} docs for all options available."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "AtviseFile"
      ],
      "spread": false,
      "description": "The cloned file."
    }
  },
  {
    "__docId__": 387,
    "kind": "method",
    "name": "read",
    "memberof": "src/lib/server/AtviseFile.js~AtviseFile",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/AtviseFile.js~AtviseFile.read",
    "access": "public",
    "description": "Creates a new AtviseFile and reads it's contents.",
    "lineNumber": 872,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "See {@link vinyl~File} for available options."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": "Resolved with the new file of rejected with the error that occured while\ntrying to read it's path."
    }
  },
  {
    "__docId__": 388,
    "kind": "file",
    "name": "src/lib/server/CreateNodeStream.js",
    "content": "import { StatusCodes } from 'node-opcua/lib/datamodel/opcua_status_code';\nimport { DataType } from 'node-opcua/lib/datamodel/variant';\nimport { NodeClass } from 'node-opcua/lib/datamodel/nodeclass';\nimport Logger from 'gulplog';\nimport NodeId from '../model/opcua/NodeId';\nimport { ReferenceTypeIds, ReferenceTypeNames } from '../model/Node';\nimport CallScriptStream from './scripts/CallScriptStream';\n\n/**\n * A stream that creates OPC-UA nodes for the passed {@link AtviseFiles}s.\n */\nexport default class CreateNodeStream extends CallScriptStream {\n  /**\n   * Id of the *CreateNode* script added with `atscm import`.\n   * @type {NodeId}\n   */\n  get scriptId() {\n    return new NodeId(\n      NodeId.NodeIdType.STRING,\n      'SYSTEM.LIBRARY.ATVISE.SERVERSCRIPTS.atscm.CreateNode',\n      1\n    );\n  }\n\n  /**\n   * The options required to create a node for the given file.\n   * @param {AtviseFile} file The processed file.\n   * @return {Object} The options passed to the *CreateNode* script.\n   */\n  scriptParameters(file) {\n    const options = {\n      nodeId: file.nodeId,\n      parentNodeId: file.parent ? file.parent.nodeId : 85,\n      nodeClass: file.nodeClass.value,\n      typeDefinition: file.typeDefinition,\n      browseName: file.idName,\n    };\n\n    const toParentRefs = file.references.get(ReferenceTypeIds.toParent);\n    if (toParentRefs) {\n      options.reference = ReferenceTypeNames[[...toParentRefs][0]];\n    }\n\n    const rules = file.references.get(ReferenceTypeIds.HasModellingRule);\n    if (rules) {\n      options.modellingRule = [...rules][0];\n    }\n\n    if (file.nodeClass.value === NodeClass.Variable.value) {\n      options.dataType = file.variantValue.dataType.value;\n      options.valueRank = file.variantValue.arrayType.value;\n      options.value = file.variantValue.value;\n    }\n\n    return {\n      paramObjString: {\n        dataType: DataType.String,\n        value: JSON.stringify(options),\n      },\n    };\n  }\n\n  /**\n   * Prints an error message telling that creating a node failed.\n   * @param {AtviseFile} file The file who's node could not be created.\n   * @return {string} The resulting error message.\n   */\n  processErrorMessage(file) {\n    return `Error creating node ${file.nodeId}`;\n  }\n\n  /**\n   * Handles the results of a script call.\n   * @param {AtviseFile} file The file the script was called with.\n   * @param {node-opcua~Variant[]} outArgs The raw method results.\n   * @param {function(err: Error)} callback Called once finished.\n   */\n  handleOutputArguments(file, outArgs, callback) {\n    if (outArgs[0].value !== StatusCodes.Good) {\n      callback(new Error(outArgs[1].value));\n    } else {\n      const [{ value: createdNode }, { value: createFailed }] = outArgs[3].value;\n\n      if (createFailed) {\n        Logger.warn('Failed to create node', file.nodeId.toString());\n      } else if (createdNode) {\n        Logger.debug('Created node', file.nodeId.toString());\n        this.push(file);\n      } else {\n        Logger.debug('Node', file.nodeId.toString(), 'already exists');\n        this.push(file);\n      }\n\n      callback(null);\n    }\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/server/CreateNodeStream.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 389,
    "kind": "class",
    "name": "CreateNodeStream",
    "memberof": "src/lib/server/CreateNodeStream.js",
    "static": true,
    "longname": "src/lib/server/CreateNodeStream.js~CreateNodeStream",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/CreateNodeStream.js",
    "importStyle": "CreateNodeStream",
    "description": "A stream that creates OPC-UA nodes for the passed {@link AtviseFiles}s.",
    "lineNumber": 12,
    "interface": false,
    "extends": [
      "src/lib/server/scripts/CallScriptStream.js~CallScriptStream"
    ]
  },
  {
    "__docId__": 390,
    "kind": "get",
    "name": "scriptId",
    "memberof": "src/lib/server/CreateNodeStream.js~CreateNodeStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/CreateNodeStream.js~CreateNodeStream#scriptId",
    "access": "public",
    "description": "Id of the *CreateNode* script added with `atscm import`.",
    "lineNumber": 17,
    "type": {
      "nullable": null,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 391,
    "kind": "method",
    "name": "scriptParameters",
    "memberof": "src/lib/server/CreateNodeStream.js~CreateNodeStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/CreateNodeStream.js~CreateNodeStream#scriptParameters",
    "access": "public",
    "description": "The options required to create a node for the given file.",
    "lineNumber": 30,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The processed file."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Object"
      ],
      "spread": false,
      "description": "The options passed to the *CreateNode* script."
    }
  },
  {
    "__docId__": 392,
    "kind": "method",
    "name": "processErrorMessage",
    "memberof": "src/lib/server/CreateNodeStream.js~CreateNodeStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/CreateNodeStream.js~CreateNodeStream#processErrorMessage",
    "access": "public",
    "description": "Prints an error message telling that creating a node failed.",
    "lineNumber": 68,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file who's node could not be created."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": "The resulting error message."
    }
  },
  {
    "__docId__": 393,
    "kind": "method",
    "name": "handleOutputArguments",
    "memberof": "src/lib/server/CreateNodeStream.js~CreateNodeStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/CreateNodeStream.js~CreateNodeStream#handleOutputArguments",
    "access": "public",
    "description": "Handles the results of a script call.",
    "lineNumber": 78,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file the script was called with."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~Variant[]"
        ],
        "spread": false,
        "optional": false,
        "name": "outArgs",
        "description": "The raw method results."
      },
      {
        "nullable": null,
        "types": [
          "function(err: Error)"
        ],
        "spread": false,
        "optional": false,
        "name": "callback",
        "description": "Called once finished."
      }
    ],
    "return": null
  },
  {
    "__docId__": 394,
    "kind": "file",
    "name": "src/lib/server/NodeBrowser.js",
    "content": "import { ObjectIds } from 'node-opcua/lib/opcua_node_ids.js';\nimport { BrowseDirection } from 'node-opcua/lib/services/browse_service.js';\nimport { AttributeIds } from 'node-opcua/lib/services/read_service';\nimport { VariantArrayType, DataType } from 'node-opcua/lib/datamodel/variant';\nimport Logger from 'gulplog';\nimport PromiseQueue from 'p-queue';\nimport ProjectConfig from '../../config/ProjectConfig';\nimport NodeId from '../model/opcua/NodeId';\nimport { ServerNode, ReferenceTypeIds, ReferenceTypeNames } from '../model/Node';\nimport Session from './Session';\n\n/**\n * A set of all hierarchical reference types.\n * @type {Set<number>}\n */\nconst HierachicalReferencesTypeIds = new Set([\n  ReferenceTypeIds.HasChild,\n  ReferenceTypeIds.Aggregates,\n  ReferenceTypeIds.HasComponent,\n  ReferenceTypeIds.HasOrderedComponent,\n  ReferenceTypeIds.HasHistoricalConfiguration,\n  ReferenceTypeIds.HasProperty,\n  ReferenceTypeIds.HasSubtype,\n  ReferenceTypeIds.HasEventSource,\n  ReferenceTypeIds.HasNotifier,\n  ReferenceTypeIds.Organizes,\n]);\n\n/**\n * A node discovered while browsing the server's database.\n */\nexport class BrowsedNode extends ServerNode {\n  /**\n   * Creates a new node.\n   * @param {Object} options The options to use.\n   * @param {?BrowsedNode} options.parent The parent node.\n   * @param {Object} options.reference The reference to pick metadata from.\n   */\n  constructor({ parent, reference, nodeClass, name }) {\n    super({\n      parent,\n      nodeClass: reference ? reference.nodeClass : nodeClass,\n      name: reference ? reference.browseName.name : name,\n    });\n\n    if (reference) {\n      // NOTE: You should always provide reference, this only for #createChild\n      this.addReference(ReferenceTypeIds.toParent, reference.referenceTypeId.value);\n\n      /** The node's id. @type {NodeId} */\n      this.id = reference.nodeId;\n    }\n\n    /** The node's value\n     * @type {node-opcua~Variant} */\n    this.value = {};\n  }\n\n  /**\n   * Add multiple references at once.\n   * @param {Object[]} references The references to add.\n   */\n  addReferences(references) {\n    references.forEach((reference) => {\n      this.addReference(reference.referenceTypeId.value, reference.nodeId.value);\n    });\n  }\n\n  /**\n   * Creates new child node.\n   * @param {Object} options The options to use.\n   * @see {Node#createChild}\n   */\n  createChild(options) {\n    const node = super.createChild(options);\n\n    node.id = this.id;\n\n    return node;\n  }\n}\n\n/**\n * Browses the server database.\n */\nexport default class NodeBrowser {\n  /**\n   * Creates a new node browser.\n   * @param {Object} options The options to use.\n   * @param {number} [options.concurrency=250] The maximum of nodes to process in parallel.\n   * @param {function(node: BrowsedNode): Promise<any>} options.handleNode A custom node handler.\n   * @param {boolean} [options.recursive] If the whole node tree should be processed.\n   */\n  constructor({\n    concurrency = 250,\n    ignoreNodes = ProjectConfig.ignoreNodes,\n    handleNode,\n    recursive = true,\n  } = {}) {\n    /** The queue used to process nodes in parallel\n     * @type {p-queue~PQueue} */\n    this.queue = new PromiseQueue({\n      // autoStart: false,\n      concurrency,\n    });\n\n    /** A map of nodes already handled. Keys are ids, values are `true` if the node was already\n     * pushed and `false` otherwise.\n     * @type {Map<string, boolean>}\n     * */\n    this._handled = new Map();\n\n    this._waitingFor = {};\n\n    /** A regular expression matching all ignored nodes. @type {RegExp} */\n    this._ignoreNodesRegExp = new RegExp(`^(${ignoreNodes.map((n) => n.value).join('|')})`);\n\n    /** If the browser should recurse. @type {boolean} */\n    this._recursive = recursive;\n\n    /** If a warning should be printed for attempting to pull sort order nodes\n     * @type {boolean} */\n    this._printSortOrderWarning = recursive;\n\n    /** The custom node handler. @type {function(node: BrowsedNode): Promise<any>} */\n    this._handleNode = handleNode;\n\n    /** The number of pushed (discovered and handled) nodes. @type {number} */\n    this._pushed = 0;\n\n    /** A map that maps node ids against their discovered hierarchical parent nodes. Used to detect\n     * reference conflicts.\n     * @type {Map<string, string>} */\n    this.parentNode = new Map();\n\n    this.ensureHandled = new Set();\n  }\n\n  /**\n   * Reads the given node's value.\n   * @param {BrowsedNode} node The node to read.\n   */\n  _readValue(node) {\n    if (!node.isVariable) {\n      return null;\n    }\n    return new Promise((resolve, reject) => {\n      this._session.readVariableValue(node.id, (err, result) => {\n        if (err) {\n          return reject(err);\n        }\n        return resolve(result && result.value);\n      });\n    }).then((value) => {\n      if (node.nodeId.endsWith('.SortOrder')) {\n        const removed = [];\n        const siblings = node.parent.children.map((c) => c.idName).filter((n) => n !== 'SortOrder');\n        const existing = value.value\n          .map(({ name }) => name)\n          .filter((name) => {\n            const exists = siblings.find((c) => c === name);\n\n            if (exists) {\n              return true;\n            }\n\n            removed.push(name);\n            return false;\n          });\n\n        // We could also add missing references here...\n\n        if (removed.length) {\n          // eslint-disable-next-line no-param-reassign\n          value.value = existing.map((name) => ({ namespaceIndex: 1, name }));\n          Logger.warn(`Removed ${removed.length} invalid references from '${node.nodeId}'`);\n        }\n      }\n\n      if (value) {\n        return value;\n      }\n\n      // Node is a variable but has no value -> Need to read dataType and arrayType directly.\n      return new Promise((resolve, reject) => {\n        const toRead = [AttributeIds.DataType, AttributeIds.ValueRank].map((attributeId) => ({\n          nodeId: node.id,\n          attributeId,\n        }));\n        this._session.read(\n          toRead,\n          (\n            err,\n            _,\n            [\n              {\n                value: { value: dataType },\n              },\n              {\n                value: { value: valueRank },\n              },\n            ] = []\n          ) => {\n            if (err) return reject(err);\n\n            // FIXME: valueRank -2 (Any) and -3 (ScalarOrOneDimension) are not handled properly here\n            const arrayType = valueRank < 0 ? VariantArrayType.Scalar : VariantArrayType.Array;\n\n            return resolve({\n              dataType: DataType[dataType.value],\n              arrayType,\n              value: null,\n            });\n          }\n        );\n      });\n    });\n  }\n\n  // FIXME: Debounce á la https://runkit.com/5c347d277da2ad00125b6bc2/5c50161cbc21520012c42290\n  // FIXME: Move to api\n  /**\n   * Browses the server address space at the given node id.\n   * @param {Object} options The options to use.\n   */\n  _browse({ nodeId, browseDirection = BrowseDirection.Forward, resultMask = 63 }) {\n    return new Promise((resolve, reject) => {\n      this._session.browse({ nodeId, browseDirection, resultMask }, (err, data = []) =>\n        err ? reject(err) : resolve(data[0].references)\n      );\n    });\n  }\n\n  /**\n   * Browses a node.\n   * @param {BrowsedNode} node The node to browse.\n   */\n  _browseNode(node) {\n    return this._browse({ nodeId: node.id }).then((allReferences) => {\n      const children = [];\n      const references = [];\n\n      const typeDefinitionReference = allReferences.find(\n        (ref) => ref.referenceTypeId.value === ReferenceTypeIds.HasTypeDefinition\n      );\n\n      const isUserGroup =\n        typeDefinitionReference &&\n        typeDefinitionReference.nodeId.value === 'ObjectTypes.ATVISE.Group';\n\n      allReferences.forEach((reference) => {\n        // \"Cast\" ref.nodeId to NodeId\n        Object.setPrototypeOf(reference.nodeId, NodeId.prototype);\n\n        const ignored = this._ignoreNodesRegExp.test(reference.nodeId.value);\n        const external = this._isExternalReference(reference.nodeId.value);\n\n        if (\n          HierachicalReferencesTypeIds.has(reference.referenceTypeId.value) &&\n          !ignored &&\n          !external\n        ) {\n          if (\n            reference.referenceTypeId.value === ReferenceTypeIds.HasHistoricalConfiguration ||\n            (isUserGroup && reference.nodeId.value.split(node.nodeId).length === 1)\n          ) {\n            references.push(reference);\n            return;\n          }\n\n          if (\n            !ProjectConfig.preserveSortOrderNodes &&\n            reference.nodeId.value.endsWith('.SortOrder')\n          ) {\n            if (this._printSortOrderWarning) {\n              Logger.warn(`Skipped pulling an atvise builder sort order node.\n - Reason: These nodes are not consistent across pulls.\n - You can force pulling them by setting Atviseproject.preserveSortOrderNodes.`);\n              this._printSortOrderWarning = false;\n            }\n            return;\n          }\n\n          const [prefix, subPath] = reference.nodeId.value.split(node.id.value);\n          if (!subPath || prefix !== '') {\n            if (!ProjectConfig.isExternal(reference.nodeId.parent.value)) {\n              references.push(reference);\n\n              if (this._handled.get(reference.nodeId.value) === undefined) {\n                this.ensureHandled.add(reference.nodeId.value);\n              }\n              return;\n            }\n          }\n\n          const earlierParent = this.parentNode.get(reference.nodeId.value);\n          if (earlierParent) {\n            Logger.warn(`'${\n              reference.nodeId.value\n            }' was discovered as a child node of both '${earlierParent}' and '${node.id.value}'.\n  - Reference type (to the latter): ${ReferenceTypeNames[reference.referenceTypeId.value]} (${\n              reference.referenceTypeId.value\n            })`);\n          }\n\n          if (this._handled.get(reference.nodeId.value) === undefined) {\n            this.parentNode.set(reference.nodeId.value, node.id.value);\n            children.push(\n              new BrowsedNode({\n                parent: node,\n                reference,\n              })\n            );\n          } // else node is already handled\n        } else if (reference.referenceTypeId.value !== 50) {\n          // Added by atvise builder\n          // 'HasModelParent' reference set in atvise 3.3.2+\n          // Always points to parent node, which atscm already handles\n          if (\n            reference.referenceTypeId.value === 334 &&\n            reference.nodeId.value === (node.parent && node.parent.id.value)\n          ) {\n            return;\n          }\n\n          // Do not add ignored\n          if (!ignored) {\n            references.push(reference);\n          } else {\n            Logger.debug(\n              `Ignored reference from ${node.id.value} (${\n                ReferenceTypeNames[reference.referenceTypeId.value]\n              }) to ${reference.nodeId.value}`\n            );\n          }\n        }\n      });\n\n      // eslint-disable-next-line no-param-reassign\n      node.children = children;\n      node.addReferences(references);\n\n      return { children, references };\n    });\n  }\n\n  /**\n   * Finishes processing a given node: After calling {@link NodeBrowser#_handleNode}, it resolves\n   * is's dependencies.\n   * @param {BrowsedNode} node The node handled.\n   */\n  async _push(node) {\n    if (this._handled.get(node.id.value)) {\n      Logger.error('Prevented duplicate handling of', node.id.value);\n      return;\n    }\n\n    // Prevent duplicate pushes while reading value file\n    this._handled.set(node.id.value, 'processing');\n\n    // eslint-disable-next-line no-param-reassign\n    node.value = (await this._readValue(node)) || node.value;\n\n    // TODO: Remove additional properties (children, ...) for better memory-usage\n\n    const originalId = node.id.value;\n\n    await this._handleNode(node);\n\n    this._pushed += 1;\n\n    // Do not proceed if queue is stopped (because an error occured)\n    if (!this._recursive || this.queue.isPaused) {\n      // Queue is stopped, not adding...\n      return;\n    }\n\n    this.queue.addAll(node.children.map((child) => () => this._process(child)));\n\n    const idValue = node.id.value;\n    this._handled.set(idValue, true);\n    this.ensureHandled.delete(originalId);\n\n    // Handle dependencies\n    if (this._waitingFor[idValue]) {\n      this._waitingFor[idValue].forEach((dep) => {\n        // eslint-disable-next-line no-param-reassign\n        if (--dep.dependencies === 0) {\n          // Adding as dependencies are resolved\n          this.queue.add(() => this._push(dep)).catch(this._reject);\n        }\n      });\n\n      delete this._waitingFor[idValue];\n    }\n  }\n\n  /**\n   * Instructs the browser to handle a node that would otherwise be queued behind others (eg: its\n   * parent node).\n   * @param {BrowsedNode} node The node to add.\n   * @return {Promise<?BrowsedNode>} The fully processed node.\n   */\n  addNode(node) {\n    if (this.queue.isPaused) {\n      Logger.debug('Queue is stopped, not adding...');\n      return Promise.resolve();\n    }\n\n    return this.queue.add(() => this._handleNode(node, { transform: false })).catch(this._reject);\n  }\n\n  /**\n   * Returns `true` for node ids that should be treated as external references.\n   * @param {string|number} idValue Value of the id to check.\n   * @return {boolean} If the id should be treated as external.\n   */\n  _isExternalReference(idValue) {\n    // FIXME: Allow plugins\n    return typeof idValue !== 'string' || !this._sourceNodesRegExp.test(idValue);\n  }\n\n  /**\n   * Returns `true` if a node has dependencies it should be queued behind.\n   * @param {BrowsedNode} node The node to check.\n   */\n  _hasDependencies(node) {\n    let dependencyCount = 0;\n\n    for (const references of node.references.values()) {\n      for (const reference of references) {\n        if (\n          this._handled.get(reference) !== true &&\n          !this._isExternalReference(reference) &&\n          !this._ignoreNodesRegExp.test(reference)\n        ) {\n          dependencyCount++;\n          this._waitingFor[reference] = (this._waitingFor[reference] || []).concat(node);\n        }\n      }\n    }\n\n    // eslint-disable-next-line no-param-reassign\n    node.dependencies = dependencyCount;\n\n    return dependencyCount > 0;\n  }\n\n  /**\n   * Processes a single node: Requires special error handling.\n   * @param {BrowsedNode} node The node to process.\n   * @return {Promise<?BrowsedNode>} The fully processed node.\n   */\n  async _process(node) {\n    try {\n      if (this._handled.has(node.id.value)) {\n        // Already queued\n        return undefined;\n      }\n      this._handled.set(node.id.value, false);\n      await this._browseNode(node);\n\n      if (!this._hasDependencies(node)) {\n        await this._push(node);\n      }\n    } catch (err) {\n      this._reject(err);\n    }\n\n    return node;\n  }\n\n  /**\n   * Discovers and browses the source nodes.\n   * @param {Array<string, NodeId>} nodeIds The source ids.\n   * @return {Promise<Node[]>} Resolved once finished.\n   */\n  _getSourceNodes(nodeIds) {\n    const browseUp = ({ nodeId, path = [] }) =>\n      this._browse({\n        nodeId,\n        browseDirection: BrowseDirection.Inverse,\n      }).then((references) => {\n        for (const reference of references) {\n          if (HierachicalReferencesTypeIds.has(reference.referenceTypeId.value)) {\n            path.unshift(reference.nodeId);\n            return reference.nodeId.value === ObjectIds.RootFolder\n              ? path\n              : browseUp({ nodeId: reference.nodeId, path });\n          }\n        }\n        throw new Error(`Unable to find parent node of ${nodeId}`);\n      });\n\n    const browseDown = (path, target) =>\n      Promise.all(\n        path.map((nodeId, i) =>\n          this._browse({ nodeId }).then((references) =>\n            references.find(\n              (ref) => ref.nodeId.value === (path[i + 1] ? path[i + 1].value : target.value)\n            )\n          )\n        )\n      );\n\n    return Promise.all(\n      nodeIds.map((nodeId) =>\n        browseUp({ nodeId })\n          .then((path) => browseDown(path, nodeId))\n          .then((pathDown) =>\n            pathDown.reduce((parent, reference) => new BrowsedNode({ parent, reference }), null)\n          )\n      )\n    );\n  }\n\n  /**\n   * Starts the browser of the given nodes.\n   * @param {NodeId[]} nodeIds The nodes to browse.\n   * @return {Promise<any>} Resolved once all nodes are finished.\n   */\n  async browse(nodeIds) {\n    this._sourceNodesRegExp = new RegExp(\n      `^(${nodeIds.map(({ value }) => `${value.replace(/\\./g, '\\\\.')}`).join('|')})`\n    );\n\n    this._session = await Session.create();\n\n    // Add source nodes\n    const nodes = await this._getSourceNodes(nodeIds);\n    this.queue.addAll(nodes.map((node) => () => this._process(node)));\n\n    // Queue error handling\n    let processError = null;\n    this._reject = (err) => {\n      if (processError) {\n        // Multiple errors occured. In most cases this means, that the server connection was closed\n        // after the first error.\n        Logger.debug('Additional error', err);\n        return;\n      }\n\n      processError = err;\n      this.queue.pause();\n      this.queue.clear();\n    };\n\n    return new Promise((resolve, reject) => {\n      this.queue.onIdle().then(async () => {\n        await Session.close(this._session);\n\n        if (processError) {\n          reject(processError);\n          return;\n        }\n\n        if (Object.keys(this._waitingFor).length) {\n          const unresolved = Object.entries(this._waitingFor).reduce(\n            (all, [to, children]) =>\n              all.concat(\n                children.map((c) => ({\n                  from: c.id.value,\n                  to,\n                  type:\n                    ReferenceTypeNames[\n                      Array.from(c.references).find(([, refs]) => refs.has(to))[0]\n                    ],\n                }))\n              ),\n            []\n          );\n\n          reject(\n            new Error(`Unable to resolve reference${unresolved.length > 1 ? 's' : ''}:\n\n  ${unresolved.map(({ from, type, to }) => `${from} → (${type}) → ${to}`).join('\\n  ')}\n`)\n          );\n          return;\n        }\n\n        if (this.ensureHandled.size) {\n          reject(\n            new Error(`Some referenced nodes were not handled,\n - ${Array.from(this.ensureHandled).join('\\n - ')}`)\n          );\n          return;\n        }\n\n        if (Array.from(this._handled).find(([, pushed]) => !pushed)) {\n          throw new Error('A node was processed, but not pushed');\n        }\n\n        resolve();\n      });\n    });\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/server/NodeBrowser.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 395,
    "kind": "variable",
    "name": "HierachicalReferencesTypeIds",
    "memberof": "src/lib/server/NodeBrowser.js",
    "static": true,
    "longname": "src/lib/server/NodeBrowser.js~HierachicalReferencesTypeIds",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/NodeBrowser.js",
    "importStyle": null,
    "description": "A set of all hierarchical reference types.",
    "lineNumber": 16,
    "type": {
      "nullable": null,
      "types": [
        "Set<number>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 396,
    "kind": "class",
    "name": "BrowsedNode",
    "memberof": "src/lib/server/NodeBrowser.js",
    "static": true,
    "longname": "src/lib/server/NodeBrowser.js~BrowsedNode",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/NodeBrowser.js",
    "importStyle": "{BrowsedNode}",
    "description": "A node discovered while browsing the server's database.",
    "lineNumber": 32,
    "interface": false,
    "extends": [
      "src/lib/model/Node.js~ServerNode"
    ]
  },
  {
    "__docId__": 397,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/server/NodeBrowser.js~BrowsedNode",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~BrowsedNode#constructor",
    "access": "public",
    "description": "Creates a new node.",
    "lineNumber": 39,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "The options to use."
      },
      {
        "nullable": true,
        "types": [
          "BrowsedNode"
        ],
        "spread": false,
        "optional": false,
        "name": "options.parent",
        "description": "The parent node."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options.reference",
        "description": "The reference to pick metadata from."
      }
    ]
  },
  {
    "__docId__": 398,
    "kind": "member",
    "name": "id",
    "memberof": "src/lib/server/NodeBrowser.js~BrowsedNode",
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~BrowsedNode#id",
    "access": "public",
    "description": "The node's id. @type {NodeId}",
    "lineNumber": 51,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 399,
    "kind": "member",
    "name": "value",
    "memberof": "src/lib/server/NodeBrowser.js~BrowsedNode",
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~BrowsedNode#value",
    "access": "public",
    "description": "The node's value",
    "lineNumber": 56,
    "type": {
      "nullable": null,
      "types": [
        "node-opcua~Variant"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 400,
    "kind": "method",
    "name": "addReferences",
    "memberof": "src/lib/server/NodeBrowser.js~BrowsedNode",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~BrowsedNode#addReferences",
    "access": "public",
    "description": "Add multiple references at once.",
    "lineNumber": 63,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object[]"
        ],
        "spread": false,
        "optional": false,
        "name": "references",
        "description": "The references to add."
      }
    ],
    "return": null
  },
  {
    "__docId__": 401,
    "kind": "method",
    "name": "createChild",
    "memberof": "src/lib/server/NodeBrowser.js~BrowsedNode",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~BrowsedNode#createChild",
    "access": "public",
    "description": "Creates new child node.",
    "see": [
      "{Node#createChild}"
    ],
    "lineNumber": 74,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "The options to use."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 402,
    "kind": "class",
    "name": "NodeBrowser",
    "memberof": "src/lib/server/NodeBrowser.js",
    "static": true,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/NodeBrowser.js",
    "importStyle": "NodeBrowser",
    "description": "Browses the server database.",
    "lineNumber": 86,
    "interface": false
  },
  {
    "__docId__": 403,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#constructor",
    "access": "public",
    "description": "Creates a new node browser.",
    "lineNumber": 94,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "The options to use."
      },
      {
        "nullable": null,
        "types": [
          "number"
        ],
        "spread": false,
        "optional": true,
        "defaultValue": "250",
        "defaultRaw": 250,
        "name": "options.concurrency",
        "description": "The maximum of nodes to process in parallel."
      },
      {
        "nullable": null,
        "types": [
          "function(node: BrowsedNode): Promise<any>"
        ],
        "spread": false,
        "optional": false,
        "name": "options.handleNode",
        "description": "A custom node handler."
      },
      {
        "nullable": null,
        "types": [
          "boolean"
        ],
        "spread": false,
        "optional": true,
        "name": "options.recursive",
        "description": "If the whole node tree should be processed."
      }
    ]
  },
  {
    "__docId__": 404,
    "kind": "member",
    "name": "queue",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#queue",
    "access": "public",
    "description": "The queue used to process nodes in parallel",
    "lineNumber": 102,
    "type": {
      "nullable": null,
      "types": [
        "p-queue~PQueue"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 405,
    "kind": "member",
    "name": "_handled",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_handled",
    "access": "private",
    "description": "A map of nodes already handled. Keys are ids, values are `true` if the node was already\npushed and `false` otherwise.",
    "lineNumber": 111,
    "type": {
      "nullable": null,
      "types": [
        "Map<string, boolean>"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 406,
    "kind": "member",
    "name": "_waitingFor",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_waitingFor",
    "access": "private",
    "description": null,
    "lineNumber": 113,
    "undocument": true,
    "type": {
      "types": [
        "{}"
      ]
    }
  },
  {
    "__docId__": 407,
    "kind": "member",
    "name": "_ignoreNodesRegExp",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_ignoreNodesRegExp",
    "access": "private",
    "description": "A regular expression matching all ignored nodes. @type {RegExp}",
    "lineNumber": 116,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 408,
    "kind": "member",
    "name": "_recursive",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_recursive",
    "access": "private",
    "description": "If the browser should recurse. @type {boolean}",
    "lineNumber": 119,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 409,
    "kind": "member",
    "name": "_printSortOrderWarning",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_printSortOrderWarning",
    "access": "private",
    "description": "If a warning should be printed for attempting to pull sort order nodes",
    "lineNumber": 123,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 410,
    "kind": "member",
    "name": "_handleNode",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_handleNode",
    "access": "private",
    "description": "The custom node handler. @type {function(node: BrowsedNode): Promise<any>}",
    "lineNumber": 126,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 411,
    "kind": "member",
    "name": "_pushed",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_pushed",
    "access": "private",
    "description": "The number of pushed (discovered and handled) nodes. @type {number}",
    "lineNumber": 129,
    "type": {
      "types": [
        "number"
      ]
    }
  },
  {
    "__docId__": 412,
    "kind": "member",
    "name": "parentNode",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#parentNode",
    "access": "public",
    "description": "A map that maps node ids against their discovered hierarchical parent nodes. Used to detect\nreference conflicts.",
    "lineNumber": 134,
    "type": {
      "nullable": null,
      "types": [
        "Map<string, string>"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 413,
    "kind": "member",
    "name": "ensureHandled",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#ensureHandled",
    "access": "public",
    "description": null,
    "lineNumber": 136,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 414,
    "kind": "method",
    "name": "_readValue",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_readValue",
    "access": "private",
    "description": "Reads the given node's value.",
    "lineNumber": 143,
    "params": [
      {
        "nullable": null,
        "types": [
          "BrowsedNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The node to read."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 415,
    "kind": "method",
    "name": "_browse",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_browse",
    "access": "private",
    "description": "Browses the server address space at the given node id.",
    "lineNumber": 226,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "The options to use."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 416,
    "kind": "method",
    "name": "_browseNode",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_browseNode",
    "access": "private",
    "description": "Browses a node.",
    "lineNumber": 238,
    "params": [
      {
        "nullable": null,
        "types": [
          "BrowsedNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The node to browse."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 418,
    "kind": "method",
    "name": "_push",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "generator": false,
    "async": true,
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_push",
    "access": "private",
    "description": "Finishes processing a given node: After calling {@link NodeBrowser#_handleNode}, it resolves\nis's dependencies.",
    "lineNumber": 352,
    "params": [
      {
        "nullable": null,
        "types": [
          "BrowsedNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The node handled."
      }
    ],
    "return": null
  },
  {
    "__docId__": 420,
    "kind": "method",
    "name": "addNode",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#addNode",
    "access": "public",
    "description": "Instructs the browser to handle a node that would otherwise be queued behind others (eg: its\nparent node).",
    "lineNumber": 404,
    "params": [
      {
        "nullable": null,
        "types": [
          "BrowsedNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The node to add."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise<?BrowsedNode>"
      ],
      "spread": false,
      "description": "The fully processed node."
    }
  },
  {
    "__docId__": 421,
    "kind": "method",
    "name": "_isExternalReference",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_isExternalReference",
    "access": "private",
    "description": "Returns `true` for node ids that should be treated as external references.",
    "lineNumber": 418,
    "params": [
      {
        "nullable": null,
        "types": [
          "string",
          "number"
        ],
        "spread": false,
        "optional": false,
        "name": "idValue",
        "description": "Value of the id to check."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": "If the id should be treated as external."
    }
  },
  {
    "__docId__": 422,
    "kind": "method",
    "name": "_hasDependencies",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_hasDependencies",
    "access": "private",
    "description": "Returns `true` if a node has dependencies it should be queued behind.",
    "lineNumber": 427,
    "params": [
      {
        "nullable": null,
        "types": [
          "BrowsedNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The node to check."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 423,
    "kind": "method",
    "name": "_process",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "generator": false,
    "async": true,
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_process",
    "access": "private",
    "description": "Processes a single node: Requires special error handling.",
    "lineNumber": 454,
    "params": [
      {
        "nullable": null,
        "types": [
          "BrowsedNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The node to process."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise<?BrowsedNode>"
      ],
      "spread": false,
      "description": "The fully processed node."
    }
  },
  {
    "__docId__": 424,
    "kind": "method",
    "name": "_getSourceNodes",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_getSourceNodes",
    "access": "private",
    "description": "Discovers and browses the source nodes.",
    "lineNumber": 478,
    "params": [
      {
        "nullable": null,
        "types": [
          "Array<string, NodeId>"
        ],
        "spread": false,
        "optional": false,
        "name": "nodeIds",
        "description": "The source ids."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise<Node[]>"
      ],
      "spread": false,
      "description": "Resolved once finished."
    }
  },
  {
    "__docId__": 425,
    "kind": "method",
    "name": "browse",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "generator": false,
    "async": true,
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#browse",
    "access": "public",
    "description": "Starts the browser of the given nodes.",
    "lineNumber": 522,
    "params": [
      {
        "nullable": null,
        "types": [
          "NodeId[]"
        ],
        "spread": false,
        "optional": false,
        "name": "nodeIds",
        "description": "The nodes to browse."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise<any>"
      ],
      "spread": false,
      "description": "Resolved once all nodes are finished."
    }
  },
  {
    "__docId__": 426,
    "kind": "member",
    "name": "_sourceNodesRegExp",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_sourceNodesRegExp",
    "access": "private",
    "description": null,
    "lineNumber": 523,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 427,
    "kind": "member",
    "name": "_session",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_session",
    "access": "private",
    "description": null,
    "lineNumber": 527,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 428,
    "kind": "member",
    "name": "_reject",
    "memberof": "src/lib/server/NodeBrowser.js~NodeBrowser",
    "static": false,
    "longname": "src/lib/server/NodeBrowser.js~NodeBrowser#_reject",
    "access": "private",
    "description": null,
    "lineNumber": 535,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 429,
    "kind": "file",
    "name": "src/lib/server/NodeStream.js",
    "content": "import { Readable } from 'stream';\nimport Logger from 'gulplog';\nimport Project from '../../config/ProjectConfig';\nimport NodeBrowser from './NodeBrowser';\n\n/**\n * A stream of server nodes.\n */\nexport default class NodeStream extends Readable {\n  /**\n   * Creates new node stream.\n   * @param {NodeId[]} nodesToBrowse The nodes to browse.\n   * @param {Object} [options] The options to use.\n   * @param {boolean} [options.recursive] If the stream should recurse child nodes.\n   * @param {NodeId[]} [options.ignoreNodes] The nodes to ignore.\n   */\n  constructor(nodesToBrowse, options = {}) {\n    if (!nodesToBrowse || !(nodesToBrowse instanceof Array) || nodesToBrowse.length === 0) {\n      throw new Error('nodesToBrowse is required');\n    }\n\n    if (options && options.ignoreNodes && !(options.ignoreNodes instanceof Array)) {\n      throw new Error('ignoreNodes must be an array of node ids');\n    }\n\n    super(Object.assign({}, options, { objectMode: true }));\n\n    // Handle options\n    /**\n     * If the discovered nodes should be browsed as well.\n     * @type {Boolean}\n     */\n    this.recursive = true;\n    if (options.recursive !== undefined) {\n      this.recursive = options.recursive;\n    }\n\n    let ignoreNodes = Project.ignoreNodes;\n    if (options.ignoreNodes !== undefined) {\n      ignoreNodes = options.ignoreNodes;\n    }\n\n    /**\n     * The timestamp when the stream started.\n     * @type {number}\n     */\n    this._start = Date.now();\n\n    const nodes = nodesToBrowse.filter((nodeId) => {\n      // FIXME: Move to node browser and implement\n      const ignored = false && this.isIgnored({ nodeId });\n\n      if (ignored) {\n        Logger.warn(`${nodeId} is set to be browsed, but ignored.`);\n        Logger.info(` - Remove ${nodeId} from Atviseproject#nodes if this is intentionally.`);\n      }\n\n      return !ignored;\n    });\n\n    if (!nodes.length) {\n      throw new Error('Nothing to browse');\n    }\n\n    /**\n     * If the stream is destroyed.\n     * @type {boolean}\n     */\n    this._isDestroyed = false;\n\n    // Write nodes to read\n\n    /**\n     * The stream's browser\n     * @type {NodeBrowser}\n     */\n    this._browser = new NodeBrowser({\n      nodes,\n      ignoreNodes,\n      recursive: options.recursive === undefined ? true : options.recursive,\n    });\n\n    this._browser.onNode = (node) => {\n      if (node.nodeId.match(/\\s$/)) {\n        Logger.warn(`Node '${node.nodeId}' has trailing spaces in it's name.`);\n        Logger.info(' - Rename it to prevent errors on windows.');\n      }\n      if (!this.push(node)) {\n        this._browser.stop();\n      }\n    };\n\n    this._browser.onEnd = () => {\n      this.push(null);\n      this.destroy();\n    };\n\n    this._browser.onError = (err) => {\n      if (this.isDestroyed) {\n        return;\n      }\n      this.emit('error', err);\n      this.destroy();\n    };\n  }\n\n  /**\n   * If the stream is destoyed.\n   * @type {boolean}\n   */\n  get isDestroyed() {\n    return this._isDestroyed;\n  }\n\n  /**\n   * Starts the browser.\n   */\n  _read() {\n    this._browser.start();\n  }\n\n  /**\n   * Destroys the stream.\n   * @param {?Error} err The error that caused the destroy.\n   * @param {function(err: ?Error): void} callback Called once finished.\n   */\n  _destroy(err, callback) {\n    this._isDestroyed = true;\n\n    super.destroy(err, () => {\n      this._browser\n        .destroy()\n        .then(() => callback(err))\n        .catch((destroyErr) => callback(err || destroyErr));\n    });\n  }\n\n  /**\n   * The number of processed nodes.\n   * @type {number}\n   */\n  get processed() {\n    return this._browser._pushed.size;\n  }\n\n  /**\n   * The number of processed chunks per second.\n   * @type {number}\n   */\n  get opsPerSecond() {\n    return this.processed / ((Date.now() - this._start) / 1000) || 0;\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/server/NodeStream.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 430,
    "kind": "class",
    "name": "NodeStream",
    "memberof": "src/lib/server/NodeStream.js",
    "static": true,
    "longname": "src/lib/server/NodeStream.js~NodeStream",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/NodeStream.js",
    "importStyle": "NodeStream",
    "description": "A stream of server nodes.",
    "lineNumber": 9,
    "interface": false,
    "extends": [
      "stream~Readable"
    ]
  },
  {
    "__docId__": 431,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/server/NodeStream.js~NodeStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/NodeStream.js~NodeStream#constructor",
    "access": "public",
    "description": "Creates new node stream.",
    "lineNumber": 17,
    "params": [
      {
        "nullable": null,
        "types": [
          "NodeId[]"
        ],
        "spread": false,
        "optional": false,
        "name": "nodesToBrowse",
        "description": "The nodes to browse."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": true,
        "name": "options",
        "description": "The options to use."
      },
      {
        "nullable": null,
        "types": [
          "boolean"
        ],
        "spread": false,
        "optional": true,
        "name": "options.recursive",
        "description": "If the stream should recurse child nodes."
      },
      {
        "nullable": null,
        "types": [
          "NodeId[]"
        ],
        "spread": false,
        "optional": true,
        "name": "options.ignoreNodes",
        "description": "The nodes to ignore."
      }
    ]
  },
  {
    "__docId__": 432,
    "kind": "member",
    "name": "recursive",
    "memberof": "src/lib/server/NodeStream.js~NodeStream",
    "static": false,
    "longname": "src/lib/server/NodeStream.js~NodeStream#recursive",
    "access": "public",
    "description": "If the discovered nodes should be browsed as well.",
    "lineNumber": 33,
    "type": {
      "nullable": null,
      "types": [
        "Boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 434,
    "kind": "member",
    "name": "_start",
    "memberof": "src/lib/server/NodeStream.js~NodeStream",
    "static": false,
    "longname": "src/lib/server/NodeStream.js~NodeStream#_start",
    "access": "private",
    "description": "The timestamp when the stream started.",
    "lineNumber": 47,
    "type": {
      "nullable": null,
      "types": [
        "number"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 435,
    "kind": "member",
    "name": "_isDestroyed",
    "memberof": "src/lib/server/NodeStream.js~NodeStream",
    "static": false,
    "longname": "src/lib/server/NodeStream.js~NodeStream#_isDestroyed",
    "access": "private",
    "description": "If the stream is destroyed.",
    "lineNumber": 69,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 436,
    "kind": "member",
    "name": "_browser",
    "memberof": "src/lib/server/NodeStream.js~NodeStream",
    "static": false,
    "longname": "src/lib/server/NodeStream.js~NodeStream#_browser",
    "access": "private",
    "description": "The stream's browser",
    "lineNumber": 77,
    "type": {
      "nullable": null,
      "types": [
        "NodeBrowser"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 437,
    "kind": "get",
    "name": "isDestroyed",
    "memberof": "src/lib/server/NodeStream.js~NodeStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/NodeStream.js~NodeStream#isDestroyed",
    "access": "public",
    "description": "If the stream is destoyed.",
    "lineNumber": 111,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 438,
    "kind": "method",
    "name": "_read",
    "memberof": "src/lib/server/NodeStream.js~NodeStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/NodeStream.js~NodeStream#_read",
    "access": "private",
    "description": "Starts the browser.",
    "lineNumber": 118,
    "params": [],
    "return": null
  },
  {
    "__docId__": 439,
    "kind": "method",
    "name": "_destroy",
    "memberof": "src/lib/server/NodeStream.js~NodeStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/NodeStream.js~NodeStream#_destroy",
    "access": "private",
    "description": "Destroys the stream.",
    "lineNumber": 127,
    "params": [
      {
        "nullable": true,
        "types": [
          "Error"
        ],
        "spread": false,
        "optional": false,
        "name": "err",
        "description": "The error that caused the destroy."
      },
      {
        "nullable": null,
        "types": [
          "function(err: ?Error): void"
        ],
        "spread": false,
        "optional": false,
        "name": "callback",
        "description": "Called once finished."
      }
    ],
    "return": null
  },
  {
    "__docId__": 441,
    "kind": "get",
    "name": "processed",
    "memberof": "src/lib/server/NodeStream.js~NodeStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/NodeStream.js~NodeStream#processed",
    "access": "public",
    "description": "The number of processed nodes.",
    "lineNumber": 142,
    "type": {
      "nullable": null,
      "types": [
        "number"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 442,
    "kind": "get",
    "name": "opsPerSecond",
    "memberof": "src/lib/server/NodeStream.js~NodeStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/NodeStream.js~NodeStream#opsPerSecond",
    "access": "public",
    "description": "The number of processed chunks per second.",
    "lineNumber": 150,
    "type": {
      "nullable": null,
      "types": [
        "number"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 443,
    "kind": "file",
    "name": "src/lib/server/QueueStream.js",
    "content": "/* Needed as long as https://github.com/gajus/eslint-plugin-jsdoc/issues/56 is open */\n/* eslint-disable jsdoc/check-param-names */\n\nimport { StatusCodes } from 'node-opcua/lib/datamodel/opcua_status_code';\nimport Logger from 'gulplog';\nimport Stream from './Stream';\n\n/**\n * A stream that process atvise server requests in parallel.\n * @abstract\n */\nexport default class QueueStream extends Stream {\n  /**\n   * Creates a new QueueStream with the given options.\n   * @param {Object} [options] The options to use.\n   * @param {number} [options.maxParallel] The maximum of parallel tasks to execute.\n   */\n  constructor(options = {}) {\n    const maxParallel = options.maxParallel || 250;\n    super(Object.assign(options, { highWaterMark: maxParallel }));\n\n    /**\n     * The number of running operations.\n     * @type {Number}\n     */\n    this._processing = 0;\n\n    /**\n     * The number of chunks processed so far.\n     * @type {Number}\n     */\n    this._processed = 0;\n\n    /**\n     * The queued chunks.\n     * @type {*[]}\n     */\n    this._queued = [];\n\n    /**\n     * The maximum of parallel tasks to execute\n     * @type {number}\n     */\n    this._maxParallel = maxParallel;\n\n    /**\n     * The timestamp of the date when the stream was created.\n     * @type {Number}\n     */\n    this._start = new Date().getTime();\n\n    this.on('processed-chunk', () => {\n      if (!this.queueEmpty) {\n        this._processChunk(this._queued.shift());\n      } else if (this._processing === 0) {\n        this.emit('drained');\n      }\n    });\n  }\n\n  /**\n   * `true` if there are queued operations or an operation is running right now.\n   * @type {boolean}\n   */\n  get hasPending() {\n    return this._processing > 0 || this._queued.length > 0;\n  }\n\n  /**\n   * `true` if there are no queued operations.\n   * @type {boolean}\n   */\n  get queueEmpty() {\n    return this._queued.length === 0;\n  }\n\n  /**\n   * The number of chunks already processed.\n   * @type {number}\n   */\n  get processed() {\n    return this._processed;\n  }\n\n  /**\n   * The number of processed chunks per second.\n   * @type {number}\n   */\n  get opsPerSecond() {\n    return this._processed / ((new Date().getTime() - this._start) / 1000) || 0;\n  }\n\n  /**\n   * The error message to use when processing a chunk fails. **Must be overridden by all\n   * subclasses!**.\n   * @param {*} chunk The chunk being processed.\n   * @return {string} The error message to use.\n   * @abstract\n   */\n  // eslint-disable-next-line no-unused-vars\n  processErrorMessage(chunk) {\n    throw new Error('QueueStream#processErrorMessage must be implemented by all subclasses');\n  }\n\n  /**\n   * The function to call when a chunk is ready to be processed. **Must be overridden by all\n   * subclasses.**.\n   * @param {*} chunk The chunk to process.\n   * @param {function(err: Error, statusCode: node-opcua~StatusCodes, onSuccess: function)}\n   * handleErrors Call this function to handle errors and bad status codes. When no error occured\n   * and the status code received is fine, `onSuccess` is called. Further processing of valid\n   * chunks, for example Recursions should happen in `onSuccess`. **Note that `onSuccess` is an\n   * asynchronous function with a callback as an argument.**.\n   * @example <caption>Basic implementation</caption>\n   * class MyQueueStream extends QueueStream {\n   *   ...\n   *   processChunk(chunk, handle) {\n   *     client.session.doSomething((err, result, statusCode) => handle(err, statusCode, done => {\n   *       // This is called if err is falsy and status code is node-opcua~StatusCodes.Good\n   *       doSomethingWith(result);\n   *       done();\n   *     }));\n   *   }\n   *   ...\n   * }\n   * @example <caption>Implement a recursion</caption>\n   * class RecursiveQueueStream extends QueueStream {\n   *   ...\n   *   processChunk(chunk, handle) {\n   *     client.session.doSomething((err, result, statusCode) => handle(err, statusCode, done => {\n   *       // Write the result back to the stream.\n   *       // This means, that `result` will be queued and, as soon as possible, #processChunk will\n   *       // be called with `result` as the `chunk` argument.\n   *       this.write(result, null, done);\n   *     }));\n   *   }\n   *   ...\n   * }\n   * @example <caption>Allowing some invalid status codes</caption>\n   * import { StatusCodes } from 'node-opcua';\n   *\n   * class FriendlyQueueStream extends QueueStream {\n   *   ...\n   *   processChunk(chunk, handle) {\n   *     client.session.doSomething((err, result, statusCode) => {\n   *       if (statusCode === StatusCodes.BadUserAccessDenied) {\n   *         Logger.warn(`Ignored invalid status: ${statusCode.description}`);\n   *         handle(err, StatusCodes.Good, done => done());\n   *       } else {\n   *         handle(err, statusCode, done => done());\n   *       }\n   *     });\n   *   }\n   *   ...\n   * }\n   * @abstract\n   */\n  processChunk(chunk, handleErrors) {\n    // eslint-disable-line no-unused-vars\n    handleErrors(new Error('QueueStream#processChunk must be implemented by all subclasses'));\n  }\n\n  /**\n   * Calls {@link QueueStream#processChunk} and handles errors and invalid status codes.\n   * @param {*} chunk The chunk to process.\n   * @emits {*} Emits a `processed-chunk` event once a chunk was processed.\n   */\n  _processChunk(chunk) {\n    this._processing++;\n\n    this.processChunk(chunk, (err, statusCode, onSuccess) => {\n      const finished = (error) => {\n        this._processing--;\n        this._processed++;\n        this.emit('processed-chunk', chunk, error);\n      };\n\n      let error = err;\n\n      if (err) {\n        const message = `${this.processErrorMessage(chunk)}: ${err.message}`;\n\n        if (process.env.CONTINUE_ON_FAILURE === 'true') {\n          Logger.error(`FAILURE: ${message}`);\n        } else {\n          this.emit('error', Object.assign(err, { message }));\n        }\n      } else if (statusCode !== StatusCodes.Good) {\n        const message = `${this.processErrorMessage(chunk)}: ${statusCode.description}`;\n        error = new Error(message);\n\n        if (process.env.CONTINUE_ON_FAILURE === 'true') {\n          Logger.error(`FAILURE: ${message}`);\n        } else {\n          this.emit('error', new Error(message));\n        }\n      } else {\n        onSuccess(finished);\n        return;\n      }\n\n      finished(error);\n    });\n  }\n\n  /**\n   * Enqueues the given chunk for processing.\n   * @param {*} chunk The chunk to enqueue.\n   */\n  _enqueueChunk(chunk) {\n    if (this._processing < this._maxParallel) {\n      this._processChunk(chunk);\n    } else {\n      this._queued.push(chunk);\n    }\n  }\n\n  /**\n   * Calls {@link QueueStream#_enqueueChunk} as soon as the stream's session is opened.\n   * @param {*} chunk The chunk to transform.\n   * @param {string} enc The encoding used.\n   * @param {Function} callback Called once the chunk has been enqueued.\n   */\n  _transform(chunk, enc, callback) {\n    if (this.session) {\n      this._enqueueChunk(chunk);\n      callback();\n    } else {\n      this.once('session-open', () => {\n        this._enqueueChunk(chunk);\n        callback();\n      });\n    }\n  }\n\n  /**\n   * Waits for pending operations to complete.\n   * @param {Function} callback Called once all queued chunks have been processed.\n   */\n  _flush(callback) {\n    if (this.hasPending) {\n      this.once('drained', () => {\n        super._flush(callback);\n      });\n    } else {\n      super._flush(callback);\n    }\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/server/QueueStream.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 444,
    "kind": "class",
    "name": "QueueStream",
    "memberof": "src/lib/server/QueueStream.js",
    "static": true,
    "longname": "src/lib/server/QueueStream.js~QueueStream",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/QueueStream.js",
    "importStyle": "QueueStream",
    "description": "A stream that process atvise server requests in parallel.",
    "lineNumber": 12,
    "abstract": true,
    "interface": false,
    "extends": [
      "src/lib/server/Stream.js~Stream"
    ]
  },
  {
    "__docId__": 445,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/server/QueueStream.js~QueueStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/QueueStream.js~QueueStream#constructor",
    "access": "public",
    "description": "Creates a new QueueStream with the given options.",
    "lineNumber": 18,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": true,
        "name": "options",
        "description": "The options to use."
      },
      {
        "nullable": null,
        "types": [
          "number"
        ],
        "spread": false,
        "optional": true,
        "name": "options.maxParallel",
        "description": "The maximum of parallel tasks to execute."
      }
    ]
  },
  {
    "__docId__": 446,
    "kind": "member",
    "name": "_processing",
    "memberof": "src/lib/server/QueueStream.js~QueueStream",
    "static": false,
    "longname": "src/lib/server/QueueStream.js~QueueStream#_processing",
    "access": "private",
    "description": "The number of running operations.",
    "lineNumber": 26,
    "type": {
      "nullable": null,
      "types": [
        "Number"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 447,
    "kind": "member",
    "name": "_processed",
    "memberof": "src/lib/server/QueueStream.js~QueueStream",
    "static": false,
    "longname": "src/lib/server/QueueStream.js~QueueStream#_processed",
    "access": "private",
    "description": "The number of chunks processed so far.",
    "lineNumber": 32,
    "type": {
      "nullable": null,
      "types": [
        "Number"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 448,
    "kind": "member",
    "name": "_queued",
    "memberof": "src/lib/server/QueueStream.js~QueueStream",
    "static": false,
    "longname": "src/lib/server/QueueStream.js~QueueStream#_queued",
    "access": "private",
    "description": "The queued chunks.",
    "lineNumber": 38,
    "type": {
      "nullable": null,
      "types": [
        "*[]"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 449,
    "kind": "member",
    "name": "_maxParallel",
    "memberof": "src/lib/server/QueueStream.js~QueueStream",
    "static": false,
    "longname": "src/lib/server/QueueStream.js~QueueStream#_maxParallel",
    "access": "private",
    "description": "The maximum of parallel tasks to execute",
    "lineNumber": 44,
    "type": {
      "nullable": null,
      "types": [
        "number"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 450,
    "kind": "member",
    "name": "_start",
    "memberof": "src/lib/server/QueueStream.js~QueueStream",
    "static": false,
    "longname": "src/lib/server/QueueStream.js~QueueStream#_start",
    "access": "private",
    "description": "The timestamp of the date when the stream was created.",
    "lineNumber": 50,
    "type": {
      "nullable": null,
      "types": [
        "Number"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 451,
    "kind": "get",
    "name": "hasPending",
    "memberof": "src/lib/server/QueueStream.js~QueueStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/QueueStream.js~QueueStream#hasPending",
    "access": "public",
    "description": "`true` if there are queued operations or an operation is running right now.",
    "lineNumber": 65,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 452,
    "kind": "get",
    "name": "queueEmpty",
    "memberof": "src/lib/server/QueueStream.js~QueueStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/QueueStream.js~QueueStream#queueEmpty",
    "access": "public",
    "description": "`true` if there are no queued operations.",
    "lineNumber": 73,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 453,
    "kind": "get",
    "name": "processed",
    "memberof": "src/lib/server/QueueStream.js~QueueStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/QueueStream.js~QueueStream#processed",
    "access": "public",
    "description": "The number of chunks already processed.",
    "lineNumber": 81,
    "type": {
      "nullable": null,
      "types": [
        "number"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 454,
    "kind": "get",
    "name": "opsPerSecond",
    "memberof": "src/lib/server/QueueStream.js~QueueStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/QueueStream.js~QueueStream#opsPerSecond",
    "access": "public",
    "description": "The number of processed chunks per second.",
    "lineNumber": 89,
    "type": {
      "nullable": null,
      "types": [
        "number"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 455,
    "kind": "method",
    "name": "processErrorMessage",
    "memberof": "src/lib/server/QueueStream.js~QueueStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/QueueStream.js~QueueStream#processErrorMessage",
    "access": "public",
    "description": "The error message to use when processing a chunk fails. **Must be overridden by all\nsubclasses!**.",
    "lineNumber": 101,
    "params": [
      {
        "nullable": null,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "chunk",
        "description": "The chunk being processed."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": "The error message to use."
    },
    "abstract": true
  },
  {
    "__docId__": 456,
    "kind": "method",
    "name": "processChunk",
    "memberof": "src/lib/server/QueueStream.js~QueueStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/QueueStream.js~QueueStream#processChunk",
    "access": "public",
    "description": "The function to call when a chunk is ready to be processed. **Must be overridden by all\nsubclasses.**.",
    "examples": [
      "<caption>Basic implementation</caption>\nclass MyQueueStream extends QueueStream {\n  ...\n  processChunk(chunk, handle) {\n    client.session.doSomething((err, result, statusCode) => handle(err, statusCode, done => {\n      // This is called if err is falsy and status code is node-opcua~StatusCodes.Good\n      doSomethingWith(result);\n      done();\n    }));\n  }\n  ...\n}",
      "<caption>Implement a recursion</caption>\nclass RecursiveQueueStream extends QueueStream {\n  ...\n  processChunk(chunk, handle) {\n    client.session.doSomething((err, result, statusCode) => handle(err, statusCode, done => {\n      // Write the result back to the stream.\n      // This means, that `result` will be queued and, as soon as possible, #processChunk will\n      // be called with `result` as the `chunk` argument.\n      this.write(result, null, done);\n    }));\n  }\n  ...\n}",
      "<caption>Allowing some invalid status codes</caption>\nimport { StatusCodes } from 'node-opcua';\n\nclass FriendlyQueueStream extends QueueStream {\n  ...\n  processChunk(chunk, handle) {\n    client.session.doSomething((err, result, statusCode) => {\n      if (statusCode === StatusCodes.BadUserAccessDenied) {\n        Logger.warn(`Ignored invalid status: ${statusCode.description}`);\n        handle(err, StatusCodes.Good, done => done());\n      } else {\n        handle(err, statusCode, done => done());\n      }\n    });\n  }\n  ...\n}"
    ],
    "lineNumber": 158,
    "params": [
      {
        "nullable": null,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "chunk",
        "description": "The chunk to process."
      },
      {
        "nullable": null,
        "types": [
          "function(err: Error, statusCode: node-opcua~StatusCodes, onSuccess: function)"
        ],
        "spread": false,
        "optional": false,
        "name": "handleErrors",
        "description": "Call this function to handle errors and bad status codes. When no error occured\nand the status code received is fine, `onSuccess` is called. Further processing of valid\nchunks, for example Recursions should happen in `onSuccess`. **Note that `onSuccess` is an\nasynchronous function with a callback as an argument.**."
      }
    ],
    "abstract": true,
    "return": null
  },
  {
    "__docId__": 457,
    "kind": "method",
    "name": "_processChunk",
    "memberof": "src/lib/server/QueueStream.js~QueueStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/QueueStream.js~QueueStream#_processChunk",
    "access": "private",
    "description": "Calls {@link QueueStream#processChunk} and handles errors and invalid status codes.",
    "lineNumber": 168,
    "params": [
      {
        "nullable": null,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "chunk",
        "description": "The chunk to process."
      }
    ],
    "emits": [
      {
        "types": [
          "*"
        ],
        "description": "Emits a `processed-chunk` event once a chunk was processed."
      }
    ],
    "return": null
  },
  {
    "__docId__": 458,
    "kind": "method",
    "name": "_enqueueChunk",
    "memberof": "src/lib/server/QueueStream.js~QueueStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/QueueStream.js~QueueStream#_enqueueChunk",
    "access": "private",
    "description": "Enqueues the given chunk for processing.",
    "lineNumber": 210,
    "params": [
      {
        "nullable": null,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "chunk",
        "description": "The chunk to enqueue."
      }
    ],
    "return": null
  },
  {
    "__docId__": 459,
    "kind": "method",
    "name": "_transform",
    "memberof": "src/lib/server/QueueStream.js~QueueStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/QueueStream.js~QueueStream#_transform",
    "access": "private",
    "description": "Calls {@link QueueStream#_enqueueChunk} as soon as the stream's session is opened.",
    "lineNumber": 224,
    "params": [
      {
        "nullable": null,
        "types": [
          "*"
        ],
        "spread": false,
        "optional": false,
        "name": "chunk",
        "description": "The chunk to transform."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "enc",
        "description": "The encoding used."
      },
      {
        "nullable": null,
        "types": [
          "Function"
        ],
        "spread": false,
        "optional": false,
        "name": "callback",
        "description": "Called once the chunk has been enqueued."
      }
    ],
    "return": null
  },
  {
    "__docId__": 460,
    "kind": "method",
    "name": "_flush",
    "memberof": "src/lib/server/QueueStream.js~QueueStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/QueueStream.js~QueueStream#_flush",
    "access": "private",
    "description": "Waits for pending operations to complete.",
    "lineNumber": 240,
    "params": [
      {
        "nullable": null,
        "types": [
          "Function"
        ],
        "spread": false,
        "optional": false,
        "name": "callback",
        "description": "Called once all queued chunks have been processed."
      }
    ],
    "return": null
  },
  {
    "__docId__": 461,
    "kind": "file",
    "name": "src/lib/server/Session.js",
    "content": "import { join } from 'path';\nimport Emitter from 'events';\nimport { StatusCodes } from 'node-opcua/lib/datamodel/opcua_status_code';\nimport { OPCUAClient, ClientSession } from 'node-opcua/lib/client/opcua_client';\nimport Logger from 'gulplog';\nimport ProjectConfig from '../../config/ProjectConfig';\nimport { promisified } from '../helpers/async';\n\n/**\n * The currently open sessions.\n * @type {Set<node-opcua~ClientSession>}\n */\nconst openSessions = new Set();\n\n/**\n * The sessions currentyl being opened.\n * @type {Set<node-opcua~ClientSession>}\n */\nconst openingSessions = new Set();\n\n/**\n * A wrapper around {@link node-opcua~ClientSession} used to connect to atvise server.\n * The sessions currentyl being opened.\n * @type {Set<node-opcua~ClientSession>}\n */\nexport default class Session {\n  /**\n   * Creates an {@link node-opcuaOPCUAClient} and opens a new  {@link node-opcua~ClientSession}.\n   * @return {Promise<node-opcua~ClientSession, Error>} Fulfilled with an already opened\n   * {@link node-opcua~ClientSession}.\n   */\n  static async _create() {\n    const client = new OPCUAClient({\n      requestedSessionTimeout: 600000,\n      keepSessionAlive: true,\n      certificateFile: join(__dirname, '../../../res/certificates/certificate.pem'),\n      privateKeyFile: join(__dirname, '../../../res/certificates/key.pem'),\n    });\n\n    const endpoint = `opc.tcp://${ProjectConfig.host}:${ProjectConfig.port.opc}`;\n\n    const timer = setTimeout(() => {\n      Logger.warn(`It takes unusually long to connect to the atvise server at ${endpoint}.\n - Are you sure it is running?`);\n    }, ProjectConfig.timeout);\n\n    await promisified((cb) => client.connect(endpoint, cb));\n    Logger.debug(`Connected to ${endpoint}`);\n    clearTimeout(timer);\n\n    const session = await promisified((cb) =>\n      client.createSession(\n        {\n          userName: ProjectConfig.login.username,\n          password: ProjectConfig.login.password,\n        },\n        cb\n      )\n    ).catch((err) => {\n      if (\n        [\n          'userName === null || typeof userName === \"string\"',\n          'password === null || typeof password === \"string\"',\n        ].includes(err.message) ||\n        (err.response &&\n          err.response.responseHeader.serviceResult === StatusCodes.BadUserAccessDenied)\n      ) {\n        throw new Error('Unable to create session: Invalid login');\n      }\n\n      throw err;\n    });\n\n    openSessions.add(session);\n    return Object.assign(session, { _emitter: new Emitter() });\n  }\n\n  /**\n   * Creates an {@link node-opcuaOPCUAClient} and opens a new  {@link node-opcua~ClientSession}. If\n   * pooling is active, the shared session will be reused.\n   * @return {Promise<node-opcua~ClientSession, Error>} Fulfilled with an already opened\n   * {@link node-opcua~ClientSession}.\n   */\n  static create() {\n    const create = () => {\n      const c = this._create();\n      openingSessions.add(c);\n\n      return c.then((s) => openingSessions.delete(c) && s);\n    };\n\n    if (!this._pool) {\n      return create();\n    }\n\n    if (!this._createShared) {\n      /**\n       * A promise that resolves once the shared session is created.\n       * @type {Promise<node-opcua~ClientSession}\n       */\n      this._createShared = create();\n    }\n\n    return this._createShared;\n  }\n\n  // eslint-disable-next-line jsdoc/require-description-complete-sentence\n  /**\n   * Starts pooling (reusing) sessions. Note that you'll have to manually close sessions using\n   * {@link Session.closeOpen}.\n   */\n  static pool() {\n    /**\n     * If sessions should be reused.\n     * @type {boolean}\n     */\n    this._pool = true;\n  }\n\n  /**\n   * Closes the given session. Waits for currently opening sessions to open.\n   * @param {node-opcua~ClientSession} session The session to close.\n   * @return {Promise<node-opcua~ClientSession, Error>} Fulfilled with the (now closed!) session or\n   * rejected with the error that occured while closing.\n   */\n  static async _close(session) {\n    openSessions.delete(session);\n\n    await new Promise((resolve) => session.close(true, () => resolve()));\n    await new Promise((resolve) => session._client && session._client.disconnect(() => resolve()));\n\n    return session;\n  }\n\n  /**\n   * Closes the given session. When session pooling is active the session won't actually be closed\n   * and the returned Promise will resolve immediately.\n   * @param {node-opcua~ClientSession} session The session to close.\n   * @return {Promise<node-opcua~ClientSession, Error>} Fulfilled with the (maybe closed) session or\n   * rejected with the error that occured while closing.\n   */\n  static close(session) {\n    if (!session || !(session instanceof ClientSession)) {\n      return Promise.reject(new Error('session is required'));\n    }\n\n    if (this._pool) {\n      return Promise.resolve();\n    }\n\n    return this._close(session);\n  }\n\n  /**\n   * The sessions currently open. Starting with version 1.0.0-beta.25 there will be one at most.\n   * @type {Session[]}\n   */\n  static get open() {\n    return Array.from(openSessions);\n  }\n\n  /**\n   * Closes all open sessions.\n   * @return {Promise<Error, Session[]>} Rejected with the error that occurred while closing the\n   * sessions or fulfilled with the (now closed) sessions affected.\n   */\n  static async closeOpen() {\n    await Promise.all(openingSessions);\n\n    return Promise.all(Array.from(openSessions).map((session) => this._close(session)));\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/server/Session.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 462,
    "kind": "variable",
    "name": "openSessions",
    "memberof": "src/lib/server/Session.js",
    "static": true,
    "longname": "src/lib/server/Session.js~openSessions",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/Session.js",
    "importStyle": null,
    "description": "The currently open sessions.",
    "lineNumber": 13,
    "type": {
      "nullable": null,
      "types": [
        "Set<node-opcua~ClientSession>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 463,
    "kind": "variable",
    "name": "openingSessions",
    "memberof": "src/lib/server/Session.js",
    "static": true,
    "longname": "src/lib/server/Session.js~openingSessions",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/Session.js",
    "importStyle": null,
    "description": "The sessions currentyl being opened.",
    "lineNumber": 19,
    "type": {
      "nullable": null,
      "types": [
        "Set<node-opcua~ClientSession>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 464,
    "kind": "class",
    "name": "Session",
    "memberof": "src/lib/server/Session.js",
    "static": true,
    "longname": "src/lib/server/Session.js~Session",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/Session.js",
    "importStyle": "Session",
    "description": "A wrapper around {@link node-opcua~ClientSession} used to connect to atvise server.\nThe sessions currentyl being opened.",
    "lineNumber": 26,
    "type": {
      "nullable": null,
      "types": [
        "Set<node-opcua~ClientSession>"
      ],
      "spread": false,
      "description": null
    },
    "interface": false
  },
  {
    "__docId__": 465,
    "kind": "method",
    "name": "_create",
    "memberof": "src/lib/server/Session.js~Session",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/lib/server/Session.js~Session._create",
    "access": "private",
    "description": "Creates an {@link node-opcuaOPCUAClient} and opens a new  {@link node-opcua~ClientSession}.",
    "lineNumber": 32,
    "return": {
      "nullable": null,
      "types": [
        "Promise<node-opcua~ClientSession, Error>"
      ],
      "spread": false,
      "description": "Fulfilled with an already opened\n{@link node-opcua~ClientSession}."
    },
    "params": []
  },
  {
    "__docId__": 466,
    "kind": "method",
    "name": "create",
    "memberof": "src/lib/server/Session.js~Session",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/Session.js~Session.create",
    "access": "public",
    "description": "Creates an {@link node-opcuaOPCUAClient} and opens a new  {@link node-opcua~ClientSession}. If\npooling is active, the shared session will be reused.",
    "lineNumber": 84,
    "return": {
      "nullable": null,
      "types": [
        "Promise<node-opcua~ClientSession, Error>"
      ],
      "spread": false,
      "description": "Fulfilled with an already opened\n{@link node-opcua~ClientSession}."
    },
    "params": []
  },
  {
    "__docId__": 467,
    "kind": "member",
    "name": "_createShared",
    "memberof": "src/lib/server/Session.js~Session",
    "static": true,
    "longname": "src/lib/server/Session.js~Session._createShared",
    "access": "private",
    "description": "A promise that resolves once the shared session is created.",
    "lineNumber": 101,
    "type": {
      "nullable": null,
      "types": [
        "Promise<node-opcua~ClientSession"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 468,
    "kind": "method",
    "name": "pool",
    "memberof": "src/lib/server/Session.js~Session",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/Session.js~Session.pool",
    "access": "public",
    "description": "Starts pooling (reusing) sessions. Note that you'll have to manually close sessions using\n{@link Session.closeOpen}.",
    "lineNumber": 112,
    "params": [],
    "return": null
  },
  {
    "__docId__": 469,
    "kind": "member",
    "name": "_pool",
    "memberof": "src/lib/server/Session.js~Session",
    "static": true,
    "longname": "src/lib/server/Session.js~Session._pool",
    "access": "private",
    "description": "If sessions should be reused.",
    "lineNumber": 117,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 470,
    "kind": "method",
    "name": "_close",
    "memberof": "src/lib/server/Session.js~Session",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/lib/server/Session.js~Session._close",
    "access": "private",
    "description": "Closes the given session. Waits for currently opening sessions to open.",
    "lineNumber": 126,
    "params": [
      {
        "nullable": null,
        "types": [
          "node-opcua~ClientSession"
        ],
        "spread": false,
        "optional": false,
        "name": "session",
        "description": "The session to close."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise<node-opcua~ClientSession, Error>"
      ],
      "spread": false,
      "description": "Fulfilled with the (now closed!) session or\nrejected with the error that occured while closing."
    }
  },
  {
    "__docId__": 471,
    "kind": "method",
    "name": "close",
    "memberof": "src/lib/server/Session.js~Session",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/Session.js~Session.close",
    "access": "public",
    "description": "Closes the given session. When session pooling is active the session won't actually be closed\nand the returned Promise will resolve immediately.",
    "lineNumber": 142,
    "params": [
      {
        "nullable": null,
        "types": [
          "node-opcua~ClientSession"
        ],
        "spread": false,
        "optional": false,
        "name": "session",
        "description": "The session to close."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise<node-opcua~ClientSession, Error>"
      ],
      "spread": false,
      "description": "Fulfilled with the (maybe closed) session or\nrejected with the error that occured while closing."
    }
  },
  {
    "__docId__": 472,
    "kind": "get",
    "name": "open",
    "memberof": "src/lib/server/Session.js~Session",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/Session.js~Session.open",
    "access": "public",
    "description": "The sessions currently open. Starting with version 1.0.0-beta.25 there will be one at most.",
    "lineNumber": 158,
    "type": {
      "nullable": null,
      "types": [
        "Session[]"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 473,
    "kind": "method",
    "name": "closeOpen",
    "memberof": "src/lib/server/Session.js~Session",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/lib/server/Session.js~Session.closeOpen",
    "access": "public",
    "description": "Closes all open sessions.",
    "lineNumber": 167,
    "return": {
      "nullable": null,
      "types": [
        "Promise<Error, Session[]>"
      ],
      "spread": false,
      "description": "Rejected with the error that occurred while closing the\nsessions or fulfilled with the (now closed) sessions affected."
    },
    "params": []
  },
  {
    "__docId__": 474,
    "kind": "file",
    "name": "src/lib/server/Stream.js",
    "content": "import { ctor as throughStreamClass } from 'through2';\nimport Session from './Session';\n\n/**\n * An object transform stream connected to atvise server.\n */\nexport default class Stream extends throughStreamClass({ objectMode: true }) {\n  /**\n   * Creates a new Stream and starts opening a new session to atvise server.\n   * @param {Object} [options] The options to use. See the through2 documentation for details.\n   * @param {boolean} [options.keepSessionAlive=false] If the ativse server session should be closed\n   * one the stream ends.\n   * @emits {Session} Emits an `session-open` event once the session is open, passing the Session\n   * instance.\n   * @see https://github.Com/rvagg/through2#options\n   */\n  constructor(options = {}) {\n    super(options);\n\n    /**\n     * `true` if the stream's atvise server session should be kept alive once the stream ends.\n     * @type {Boolean}\n     */\n    this._keepSessionAlive = options.keepSessionAlive || false;\n\n    Session.create()\n      .then((session) => (this.session = session))\n      .then((session) => this.emit('session-open', session))\n      .catch((err) => this.emit('error', err));\n  }\n\n  /**\n   * Called just before the stream is closed: Closes the open session.\n   * @param {function(err: ?Error, data: Object)} callback Called once the session is closed.\n   */\n  _flush(callback) {\n    if (this.session && !this._keepSessionAlive) {\n      Session.close(this.session)\n        .then(() => callback())\n        .catch((err) => callback(err));\n    } else {\n      callback();\n    }\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/server/Stream.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 475,
    "kind": "class",
    "name": "Stream",
    "memberof": "src/lib/server/Stream.js",
    "static": true,
    "longname": "src/lib/server/Stream.js~Stream",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/Stream.js",
    "importStyle": "Stream",
    "description": "An object transform stream connected to atvise server.",
    "lineNumber": 7,
    "interface": false,
    "expressionExtends": "throughStreamClass({ objectMode: true })"
  },
  {
    "__docId__": 476,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/server/Stream.js~Stream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/Stream.js~Stream#constructor",
    "access": "public",
    "description": "Creates a new Stream and starts opening a new session to atvise server.",
    "see": [
      "https://github.Com/rvagg/through2#options"
    ],
    "lineNumber": 17,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": true,
        "name": "options",
        "description": "The options to use. See the through2 documentation for details."
      },
      {
        "nullable": null,
        "types": [
          "boolean"
        ],
        "spread": false,
        "optional": true,
        "defaultValue": "false",
        "defaultRaw": false,
        "name": "options.keepSessionAlive",
        "description": "If the ativse server session should be closed\none the stream ends."
      }
    ],
    "emits": [
      {
        "types": [
          "Session"
        ],
        "description": "Emits an `session-open` event once the session is open, passing the Session\ninstance."
      }
    ]
  },
  {
    "__docId__": 477,
    "kind": "member",
    "name": "_keepSessionAlive",
    "memberof": "src/lib/server/Stream.js~Stream",
    "static": false,
    "longname": "src/lib/server/Stream.js~Stream#_keepSessionAlive",
    "access": "private",
    "description": "`true` if the stream's atvise server session should be kept alive once the stream ends.",
    "lineNumber": 24,
    "type": {
      "nullable": null,
      "types": [
        "Boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 478,
    "kind": "method",
    "name": "_flush",
    "memberof": "src/lib/server/Stream.js~Stream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/Stream.js~Stream#_flush",
    "access": "private",
    "description": "Called just before the stream is closed: Closes the open session.",
    "lineNumber": 36,
    "params": [
      {
        "nullable": null,
        "types": [
          "function(err: ?Error, data: Object)"
        ],
        "spread": false,
        "optional": false,
        "name": "callback",
        "description": "Called once the session is closed."
      }
    ],
    "return": null
  },
  {
    "__docId__": 479,
    "kind": "file",
    "name": "src/lib/server/Types.js",
    "content": "import { DataType } from 'node-opcua/lib/datamodel/variant';\nimport NodeId from '../model/opcua/NodeId';\n\n/**\n * Special, atvise releated OPC-UA type.\n */\nclass AtviseType {\n  /**\n   * Creates a new atvise type.\n   * @param {string} nodeIdValue The type's OPC-UA node id value.\n   * @param {string} identifier Atscm's identifier for the new type.\n   * @param {node-opcua~DataType} dataType The type's parent OPC-UA type.\n   * @param {string|boolean} [fileExtensionOrKeep] The file extension to use when storing or `true`\n   * or `false` indicating if the extension should be kept.\n   */\n  constructor(nodeIdValue, identifier, dataType, fileExtensionOrKeep) {\n    /**\n     * Node id of the type's definition\n     * @type {node-opcua~NodeId}\n     */\n    this.typeDefinition = new NodeId(`VariableTypes.ATVISE.${nodeIdValue}`);\n\n    /**\n     * Atscm's identifier for the type.\n     * @type {String}\n     */\n    this.identifier = identifier;\n    /**\n     * The type's parent OPC-UA type.\n     * @type {node-opcua~DataType}\n     */\n    this.dataType = dataType;\n    if (fileExtensionOrKeep !== undefined) {\n      if (typeof fileExtensionOrKeep === 'string') {\n        /**\n         * The file extension to use when storing.\n         * @type {String}\n         */\n        this.fileExtension = fileExtensionOrKeep;\n      } else {\n        /**\n         * If the extension should be kept when storing.\n         * @type {Boolean}\n         */\n        this.keepExtension = fileExtensionOrKeep;\n      }\n    }\n  }\n}\n\n/**\n * An atvise-related resource type.\n */\nexport class AtviseResourceType extends AtviseType {\n  /**\n   * Creates a new resource type.\n   * @param {string} name The type's OPC-UA node id value.\n   * @param {string} identifier Atscm's identifier for the new type.\n   */\n  constructor(name, identifier) {\n    super(`Resource.${name}`, identifier, DataType.ByteString, true);\n  }\n}\n\n/**\n * The atvise types to handle. **Ordering matters:** The {@link MappingTransformer} takes the first\n * match, therefore **plain types should always come before resource types!**\n * @type {AtviseType[]}\n */\nconst AtviseTypes = [\n  new AtviseType('HtmlHelp', 'help', DataType.ByteString, 'html'),\n  new AtviseType('QuickDynamic', 'qd', DataType.XmlElement),\n  new AtviseType('ScriptCode', 'script', DataType.XmlElement),\n  new AtviseType('Display', 'display', DataType.XmlElement),\n  new AtviseType('TranslationTable', 'locs', DataType.XmlElement),\n  new AtviseResourceType('Pdf', 'pdf'),\n  new AtviseResourceType('Html', 'html'),\n  new AtviseResourceType('Html', 'htm'),\n  new AtviseResourceType('Javascript', 'js'),\n  new AtviseResourceType('Wave', 'wav'),\n  new AtviseResourceType('Gif', 'gif'),\n  new AtviseResourceType('Png', 'png'),\n  new AtviseResourceType('Aac', 'm4a'),\n  new AtviseResourceType('Ogg', 'ogg'),\n  new AtviseResourceType('Icon', 'ico'),\n  new AtviseResourceType('Css', 'css'),\n  new AtviseResourceType('Svg', 'svg'),\n  new AtviseResourceType('Jpeg', 'jpg'),\n  new AtviseResourceType('OctetStream', '*'),\n];\n\nexport default AtviseTypes;\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/server/Types.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 480,
    "kind": "class",
    "name": "AtviseType",
    "memberof": "src/lib/server/Types.js",
    "static": true,
    "longname": "src/lib/server/Types.js~AtviseType",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/server/Types.js",
    "importStyle": null,
    "description": "Special, atvise releated OPC-UA type.",
    "lineNumber": 7,
    "interface": false,
    "ignore": true
  },
  {
    "__docId__": 481,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/server/Types.js~AtviseType",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/Types.js~AtviseType#constructor",
    "access": "public",
    "description": "Creates a new atvise type.",
    "lineNumber": 16,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "nodeIdValue",
        "description": "The type's OPC-UA node id value."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "identifier",
        "description": "Atscm's identifier for the new type."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~DataType"
        ],
        "spread": false,
        "optional": false,
        "name": "dataType",
        "description": "The type's parent OPC-UA type."
      },
      {
        "nullable": null,
        "types": [
          "string",
          "boolean"
        ],
        "spread": false,
        "optional": true,
        "name": "fileExtensionOrKeep",
        "description": "The file extension to use when storing or `true`\nor `false` indicating if the extension should be kept."
      }
    ]
  },
  {
    "__docId__": 482,
    "kind": "member",
    "name": "typeDefinition",
    "memberof": "src/lib/server/Types.js~AtviseType",
    "static": false,
    "longname": "src/lib/server/Types.js~AtviseType#typeDefinition",
    "access": "public",
    "description": "Node id of the type's definition",
    "lineNumber": 21,
    "type": {
      "nullable": null,
      "types": [
        "node-opcua~NodeId"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 483,
    "kind": "member",
    "name": "identifier",
    "memberof": "src/lib/server/Types.js~AtviseType",
    "static": false,
    "longname": "src/lib/server/Types.js~AtviseType#identifier",
    "access": "public",
    "description": "Atscm's identifier for the type.",
    "lineNumber": 27,
    "type": {
      "nullable": null,
      "types": [
        "String"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 484,
    "kind": "member",
    "name": "dataType",
    "memberof": "src/lib/server/Types.js~AtviseType",
    "static": false,
    "longname": "src/lib/server/Types.js~AtviseType#dataType",
    "access": "public",
    "description": "The type's parent OPC-UA type.",
    "lineNumber": 32,
    "type": {
      "nullable": null,
      "types": [
        "node-opcua~DataType"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 485,
    "kind": "member",
    "name": "fileExtension",
    "memberof": "src/lib/server/Types.js~AtviseType",
    "static": false,
    "longname": "src/lib/server/Types.js~AtviseType#fileExtension",
    "access": "public",
    "description": "The file extension to use when storing.",
    "lineNumber": 39,
    "type": {
      "nullable": null,
      "types": [
        "String"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 486,
    "kind": "member",
    "name": "keepExtension",
    "memberof": "src/lib/server/Types.js~AtviseType",
    "static": false,
    "longname": "src/lib/server/Types.js~AtviseType#keepExtension",
    "access": "public",
    "description": "If the extension should be kept when storing.",
    "lineNumber": 45,
    "type": {
      "nullable": null,
      "types": [
        "Boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 487,
    "kind": "class",
    "name": "AtviseResourceType",
    "memberof": "src/lib/server/Types.js",
    "static": true,
    "longname": "src/lib/server/Types.js~AtviseResourceType",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/Types.js",
    "importStyle": "{AtviseResourceType}",
    "description": "An atvise-related resource type.",
    "lineNumber": 54,
    "interface": false,
    "extends": [
      "AtviseType"
    ]
  },
  {
    "__docId__": 488,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/server/Types.js~AtviseResourceType",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/Types.js~AtviseResourceType#constructor",
    "access": "public",
    "description": "Creates a new resource type.",
    "lineNumber": 60,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "name",
        "description": "The type's OPC-UA node id value."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "identifier",
        "description": "Atscm's identifier for the new type."
      }
    ]
  },
  {
    "__docId__": 489,
    "kind": "variable",
    "name": "AtviseTypes",
    "memberof": "src/lib/server/Types.js",
    "static": true,
    "longname": "src/lib/server/Types.js~AtviseTypes",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/Types.js",
    "importStyle": "AtviseTypes",
    "description": "The atvise types to handle. **Ordering matters:** The {@link MappingTransformer} takes the first\nmatch, therefore **plain types should always come before resource types!**",
    "lineNumber": 70,
    "type": {
      "nullable": null,
      "types": [
        "AtviseType[]"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 490,
    "kind": "file",
    "name": "src/lib/server/WaitingStream.js",
    "content": "import Logger from 'gulplog';\nimport ProjectConfig from '../../config/ProjectConfig';\nimport QueueStream from './QueueStream';\n\n/**\n * A mixin that transforms a regular stream into a {@link WaitingStream}, which makes it wait for a\n * node's dependencies to be transformed.\n * @param {QueueStream} Stream The node stream to inherit from.\n * @return {Class<WaitingStream>} The resulting stream class.\n * @example <caption>Basic usage</caption>\n * import QueueStream from 'atscm/src/lib/server/QueueStream';\n * import { waitForDependencies } from 'atscm/src/lib/server/WaitingStream';\n *\n * class MyWaitingStream extends waitForDependencies(QueueStream) {\n *\n *   dependenciesFor(file) {\n *     return [\n *       // An array of node ids\n *     ];\n *   }\n *\n * }\n */\nexport const waitForDependencies = (Stream) =>\n  class Waiting extends Stream {\n    /**\n     * Creates a new WaitingStream.\n     * @param {Object} options Options passed to the underlying {@link Stream} subclass.\n     */\n    constructor(options = {}) {\n      super(options);\n\n      this._dependencies = {};\n      this._waitingFor = {};\n      this._finishedProcessing = {};\n\n      this.on('processed-chunk', (file) => {\n        const key = file.nodeId.toString();\n        const dependents = this._waitingFor[key];\n        delete this._waitingFor[key];\n        this._finishedProcessing[key] = true;\n\n        if (dependents) {\n          dependents.forEach((d) => {\n            const k = d.nodeId.toString();\n            this._dependencies[k] -= 1;\n\n            if (this._dependencies[k] === 0) {\n              super._enqueueChunk(d);\n              delete this._dependencies[k];\n            }\n          });\n        }\n\n        this.emit('finished-chunk');\n      });\n    }\n\n    /**\n     * **Must be implemented by all subclasses:** Returns the dependencies for a given file.\n     * @typedef {function(file: AtviseFile): NodeId[]} WWaiting#dependenciesFor\n     * @param {AtviseFile} file The file to get the dependencies for.\n     * @return {NodeId[]} The file's dependencies.\n     * @abstract\n     */\n    // eslint-disable-next-line no-unused-vars\n    dependenciesFor(file) {\n      throw new Error('#dependenciesFor must be implemented by all subclasses');\n    }\n\n    /**\n     * Enqueues a file after it's dependencies.\n     * @param {AtviseFile} file The file to process.\n     */\n    _enqueueChunk(file) {\n      const dependencies = this.dependenciesFor(file)\n        .filter((id) => {\n          if (id.namespace === 0 || !id.value || ProjectConfig.nodes.includes(id)) {\n            return false;\n          }\n\n          return (\n            !id.value.match(/^(Object|Variable)Types$/) &&\n            !id.value.match(/^(Object|Variable)Types\\.ATVISE/) &&\n            !id.value.match(/^SYSTEM\\.LIBRARY\\.ATVISE/)\n          );\n        })\n        .map((id) => id.toString());\n\n      if (dependencies && dependencies.length) {\n        const needToWait = dependencies.reduce((wait, dependency) => {\n          if (!this._finishedProcessing[dependency]) {\n            const name = file.nodeId.toString();\n\n            this._waitingFor[dependency] = (this._waitingFor[dependency] || []).concat(file);\n            this._dependencies[name] = (this._dependencies[name] || 0) + 1;\n\n            return true;\n          }\n          return wait;\n        }, false);\n\n        if (needToWait) {\n          return;\n        }\n      }\n\n      super._enqueueChunk(file);\n    }\n\n    /**\n     * Delays the streams end until all chunks have been processed.\n     * @param {function(err: Error)} callback Called once all chunks have been processed.\n     */\n    _flush(callback) {\n      const checkProcessing = () => {\n        if (this._processing || this.hasPending) {\n          this.once('finished-chunk', () => checkProcessing());\n        } else if (Object.keys(this._waitingFor).length > 0) {\n          const first = Object.keys(this._waitingFor)[0];\n\n          Logger.debug(`Missing dependency. Trying to process dependents of ${first}`);\n\n          this.once('finished-chunk', () => checkProcessing());\n          this.emit('processed-chunk', { nodeId: first });\n        } else {\n          super._flush(callback);\n        }\n      };\n\n      checkProcessing();\n    }\n  };\n\n/**\n * A {@link QueueStream} that waits for a file's dependencies to be processed before the file is\n * processed itself.\n * @abstract\n */\nexport default class WaitingStream extends waitForDependencies(QueueStream) {}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/server/WaitingStream.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 491,
    "kind": "function",
    "name": "waitForDependencies",
    "memberof": "src/lib/server/WaitingStream.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/server/WaitingStream.js~waitForDependencies",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/WaitingStream.js",
    "importStyle": "{waitForDependencies}",
    "description": "A mixin that transforms a regular stream into a {@link WaitingStream}, which makes it wait for a\nnode's dependencies to be transformed.",
    "examples": [
      "<caption>Basic usage</caption>\nimport QueueStream from 'atscm/src/lib/server/QueueStream';\nimport { waitForDependencies } from 'atscm/src/lib/server/WaitingStream';\n\nclass MyWaitingStream extends waitForDependencies(QueueStream) {\n\n  dependenciesFor(file) {\n    return [\n      // An array of node ids\n    ];\n  }\n\n}"
    ],
    "lineNumber": 24,
    "params": [
      {
        "nullable": null,
        "types": [
          "QueueStream"
        ],
        "spread": false,
        "optional": false,
        "name": "Stream",
        "description": "The node stream to inherit from."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Class<WaitingStream>"
      ],
      "spread": false,
      "description": "The resulting stream class."
    }
  },
  {
    "__docId__": 492,
    "kind": "typedef",
    "name": "WWaiting#dependenciesFor",
    "memberof": "src/lib/server/WaitingStream.js",
    "static": false,
    "longname": "src/lib/server/WaitingStream.js~WWaiting#dependenciesFor",
    "access": "public",
    "description": "**Must be implemented by all subclasses:** Returns the dependencies for a given file.",
    "lineNumber": 67,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file to get the dependencies for."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "NodeId[]"
      ],
      "spread": false,
      "description": "The file's dependencies."
    },
    "abstract": true,
    "type": {
      "types": [
        "function(file: AtviseFile): NodeId[]"
      ],
      "optional": false,
      "name": "WWaiting#dependenciesFor"
    }
  },
  {
    "__docId__": 493,
    "kind": "class",
    "name": "WaitingStream",
    "memberof": "src/lib/server/WaitingStream.js",
    "static": true,
    "longname": "src/lib/server/WaitingStream.js~WaitingStream",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/WaitingStream.js",
    "importStyle": "WaitingStream",
    "description": "A {@link QueueStream} that waits for a file's dependencies to be processed before the file is\nprocessed itself.",
    "lineNumber": 140,
    "abstract": true,
    "interface": false,
    "expressionExtends": "waitForDependencies(QueueStream)"
  },
  {
    "__docId__": 494,
    "kind": "file",
    "name": "src/lib/server/Watcher.js",
    "content": "/* eslint-plugin-jsdoc does not recognize the \"emits\" tag */\n/* eslint-disable jsdoc/check-tag-names */\n\n/* Needed as long as https://github.com/gajus/eslint-plugin-jsdoc/issues/56 is open */\n/* eslint-disable jsdoc/check-param-names */\n\nimport Emitter from 'events';\nimport { ClientSubscription } from 'node-opcua/lib/client/client_subscription';\nimport { AttributeIds } from 'node-opcua/lib/services/read_service';\nimport { NodeClass } from 'node-opcua/lib/datamodel/nodeclass';\nimport Logger from 'gulplog';\nimport ProjectConfig from '../../config/ProjectConfig';\nimport { reportProgress } from '../helpers/log';\nimport Session from './Session';\nimport NodeBrowser from './NodeBrowser';\n\n/**\n * Watches the given nodes for value changes.\n * @emit {ReadStream.ReadResult} Emits `change` events when a watched node changes.\n */\nexport default class Watcher extends Emitter {\n  /**\n   * Creates a new Watcher with the given nodes.\n   * @param {NodeId[]} nodes The nodes to watch (recursively).\n   */\n  constructor(nodes = ProjectConfig.nodesToWatch) {\n    super();\n\n    /**\n     * The browser used to subscribe to server nodes.\n     * @type {NodeBrowser}\n     */\n    this._nodeBrowser = new NodeBrowser({\n      handleNode: this._subscribe.bind(this),\n    });\n\n    reportProgress(this._nodeBrowser.browse(nodes), {\n      getter: () => this._nodeBrowser._pushed,\n      formatter: (count) => `Subscribed to ${count} nodes`,\n    })\n      .then(() => this.emit('ready'))\n      .catch((err) => this.emit('error', err));\n\n    /**\n     * Resolved once the server subscription is set up.\n     * @type {Promise<any>}\n     */\n    this.subscriptionStarted = this._setupSubscription().catch((err) => this.emit('error', err));\n  }\n\n  /**\n   * Initializes a server subscription.\n   * @return {Promise<node-opcua~ClientSubscription>} A setup subscription.\n   */\n  _setupSubscription() {\n    return Session.create().then(\n      (session) =>\n        new Promise((resolve, reject) => {\n          /** The current session, if connected @type {Session} */\n          this._session = session;\n\n          const subscription = new ClientSubscription(session, {\n            requestedPublishingInterval: 100,\n            requestedLifetimeCount: 1000,\n            requestedMaxKeepAliveCount: 12,\n            maxNotificationsPerPublish: 10,\n            publishingEnabled: true,\n            priority: 10,\n          });\n\n          subscription.on('started', () => resolve(subscription));\n          subscription.on('failure', (err) => reject(err));\n        })\n    );\n  }\n\n  /**\n   * Subscribes to value changes of a single node.\n   * @param {BrowsedNode} node A browsed node.\n   */\n  async _subscribe(node) {\n    if (node.nodeClass !== NodeClass.Variable) {\n      return undefined;\n    }\n    const subscription = await this.subscriptionStarted;\n\n    const nodeId = node.id;\n\n    const item = subscription.monitor(\n      {\n        nodeId,\n        attributeId: AttributeIds.Value,\n      },\n      {\n        clientHandle: 13,\n        samplingInterval: 250,\n        queueSize: 123,\n        discardOldest: true,\n      }\n    );\n\n    return new Promise((resolve, reject) => {\n      // Sometimes the changed event is not emitted...\n      // Fixes #202\n      const timeout = setTimeout(() => {\n        Logger.debug(`Error monitoring '${nodeId.value}': Did not receive initial value. Retry...`);\n\n        try {\n          item.terminate();\n        } catch (e) {\n          Logger.warn('Failed to terminate subscription', e);\n        }\n\n        return this._subscribe(node).then(resolve, reject);\n      }, 1000);\n\n      item.once('changed', () => {\n        clearTimeout(timeout);\n        item.on(\n          'changed',\n          this._handleChange.bind(this, {\n            nodeId,\n          })\n        );\n\n        resolve();\n      });\n      item.on('err', (err) => {\n        clearTimeout(timeout);\n        reject(err instanceof Error ? err : new Error(err));\n      });\n    }).catch((err) => {\n      throw Object.assign(err, { node });\n    });\n  }\n\n  /**\n   * Called once a change has been detected and emits a 'change' or 'delete' event.\n   * @param {Object} node The node that changed.\n   * @param {?node-opcua~Variant} dataValue The current value.\n   */\n  _handleChange({ nodeId }, dataValue) {\n    this.emit(dataValue.value ? 'change' : 'delete', {\n      // nodeClass,\n      nodeId,\n      value: dataValue.value,\n      mtime: dataValue.serverTimestamp,\n    });\n  }\n\n  /**\n   * Ends monitoring nodes.\n   */\n  close() {\n    if (this._session) {\n      Session.close(this._session).catch((err) => this.emit('error', err));\n    }\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/server/Watcher.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 495,
    "kind": "class",
    "name": "Watcher",
    "memberof": "src/lib/server/Watcher.js",
    "static": true,
    "longname": "src/lib/server/Watcher.js~Watcher",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/Watcher.js",
    "importStyle": "Watcher",
    "description": "Watches the given nodes for value changes.",
    "lineNumber": 21,
    "unknown": [
      {
        "tagName": "@emit",
        "tagValue": "{ReadStream.ReadResult} Emits `change` events when a watched node changes."
      }
    ],
    "interface": false,
    "extends": [
      "events~Emitter"
    ]
  },
  {
    "__docId__": 496,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/server/Watcher.js~Watcher",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/Watcher.js~Watcher#constructor",
    "access": "public",
    "description": "Creates a new Watcher with the given nodes.",
    "lineNumber": 26,
    "params": [
      {
        "nullable": null,
        "types": [
          "NodeId[]"
        ],
        "spread": false,
        "optional": false,
        "name": "nodes",
        "description": "The nodes to watch (recursively)."
      }
    ]
  },
  {
    "__docId__": 497,
    "kind": "member",
    "name": "_nodeBrowser",
    "memberof": "src/lib/server/Watcher.js~Watcher",
    "static": false,
    "longname": "src/lib/server/Watcher.js~Watcher#_nodeBrowser",
    "access": "private",
    "description": "The browser used to subscribe to server nodes.",
    "lineNumber": 33,
    "type": {
      "nullable": null,
      "types": [
        "NodeBrowser"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 498,
    "kind": "member",
    "name": "subscriptionStarted",
    "memberof": "src/lib/server/Watcher.js~Watcher",
    "static": false,
    "longname": "src/lib/server/Watcher.js~Watcher#subscriptionStarted",
    "access": "public",
    "description": "Resolved once the server subscription is set up.",
    "lineNumber": 48,
    "type": {
      "nullable": null,
      "types": [
        "Promise<any>"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 499,
    "kind": "method",
    "name": "_setupSubscription",
    "memberof": "src/lib/server/Watcher.js~Watcher",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/Watcher.js~Watcher#_setupSubscription",
    "access": "private",
    "description": "Initializes a server subscription.",
    "lineNumber": 55,
    "return": {
      "nullable": null,
      "types": [
        "Promise<node-opcua~ClientSubscription>"
      ],
      "spread": false,
      "description": "A setup subscription."
    },
    "params": []
  },
  {
    "__docId__": 500,
    "kind": "member",
    "name": "_session",
    "memberof": "src/lib/server/Watcher.js~Watcher",
    "static": false,
    "longname": "src/lib/server/Watcher.js~Watcher#_session",
    "access": "private",
    "description": "The current session, if connected @type {Session}",
    "lineNumber": 60,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 501,
    "kind": "method",
    "name": "_subscribe",
    "memberof": "src/lib/server/Watcher.js~Watcher",
    "generator": false,
    "async": true,
    "static": false,
    "longname": "src/lib/server/Watcher.js~Watcher#_subscribe",
    "access": "private",
    "description": "Subscribes to value changes of a single node.",
    "lineNumber": 81,
    "params": [
      {
        "nullable": null,
        "types": [
          "BrowsedNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "A browsed node."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 502,
    "kind": "method",
    "name": "_handleChange",
    "memberof": "src/lib/server/Watcher.js~Watcher",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/Watcher.js~Watcher#_handleChange",
    "access": "private",
    "description": "Called once a change has been detected and emits a 'change' or 'delete' event.",
    "lineNumber": 142,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The node that changed."
      },
      {
        "nullable": true,
        "types": [
          "node-opcua~Variant"
        ],
        "spread": false,
        "optional": false,
        "name": "dataValue",
        "description": "The current value."
      }
    ],
    "return": null
  },
  {
    "__docId__": 503,
    "kind": "method",
    "name": "close",
    "memberof": "src/lib/server/Watcher.js~Watcher",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/Watcher.js~Watcher#close",
    "access": "public",
    "description": "Ends monitoring nodes.",
    "lineNumber": 154,
    "params": [],
    "return": null
  },
  {
    "__docId__": 504,
    "kind": "file",
    "name": "src/lib/server/WriteStream.js",
    "content": "/* Needed as long as https://github.com/gajus/eslint-plugin-jsdoc/issues/56 is open */\n/* eslint-disable jsdoc/check-param-names */\n\nimport Logger from 'gulplog';\nimport { StatusCodes } from 'node-opcua/lib/datamodel/opcua_status_code';\nimport { NodeClass } from 'node-opcua/lib/datamodel/nodeclass';\nimport WaitingStream from './WaitingStream';\n\n// FIXME: Extend QueueStream directly\n\n/**\n * A stream that writes all read {@link AtviseFile}s to their corresponding nodes on atvise server.\n * The underlying {@link TreeStream} ensures the nodes are processed in an order that respects the\n * parent-child relations between nodes. Nodes are created (if needed) before their children are\n * processed.\n */\nexport default class WriteStream extends WaitingStream {\n  /**\n   * Creates a new write stream with the given {@link CreateNodeStream} and\n   * {@link AddReferencesStream}. Implementer have to ensure this create stream is actually piped.\n   * @param {CreateNodeStream} createStream The stream that handles node creations.\n   * @param {AddReferencesStream} addReferencesStream The stream that adds missing node references.\n   * @param {Object} options The options passed to the underlying {@link TreeStream}.\n   */\n  constructor(createStream, addReferencesStream, options) {\n    super(options);\n\n    /**\n     * If a node has to be created first, it's callback is added to this map.\n     * @type {Map<String, function(err: Error)}\n     */\n    this._createCallbacks = {};\n\n    createStream.on('processed-chunk', ({ nodeId }) => {\n      const key = nodeId.toString();\n\n      if (this._createCallbacks[key]) {\n        this._createCallbacks[key](null);\n      }\n    });\n\n    /**\n     * The stream responsible for adding additional references.\n     * @type {AddReferencesStream}\n     */\n    this._addReferencesStream = addReferencesStream;\n  }\n\n  /**\n   * The error message to use when writing a file fails.\n   * @param {AtviseFile} file The file being processed.\n   * @return {string} The error message to use.\n   */\n  processErrorMessage(file) {\n    return `Error writing ${file.nodeId}`;\n  }\n\n  /**\n   * Pushes a node to the piped create stream and waits for the node to be created.\n   * @param {AtviseFile} file The file create the node for.\n   * @param {function(err: Error, statusCode: node-opcua~StatusCodes, onSuccess: function)}\n   * handleErrors The error handler to call. See {@link QueueStream#processChunk} for details.\n   */\n  _createNode(file, handleErrors) {\n    this._createCallbacks[file.nodeId.toString()] = (err) => {\n      handleErrors(err, StatusCodes.Good, (done) => done());\n    };\n\n    this.push(file);\n  }\n\n  /**\n   * Returns a files parent node and type definition.\n   * @param {AtviseFile} file The file to check.\n   * @return {NodeId[]} The files dependencies.\n   */\n  dependenciesFor() {\n    return [];\n  }\n\n  /**\n   * Writes an {@link AtviseFile} to it's corresponding node on atvise server.\n   * @param {AtviseFile} file The file to write.\n   * @param {function(err: Error, statusCode: node-opcua~StatusCodes, onSuccess: function)}\n   * handleErrors The error handler to call. See {@link QueueStream#processChunk} for details.\n   */\n  processChunk(file, handleErrors) {\n    if (file.nodeClass.value !== NodeClass.Variable.value) {\n      // Non-variable nodes are just pushed\n      this._createNode(file, handleErrors);\n      return;\n    }\n\n    try {\n      this.session.writeSingleNode(\n        `ns=1;s=${file.nodeId}`,\n        file.variantValue,\n        (err, statusCode) => {\n          if (\n            statusCode === StatusCodes.BadUserAccessDenied ||\n            statusCode === StatusCodes.BadNotWritable\n          ) {\n            Logger.warn(`Error writing node ${file.nodeId}\n  - Make sure it is not opened in atvise builder\n  - Make sure the corresponding datasource is connected`);\n            handleErrors(err, StatusCodes.Good, (done) => done());\n          } else if (statusCode === StatusCodes.BadNodeIdUnknown) {\n            Logger.debug(`Node ${file.nodeId} does not exist: Attempting to create it...`);\n\n            this._createNode(file, handleErrors);\n          } else {\n            handleErrors(err, statusCode, (done) => {\n              // Push to add references stream\n              this._addReferencesStream.push(file);\n\n              done();\n            });\n          }\n        }\n      );\n    } catch (e) {\n      handleErrors(e);\n    }\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/server/WriteStream.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 505,
    "kind": "class",
    "name": "WriteStream",
    "memberof": "src/lib/server/WriteStream.js",
    "static": true,
    "longname": "src/lib/server/WriteStream.js~WriteStream",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/WriteStream.js",
    "importStyle": "WriteStream",
    "description": "A stream that writes all read {@link AtviseFile}s to their corresponding nodes on atvise server.\nThe underlying {@link TreeStream} ensures the nodes are processed in an order that respects the\nparent-child relations between nodes. Nodes are created (if needed) before their children are\nprocessed.",
    "lineNumber": 17,
    "interface": false,
    "extends": [
      "src/lib/server/WaitingStream.js~WaitingStream"
    ]
  },
  {
    "__docId__": 506,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/server/WriteStream.js~WriteStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/WriteStream.js~WriteStream#constructor",
    "access": "public",
    "description": "Creates a new write stream with the given {@link CreateNodeStream} and\n{@link AddReferencesStream}. Implementer have to ensure this create stream is actually piped.",
    "lineNumber": 25,
    "params": [
      {
        "nullable": null,
        "types": [
          "CreateNodeStream"
        ],
        "spread": false,
        "optional": false,
        "name": "createStream",
        "description": "The stream that handles node creations."
      },
      {
        "nullable": null,
        "types": [
          "AddReferencesStream"
        ],
        "spread": false,
        "optional": false,
        "name": "addReferencesStream",
        "description": "The stream that adds missing node references."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "The options passed to the underlying {@link TreeStream}."
      }
    ]
  },
  {
    "__docId__": 507,
    "kind": "member",
    "name": "_createCallbacks",
    "memberof": "src/lib/server/WriteStream.js~WriteStream",
    "static": false,
    "longname": "src/lib/server/WriteStream.js~WriteStream#_createCallbacks",
    "access": "private",
    "description": "If a node has to be created first, it's callback is added to this map.",
    "lineNumber": 32,
    "type": {
      "nullable": null,
      "types": [
        "Map<String, function(err: Error)"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 508,
    "kind": "member",
    "name": "_addReferencesStream",
    "memberof": "src/lib/server/WriteStream.js~WriteStream",
    "static": false,
    "longname": "src/lib/server/WriteStream.js~WriteStream#_addReferencesStream",
    "access": "private",
    "description": "The stream responsible for adding additional references.",
    "lineNumber": 46,
    "type": {
      "nullable": null,
      "types": [
        "AddReferencesStream"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 509,
    "kind": "method",
    "name": "processErrorMessage",
    "memberof": "src/lib/server/WriteStream.js~WriteStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/WriteStream.js~WriteStream#processErrorMessage",
    "access": "public",
    "description": "The error message to use when writing a file fails.",
    "lineNumber": 54,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file being processed."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": "The error message to use."
    }
  },
  {
    "__docId__": 510,
    "kind": "method",
    "name": "_createNode",
    "memberof": "src/lib/server/WriteStream.js~WriteStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/WriteStream.js~WriteStream#_createNode",
    "access": "private",
    "description": "Pushes a node to the piped create stream and waits for the node to be created.",
    "lineNumber": 64,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file create the node for."
      },
      {
        "nullable": null,
        "types": [
          "function(err: Error, statusCode: node-opcua~StatusCodes, onSuccess: function)"
        ],
        "spread": false,
        "optional": false,
        "name": "handleErrors",
        "description": "The error handler to call. See {@link QueueStream#processChunk} for details."
      }
    ],
    "return": null
  },
  {
    "__docId__": 511,
    "kind": "method",
    "name": "dependenciesFor",
    "memberof": "src/lib/server/WriteStream.js~WriteStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/WriteStream.js~WriteStream#dependenciesFor",
    "access": "public",
    "description": "Returns a files parent node and type definition.",
    "lineNumber": 77,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file to check."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "NodeId[]"
      ],
      "spread": false,
      "description": "The files dependencies."
    }
  },
  {
    "__docId__": 512,
    "kind": "method",
    "name": "processChunk",
    "memberof": "src/lib/server/WriteStream.js~WriteStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/WriteStream.js~WriteStream#processChunk",
    "access": "public",
    "description": "Writes an {@link AtviseFile} to it's corresponding node on atvise server.",
    "lineNumber": 87,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file to write."
      },
      {
        "nullable": null,
        "types": [
          "function(err: Error, statusCode: node-opcua~StatusCodes, onSuccess: function)"
        ],
        "spread": false,
        "optional": false,
        "name": "handleErrors",
        "description": "The error handler to call. See {@link QueueStream#processChunk} for details."
      }
    ],
    "return": null
  },
  {
    "__docId__": 513,
    "kind": "file",
    "name": "src/lib/server/scripts/CallMethodStream.js",
    "content": "import { StatusCodes } from 'node-opcua/lib/datamodel/opcua_status_code';\nimport QueueStream from '../QueueStream';\n\n/**\n * A stream that calls an OPC-UA method for all input files.\n * @abstract\n */\nexport default class CallMethodStream extends QueueStream {\n  /**\n   * **Must be implemented in all subclasses:** The {@link NodeId} of the method to call.\n   * @type {NodeId} The method's id.\n   */\n  get methodId() {\n    throw new Error('Must be implemented in all subclasses');\n  }\n\n  /**\n   * The {@link NodeId} of the object from which the method should get called. Defaults to the value\n   * of {@link NodeId#parent} of {@link CallMethodStream#methodId}.\n   * @type {NodeId} The call-object's id.\n   */\n  get methodBaseId() {\n    return this.methodId.parent;\n  }\n\n  /**\n   * The input arguments the method should be called with for a file. Needs to be overridden by\n   * subclasses in most cases. Returning `null` indicates no method call is needed.\n   * @param {vinyl~File} file The file beeing processed.\n   * @return {?node-opcua~Variant[]} The resulting input arguments.\n   */\n  // eslint-disable-next-line no-unused-vars\n  inputArguments(file) {\n    return [];\n  }\n\n  /**\n   * Creates a call method request object for a file.\n   * @param {vinyl~File} file The file beeing processed.\n   * @return {?node-opcua~CallMethodRequest} The resulting call request.\n   */\n  callRequest(file) {\n    const args = this.inputArguments(file);\n\n    if (args === null) {\n      return null;\n    }\n\n    return {\n      objectId: this.methodBaseId,\n      methodId: this.methodId,\n      inputArguments: args,\n    };\n  }\n\n  /**\n   * **Must be implemented by all subclasses:** If the method call returns a status code of\n   * *{@link node-opcua~StatusCodes}.Good*, this method decides if the output matches the expected\n   * results.\n   * @param {vinyl~File} file The file beeing processed.\n   * @param {node-opcua~Variant[]} outputArgs The output arguments.\n   * @param {function(err: Error)} callback Call this method with an error to indicate the method\n   * call didn't work as expected.\n   */\n  // eslint-disable-next-line no-unused-vars\n  handleOutputArguments(file, outputArgs, callback) {\n    throw new Error('Must be implemented in all subclasses');\n  }\n\n  /**\n   * Returns an error message specifically for the given file.\n   * @param {vinyl~File} file The file to generate the error message for.\n   * @return {string} The specific error message.\n   */\n  processErrorMessage(file) {\n    return `Error running ${this.methodId.toString()} for ${file.relative}`;\n  }\n\n  /**\n   * Performs an opcua method call for the given file.\n   * @param {vinyl~File} file The file being processed.\n   * @param {function(err: Error, status: node-opcua~StatusCodes, success: function)} handleErrors\n   * The error handler to call. See {@link QueueStream#processChunk} for details.\n   */\n  processChunk(file, handleErrors) {\n    try {\n      const request = this.callRequest(file);\n\n      if (!request) {\n        handleErrors(null, StatusCodes.Good, (done) => done());\n        return;\n      }\n\n      this.session.call([request], (err, [result] = []) => {\n        if (err) {\n          handleErrors(err);\n        } else if (result.statusCode.value !== StatusCodes.Good.value) {\n          handleErrors(err, result.statusCode, (done) => done());\n        } else {\n          this.handleOutputArguments(file, result.outputArguments, (outputError) => {\n            handleErrors(outputError, StatusCodes.Good, (done) => done());\n          });\n        }\n      });\n    } catch (e) {\n      handleErrors(e);\n    }\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/server/scripts/CallMethodStream.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 514,
    "kind": "class",
    "name": "CallMethodStream",
    "memberof": "src/lib/server/scripts/CallMethodStream.js",
    "static": true,
    "longname": "src/lib/server/scripts/CallMethodStream.js~CallMethodStream",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/scripts/CallMethodStream.js",
    "importStyle": "CallMethodStream",
    "description": "A stream that calls an OPC-UA method for all input files.",
    "lineNumber": 8,
    "abstract": true,
    "interface": false,
    "extends": [
      "src/lib/server/QueueStream.js~QueueStream"
    ]
  },
  {
    "__docId__": 515,
    "kind": "get",
    "name": "methodId",
    "memberof": "src/lib/server/scripts/CallMethodStream.js~CallMethodStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/scripts/CallMethodStream.js~CallMethodStream#methodId",
    "access": "public",
    "description": "**Must be implemented in all subclasses:** The {@link NodeId} of the method to call.",
    "lineNumber": 13,
    "type": {
      "nullable": null,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 516,
    "kind": "get",
    "name": "methodBaseId",
    "memberof": "src/lib/server/scripts/CallMethodStream.js~CallMethodStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/scripts/CallMethodStream.js~CallMethodStream#methodBaseId",
    "access": "public",
    "description": "The {@link NodeId} of the object from which the method should get called. Defaults to the value\nof {@link NodeId#parent} of {@link CallMethodStream#methodId}.",
    "lineNumber": 22,
    "type": {
      "nullable": null,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 517,
    "kind": "method",
    "name": "inputArguments",
    "memberof": "src/lib/server/scripts/CallMethodStream.js~CallMethodStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/scripts/CallMethodStream.js~CallMethodStream#inputArguments",
    "access": "public",
    "description": "The input arguments the method should be called with for a file. Needs to be overridden by\nsubclasses in most cases. Returning `null` indicates no method call is needed.",
    "lineNumber": 33,
    "params": [
      {
        "nullable": null,
        "types": [
          "vinyl~File"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file beeing processed."
      }
    ],
    "return": {
      "nullable": true,
      "types": [
        "node-opcua~Variant[]"
      ],
      "spread": false,
      "description": "The resulting input arguments."
    }
  },
  {
    "__docId__": 518,
    "kind": "method",
    "name": "callRequest",
    "memberof": "src/lib/server/scripts/CallMethodStream.js~CallMethodStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/scripts/CallMethodStream.js~CallMethodStream#callRequest",
    "access": "public",
    "description": "Creates a call method request object for a file.",
    "lineNumber": 42,
    "params": [
      {
        "nullable": null,
        "types": [
          "vinyl~File"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file beeing processed."
      }
    ],
    "return": {
      "nullable": true,
      "types": [
        "node-opcua~CallMethodRequest"
      ],
      "spread": false,
      "description": "The resulting call request."
    }
  },
  {
    "__docId__": 519,
    "kind": "method",
    "name": "handleOutputArguments",
    "memberof": "src/lib/server/scripts/CallMethodStream.js~CallMethodStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/scripts/CallMethodStream.js~CallMethodStream#handleOutputArguments",
    "access": "public",
    "description": "**Must be implemented by all subclasses:** If the method call returns a status code of\n*{@link node-opcua~StatusCodes}.Good*, this method decides if the output matches the expected\nresults.",
    "lineNumber": 66,
    "params": [
      {
        "nullable": null,
        "types": [
          "vinyl~File"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file beeing processed."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~Variant[]"
        ],
        "spread": false,
        "optional": false,
        "name": "outputArgs",
        "description": "The output arguments."
      },
      {
        "nullable": null,
        "types": [
          "function(err: Error)"
        ],
        "spread": false,
        "optional": false,
        "name": "callback",
        "description": "Call this method with an error to indicate the method\ncall didn't work as expected."
      }
    ],
    "return": null
  },
  {
    "__docId__": 520,
    "kind": "method",
    "name": "processErrorMessage",
    "memberof": "src/lib/server/scripts/CallMethodStream.js~CallMethodStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/scripts/CallMethodStream.js~CallMethodStream#processErrorMessage",
    "access": "public",
    "description": "Returns an error message specifically for the given file.",
    "lineNumber": 75,
    "params": [
      {
        "nullable": null,
        "types": [
          "vinyl~File"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file to generate the error message for."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": "The specific error message."
    }
  },
  {
    "__docId__": 521,
    "kind": "method",
    "name": "processChunk",
    "memberof": "src/lib/server/scripts/CallMethodStream.js~CallMethodStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/scripts/CallMethodStream.js~CallMethodStream#processChunk",
    "access": "public",
    "description": "Performs an opcua method call for the given file.",
    "lineNumber": 85,
    "params": [
      {
        "nullable": null,
        "types": [
          "vinyl~File"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file being processed."
      },
      {
        "nullable": null,
        "types": [
          "function(err: Error, status: node-opcua~StatusCodes, success: function)"
        ],
        "spread": false,
        "optional": false,
        "name": "handleErrors",
        "description": "The error handler to call. See {@link QueueStream#processChunk} for details."
      }
    ],
    "return": null
  },
  {
    "__docId__": 522,
    "kind": "file",
    "name": "src/lib/server/scripts/CallScriptStream.js",
    "content": "import { DataType, VariantArrayType } from 'node-opcua/lib/datamodel/variant';\nimport { StatusCodes } from 'node-opcua/lib/datamodel/opcua_status_code';\nimport NodeId from '../../model/opcua/NodeId';\nimport CallMethodStream from './CallMethodStream';\n\n/**\n * A stream that calls atvise server scripts for all passed nodes.\n * @abstract\n */\nexport default class CallScriptStream extends CallMethodStream {\n  /**\n   * The id of the *callScript* method.\n   * @type {NodeId}\n   */\n  get methodId() {\n    return new NodeId(NodeId.NodeIdType.STRING, 'AGENT.SCRIPT.METHODS.callScript', 1);\n  }\n\n  /**\n   * **Must be implemented by all subclasses:** The id of the script to call.\n   * @type {NodeId}\n   * @abstract\n   */\n  get scriptId() {\n    throw new Error('Must be implemented by all subclasses');\n  }\n\n  /**\n   * Id of the script's base object.\n   * @type {NodeId}\n   */\n  get scriptBaseId() {\n    return this.scriptId.parent;\n  }\n\n  /**\n   * Returns the parameters to call the script with for the given file.\n   * @param {AtviseFile} file The processed file.\n   * @return {Object} The parameters passed to the script.\n   */\n  // eslint-disable-next-line no-unused-vars\n  scriptParameters(file) {\n    return {};\n  }\n\n  /**\n   * Creates the raw method input arguments for the given file.\n   * @param {AtviseFile} file The processed file.\n   * @return {?node-opcua~Variant[]} Input arguments for the *callScript* method.\n   */\n  inputArguments(file) {\n    const params = this.scriptParameters(file);\n\n    if (params === null) {\n      return null;\n    }\n\n    const paramNames = Object.keys(params);\n\n    return [\n      {\n        dataType: DataType.NodeId,\n        value: this.scriptId,\n      },\n      {\n        dataType: DataType.NodeId,\n        value: this.scriptBaseId,\n      },\n      {\n        dataType: DataType.String,\n        arrayType: VariantArrayType.Array,\n        value: paramNames,\n      },\n      {\n        dataType: DataType.Variant,\n        arrayType: VariantArrayType.Array,\n        value: paramNames.map((key) => params[key]),\n      },\n    ];\n  }\n\n  /**\n   * Returns the error message logged if running the script fails.\n   * @param {AtviseFile} file The processed file.\n   * @return {string} The resulting error message.\n   */\n  processErrorMessage(file) {\n    return `Error running script ${this.scriptId} for ${file.relative}`;\n  }\n\n  /**\n   * Calls the script specified in {@link CallScriptStream#scriptId}. If the script does not exist\n   * but could be imported by running `atscm import` a special status description is returned.\n   * @param {vinyl~File} file The file being processed.\n   * @param {function(err: Error, status: node-opcua~StatusCodes, success: function)} handleErrors\n   * The error handler to call. See {@link QueueStream#processChunk} for details.\n   */\n  processChunk(file, handleErrors) {\n    super.processChunk(file, (err, status, success) => {\n      const processedStatus = status;\n\n      const atscmScript = this.scriptId.value.match(/SERVERSCRIPTS\\.atscm\\.(.*)/);\n      if (status === StatusCodes.BadMethodInvalid && atscmScript) {\n        processedStatus.description = `The '${atscmScript[1]}' script does not exist.\n- Did you forget to run 'atscm import'?`;\n      }\n\n      handleErrors(err, processedStatus, success);\n    });\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/server/scripts/CallScriptStream.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 523,
    "kind": "class",
    "name": "CallScriptStream",
    "memberof": "src/lib/server/scripts/CallScriptStream.js",
    "static": true,
    "longname": "src/lib/server/scripts/CallScriptStream.js~CallScriptStream",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/scripts/CallScriptStream.js",
    "importStyle": "CallScriptStream",
    "description": "A stream that calls atvise server scripts for all passed nodes.",
    "lineNumber": 10,
    "abstract": true,
    "interface": false,
    "extends": [
      "src/lib/server/scripts/CallMethodStream.js~CallMethodStream"
    ]
  },
  {
    "__docId__": 524,
    "kind": "get",
    "name": "methodId",
    "memberof": "src/lib/server/scripts/CallScriptStream.js~CallScriptStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/scripts/CallScriptStream.js~CallScriptStream#methodId",
    "access": "public",
    "description": "The id of the *callScript* method.",
    "lineNumber": 15,
    "type": {
      "nullable": null,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 525,
    "kind": "get",
    "name": "scriptId",
    "memberof": "src/lib/server/scripts/CallScriptStream.js~CallScriptStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/scripts/CallScriptStream.js~CallScriptStream#scriptId",
    "access": "public",
    "description": "**Must be implemented by all subclasses:** The id of the script to call.",
    "lineNumber": 24,
    "type": {
      "nullable": null,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": null
    },
    "abstract": true
  },
  {
    "__docId__": 526,
    "kind": "get",
    "name": "scriptBaseId",
    "memberof": "src/lib/server/scripts/CallScriptStream.js~CallScriptStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/scripts/CallScriptStream.js~CallScriptStream#scriptBaseId",
    "access": "public",
    "description": "Id of the script's base object.",
    "lineNumber": 32,
    "type": {
      "nullable": null,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 527,
    "kind": "method",
    "name": "scriptParameters",
    "memberof": "src/lib/server/scripts/CallScriptStream.js~CallScriptStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/scripts/CallScriptStream.js~CallScriptStream#scriptParameters",
    "access": "public",
    "description": "Returns the parameters to call the script with for the given file.",
    "lineNumber": 42,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The processed file."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Object"
      ],
      "spread": false,
      "description": "The parameters passed to the script."
    }
  },
  {
    "__docId__": 528,
    "kind": "method",
    "name": "inputArguments",
    "memberof": "src/lib/server/scripts/CallScriptStream.js~CallScriptStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/scripts/CallScriptStream.js~CallScriptStream#inputArguments",
    "access": "public",
    "description": "Creates the raw method input arguments for the given file.",
    "lineNumber": 51,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The processed file."
      }
    ],
    "return": {
      "nullable": true,
      "types": [
        "node-opcua~Variant[]"
      ],
      "spread": false,
      "description": "Input arguments for the *callScript* method."
    }
  },
  {
    "__docId__": 529,
    "kind": "method",
    "name": "processErrorMessage",
    "memberof": "src/lib/server/scripts/CallScriptStream.js~CallScriptStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/scripts/CallScriptStream.js~CallScriptStream#processErrorMessage",
    "access": "public",
    "description": "Returns the error message logged if running the script fails.",
    "lineNumber": 87,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The processed file."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": "The resulting error message."
    }
  },
  {
    "__docId__": 530,
    "kind": "method",
    "name": "processChunk",
    "memberof": "src/lib/server/scripts/CallScriptStream.js~CallScriptStream",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/server/scripts/CallScriptStream.js~CallScriptStream#processChunk",
    "access": "public",
    "description": "Calls the script specified in {@link CallScriptStream#scriptId}. If the script does not exist\nbut could be imported by running `atscm import` a special status description is returned.",
    "lineNumber": 98,
    "params": [
      {
        "nullable": null,
        "types": [
          "vinyl~File"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file being processed."
      },
      {
        "nullable": null,
        "types": [
          "function(err: Error, status: node-opcua~StatusCodes, success: function)"
        ],
        "spread": false,
        "optional": false,
        "name": "handleErrors",
        "description": "The error handler to call. See {@link QueueStream#processChunk} for details."
      }
    ],
    "return": null
  },
  {
    "__docId__": 531,
    "kind": "file",
    "name": "src/lib/server/scripts/version.js",
    "content": "/* eslint-disable import/prefer-default-export */\n\nimport NodeId from '../../model/opcua/NodeId';\n\n/**\n * The node containing the currently installed server-scripts version.\n * @type {NodeId}\n */\nexport const versionNode = new NodeId('SYSTEM.LIBRARY.ATVISE.SERVERSCRIPTS.atscm.version');\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/server/scripts/version.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 532,
    "kind": "variable",
    "name": "versionNode",
    "memberof": "src/lib/server/scripts/version.js",
    "static": true,
    "longname": "src/lib/server/scripts/version.js~versionNode",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/server/scripts/version.js",
    "importStyle": "{versionNode}",
    "description": "The node containing the currently installed server-scripts version.",
    "lineNumber": 9,
    "type": {
      "nullable": null,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 533,
    "kind": "file",
    "name": "src/lib/transform/ConfigTransformer.ts",
    "content": "import { DataType, VariantArrayType } from 'node-opcua/lib/datamodel/variant';\nimport XMLTransformer from './XMLTransformer';\n\nexport default class ConfigTransformer<C = Record<string, unknown>> extends XMLTransformer {\n  /**\n   * Returns an object containing all non-empty properties of the input object. Returns null if no\n   * properties are non-empty.\n   * @param input The config to process.\n   */\n  protected nonEmptyConfig(input: C) {\n    let result: C | null = null;\n\n    for (const [key, value] of Object.entries(input)) {\n      if (Array.isArray(value) ? value.length > 0 : value !== undefined) {\n        result = result || ({} as C);\n        result[key] = value;\n      }\n    }\n\n    return result;\n  }\n\n  /**\n   * Writes the config file to disk if needed.\n   * @param config The config to write.\n   * @param node The original source node.\n   * @param context The current transformer context.\n   * @return `true` it the config was actually written.\n   */\n  protected writeConfigFile(config: C, node, context) {\n    const processed = this.nonEmptyConfig(config);\n\n    if (processed) {\n      const configFile = (this.constructor as typeof XMLTransformer).splitFile(node, '.json');\n      configFile.value = {\n        dataType: DataType.String,\n        arrayType: VariantArrayType.Scalar,\n        value: JSON.stringify(config, null, '  '),\n      };\n      context.addNode(configFile);\n    }\n\n    return !!processed;\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/transform/ConfigTransformer.ts",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 534,
    "kind": "class",
    "name": "ConfigTransformer",
    "memberof": "src/lib/transform/ConfigTransformer.ts",
    "static": true,
    "longname": "src/lib/transform/ConfigTransformer.ts~ConfigTransformer",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/transform/ConfigTransformer.ts",
    "importStyle": "ConfigTransformer",
    "description": "",
    "lineNumber": 4,
    "interface": false,
    "extends": [
      "src/lib/transform/XMLTransformer.js~XMLTransformer"
    ]
  },
  {
    "__docId__": 535,
    "kind": "method",
    "name": "nonEmptyConfig",
    "memberof": "src/lib/transform/ConfigTransformer.ts~ConfigTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/transform/ConfigTransformer.ts~ConfigTransformer#nonEmptyConfig",
    "access": "public",
    "description": "Returns an object containing all non-empty properties of the input object. Returns null if no\nproperties are non-empty.",
    "lineNumber": 10,
    "params": [
      {
        "nullable": null,
        "types": [
          "C"
        ],
        "spread": false,
        "optional": false,
        "name": "input",
        "description": ""
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 536,
    "kind": "method",
    "name": "writeConfigFile",
    "memberof": "src/lib/transform/ConfigTransformer.ts~ConfigTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/transform/ConfigTransformer.ts~ConfigTransformer#writeConfigFile",
    "access": "public",
    "description": "Writes the config file to disk if needed.",
    "lineNumber": 30,
    "params": [
      {
        "nullable": null,
        "types": [
          "C"
        ],
        "spread": false,
        "optional": false,
        "name": "config",
        "description": ""
      },
      {
        "nullable": null,
        "types": [
          "undefined"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": ""
      },
      {
        "nullable": null,
        "types": [
          "undefined"
        ],
        "spread": false,
        "optional": false,
        "name": "context",
        "description": ""
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 537,
    "kind": "file",
    "name": "src/lib/transform/PartialTransformer.js",
    "content": "import Transformer from './Transformer';\n\n/**\n * A transformer that transforms only some of the files read.\n * @abstract\n * @example <caption>Minimum implementation</caption>\n * class MyTransformer extends PartialTransformer {\n *   shouldBeTransformed(node) {\n *     return true; // or false\n *   }\n *   transformFromFilesystem(state, context) {\n *     if (!this.shouldBeTransformed(state.node)) { return; }\n *\n *     // Apply actual transformation\n *   }\n * }\n */\nexport default class ModernPartialTransformer extends Transformer {\n  /**\n   * `true` if `file` should be transformed.\n   * @param {AtviseFile} file The file to transform or not.\n   * @return {boolean}\n   * @abstract\n   */\n  // eslint-disable-next-line no-unused-vars\n  shouldBeTransformed(file) {\n    throw new Error('PartialTransformer#shouldBeTransformed must be implemented by all subclasses');\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/transform/PartialTransformer.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 538,
    "kind": "class",
    "name": "ModernPartialTransformer",
    "memberof": "src/lib/transform/PartialTransformer.js",
    "static": true,
    "longname": "src/lib/transform/PartialTransformer.js~ModernPartialTransformer",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/transform/PartialTransformer.js",
    "importStyle": "ModernPartialTransformer",
    "description": "A transformer that transforms only some of the files read.",
    "examples": [
      "<caption>Minimum implementation</caption>\nclass MyTransformer extends PartialTransformer {\n  shouldBeTransformed(node) {\n    return true; // or false\n  }\n  transformFromFilesystem(state, context) {\n    if (!this.shouldBeTransformed(state.node)) { return; }\n\n    // Apply actual transformation\n  }\n}"
    ],
    "lineNumber": 18,
    "abstract": true,
    "interface": false,
    "extends": [
      "src/lib/transform/Transformer.js~Transformer"
    ]
  },
  {
    "__docId__": 539,
    "kind": "method",
    "name": "shouldBeTransformed",
    "memberof": "src/lib/transform/PartialTransformer.js~ModernPartialTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/transform/PartialTransformer.js~ModernPartialTransformer#shouldBeTransformed",
    "access": "public",
    "description": "`true` if `file` should be transformed.",
    "lineNumber": 26,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file to transform or not."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": ""
    },
    "abstract": true
  },
  {
    "__docId__": 540,
    "kind": "file",
    "name": "src/lib/transform/SplittingTransformer.js",
    "content": "import { extname, basename, join } from 'path';\nimport { readdir } from 'fs-extra';\nimport { escapeForRegExp } from '../regexp';\nimport PartialTransformer from './PartialTransformer.js';\n\n/**\n * A transformer that splits a node into multiple source nodes when pulling.\n */\nexport default class SplittingTransformer extends PartialTransformer {\n  /**\n   * The extension to add to container node names when they are pulled.\n   * @abstract\n   * @type {string}\n   */\n  static get extension() {\n    throw new Error('Must be implemented by all subclasses');\n  }\n\n  /**\n   * The source file extensions to allow.\n   * @abstract\n   * @type {string[]}\n   */\n  static get sourceExtensions() {\n    throw new Error('Must be implemented by all subclasses');\n  }\n\n  /**\n   * Splits a {@link Node}: The resulting is a clone of the input file, with a different path.\n   * @param {Node} node The file to split.\n   * @param {?string} newExtension The extension the resulting file gets.\n   * @return {Node} The resulting node.\n   */\n  static splitFile(node, newExtension) {\n    Object.assign(node, {\n      fullyMapped: true,\n      value: Object.assign(node.value, {\n        noWrite: true,\n      }),\n    });\n\n    return node.createChild({ extension: newExtension });\n  }\n\n  /**\n   * Renames a container node, should be called by all subclasses.\n   * @param {BrowsedNode} node A container node.\n   * @param {any} context The tranform context.\n   */\n  // eslint-disable-next-line no-unused-vars\n  async transformFromDB(node, context) {\n    node.renameTo(`${node.name}${this.constructor.extension}`);\n  }\n\n  /**\n   * Returns `false` for all container nodes, so they don't get read.\n   * @param {BrowsedNode} node The node to check.\n   * @return {?boolean} If the node should be read.\n   */\n  readNodeFile(node) {\n    return this.shouldBeTransformed(node) ? false : undefined;\n  }\n\n  /**\n   * Combines the container node and the source nodes to one single node.\n   * @abstract\n   * @param {BrowsedNode} node The container node.\n   * @param {Map<string, BrowsedNode>} sourceNodes The source nodes.\n   * @param {any} context The current context.\n   */\n  // eslint-disable-next-line no-unused-vars\n  combineNodes(node, sourceNodes, context) {\n    throw new Error('Must be implemented by all subclasses');\n  }\n\n  /**\n   * Combines the container node and the source nodes to one single node by calling\n   * {@link SplittingTransformer#combineNodes}.\n   * @param {BrowsedNode} node The container node.\n   * @param {{ [extension: string]: BrowedNode }} sourceNodes The source nodes.\n   * @param {any} context The current context.\n   */\n  _combineNodes(node, sourceNodes, context) {\n    this.combineNodes(node, sourceNodes, context);\n    node.renameTo(basename(node.name, this.constructor.extension));\n  }\n\n  /**\n   * Reads a given container nodes source nodes and combines them.\n   * @param {BrowsedNode} node The node to transform.\n   * @param {Object} context The browser context.\n   */\n  async transformFromFilesystem(node, context) {\n    if (!this.shouldBeTransformed(node)) {\n      return;\n    }\n\n    const [name, hasExtension] = node.fileName.split(this.constructor.extension);\n\n    if (hasExtension !== '') {\n      // FIXME: Remove\n      throw new Error(`${node.relative} shouldn't be transformed`);\n    }\n\n    const regExp = new RegExp(\n      `^\\\\.${escapeForRegExp(name)}(${this.constructor.sourceExtensions.join('|')})\\\\.json$`\n    );\n\n    // Find source files an child definition files\n    const sourceFiles = [];\n    const childFiles = [];\n\n    const children = (await readdir(node.relative)).reduce((current, f) => {\n      if (f.match(regExp)) {\n        sourceFiles.push(f);\n      } else if (f.match(/^\\..*\\.json$/)) {\n        // Other definition file -> child node\n        current.push({ name: f, path: join(node.relative, f) });\n        childFiles.push(f);\n      } else if (!sourceFiles.includes(`.${f}.json`) && !childFiles.includes(`.${f}.json`)) {\n        // This might be a child object's folder...\n        current.push({ name: f, path: join(node.relative, f) });\n      }\n\n      return current;\n    }, []);\n\n    // Manually set node.children for the container as source browser only handles definition files\n    Object.assign(node, { children });\n\n    const sourceNodes = await Promise.all(\n      sourceFiles.map((f) =>\n        context.readNode({\n          path: join(node.relative, f),\n          tree: { parent: node },\n        })\n      )\n    );\n\n    this._combineNodes(\n      node,\n      sourceNodes.reduce(\n        (result, n) =>\n          Object.assign(result, {\n            [extname(n.fileName)]: n,\n          }),\n        {}\n      ),\n      context\n    );\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/transform/SplittingTransformer.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 541,
    "kind": "class",
    "name": "SplittingTransformer",
    "memberof": "src/lib/transform/SplittingTransformer.js",
    "static": true,
    "longname": "src/lib/transform/SplittingTransformer.js~SplittingTransformer",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/transform/SplittingTransformer.js",
    "importStyle": "SplittingTransformer",
    "description": "A transformer that splits a node into multiple source nodes when pulling.",
    "lineNumber": 9,
    "interface": false,
    "extends": [
      "src/lib/transform/PartialTransformer.js~PartialTransformer"
    ]
  },
  {
    "__docId__": 542,
    "kind": "get",
    "name": "extension",
    "memberof": "src/lib/transform/SplittingTransformer.js~SplittingTransformer",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/transform/SplittingTransformer.js~SplittingTransformer.extension",
    "access": "public",
    "description": "The extension to add to container node names when they are pulled.",
    "lineNumber": 15,
    "type": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    },
    "abstract": true
  },
  {
    "__docId__": 543,
    "kind": "get",
    "name": "sourceExtensions",
    "memberof": "src/lib/transform/SplittingTransformer.js~SplittingTransformer",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/transform/SplittingTransformer.js~SplittingTransformer.sourceExtensions",
    "access": "public",
    "description": "The source file extensions to allow.",
    "lineNumber": 24,
    "type": {
      "nullable": null,
      "types": [
        "string[]"
      ],
      "spread": false,
      "description": null
    },
    "abstract": true
  },
  {
    "__docId__": 544,
    "kind": "method",
    "name": "splitFile",
    "memberof": "src/lib/transform/SplittingTransformer.js~SplittingTransformer",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/transform/SplittingTransformer.js~SplittingTransformer.splitFile",
    "access": "public",
    "description": "Splits a {@link Node}: The resulting is a clone of the input file, with a different path.",
    "lineNumber": 34,
    "params": [
      {
        "nullable": null,
        "types": [
          "Node"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The file to split."
      },
      {
        "nullable": true,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "newExtension",
        "description": "The extension the resulting file gets."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Node"
      ],
      "spread": false,
      "description": "The resulting node."
    }
  },
  {
    "__docId__": 545,
    "kind": "method",
    "name": "transformFromDB",
    "memberof": "src/lib/transform/SplittingTransformer.js~SplittingTransformer",
    "generator": false,
    "async": true,
    "static": false,
    "longname": "src/lib/transform/SplittingTransformer.js~SplittingTransformer#transformFromDB",
    "access": "public",
    "description": "Renames a container node, should be called by all subclasses.",
    "lineNumber": 51,
    "params": [
      {
        "nullable": null,
        "types": [
          "BrowsedNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "A container node."
      },
      {
        "nullable": null,
        "types": [
          "any"
        ],
        "spread": false,
        "optional": false,
        "name": "context",
        "description": "The tranform context."
      }
    ],
    "return": null
  },
  {
    "__docId__": 546,
    "kind": "method",
    "name": "readNodeFile",
    "memberof": "src/lib/transform/SplittingTransformer.js~SplittingTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/transform/SplittingTransformer.js~SplittingTransformer#readNodeFile",
    "access": "public",
    "description": "Returns `false` for all container nodes, so they don't get read.",
    "lineNumber": 60,
    "params": [
      {
        "nullable": null,
        "types": [
          "BrowsedNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The node to check."
      }
    ],
    "return": {
      "nullable": true,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": "If the node should be read."
    }
  },
  {
    "__docId__": 547,
    "kind": "method",
    "name": "combineNodes",
    "memberof": "src/lib/transform/SplittingTransformer.js~SplittingTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/transform/SplittingTransformer.js~SplittingTransformer#combineNodes",
    "access": "public",
    "description": "Combines the container node and the source nodes to one single node.",
    "lineNumber": 72,
    "params": [
      {
        "nullable": null,
        "types": [
          "BrowsedNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The container node."
      },
      {
        "nullable": null,
        "types": [
          "Map<string, BrowsedNode>"
        ],
        "spread": false,
        "optional": false,
        "name": "sourceNodes",
        "description": "The source nodes."
      },
      {
        "nullable": null,
        "types": [
          "any"
        ],
        "spread": false,
        "optional": false,
        "name": "context",
        "description": "The current context."
      }
    ],
    "abstract": true,
    "return": null
  },
  {
    "__docId__": 548,
    "kind": "method",
    "name": "_combineNodes",
    "memberof": "src/lib/transform/SplittingTransformer.js~SplittingTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/transform/SplittingTransformer.js~SplittingTransformer#_combineNodes",
    "access": "private",
    "description": "Combines the container node and the source nodes to one single node by calling\n{@link SplittingTransformer#combineNodes}.",
    "lineNumber": 83,
    "params": [
      {
        "nullable": null,
        "types": [
          "BrowsedNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The container node."
      },
      {
        "nullable": null,
        "types": [
          "{ [extension: string]: BrowedNode }"
        ],
        "spread": false,
        "optional": false,
        "name": "sourceNodes",
        "description": "The source nodes."
      },
      {
        "nullable": null,
        "types": [
          "any"
        ],
        "spread": false,
        "optional": false,
        "name": "context",
        "description": "The current context."
      }
    ],
    "return": null
  },
  {
    "__docId__": 549,
    "kind": "method",
    "name": "transformFromFilesystem",
    "memberof": "src/lib/transform/SplittingTransformer.js~SplittingTransformer",
    "generator": false,
    "async": true,
    "static": false,
    "longname": "src/lib/transform/SplittingTransformer.js~SplittingTransformer#transformFromFilesystem",
    "access": "public",
    "description": "Reads a given container nodes source nodes and combines them.",
    "lineNumber": 93,
    "params": [
      {
        "nullable": null,
        "types": [
          "BrowsedNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The node to transform."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "context",
        "description": "The browser context."
      }
    ],
    "return": null
  },
  {
    "__docId__": 550,
    "kind": "file",
    "name": "src/lib/transform/Transformer.js",
    "content": "import Logger from 'gulplog';\n\n/**\n * The directions a transformer can be run in.\n * @type {{FromDB: string, FromFilesystem: string}}\n */\nexport const TransformDirection = {\n  FromDB: 'FromDB',\n  FromFilesystem: 'FromFilesystem',\n};\n\n/**\n * Checks if the given string is a valid {@link TransformDirection}.\n * @param {string} direction The direction string to check.\n * @return {boolean} `true` if the direction is valid.\n */\nfunction isValidDirection(direction) {\n  return [TransformDirection.FromDB, TransformDirection.FromFilesystem].includes(direction);\n}\n\n/**\n * The base transformer class.\n * @abstract\n */\nexport default class Transformer {\n  /**\n   * Returns a function that combines multiple transformer actions.\n   * @param {Transformer[]} transformers An array of transformers.\n   * @param {TransformDirection} direction The direction to use.\n   * @return {function(node: Node): Promise<any>} The combined transform function.\n   */\n  static combinedTransformer(transformers, direction) {\n    const directed = transformers.map((t) => t.withDirection(direction));\n\n    if (direction === TransformDirection.FromFilesystem) {\n      directed.reverse();\n    }\n\n    return async (node, context) => {\n      for (const transformer of directed) {\n        if ((await transformer.compatTransform(direction, node, context)) !== undefined) {\n          // break;\n        }\n      }\n    };\n  }\n\n  /**\n   * Creates a new Transformer with the specified options.\n   * @param {Object} [options] The options to use.\n   * @param {TransformDirection} [options.direction] The direction to use.\n   * @throws {Error} Throws an error if the given direction is invalid.\n   */\n  constructor({ direction } = {}) {\n    if (direction) {\n      if (!isValidDirection(direction)) {\n        throw new Error('Invalid direction');\n      }\n      this.direction = direction;\n    }\n  }\n\n  /**\n   * Returns the Transformer with the given direction.\n   * @param {TransformDirection} direction The direction to use.\n   * @return {Transformer} Itself, to be chainable.\n   * @throws {Error} Throws an error if the given direction is invalid.\n   */\n  withDirection(direction) {\n    if (!isValidDirection(direction)) {\n      throw new Error('Invalid direction');\n    }\n\n    /**\n     * The transformer's direction\n     * @type {TransformerDirection}\n     */\n    this.direction = direction;\n    return this;\n  }\n\n  /**\n   * Determines if a node's value node should be read, e.G. The *Variable.Bool* file for a node\n   * defined in *.Variable.Bool.Json*.\n   * @param {FileNode} node The node to read or not.\n   * @return {boolean?} *true* if the node's value file should be read, undefined to let other\n   * transformers decide.\n   */\n  // eslint-disable-next-line no-unused-vars\n  readNodeFile(node) {\n    return undefined;\n  }\n\n  /**\n   * **Must be overridden by all subclasses:** Transforms the given node when using\n   * {@link TransformDirection.FromDB}.\n   * @param {BrowsedNode} node The node to split.\n   * @param {Object} context The transform context.\n   */\n  // eslint-disable-next-line no-unused-vars\n  async transformFromDB(node, context) {\n    throw new Error('Transformer#transformFromDB must be overridden by all subclasses');\n  }\n\n  /**\n   * **Must be overridden by all subclasses:** Transforms the given node when using\n   * {@link TransformDirection.FromFilesystem}.\n   * @param {BrowsedNode} node The node to transform.\n   * @param {Object} context The browser context.\n   */\n  // eslint-disable-next-line no-unused-vars\n  async transformFromFilesystem(node, context) {\n    throw new Error('Transformer#transformFromFilesystem must be overridden by all subclasses');\n  }\n\n  /**\n   * A transform wrapper that works with both async/await (atscm >= 1) and callback-based\n   * (atscm < 1)transformers.\n   * @param {TransformDirection} direction The direction to use.\n   * @param {Node} node The node to transform.\n   * @param {Object} context The browser context.\n   */\n  compatTransform(direction, node, context) {\n    const transform = (direction === TransformDirection.FromDB\n      ? this.transformFromDB\n      : this.transformFromFilesystem\n    ).bind(this);\n\n    const fnName = `${this.constructor.name}#transform${\n      direction === TransformDirection.FromDB ? 'FromDB' : 'FromFilesystem'\n    }`;\n\n    return new Promise((resolve, reject) => {\n      const promise = transform(node, context, (err, result) => {\n        if (!this.constructor._warnedStreamAPI) {\n          this.constructor._warnedStreamAPI = true;\n          Logger.debug(`Deprecated: ${fnName} uses the Stream API instead of async/await.`);\n        }\n        if (err) {\n          return reject(Object.assign(err, { node }));\n        }\n\n        // Handle \"repush\"\n        if (result === node) {\n          return resolve();\n        }\n\n        return resolve(result);\n      });\n\n      if (promise instanceof Promise) {\n        promise.then(resolve, (err) => reject(Object.assign(err, { node })));\n      } else if (this.transformFromDB.length < 3) {\n        reject(\n          new Error(`${fnName} did not return a Promise.\n  - Did you forget \\`async\\`?`)\n        );\n      }\n    });\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/transform/Transformer.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 551,
    "kind": "variable",
    "name": "TransformDirection",
    "memberof": "src/lib/transform/Transformer.js",
    "static": true,
    "longname": "src/lib/transform/Transformer.js~TransformDirection",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/transform/Transformer.js",
    "importStyle": "{TransformDirection}",
    "description": "The directions a transformer can be run in.",
    "lineNumber": 7,
    "type": {
      "nullable": null,
      "types": [
        "{FromDB: string, FromFilesystem: string}"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 552,
    "kind": "function",
    "name": "isValidDirection",
    "memberof": "src/lib/transform/Transformer.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/transform/Transformer.js~isValidDirection",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/transform/Transformer.js",
    "importStyle": null,
    "description": "Checks if the given string is a valid {@link TransformDirection}.",
    "lineNumber": 17,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "direction",
        "description": "The direction string to check."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": "`true` if the direction is valid."
    },
    "ignore": true
  },
  {
    "__docId__": 553,
    "kind": "class",
    "name": "Transformer",
    "memberof": "src/lib/transform/Transformer.js",
    "static": true,
    "longname": "src/lib/transform/Transformer.js~Transformer",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/transform/Transformer.js",
    "importStyle": "Transformer",
    "description": "The base transformer class.",
    "lineNumber": 25,
    "abstract": true,
    "interface": false
  },
  {
    "__docId__": 554,
    "kind": "method",
    "name": "combinedTransformer",
    "memberof": "src/lib/transform/Transformer.js~Transformer",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/transform/Transformer.js~Transformer.combinedTransformer",
    "access": "public",
    "description": "Returns a function that combines multiple transformer actions.",
    "lineNumber": 32,
    "params": [
      {
        "nullable": null,
        "types": [
          "Transformer[]"
        ],
        "spread": false,
        "optional": false,
        "name": "transformers",
        "description": "An array of transformers."
      },
      {
        "nullable": null,
        "types": [
          "TransformDirection"
        ],
        "spread": false,
        "optional": false,
        "name": "direction",
        "description": "The direction to use."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "function(node: Node): Promise<any>"
      ],
      "spread": false,
      "description": "The combined transform function."
    }
  },
  {
    "__docId__": 555,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/transform/Transformer.js~Transformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/transform/Transformer.js~Transformer#constructor",
    "access": "public",
    "description": "Creates a new Transformer with the specified options.",
    "lineNumber": 54,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": true,
        "name": "options",
        "description": "The options to use."
      },
      {
        "nullable": null,
        "types": [
          "TransformDirection"
        ],
        "spread": false,
        "optional": true,
        "name": "options.direction",
        "description": "The direction to use."
      }
    ],
    "throws": [
      {
        "types": [
          "Error"
        ],
        "description": "Throws an error if the given direction is invalid."
      }
    ]
  },
  {
    "__docId__": 556,
    "kind": "member",
    "name": "direction",
    "memberof": "src/lib/transform/Transformer.js~Transformer",
    "static": false,
    "longname": "src/lib/transform/Transformer.js~Transformer#direction",
    "access": "public",
    "description": null,
    "lineNumber": 59,
    "undocument": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 557,
    "kind": "method",
    "name": "withDirection",
    "memberof": "src/lib/transform/Transformer.js~Transformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/transform/Transformer.js~Transformer#withDirection",
    "access": "public",
    "description": "Returns the Transformer with the given direction.",
    "lineNumber": 69,
    "params": [
      {
        "nullable": null,
        "types": [
          "TransformDirection"
        ],
        "spread": false,
        "optional": false,
        "name": "direction",
        "description": "The direction to use."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Transformer"
      ],
      "spread": false,
      "description": "Itself, to be chainable."
    },
    "throws": [
      {
        "types": [
          "Error"
        ],
        "description": "Throws an error if the given direction is invalid."
      }
    ]
  },
  {
    "__docId__": 559,
    "kind": "method",
    "name": "readNodeFile",
    "memberof": "src/lib/transform/Transformer.js~Transformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/transform/Transformer.js~Transformer#readNodeFile",
    "access": "public",
    "description": "Determines if a node's value node should be read, e.G. The *Variable.Bool* file for a node\ndefined in *.Variable.Bool.Json*.",
    "lineNumber": 90,
    "params": [
      {
        "nullable": null,
        "types": [
          "FileNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The node to read or not."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "boolean?"
      ],
      "spread": false,
      "description": "*true* if the node's value file should be read, undefined to let other\ntransformers decide."
    }
  },
  {
    "__docId__": 560,
    "kind": "method",
    "name": "transformFromDB",
    "memberof": "src/lib/transform/Transformer.js~Transformer",
    "generator": false,
    "async": true,
    "static": false,
    "longname": "src/lib/transform/Transformer.js~Transformer#transformFromDB",
    "access": "public",
    "description": "**Must be overridden by all subclasses:** Transforms the given node when using\n{@link TransformDirection.FromDB}.",
    "lineNumber": 101,
    "params": [
      {
        "nullable": null,
        "types": [
          "BrowsedNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The node to split."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "context",
        "description": "The transform context."
      }
    ],
    "return": null
  },
  {
    "__docId__": 561,
    "kind": "method",
    "name": "transformFromFilesystem",
    "memberof": "src/lib/transform/Transformer.js~Transformer",
    "generator": false,
    "async": true,
    "static": false,
    "longname": "src/lib/transform/Transformer.js~Transformer#transformFromFilesystem",
    "access": "public",
    "description": "**Must be overridden by all subclasses:** Transforms the given node when using\n{@link TransformDirection.FromFilesystem}.",
    "lineNumber": 112,
    "params": [
      {
        "nullable": null,
        "types": [
          "BrowsedNode"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The node to transform."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "context",
        "description": "The browser context."
      }
    ],
    "return": null
  },
  {
    "__docId__": 562,
    "kind": "method",
    "name": "compatTransform",
    "memberof": "src/lib/transform/Transformer.js~Transformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/transform/Transformer.js~Transformer#compatTransform",
    "access": "public",
    "description": "A transform wrapper that works with both async/await (atscm >= 1) and callback-based\n(atscm < 1)transformers.",
    "lineNumber": 123,
    "params": [
      {
        "nullable": null,
        "types": [
          "TransformDirection"
        ],
        "spread": false,
        "optional": false,
        "name": "direction",
        "description": "The direction to use."
      },
      {
        "nullable": null,
        "types": [
          "Node"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The node to transform."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "context",
        "description": "The browser context."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 563,
    "kind": "file",
    "name": "src/lib/transform/XMLTransformer.js",
    "content": "import { EOL } from 'os';\nimport { parse, render, isElement, moveToTop, attributeValues } from 'modify-xml';\nimport { TransformDirection } from './Transformer';\nimport SplittingTransformer from './SplittingTransformer';\n\nfunction walk(element, action, filter = isElement) {\n  action(element);\n\n  if (element.childNodes) {\n    for (const child of element.childNodes.filter((n) => filter(n))) {\n      walk(child, action);\n    }\n  }\n}\n\n/**\n * A transformer used to transform XML documents.\n */\nexport default class XMLTransformer extends SplittingTransformer {\n  /**\n   * Creates a new XMLTransformer based on some options.\n   * @param {Object} [options] The options to use.\n   */\n  constructor({ sortXMLAttributes = false, removeBuilderRefs = false, ...options } = {}) {\n    super(options);\n\n    /** @protected */\n    this.sortXMLAttributes = sortXMLAttributes;\n\n    /** @protected */\n    this.removeBuilderRefs = removeBuilderRefs;\n\n    function build(object, buildOptions) {\n      const root = object.childNodes.find((n) => isElement(n));\n\n      if (root) {\n        moveToTop(root, 'metadata');\n        moveToTop(root, 'defs');\n        moveToTop(root, 'desc');\n        moveToTop(root, 'title');\n      }\n\n      if (sortXMLAttributes || removeBuilderRefs)\n        walk(root, (e) => {\n          /* eslint-disable no-param-reassign */\n          if (removeBuilderRefs)\n            e.attributes = e.attributes.filter((a) => !['atv:refpx', 'atv:refpy'].includes(a.name));\n\n          if (sortXMLAttributes)\n            e.attributes = e.attributes.sort((a, b) => (b.name > a.name ? -1 : 1));\n\n          delete e.openTag;\n          /* eslint-enable no-param-reassign */\n        });\n\n      return render(object, { indent: ' '.repeat(buildOptions.spaces) });\n    }\n\n    // eslint-disable-next-line jsdoc/require-param\n    /**\n     * The builder to use with direction {@link TransformDirection.FromDB}.\n     * @type {function(object: Object): string}\n     */\n    this._fromDBBuilder = (object) => {\n      const xml = build(object, { compact: false, spaces: 2 });\n      return xml.replace(/\\r?\\n/g, EOL);\n    };\n\n    // eslint-disable-next-line jsdoc/require-param\n    /**\n     * The builder to use with direction {@link TransformDirection.FromFilesystem}.\n     * @type {function(object: Object): string}\n     */\n    this._fromFilesystemBuilder = (object) => {\n      const xml = build(object, { compact: false, spaces: 1 });\n      return xml.replace(/\\r?\\n/g, '\\n');\n    };\n  }\n\n  /**\n   * @protected\n   * @param {import('modify-xml').Element} node The node to handle.\n   */\n  sortedAttributeValues(node) {\n    if (!this.sortXMLAttributes) return attributeValues(node);\n\n    return Object.fromEntries(\n      Object.entries(attributeValues(node)).sort((a, b) => (b > a ? -1 : 1))\n    );\n  }\n\n  /**\n   * Returns the XML builder to use based on the current {@link Transformer#direction}.\n   * @type {function(object: Object): string}\n   */\n  get builder() {\n    return this.direction === TransformDirection.FromDB\n      ? this._fromDBBuilder\n      : this._fromFilesystemBuilder;\n  }\n\n  /**\n   * Parses XML in a node's contents.\n   * @param {Node} node The node to process.\n   */\n  decodeContents(node) {\n    const rawLines =\n      this.direction === TransformDirection.FromDB ? node.value.value.toString() : node.stringValue;\n\n    try {\n      return parse(rawLines);\n    } catch (error) {\n      if (error.line) {\n        Object.assign(error, {\n          rawLines,\n          location: {\n            start: {\n              line: error.line + 1,\n              column: error.column + 1,\n            },\n          },\n        });\n      }\n\n      throw error;\n    }\n  }\n\n  /**\n   * Builds an XML string from an object.\n   * @param {Object} object The object to encode.\n   */\n  encodeContents(object) {\n    return this.builder(object);\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/lib/transform/XMLTransformer.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 564,
    "kind": "function",
    "name": "walk",
    "memberof": "src/lib/transform/XMLTransformer.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/lib/transform/XMLTransformer.js~walk",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/lib/transform/XMLTransformer.js",
    "importStyle": null,
    "description": null,
    "lineNumber": 6,
    "undocument": true,
    "params": [
      {
        "name": "element",
        "types": [
          "*"
        ]
      },
      {
        "name": "action",
        "types": [
          "*"
        ]
      },
      {
        "name": "filter",
        "optional": true,
        "types": [
          "*"
        ],
        "defaultRaw": "isElement",
        "defaultValue": "isElement"
      }
    ],
    "return": null,
    "ignore": true
  },
  {
    "__docId__": 565,
    "kind": "class",
    "name": "XMLTransformer",
    "memberof": "src/lib/transform/XMLTransformer.js",
    "static": true,
    "longname": "src/lib/transform/XMLTransformer.js~XMLTransformer",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/lib/transform/XMLTransformer.js",
    "importStyle": "XMLTransformer",
    "description": "A transformer used to transform XML documents.",
    "lineNumber": 19,
    "interface": false,
    "extends": [
      "src/lib/transform/SplittingTransformer.js~SplittingTransformer"
    ]
  },
  {
    "__docId__": 566,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/lib/transform/XMLTransformer.js~XMLTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/transform/XMLTransformer.js~XMLTransformer#constructor",
    "access": "public",
    "description": "Creates a new XMLTransformer based on some options.",
    "lineNumber": 24,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": true,
        "name": "options",
        "description": "The options to use."
      }
    ]
  },
  {
    "__docId__": 567,
    "kind": "member",
    "name": "sortXMLAttributes",
    "memberof": "src/lib/transform/XMLTransformer.js~XMLTransformer",
    "static": false,
    "longname": "src/lib/transform/XMLTransformer.js~XMLTransformer#sortXMLAttributes",
    "access": "protected",
    "description": null,
    "lineNumber": 28,
    "ignore": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 568,
    "kind": "member",
    "name": "removeBuilderRefs",
    "memberof": "src/lib/transform/XMLTransformer.js~XMLTransformer",
    "static": false,
    "longname": "src/lib/transform/XMLTransformer.js~XMLTransformer#removeBuilderRefs",
    "access": "protected",
    "description": null,
    "lineNumber": 31,
    "ignore": true,
    "type": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 569,
    "kind": "member",
    "name": "_fromDBBuilder",
    "memberof": "src/lib/transform/XMLTransformer.js~XMLTransformer",
    "static": false,
    "longname": "src/lib/transform/XMLTransformer.js~XMLTransformer#_fromDBBuilder",
    "access": "private",
    "description": "The builder to use with direction {@link TransformDirection.FromDB}.",
    "lineNumber": 64,
    "type": {
      "nullable": null,
      "types": [
        "function(object: Object): string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 570,
    "kind": "member",
    "name": "_fromFilesystemBuilder",
    "memberof": "src/lib/transform/XMLTransformer.js~XMLTransformer",
    "static": false,
    "longname": "src/lib/transform/XMLTransformer.js~XMLTransformer#_fromFilesystemBuilder",
    "access": "private",
    "description": "The builder to use with direction {@link TransformDirection.FromFilesystem}.",
    "lineNumber": 74,
    "type": {
      "nullable": null,
      "types": [
        "function(object: Object): string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 571,
    "kind": "method",
    "name": "sortedAttributeValues",
    "memberof": "src/lib/transform/XMLTransformer.js~XMLTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/transform/XMLTransformer.js~XMLTransformer#sortedAttributeValues",
    "access": "protected",
    "description": "",
    "lineNumber": 84,
    "params": [
      {
        "nullable": null,
        "types": [
          "import('modify-xml').Element"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The node to handle."
      }
    ],
    "ignore": true,
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 572,
    "kind": "get",
    "name": "builder",
    "memberof": "src/lib/transform/XMLTransformer.js~XMLTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/transform/XMLTransformer.js~XMLTransformer#builder",
    "access": "public",
    "description": "Returns the XML builder to use based on the current {@link Transformer#direction}.",
    "lineNumber": 96,
    "type": {
      "nullable": null,
      "types": [
        "function(object: Object): string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 573,
    "kind": "method",
    "name": "decodeContents",
    "memberof": "src/lib/transform/XMLTransformer.js~XMLTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/transform/XMLTransformer.js~XMLTransformer#decodeContents",
    "access": "public",
    "description": "Parses XML in a node's contents.",
    "lineNumber": 106,
    "params": [
      {
        "nullable": null,
        "types": [
          "Node"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The node to process."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 574,
    "kind": "method",
    "name": "encodeContents",
    "memberof": "src/lib/transform/XMLTransformer.js~XMLTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/lib/transform/XMLTransformer.js~XMLTransformer#encodeContents",
    "access": "public",
    "description": "Builds an XML string from an object.",
    "lineNumber": 133,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "object",
        "description": "The object to encode."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 575,
    "kind": "file",
    "name": "src/tasks/import.js",
    "content": "import { src } from 'gulp';\nimport scripts from '@atscm/server-scripts';\nimport { version } from '@atscm/server-scripts/package.json';\nimport toPromise from 'stream-to-promise';\nimport { DataType } from 'node-opcua/lib/datamodel/variant';\nimport { StatusCodes } from 'node-opcua/lib/datamodel/opcua_status_code';\nimport Logger from 'gulplog';\nimport ImportStream from '../lib/gulp/ImportStream';\nimport { writeNode, createNode } from '../api';\nimport { versionNode } from '../lib/server/scripts/version';\nimport { delay } from '../lib/helpers/async';\nimport { handleTaskError, finishTask } from '../lib/helpers/tasks';\nimport Session from '../lib/server/Session';\nimport { setupContext } from '../hooks/hooks';\nimport checkAtserver from '../hooks/check-atserver';\n\n/**\n * Imports all xml files needed for atscm usage.\n * @return {Promise<void>} The running task.\n */\nexport default async function importTask() {\n  const srcStream = src(scripts);\n  const versionVariant = { dataType: DataType.String, value: version };\n\n  Session.pool();\n\n  const context = setupContext();\n  await checkAtserver(context);\n\n  return toPromise(srcStream.pipe(new ImportStream()))\n    .then(() => writeNode(versionNode, versionVariant))\n    .catch((err) => {\n      if (err.statusCode === StatusCodes.BadNodeIdUnknown) {\n        const maxTries = 20;\n        const retryDelay = 100;\n\n        let tryNo = 0;\n        const tryToCreate = () => {\n          tryNo++;\n\n          return createNode(versionNode, {\n            name: 'version',\n            value: versionVariant,\n          }).then(async ({ outputArguments }) => {\n            if (outputArguments[3].value.length < 2) {\n              if (tryNo < maxTries) {\n                Logger.debug(`Create script is not ready yet. Retrying after ${retryDelay}ms`);\n\n                await delay(retryDelay);\n                return tryToCreate();\n              }\n\n              throw new Error('CreateNode script is not ready yet. Try again later');\n            }\n\n            return true;\n          });\n        };\n\n        return tryToCreate().then(() => Logger.debug(`Import worked on attempt # ${tryNo}`));\n      }\n\n      throw err;\n    })\n    .then(finishTask, handleTaskError);\n}\n\nimportTask.description = 'Imports all xml resources needed for atscm usage';\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/tasks/import.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 576,
    "kind": "function",
    "name": "importTask",
    "memberof": "src/tasks/import.js",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/tasks/import.js~importTask",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/tasks/import.js",
    "importStyle": "importTask",
    "description": "Imports all xml files needed for atscm usage.",
    "lineNumber": 21,
    "return": {
      "nullable": null,
      "types": [
        "Promise<void>"
      ],
      "spread": false,
      "description": "The running task."
    },
    "params": []
  },
  {
    "__docId__": 577,
    "kind": "file",
    "name": "src/tasks/pull.js",
    "content": "import parseOptions from 'mri';\nimport { emptyDir } from 'fs-extra';\nimport Logger from 'gulplog';\nimport NodeBrowser from '../lib/server/NodeBrowser';\nimport ProjectConfig from '../config/ProjectConfig';\nimport Transformer, { TransformDirection } from '../lib/transform/Transformer.js';\nimport dest from '../lib/gulp/dest';\nimport { reportProgress } from '../lib/helpers/log';\nimport { handleTaskError, finishTask } from '../lib/helpers/tasks';\nimport Session from '../lib/server/Session';\nimport checkAtserver from '../hooks/check-atserver';\nimport { setupContext } from '../hooks/hooks';\n\n/**\n * Pulls the given nodes from the server.\n * @param {NodeId[]} nodes The nodes to pull from the server.\n * @param {Object} options Options passed to {@link NodeBrowser}.\n */\nexport function performPull(nodes, options = {}) {\n  const writeStream = dest('./src', { cleanRenameConfig: options.clean });\n  const applyTransforms = Transformer.combinedTransformer(\n    ProjectConfig.useTransformers,\n    TransformDirection.FromDB\n  );\n\n  const browser = new NodeBrowser({\n    ...options,\n    async handleNode(node, { transform = true } = {}) {\n      let removed = false;\n      const context = {\n        _added: [],\n        addNode(n) {\n          this._added.push(n);\n        },\n        remove: () => {\n          removed = true;\n        },\n      };\n\n      if (transform) {\n        await applyTransforms(node, context);\n      }\n\n      if (removed) {\n        return;\n      }\n      await writeStream.writeAsync(node);\n\n      // Enqueue added nodes\n      if (context._added.length) {\n        context._added.forEach((n) => this.addNode(n));\n      }\n    },\n  });\n\n  return Object.assign(\n    browser.browse(nodes).then(() => writeStream.writeRenamefile()),\n    {\n      browser,\n    }\n  );\n}\n\n/**\n * Pulls all nodes from atvise server.\n * @param {Object} [options] The options to use.\n * @param {boolean} [options.clean] If the source directory should be cleaned first.\n */\nexport default async function pull(options) {\n  const { clean } = typeof options === 'object' ? options : parseOptions(process.argv.slice(2));\n\n  Session.pool();\n\n  // Run hooks\n  const context = setupContext();\n  await checkAtserver(context);\n\n  if (clean) {\n    Logger.info('Using --clean, removing pulled files first');\n    await emptyDir('./src');\n  }\n\n  const promise = performPull(ProjectConfig.nodes, { clean });\n\n  return reportProgress(promise, {\n    getter: () => promise.browser._pushed,\n    formatter: (count) => `Processed ${count} nodes`,\n  }).then(finishTask, handleTaskError);\n}\n\npull.description = 'Pull all nodes from atvise server';\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/tasks/pull.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 578,
    "kind": "function",
    "name": "performPull",
    "memberof": "src/tasks/pull.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/tasks/pull.js~performPull",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/tasks/pull.js",
    "importStyle": "{performPull}",
    "description": "Pulls the given nodes from the server.",
    "lineNumber": 19,
    "params": [
      {
        "nullable": null,
        "types": [
          "NodeId[]"
        ],
        "spread": false,
        "optional": false,
        "name": "nodes",
        "description": "The nodes to pull from the server."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "Options passed to {@link NodeBrowser}."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 579,
    "kind": "function",
    "name": "pull",
    "memberof": "src/tasks/pull.js",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/tasks/pull.js~pull",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/tasks/pull.js",
    "importStyle": "pull",
    "description": "Pulls all nodes from atvise server.",
    "lineNumber": 69,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": true,
        "name": "options",
        "description": "The options to use."
      },
      {
        "nullable": null,
        "types": [
          "boolean"
        ],
        "spread": false,
        "optional": true,
        "name": "options.clean",
        "description": "If the source directory should be cleaned first."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 580,
    "kind": "file",
    "name": "src/tasks/push.js",
    "content": "import Logger from 'gulplog';\nimport { StatusCodes } from 'node-opcua/lib/datamodel/opcua_status_code';\nimport { NodeClass } from 'node-opcua/lib/datamodel/nodeclass';\nimport src from '../lib/gulp/src';\nimport { writeNode, createNode, addReferences } from '../api';\nimport Transformer, { TransformDirection } from '../lib/transform/Transformer.js';\nimport NodeId from '../lib/model/opcua/NodeId.js';\nimport { ReferenceTypeIds, ReferenceTypeNames } from '../lib/model/Node';\nimport { reportProgress } from '../lib/helpers/log.js';\nimport ProjectConfig from '../config/ProjectConfig.js';\nimport { finishTask, handleTaskError } from '../lib/helpers/tasks.js';\nimport Session from '../lib/server/Session.js';\nimport checkServerscripts from '../hooks/check-serverscripts';\nimport checkAtserver from '../hooks/check-atserver';\nimport { setupContext } from '../hooks/hooks';\n\n/**\n * Status codes indicating a node is opened in atvise builder and therefore not writable right now.\n * @type {Set<node-opcua~StatusCodes>}\n */\nconst openInBuilderStatus = new Set([StatusCodes.BadUserAccessDenied, StatusCodes.BadNotWritable]);\n\n/**\n * The reference types ignored when adding references. The corresponding references are created\n * alongside the node itself using the 'CreateNode' server script.\n * @type {Set<node-opcua~ReferenceTypeId>}\n */\nconst ignoredReferences = new Set([\n  ReferenceTypeIds.toParent,\n  ReferenceTypeIds.HasTypeDefinition,\n  // ReferenceTypeIds.HasModellingRule,\n]);\n\n/**\n * Pushes the given path to the server.\n * @param {string} path The local path to push.\n * @param {Object} options Options passed to {@link src}.\n */\nexport function performPush(path, options) {\n  const applyTransforms = Transformer.combinedTransformer(\n    ProjectConfig.useTransformers,\n    TransformDirection.FromFilesystem\n  );\n\n  const ensureReferences = (node) => {\n    const references = [...node.references].reduce((result, [key, value]) => {\n      if (ignoredReferences.has(key)) {\n        return result;\n      }\n\n      return Object.assign(result, {\n        [key]: [...value].map((s) => (typeof s === 'string' ? `ns=1;s=${s}` : s)),\n      });\n    }, {});\n\n    if (Object.keys(references).length > 0) {\n      return addReferences(node.nodeId, references)\n        .then(({ outputArguments }) => {\n          const [{ value: failures }] = outputArguments[3].value;\n\n          if (failures) {\n            throw new Error(\n              `Failed to create reference(s) from ${node.nodeId} to ${failures.join(', ')}`\n            );\n          } else {\n            Logger.debug(`Added ${Object.keys(references).length} reference(s) to ${node.nodeId}`);\n          }\n        })\n        .catch((err) => {\n          throw Object.assign(err, { node });\n        });\n    }\n\n    return Promise.resolve();\n  };\n\n  const create = (node) => {\n    const nodeId = new NodeId(node.nodeId);\n    let parentNodeId = node.parent && node.parent.nodeId;\n\n    if (!node.parent) {\n      parentNodeId = nodeId.parent;\n      Logger.debug(`Assuming ${parentNodeId} as parent of ${node.nodeId}`);\n    }\n\n    return createNode(nodeId, {\n      name: node.name,\n      parentNodeId,\n      nodeClass: node.nodeClass,\n      typeDefinition: node.typeDefinition,\n      modellingRule: node.modellingRule,\n      reference: ReferenceTypeNames[node.references.getSingle(ReferenceTypeIds.toParent)],\n      value:\n        node.nodeClass && node.nodeClass.value === NodeClass.Variable.value && node.variantValue,\n    })\n      .then(({ outputArguments }) => {\n        const [{ value: createdNode }, { value: createFailed }] = outputArguments[3].value;\n\n        if (createFailed) {\n          Logger.warn('Failed to create node', node.nodeId);\n          return Promise.resolve();\n        } else if (createdNode) {\n          Logger.debug('Created node', node.nodeId);\n        } else {\n          // Node already existed\n        }\n\n        return ensureReferences(node);\n      })\n      .catch((err) => {\n        throw Object.assign(err, { node });\n      });\n  };\n\n  return src(path, {\n    ...options,\n    readNodeFile(node) {\n      const r = ProjectConfig.useTransformers\n        .reverse()\n        .reduce((result, t) => (result === undefined ? t.readNodeFile(node) : result), undefined);\n      return r === undefined ? true : r;\n    },\n    async handleNode(node) {\n      // NOTE: context = this\n      await applyTransforms(node, this);\n\n      if (node.push === false) {\n        // Skip write\n        return false;\n      }\n\n      // Create / write node\n      if (node.nodeClass.value !== NodeClass.Variable.value) {\n        return create(node);\n      }\n\n      // console.error('write', node.nodeId, node.value);\n      return writeNode(`ns=1;s=${node.nodeId}`, node.variantValue).then(\n        () => ensureReferences(node),\n        (err) => {\n          if (openInBuilderStatus.has(err.statusCode)) {\n            Logger.warn(`Error writing node ${node.nodeId}\n    - Make sure it is not opened in atvise builder\n    - Make sure the corresponding datasource is connected`);\n            return StatusCodes.Good;\n          }\n\n          if (err.statusCode === StatusCodes.BadNodeIdUnknown) {\n            Logger.debug(`Node ${node.nodeId} does not exist: Attempting to create it...`);\n\n            return create(node);\n          }\n\n          throw Object.assign(err, { node });\n        }\n      );\n    },\n  });\n}\n\n/**\n * Pushes {@link AtviseFile}s to atvise server.\n */\nexport default async function push() {\n  Session.pool();\n\n  const context = setupContext();\n\n  const { version: atserverVersion } = await checkAtserver(context);\n  await checkServerscripts(context);\n\n  const promise = performPush('./src', { atserverVersion });\n\n  return reportProgress(promise, {\n    getter: () => promise.browser._pushedPath.size,\n    formatter: (count) => `Processed ${count} files`,\n  }).then(finishTask, handleTaskError);\n}\n\npush.description = 'Push all stored nodes to atvise server';\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/tasks/push.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 581,
    "kind": "variable",
    "name": "openInBuilderStatus",
    "memberof": "src/tasks/push.js",
    "static": true,
    "longname": "src/tasks/push.js~openInBuilderStatus",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/tasks/push.js",
    "importStyle": null,
    "description": "Status codes indicating a node is opened in atvise builder and therefore not writable right now.",
    "lineNumber": 21,
    "type": {
      "nullable": null,
      "types": [
        "Set<node-opcua~StatusCodes>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 582,
    "kind": "variable",
    "name": "ignoredReferences",
    "memberof": "src/tasks/push.js",
    "static": true,
    "longname": "src/tasks/push.js~ignoredReferences",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/tasks/push.js",
    "importStyle": null,
    "description": "The reference types ignored when adding references. The corresponding references are created\nalongside the node itself using the 'CreateNode' server script.",
    "lineNumber": 28,
    "type": {
      "nullable": null,
      "types": [
        "Set<node-opcua~ReferenceTypeId>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 583,
    "kind": "function",
    "name": "performPush",
    "memberof": "src/tasks/push.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/tasks/push.js~performPush",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/tasks/push.js",
    "importStyle": "{performPush}",
    "description": "Pushes the given path to the server.",
    "lineNumber": 39,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "path",
        "description": "The local path to push."
      },
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "Options passed to {@link src}."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 584,
    "kind": "function",
    "name": "push",
    "memberof": "src/tasks/push.js",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/tasks/push.js~push",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/tasks/push.js",
    "importStyle": "push",
    "description": "Pushes {@link AtviseFile}s to atvise server.",
    "lineNumber": 164,
    "params": [],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 585,
    "kind": "file",
    "name": "src/tasks/watch.js",
    "content": "import { join } from 'path';\nimport sane from 'sane';\nimport browserSync from 'browser-sync';\nimport Logger from 'gulplog';\nimport ServerWatcher from '../lib/server/Watcher';\nimport { delay } from '../lib/helpers/async';\nimport { handleTaskError } from '../lib/helpers/tasks';\nimport ProjectConfig from '../config/ProjectConfig';\nimport { validateDirectoryExists } from '../util/fs';\nimport { setupContext } from '../hooks/hooks';\nimport checkAtserver from '../hooks/check-atserver';\nimport checkServerscripts from '../hooks/check-serverscripts';\nimport { performPull } from './pull';\nimport { performPush } from './push';\n\n/**\n * The task executed when running `atscm watch`.\n */\nexport class WatchTask {\n  /**\n   * Creates a new watch task instance. Also creates a new Browsersync instance.\n   */\n  constructor() {\n    /**\n     * The Browsersync instance used.\n     * @type {events~Emitter}\n     */\n    this.browserSyncInstance = browserSync.create();\n\n    /**\n     * If the task is currently pulling.\n     * @type {boolean}\n     */\n    this._pulling = false;\n\n    /**\n     * If the task is currently pushing.\n     * @type {boolean}\n     */\n    this._pushing = false;\n\n    /**\n     * Timestamp of the last pull\n     * @type {number}\n     */\n    this._lastPull = 0;\n\n    /**\n     * The {@link NodeId} of the last push.\n     * @type {?NodeId}\n     */\n    this._lastPushed = null;\n  }\n\n  /**\n   * The directory to watch.\n   * @type {string}\n   */\n  get directoryToWatch() {\n    return './src';\n  }\n\n  /**\n   * Waits for a watcher (which can actually be any kind of {@link events~Emitter}) to emit a\n   * \"ready\" event.\n   * @param {events~Emitter} watcher The watcher to wait for.\n   * @return {Promise<events~Emitter, Error>} Fulfilled with the set up watcher or rejected with the\n   * watcher error that occurred while waiting for it to get ready.\n   */\n  _waitForWatcher(watcher) {\n    return new Promise((resolve, reject) => {\n      watcher.on('error', (err) => reject(err));\n      watcher.on('ready', () => resolve(watcher));\n    });\n  }\n\n  /**\n   * Starts a file watcher for the directory {@link WatchTask#directoryToWatch}.\n   * @return {Promise<sane~Watcher, Error>} Fulfilled with the file watcher once it is ready or\n   * rejected with the error that occurred while starting the watcher.\n   */\n  startFileWatcher() {\n    return validateDirectoryExists(this.directoryToWatch)\n      .catch((err) => {\n        if (err.code === 'ENOENT') {\n          Logger.info(`Create a directory at ${this.directoryToWatch} or run \\`atscm pull\\` first`);\n\n          Object.assign(err, {\n            message: `Directory ${this.directoryToWatch} does not exist`,\n          });\n        }\n\n        throw err;\n      })\n      .then(() =>\n        this._waitForWatcher(\n          sane(this.directoryToWatch, {\n            glob: '**/*.*',\n            watchman: process.platform === 'darwin',\n          })\n        )\n      );\n  }\n\n  /**\n   * Starts a watcher that watches the atvise server for changes.\n   * @return {Promise<Watcher, Error>} Fulfilled with the server watcher once it is ready or\n   * rejected with the error that occurred while starting the watcher.\n   */\n  startServerWatcher() {\n    return this._waitForWatcher(new ServerWatcher());\n  }\n\n  /**\n   * Initializes {@link WatchTask#browserSyncInstance}.\n   * @param {Object} options The options to pass to browsersync.\n   * @see https://browsersync.io/docs/options\n   */\n  initBrowserSync(options) {\n    this.browserSyncInstance.init(\n      Object.assign(\n        {\n          proxy: `${ProjectConfig.host}:${ProjectConfig.port.http}`,\n          ws: true,\n          // logLevel: 'debug', FIXME: Use log level specified in cli options\n          // logPrefix: '',\n        },\n        options\n      )\n    );\n\n    /* bs.logger.logOne = function(args, msg, level, unprefixed) {\n      args = args.slice(2);\n\n      if (this.config.useLevelPrefixes && !unprefixed) {\n        msg = this.config.prefixes[level] + msg;\n      }\n\n      msg = this.compiler.compile(msg, unprefixed);\n\n      args.unshift(msg);\n\n      Logger[level](format(...args));\n\n      this.resetTemps();\n\n      return this;\n    }; */\n  }\n\n  /**\n   * Prints an error that happened while handling a change.\n   * @param {string} contextMessage Describes the currently run action.\n   * @param {Error} err The error that occured.\n   */\n  printTaskError(contextMessage, err) {\n    try {\n      handleTaskError(err);\n    } catch (refined) {\n      Logger.error(contextMessage, refined.message, refined.stack);\n    }\n  }\n\n  /**\n   * Handles a file change.\n   * @param {string} path The path of the file that changed.\n   * @param {string} root The root of the file that changed.\n   * @return {Promise<boolean>} Resolved with `true` if the change triggered a push operation,\n   * with `false` otherwise.\n   */\n  handleFileChange(path, root) {\n    if (this._handlingChange) {\n      Logger.debug('Ignoring', path, 'changed');\n      return Promise.resolve(false);\n    }\n\n    this._handlingChange = true;\n    Logger.info(path, 'changed');\n\n    return performPush(join(root, path), { singleNode: true })\n      .catch((err) => this.printTaskError('Push failed', err))\n      .then(async () => {\n        this.browserSyncInstance.reload();\n\n        await delay(500);\n\n        this._handlingChange = false;\n      });\n  }\n\n  /**\n   * Handles an atvise server change.\n   * @param {ReadStream.ReadResult} readResult The read result of the modification.\n   * @return {Promise<boolean>} Resolved with `true` if the change triggered a pull operation,\n   * with `false` otherwise.\n   */\n  handleServerChange(readResult) {\n    if (this._handlingChange) {\n      Logger.debug('Ignoring', readResult.nodeId.value, 'changed');\n      return Promise.resolve(false);\n    }\n\n    this._handlingChange = true;\n    Logger.info(readResult.nodeId.value, 'changed');\n\n    return performPull([readResult.nodeId], { recursive: false })\n      .catch((err) => this.printTaskError('Pull failed', err))\n      .then(async () => {\n        this.browserSyncInstance.reload();\n\n        await delay(500);\n\n        this._handlingChange = false;\n      });\n  }\n\n  /**\n   * Starts the file and server watchers, initializes Browsersync and registers change event\n   * handlers.\n   * @param {Object} [options] The options to pass to browsersync.\n   * @param {boolean} [options.open=true] If the browser should be opened once browsersync is up.\n   * @return {Promise<{ serverWatcher: Watcher, fileWatcher: sane~Watcher }, Error>} Fulfilled once\n   * all watchers are set up and Browsersync was initialized.\n   */\n  run({ open = true } = {}) {\n    return Promise.all([this.startFileWatcher(), this.startServerWatcher()]).then(\n      ([fileWatcher, serverWatcher]) => {\n        this.browserSyncInstance.emitter.on('service:running', () => {\n          Logger.info('Watching for changes...');\n          Logger.debug('Press Ctrl-C to exit');\n        });\n\n        fileWatcher.on('change', this.handleFileChange.bind(this));\n        serverWatcher.on('change', this.handleServerChange.bind(this));\n\n        this.initBrowserSync({ open });\n\n        return { fileWatcher, serverWatcher };\n      }\n    );\n  }\n}\n\n/**\n * The gulp task invoced when running `atscm watch`.\n * @param {Object} options The options to pass to the watch task, see {@link WatchTask#run} for\n * available options.\n * @return {Promise<{ serverWatcher: Watcher, fileWatcher: sane~Watcher }, Error>} Fulfilled once\n * all watchers are set up and Browsersync was initialized.\n */\nexport default async function watch(options) {\n  const context = setupContext();\n  await checkAtserver(context);\n  await checkServerscripts(context);\n\n  return new WatchTask().run(options);\n}\n\nwatch.description = 'Watch local files and atvise server nodes to trigger pull/push on change';\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/tasks/watch.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 586,
    "kind": "class",
    "name": "WatchTask",
    "memberof": "src/tasks/watch.js",
    "static": true,
    "longname": "src/tasks/watch.js~WatchTask",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/tasks/watch.js",
    "importStyle": "{WatchTask}",
    "description": "The task executed when running `atscm watch`.",
    "lineNumber": 19,
    "interface": false
  },
  {
    "__docId__": 587,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/tasks/watch.js~WatchTask",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/tasks/watch.js~WatchTask#constructor",
    "access": "public",
    "description": "Creates a new watch task instance. Also creates a new Browsersync instance.",
    "lineNumber": 23
  },
  {
    "__docId__": 588,
    "kind": "member",
    "name": "browserSyncInstance",
    "memberof": "src/tasks/watch.js~WatchTask",
    "static": false,
    "longname": "src/tasks/watch.js~WatchTask#browserSyncInstance",
    "access": "public",
    "description": "The Browsersync instance used.",
    "lineNumber": 28,
    "type": {
      "nullable": null,
      "types": [
        "events~Emitter"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 589,
    "kind": "member",
    "name": "_pulling",
    "memberof": "src/tasks/watch.js~WatchTask",
    "static": false,
    "longname": "src/tasks/watch.js~WatchTask#_pulling",
    "access": "private",
    "description": "If the task is currently pulling.",
    "lineNumber": 34,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 590,
    "kind": "member",
    "name": "_pushing",
    "memberof": "src/tasks/watch.js~WatchTask",
    "static": false,
    "longname": "src/tasks/watch.js~WatchTask#_pushing",
    "access": "private",
    "description": "If the task is currently pushing.",
    "lineNumber": 40,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 591,
    "kind": "member",
    "name": "_lastPull",
    "memberof": "src/tasks/watch.js~WatchTask",
    "static": false,
    "longname": "src/tasks/watch.js~WatchTask#_lastPull",
    "access": "private",
    "description": "Timestamp of the last pull",
    "lineNumber": 46,
    "type": {
      "nullable": null,
      "types": [
        "number"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 592,
    "kind": "member",
    "name": "_lastPushed",
    "memberof": "src/tasks/watch.js~WatchTask",
    "static": false,
    "longname": "src/tasks/watch.js~WatchTask#_lastPushed",
    "access": "private",
    "description": "The {@link NodeId} of the last push.",
    "lineNumber": 52,
    "type": {
      "nullable": true,
      "types": [
        "NodeId"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 593,
    "kind": "get",
    "name": "directoryToWatch",
    "memberof": "src/tasks/watch.js~WatchTask",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/tasks/watch.js~WatchTask#directoryToWatch",
    "access": "public",
    "description": "The directory to watch.",
    "lineNumber": 59,
    "type": {
      "nullable": null,
      "types": [
        "string"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 594,
    "kind": "method",
    "name": "_waitForWatcher",
    "memberof": "src/tasks/watch.js~WatchTask",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/tasks/watch.js~WatchTask#_waitForWatcher",
    "access": "private",
    "description": "Waits for a watcher (which can actually be any kind of {@link events~Emitter}) to emit a\n\"ready\" event.",
    "lineNumber": 70,
    "params": [
      {
        "nullable": null,
        "types": [
          "events~Emitter"
        ],
        "spread": false,
        "optional": false,
        "name": "watcher",
        "description": "The watcher to wait for."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise<events~Emitter, Error>"
      ],
      "spread": false,
      "description": "Fulfilled with the set up watcher or rejected with the\nwatcher error that occurred while waiting for it to get ready."
    }
  },
  {
    "__docId__": 595,
    "kind": "method",
    "name": "startFileWatcher",
    "memberof": "src/tasks/watch.js~WatchTask",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/tasks/watch.js~WatchTask#startFileWatcher",
    "access": "public",
    "description": "Starts a file watcher for the directory {@link WatchTask#directoryToWatch}.",
    "lineNumber": 82,
    "return": {
      "nullable": null,
      "types": [
        "Promise<sane~Watcher, Error>"
      ],
      "spread": false,
      "description": "Fulfilled with the file watcher once it is ready or\nrejected with the error that occurred while starting the watcher."
    },
    "params": []
  },
  {
    "__docId__": 596,
    "kind": "method",
    "name": "startServerWatcher",
    "memberof": "src/tasks/watch.js~WatchTask",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/tasks/watch.js~WatchTask#startServerWatcher",
    "access": "public",
    "description": "Starts a watcher that watches the atvise server for changes.",
    "lineNumber": 110,
    "return": {
      "nullable": null,
      "types": [
        "Promise<Watcher, Error>"
      ],
      "spread": false,
      "description": "Fulfilled with the server watcher once it is ready or\nrejected with the error that occurred while starting the watcher."
    },
    "params": []
  },
  {
    "__docId__": 597,
    "kind": "method",
    "name": "initBrowserSync",
    "memberof": "src/tasks/watch.js~WatchTask",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/tasks/watch.js~WatchTask#initBrowserSync",
    "access": "public",
    "description": "Initializes {@link WatchTask#browserSyncInstance}.",
    "see": [
      "https://browsersync.io/docs/options"
    ],
    "lineNumber": 119,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "The options to pass to browsersync."
      }
    ],
    "return": null
  },
  {
    "__docId__": 598,
    "kind": "method",
    "name": "printTaskError",
    "memberof": "src/tasks/watch.js~WatchTask",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/tasks/watch.js~WatchTask#printTaskError",
    "access": "public",
    "description": "Prints an error that happened while handling a change.",
    "lineNumber": 156,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "contextMessage",
        "description": "Describes the currently run action."
      },
      {
        "nullable": null,
        "types": [
          "Error"
        ],
        "spread": false,
        "optional": false,
        "name": "err",
        "description": "The error that occured."
      }
    ],
    "return": null
  },
  {
    "__docId__": 599,
    "kind": "method",
    "name": "handleFileChange",
    "memberof": "src/tasks/watch.js~WatchTask",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/tasks/watch.js~WatchTask#handleFileChange",
    "access": "public",
    "description": "Handles a file change.",
    "lineNumber": 171,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "path",
        "description": "The path of the file that changed."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "root",
        "description": "The root of the file that changed."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise<boolean>"
      ],
      "spread": false,
      "description": "Resolved with `true` if the change triggered a push operation,\nwith `false` otherwise."
    }
  },
  {
    "__docId__": 600,
    "kind": "member",
    "name": "_handlingChange",
    "memberof": "src/tasks/watch.js~WatchTask",
    "static": false,
    "longname": "src/tasks/watch.js~WatchTask#_handlingChange",
    "access": "private",
    "description": null,
    "lineNumber": 177,
    "undocument": true,
    "type": {
      "types": [
        "boolean"
      ]
    }
  },
  {
    "__docId__": 602,
    "kind": "method",
    "name": "handleServerChange",
    "memberof": "src/tasks/watch.js~WatchTask",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/tasks/watch.js~WatchTask#handleServerChange",
    "access": "public",
    "description": "Handles an atvise server change.",
    "lineNumber": 197,
    "params": [
      {
        "nullable": null,
        "types": [
          "ReadStream.ReadResult"
        ],
        "spread": false,
        "optional": false,
        "name": "readResult",
        "description": "The read result of the modification."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise<boolean>"
      ],
      "spread": false,
      "description": "Resolved with `true` if the change triggered a pull operation,\nwith `false` otherwise."
    }
  },
  {
    "__docId__": 605,
    "kind": "method",
    "name": "run",
    "memberof": "src/tasks/watch.js~WatchTask",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/tasks/watch.js~WatchTask#run",
    "access": "public",
    "description": "Starts the file and server watchers, initializes Browsersync and registers change event\nhandlers.",
    "lineNumber": 225,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": true,
        "name": "options",
        "description": "The options to pass to browsersync."
      },
      {
        "nullable": null,
        "types": [
          "boolean"
        ],
        "spread": false,
        "optional": true,
        "defaultValue": "true",
        "defaultRaw": true,
        "name": "options.open",
        "description": "If the browser should be opened once browsersync is up."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise<{ serverWatcher: Watcher, fileWatcher: sane~Watcher }, Error>"
      ],
      "spread": false,
      "description": "Fulfilled once\nall watchers are set up and Browsersync was initialized."
    }
  },
  {
    "__docId__": 606,
    "kind": "function",
    "name": "watch",
    "memberof": "src/tasks/watch.js",
    "generator": false,
    "async": true,
    "static": true,
    "longname": "src/tasks/watch.js~watch",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/tasks/watch.js",
    "importStyle": "watch",
    "description": "The gulp task invoced when running `atscm watch`.",
    "lineNumber": 251,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": false,
        "name": "options",
        "description": "The options to pass to the watch task, see {@link WatchTask#run} for\navailable options."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise<{ serverWatcher: Watcher, fileWatcher: sane~Watcher }, Error>"
      ],
      "spread": false,
      "description": "Fulfilled once\nall watchers are set up and Browsersync was initialized."
    }
  },
  {
    "__docId__": 607,
    "kind": "file",
    "name": "src/transform/AlarmConfigTransformer.ts",
    "content": "import { DataType } from 'node-opcua/lib/datamodel/variant';\nimport { ItemOf } from 'node-opcua/lib/misc/enum.js';\nimport PartialTransformer from '../lib/transform/PartialTransformer';\nimport Node from '../lib/model/Node';\n\nconst limitNodeNameRegExp = /\\.(upper|lower)_limit(_deadband)?$/;\n\n/**\n * Returns an alarm limit's trigger / source node's data type.\n * Assuming a regular project structure this is the third parent node:\n * **Source** > AlarmConfiguration > AlarmCondition > FilterNode.\n * @param node The limit node to check.\n */\nfunction getLimitTriggerType(node: Node): ItemOf<typeof DataType> | undefined {\n  return (\n    node &&\n    node.parent &&\n    node.parent.parent &&\n    node.parent.parent.parent &&\n    node.parent.parent.parent.dataType\n  );\n}\n\n/**\n * A transformer ensuring no invalid alarm condition filter nodes are pulled.\n */\nexport default class LintTransformer extends PartialTransformer {\n  /**\n   * Returns `true` for all alarm condition filter nodes.\n   * @param node The node to check.\n   */\n  public shouldBeTransformed(node: Node): boolean {\n    return Boolean(\n      node.parent &&\n        node.parent.hasTypeDefinition('ObjectTypes.ATVISE.AlarmConditionControl.Limit') &&\n        node.nodeId.match(limitNodeNameRegExp)\n    );\n  }\n\n  /**\n   * Removes filter alarm condition filter nodes that have an invalid dataType.\n   * @param node The node to transform.\n   * @param context The transform context.\n   */\n  public async transformFromDB(node: Node, { remove }: { remove: () => void }): Promise<void> {\n    if (!this.shouldBeTransformed(node)) return;\n\n    const triggerDataType = getLimitTriggerType(node);\n\n    // NOTE: When no trigger node was found, the node is ignored as well\n    // This means that during incomplete pulls (e.g. in response to a watch event) these nodes are\n    // not updated.\n    if (node.dataType !== triggerDataType) {\n      remove();\n    }\n  }\n\n  /** Does nothing. */\n  public async transformFromFilesystem(): Promise<void> {\n    return;\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/transform/AlarmConfigTransformer.ts",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 608,
    "kind": "variable",
    "name": "limitNodeNameRegExp",
    "memberof": "src/transform/AlarmConfigTransformer.ts",
    "static": true,
    "longname": "src/transform/AlarmConfigTransformer.ts~limitNodeNameRegExp",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/transform/AlarmConfigTransformer.ts",
    "importStyle": null,
    "description": null,
    "lineNumber": 2,
    "undocument": true,
    "type": {
      "types": [
        "undefined"
      ]
    },
    "ignore": true
  },
  {
    "__docId__": 609,
    "kind": "function",
    "name": "getLimitTriggerType",
    "memberof": "src/transform/AlarmConfigTransformer.ts",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/transform/AlarmConfigTransformer.ts~getLimitTriggerType",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/transform/AlarmConfigTransformer.ts",
    "importStyle": null,
    "description": "Returns an alarm limit's trigger / source node's data type.\nAssuming a regular project structure this is the third parent node:\n*Source** > AlarmConfiguration > AlarmCondition > FilterNode.",
    "lineNumber": 14,
    "params": [
      {
        "nullable": null,
        "types": [
          "Node"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "undefined"
      ],
      "spread": false,
      "description": ""
    },
    "ignore": true
  },
  {
    "__docId__": 610,
    "kind": "class",
    "name": "LintTransformer",
    "memberof": "src/transform/AlarmConfigTransformer.ts",
    "static": true,
    "longname": "src/transform/AlarmConfigTransformer.ts~LintTransformer",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/transform/AlarmConfigTransformer.ts",
    "importStyle": "LintTransformer",
    "description": "A transformer ensuring no invalid alarm condition filter nodes are pulled.",
    "lineNumber": 27,
    "interface": false,
    "extends": [
      "src/lib/transform/PartialTransformer.js~PartialTransformer"
    ]
  },
  {
    "__docId__": 611,
    "kind": "method",
    "name": "shouldBeTransformed",
    "memberof": "src/transform/AlarmConfigTransformer.ts~LintTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/transform/AlarmConfigTransformer.ts~LintTransformer#shouldBeTransformed",
    "access": "public",
    "description": "Returns `true` for all alarm condition filter nodes.",
    "lineNumber": 32,
    "params": [
      {
        "nullable": null,
        "types": [
          "Node"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 612,
    "kind": "method",
    "name": "transformFromDB",
    "memberof": "src/transform/AlarmConfigTransformer.ts~LintTransformer",
    "generator": false,
    "async": true,
    "static": false,
    "longname": "src/transform/AlarmConfigTransformer.ts~LintTransformer#transformFromDB",
    "access": "public",
    "description": "Removes filter alarm condition filter nodes that have an invalid dataType.",
    "lineNumber": 45,
    "params": [
      {
        "nullable": null,
        "types": [
          "Node"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": ""
      },
      {
        "nullable": null,
        "types": [
          "undefined"
        ],
        "spread": false,
        "optional": false,
        "name": "undefined",
        "description": ""
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": ""
    }
  },
  {
    "__docId__": 613,
    "kind": "method",
    "name": "transformFromFilesystem",
    "memberof": "src/transform/AlarmConfigTransformer.ts~LintTransformer",
    "generator": false,
    "async": true,
    "static": false,
    "longname": "src/transform/AlarmConfigTransformer.ts~LintTransformer#transformFromFilesystem",
    "access": "public",
    "description": "Does nothing.",
    "lineNumber": 59,
    "return": {
      "nullable": null,
      "types": [
        "Promise"
      ],
      "spread": false,
      "description": ""
    },
    "params": []
  },
  {
    "__docId__": 614,
    "kind": "file",
    "name": "src/transform/Mapping.js",
    "content": "import { basename } from 'path';\nimport assert from 'assert';\nimport { VariantArrayType, DataType } from 'node-opcua/lib/datamodel/variant';\nimport Transformer from '../lib/transform/Transformer';\n\n/**\n * Atvise specific types that need special extensions.\n * @type {Map<string, Object>}\n */\nconst standardTypes = {\n  'VariableTypes.ATVISE.HtmlHelp': {\n    extension: '.help.html',\n    dataType: DataType.ByteString,\n  },\n  'VariableTypes.ATVISE.TranslationTable': {\n    extension: '.locs.xml',\n    dataType: DataType.XmlElement,\n  },\n};\n\n/**\n * Extensions to use for {@link node-opcua~DataType}s.\n * @type {Map<string, string>}\n */\nconst extensionForDataType = {\n  [DataType.Boolean.key]: '.bool',\n  [DataType.SByte.key]: '.sbyte',\n  [DataType.Byte.key]: '.byte',\n  [DataType.Int16.key]: '.int16',\n  [DataType.UInt16.key]: '.uint16',\n  [DataType.Int32.key]: '.int32',\n  [DataType.UInt32.key]: '.uint32',\n  [DataType.Int64.key]: '.int64',\n  [DataType.UInt64.key]: '.uint64',\n  [DataType.Float.key]: '.float',\n  [DataType.Double.key]: '.double',\n  [DataType.String.key]: '.string',\n  [DataType.DateTime.key]: '.datetime',\n  [DataType.Guid.key]: '.guid',\n  // [DataType.ByteString.key]: '.bytestring',\n  [DataType.XmlElement.key]: '.xml',\n  [DataType.NodeId.key]: '.nodeid',\n  [DataType.ExpandedNodeId.key]: '.enodeid',\n  [DataType.StatusCode.key]: '.status',\n  [DataType.QualifiedName.key]: '.name',\n  [DataType.LocalizedText.key]: '.text',\n  [DataType.ExtensionObject.key]: '.obj',\n  [DataType.DataValue.key]: '.value',\n  [DataType.Variant.key]: '.variant',\n  [DataType.DiagnosticInfo.key]: '.info',\n};\n\n/**\n * Extensions to use for {@link node-opcua~VariantArrayType}s.\n * @type {Map<string, string>}\n */\nconst extensionForArrayType = {\n  [VariantArrayType.Array.key]: '.array',\n  [VariantArrayType.Matrix.key]: '.matrix',\n};\n\n/**\n * A Transformer that maps {@link ReadStream.ReadResult}s to {@link AtviseFile}s.\n */\nexport default class MappingTransformer extends Transformer {\n  /**\n   * Creates a new mapping transformer.\n   * @param {Object} [options] The arguments passed to the {@link Transformer} constructor.\n   */\n  constructor(options = {}) {\n    super(options);\n\n    /**\n     * Contents of the reference files read but not used yet.\n     * @type {Object}\n     */\n    this._readReferenceFiles = {};\n  }\n\n  /**\n   * Writes an {@link AtviseFile} for each {@link ReadStream.ReadResult} read. If a read file has a\n   * non-standard type (definition) an additional `rc` file is pushed holding this type.\n   * @param {Node} node The read result to create the file for.\n   * @param {string} encoding The encoding used.\n   * @param {function(err: ?Error, data: ?AtviseFile)} callback Called with the error that occurred\n   * while transforming the read result or the resulting file.\n   */\n  transformFromDB(node, encoding, callback) {\n    if (!node.fullyMapped && !node.parentResolvesMetadata) {\n      // Skip mapping for e.g. split files\n      const typeDefinition = node.typeDefinition;\n      let isStandardTypeNode = false;\n\n      // Add extensions for standard types\n      for (const [def, { extension }] of Object.entries(standardTypes)) {\n        if (node.isVariable && typeDefinition === def) {\n          node.renameTo(`${node.name}${extension}`);\n          isStandardTypeNode = true;\n\n          // FIXME: Set dataType and mark as resolved\n          // FIXME: Set typeDefinition and mark as resolved\n        } else if (node.fileName.endsWith(extension)) {\n          callback(new Error(`Name conflict: ${node.nodeId} should not end with '${extension}'`));\n          return;\n        }\n      }\n\n      // Add extensions for data types\n      for (const [type, ext] of Object.entries(extensionForDataType)) {\n        if (node.isVariable && node.value && node.value.dataType.key === type) {\n          if (!isStandardTypeNode) {\n            node.renameTo(`${node.name}${ext}`);\n            break;\n          }\n\n          // FIXME: Set dataType and mark as resolved\n        }\n      }\n\n      // Add extensions for array types\n      for (const [type, ext] of Object.entries(extensionForArrayType)) {\n        if (node.isVariable && node.value.arrayType.key === type) {\n          if (!isStandardTypeNode) {\n            node.renameTo(`${node.name}${ext}`);\n          }\n\n          // FIXME: Set arrayType and mark as resolved\n        } else if (node.fileName.endsWith(ext)) {\n          callback(new Error(`Name conflict: ${node.nodeId} should not end with '${ext}'`));\n          return;\n        }\n      }\n    }\n\n    // Compact mapping: Root source folders are AGENT, SYSTEM, ObjectTypes and VariableTypes\n    // FIXME: Make optional\n    const ignore = new Set([\n      58, // Objects -> Types -> BaseObjectType\n      62, // Objects -> Types -> BaseVariableType\n      85, // Objects\n      86, // Objects -> Types\n    ]);\n\n    for (let c = node; c && c.parent && !c._compactMappingApplied; c = c.parent) {\n      if (ignore.has(c.parent.id.value)) {\n        c.parent = c.parent.parent;\n        c = node;\n      }\n    }\n\n    Object.assign(node, {\n      _compactMappingApplied: true,\n    });\n\n    callback(null, node);\n  }\n\n  /**\n   * Writes an {@link AtviseFile} for each {@link Node} read.\n   * @param {Node} node The raw file.\n   * @param {string} encoding The encoding used.\n   * @param {function(err: ?Error, data: ?AtviseFile)} callback Called with the error that occurred\n   * while transforming the read result or the resulting file.\n   */\n  transformFromFilesystem(node, encoding, callback) {\n    let isStandardTypeNode = false;\n\n    // Resolve standard type from extension\n    for (const [, { extension }] of Object.entries(standardTypes)) {\n      if (node.name.endsWith(extension)) {\n        isStandardTypeNode = true;\n\n        // FIXME: Set dataType and mark as resolved\n        // FIXME: Set typeDefinition and mark as resolved\n\n        node.renameTo(basename(node.name, extension));\n      }\n    }\n\n    // Resolve arrayType from extension\n    for (const [type, extension] of Object.entries(extensionForArrayType)) {\n      if (node.name.endsWith(extension) && !isStandardTypeNode) {\n        assert.equal(node.arrayType.key, type);\n\n        // FIXME: Set arrayType and mark as resolved\n\n        node.renameTo(basename(node.name, extension));\n        break;\n      }\n    }\n\n    // Resolve dataType from extension\n    for (const [type, extension] of Object.entries(extensionForDataType)) {\n      if (node.name.endsWith(extension) && !isStandardTypeNode && node.dataType.key === type) {\n        // FIXME: Set dataType and mark as resolved\n\n        node.renameTo(basename(node.name, extension));\n        break;\n      }\n    }\n\n    return callback(null, node);\n  }\n\n  /**\n   * `true` as the mapping transformer should infer references from config files.\n   */\n  get transformsReferenceConfigFiles() {\n    return true;\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/transform/Mapping.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 615,
    "kind": "variable",
    "name": "standardTypes",
    "memberof": "src/transform/Mapping.js",
    "static": true,
    "longname": "src/transform/Mapping.js~standardTypes",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/transform/Mapping.js",
    "importStyle": null,
    "description": "Atvise specific types that need special extensions.",
    "lineNumber": 10,
    "type": {
      "nullable": null,
      "types": [
        "Map<string, Object>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 616,
    "kind": "variable",
    "name": "extensionForDataType",
    "memberof": "src/transform/Mapping.js",
    "static": true,
    "longname": "src/transform/Mapping.js~extensionForDataType",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/transform/Mapping.js",
    "importStyle": null,
    "description": "Extensions to use for {@link node-opcua~DataType}s.",
    "lineNumber": 25,
    "type": {
      "nullable": null,
      "types": [
        "Map<string, string>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 617,
    "kind": "variable",
    "name": "extensionForArrayType",
    "memberof": "src/transform/Mapping.js",
    "static": true,
    "longname": "src/transform/Mapping.js~extensionForArrayType",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/transform/Mapping.js",
    "importStyle": null,
    "description": "Extensions to use for {@link node-opcua~VariantArrayType}s.",
    "lineNumber": 57,
    "type": {
      "nullable": null,
      "types": [
        "Map<string, string>"
      ],
      "spread": false,
      "description": null
    },
    "ignore": true
  },
  {
    "__docId__": 618,
    "kind": "class",
    "name": "MappingTransformer",
    "memberof": "src/transform/Mapping.js",
    "static": true,
    "longname": "src/transform/Mapping.js~MappingTransformer",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/transform/Mapping.js",
    "importStyle": "MappingTransformer",
    "description": "A Transformer that maps {@link ReadStream.ReadResult}s to {@link AtviseFile}s.",
    "lineNumber": 65,
    "interface": false,
    "extends": [
      "src/lib/transform/Transformer.js~Transformer"
    ]
  },
  {
    "__docId__": 619,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/transform/Mapping.js~MappingTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/transform/Mapping.js~MappingTransformer#constructor",
    "access": "public",
    "description": "Creates a new mapping transformer.",
    "lineNumber": 70,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": true,
        "name": "options",
        "description": "The arguments passed to the {@link Transformer} constructor."
      }
    ]
  },
  {
    "__docId__": 620,
    "kind": "member",
    "name": "_readReferenceFiles",
    "memberof": "src/transform/Mapping.js~MappingTransformer",
    "static": false,
    "longname": "src/transform/Mapping.js~MappingTransformer#_readReferenceFiles",
    "access": "private",
    "description": "Contents of the reference files read but not used yet.",
    "lineNumber": 77,
    "type": {
      "nullable": null,
      "types": [
        "Object"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 621,
    "kind": "method",
    "name": "transformFromDB",
    "memberof": "src/transform/Mapping.js~MappingTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/transform/Mapping.js~MappingTransformer#transformFromDB",
    "access": "public",
    "description": "Writes an {@link AtviseFile} for each {@link ReadStream.ReadResult} read. If a read file has a\nnon-standard type (definition) an additional `rc` file is pushed holding this type.",
    "lineNumber": 88,
    "params": [
      {
        "nullable": null,
        "types": [
          "Node"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The read result to create the file for."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "encoding",
        "description": "The encoding used."
      },
      {
        "nullable": null,
        "types": [
          "function(err: ?Error, data: ?AtviseFile)"
        ],
        "spread": false,
        "optional": false,
        "name": "callback",
        "description": "Called with the error that occurred\nwhile transforming the read result or the resulting file."
      }
    ],
    "return": null
  },
  {
    "__docId__": 622,
    "kind": "method",
    "name": "transformFromFilesystem",
    "memberof": "src/transform/Mapping.js~MappingTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/transform/Mapping.js~MappingTransformer#transformFromFilesystem",
    "access": "public",
    "description": "Writes an {@link AtviseFile} for each {@link Node} read.",
    "lineNumber": 165,
    "params": [
      {
        "nullable": null,
        "types": [
          "Node"
        ],
        "spread": false,
        "optional": false,
        "name": "node",
        "description": "The raw file."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "encoding",
        "description": "The encoding used."
      },
      {
        "nullable": null,
        "types": [
          "function(err: ?Error, data: ?AtviseFile)"
        ],
        "spread": false,
        "optional": false,
        "name": "callback",
        "description": "Called with the error that occurred\nwhile transforming the read result or the resulting file."
      }
    ],
    "return": {
      "types": [
        "*"
      ]
    }
  },
  {
    "__docId__": 623,
    "kind": "get",
    "name": "transformsReferenceConfigFiles",
    "memberof": "src/transform/Mapping.js~MappingTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/transform/Mapping.js~MappingTransformer#transformsReferenceConfigFiles",
    "access": "public",
    "description": "`true` as the mapping transformer should infer references from config files.",
    "lineNumber": 208,
    "type": {
      "types": [
        "boolean"
      ]
    }
  },
  {
    "__docId__": 624,
    "kind": "file",
    "name": "src/transform/Newlines.js",
    "content": "import { EOL } from 'os';\nimport { DataType } from 'node-opcua/lib/datamodel/variant';\nimport PartialTransformer from '../lib/transform/PartialTransformer';\n\n/**\n * A regular expression matching trailing newlines.\n */\nconst trailingNewlineRegExp = /\\r?\\n$/;\n\n/**\n * A transformer that handles newline characters in files. During a pull, all breaks are converted\n * the OS-native EOL character and (optionally) a trailing newline is added (for better git diffs).\n * On push, CRLF characters are used and those trailing newlines are removed again.\n */\nexport default class NewlinesTransformer extends PartialTransformer {\n  /**\n   * Creates a new newline transformer.\n   * @param {Object} [options={}] The options to use.\n   * @param {boolean} [options.trailingNewlines] If trailing newlines should be added. Pass *true*\n   * for better git diffs.\n   */\n  constructor(options = {}) {\n    super(options);\n\n    /**\n     * If newlines should be added to pulled files.\n     * @type {boolean}\n     */\n    this._addTrailingNewlines = options.trailingNewlines || false;\n  }\n\n  /**\n   * Returns `true` for all files except binary ones.\n   * @param {AtviseFile} file The file being transformed.\n   * @return {boolean} Always `true`.\n   */\n  shouldBeTransformed(file) {\n    return file.stem[0] === '.' || file.dataType !== DataType.ByteString;\n  }\n\n  /**\n   * Adds converts line breaks to the current OS's native EOL characters and adds trailing newlines.\n   * @param {AtviseFile} file The file being transformed.\n   * @param {string} enc The encoding used.\n   * @param {function(err: ?Error, data: ?AtviseFile)} callback Called with the corrected file.\n   */\n  transformFromDB(file, enc, callback) {\n    let str = file.contents.toString().replace(/\\r?\\n/g, EOL);\n\n    if (this._addTrailingNewlines && !str.match(trailingNewlineRegExp)) {\n      str += EOL;\n    }\n\n    file.contents = Buffer.from(str); // eslint-disable-line no-param-reassign\n\n    callback(null, file);\n  }\n\n  /**\n   * Removes trailing newlines and converts all breaks to CRLF.\n   * @param {AtviseFile} file The file being transformed.\n   * @param {string} enc The encoding used.\n   * @param {function(err: ?Error, data: ?AtviseFile)} callback Called with resulting file.\n   */\n  transformFromFilesystem(file, enc, callback) {\n    let str = file.contents.toString().replace(/\\r?\\n/g, '\\r\\n');\n\n    if (this._addTrailingNewlines) {\n      str = str.replace(trailingNewlineRegExp, '');\n    }\n\n    file.contents = Buffer.from(str); // eslint-disable-line no-param-reassign\n\n    callback(null, file);\n  }\n\n  /**\n   * `true` because we want to transform all files.\n   * @type {boolean}\n   */\n  get transformsReferenceConfigFiles() {\n    return true;\n  }\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/transform/Newlines.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 625,
    "kind": "variable",
    "name": "trailingNewlineRegExp",
    "memberof": "src/transform/Newlines.js",
    "static": true,
    "longname": "src/transform/Newlines.js~trailingNewlineRegExp",
    "access": "public",
    "export": false,
    "importPath": "atscm/src/transform/Newlines.js",
    "importStyle": null,
    "description": "A regular expression matching trailing newlines.",
    "lineNumber": 8,
    "type": {
      "types": [
        "undefined"
      ]
    },
    "ignore": true
  },
  {
    "__docId__": 626,
    "kind": "class",
    "name": "NewlinesTransformer",
    "memberof": "src/transform/Newlines.js",
    "static": true,
    "longname": "src/transform/Newlines.js~NewlinesTransformer",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/transform/Newlines.js",
    "importStyle": "NewlinesTransformer",
    "description": "A transformer that handles newline characters in files. During a pull, all breaks are converted\nthe OS-native EOL character and (optionally) a trailing newline is added (for better git diffs).\nOn push, CRLF characters are used and those trailing newlines are removed again.",
    "lineNumber": 15,
    "interface": false,
    "extends": [
      "src/lib/transform/PartialTransformer.js~PartialTransformer"
    ]
  },
  {
    "__docId__": 627,
    "kind": "constructor",
    "name": "constructor",
    "memberof": "src/transform/Newlines.js~NewlinesTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/transform/Newlines.js~NewlinesTransformer#constructor",
    "access": "public",
    "description": "Creates a new newline transformer.",
    "lineNumber": 22,
    "params": [
      {
        "nullable": null,
        "types": [
          "Object"
        ],
        "spread": false,
        "optional": true,
        "defaultValue": "{}",
        "defaultRaw": {},
        "name": "options",
        "description": "The options to use."
      },
      {
        "nullable": null,
        "types": [
          "boolean"
        ],
        "spread": false,
        "optional": true,
        "name": "options.trailingNewlines",
        "description": "If trailing newlines should be added. Pass *true*\nfor better git diffs."
      }
    ]
  },
  {
    "__docId__": 628,
    "kind": "member",
    "name": "_addTrailingNewlines",
    "memberof": "src/transform/Newlines.js~NewlinesTransformer",
    "static": false,
    "longname": "src/transform/Newlines.js~NewlinesTransformer#_addTrailingNewlines",
    "access": "private",
    "description": "If newlines should be added to pulled files.",
    "lineNumber": 29,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 629,
    "kind": "method",
    "name": "shouldBeTransformed",
    "memberof": "src/transform/Newlines.js~NewlinesTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/transform/Newlines.js~NewlinesTransformer#shouldBeTransformed",
    "access": "public",
    "description": "Returns `true` for all files except binary ones.",
    "lineNumber": 37,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file being transformed."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": "Always `true`."
    }
  },
  {
    "__docId__": 630,
    "kind": "method",
    "name": "transformFromDB",
    "memberof": "src/transform/Newlines.js~NewlinesTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/transform/Newlines.js~NewlinesTransformer#transformFromDB",
    "access": "public",
    "description": "Adds converts line breaks to the current OS's native EOL characters and adds trailing newlines.",
    "lineNumber": 47,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file being transformed."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "enc",
        "description": "The encoding used."
      },
      {
        "nullable": null,
        "types": [
          "function(err: ?Error, data: ?AtviseFile)"
        ],
        "spread": false,
        "optional": false,
        "name": "callback",
        "description": "Called with the corrected file."
      }
    ],
    "return": null
  },
  {
    "__docId__": 631,
    "kind": "method",
    "name": "transformFromFilesystem",
    "memberof": "src/transform/Newlines.js~NewlinesTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/transform/Newlines.js~NewlinesTransformer#transformFromFilesystem",
    "access": "public",
    "description": "Removes trailing newlines and converts all breaks to CRLF.",
    "lineNumber": 65,
    "params": [
      {
        "nullable": null,
        "types": [
          "AtviseFile"
        ],
        "spread": false,
        "optional": false,
        "name": "file",
        "description": "The file being transformed."
      },
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "enc",
        "description": "The encoding used."
      },
      {
        "nullable": null,
        "types": [
          "function(err: ?Error, data: ?AtviseFile)"
        ],
        "spread": false,
        "optional": false,
        "name": "callback",
        "description": "Called with resulting file."
      }
    ],
    "return": null
  },
  {
    "__docId__": 632,
    "kind": "get",
    "name": "transformsReferenceConfigFiles",
    "memberof": "src/transform/Newlines.js~NewlinesTransformer",
    "generator": false,
    "async": false,
    "static": false,
    "longname": "src/transform/Newlines.js~NewlinesTransformer#transformsReferenceConfigFiles",
    "access": "public",
    "description": "`true` because we want to transform all files.",
    "lineNumber": 81,
    "type": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": null
    }
  },
  {
    "__docId__": 633,
    "kind": "file",
    "name": "src/typedef/atscm.js",
    "content": "/**\n * @typedef {Object} NodeStream.BrowseResult\n * @property {NodeId} nodeId The discovered node's id.\n * @property {node-opcua~NodeClass} nodeClass The discovered node's class.\n * @property {Map<String, NodeId[]>} references An object holding arrays of references from the\n * discovered node to others, mapped by {@link node-opcua~ReferenceTypeId} keys.\n */\n\n/**\n * @typedef {NodeStream.BrowseResult} ReadStream.ReadResult\n * @property {?node-opcua~DataValue} value For *Variable* nodes this property holds the read data\n * value.\n * @property {?Date} mtime For *Variable* nodes this property holds the timestamp the node's value\n * last changed.\n */\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/typedef/atscm.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 634,
    "kind": "typedef",
    "name": "NodeStream.BrowseResult",
    "memberof": "src/typedef/atscm.js",
    "static": true,
    "longname": "src/typedef/atscm.js~NodeStream.BrowseResult",
    "access": "public",
    "description": "",
    "properties": [
      {
        "nullable": null,
        "types": [
          "NodeId"
        ],
        "spread": false,
        "optional": false,
        "name": "nodeId",
        "description": "The discovered node's id."
      },
      {
        "nullable": null,
        "types": [
          "node-opcua~NodeClass"
        ],
        "spread": false,
        "optional": false,
        "name": "nodeClass",
        "description": "The discovered node's class."
      },
      {
        "nullable": null,
        "types": [
          "Map<String, NodeId[]>"
        ],
        "spread": false,
        "optional": false,
        "name": "references",
        "description": "An object holding arrays of references from the\ndiscovered node to others, mapped by {@link node-opcua~ReferenceTypeId} keys."
      }
    ],
    "type": {
      "types": [
        "Object"
      ],
      "optional": false,
      "name": "NodeStream.BrowseResult"
    }
  },
  {
    "__docId__": 635,
    "kind": "typedef",
    "name": "ReadStream.ReadResult",
    "memberof": "src/typedef/atscm.js",
    "static": true,
    "longname": "src/typedef/atscm.js~ReadStream.ReadResult",
    "access": "public",
    "description": "",
    "properties": [
      {
        "nullable": true,
        "types": [
          "node-opcua~DataValue"
        ],
        "spread": false,
        "optional": false,
        "name": "value",
        "description": "For *Variable* nodes this property holds the read data\nvalue."
      },
      {
        "nullable": true,
        "types": [
          "Date"
        ],
        "spread": false,
        "optional": false,
        "name": "mtime",
        "description": "For *Variable* nodes this property holds the timestamp the node's value\nlast changed."
      }
    ],
    "type": {
      "types": [
        "NodeStream.BrowseResult"
      ],
      "optional": false,
      "name": "ReadStream.ReadResult"
    }
  },
  {
    "__docId__": 636,
    "kind": "file",
    "name": "src/typedef/external/inquirer.js",
    "content": "/**\n * @external {Inquirer} https://github.com/sboudrias/Inquirer.js\n */\n\n/**\n * Must be one of: 'list', 'rawlist', 'expand', 'checkbox', 'confirm', 'input', 'password',\n * 'editor'.\n * @typedef {String} inquirer~PromptType\n * @see https://github.com/sboudrias/Inquirer.js#prompt-types\n */\n\n/**\n * A function that, when called with a value, validates this value and either retunrs `true` if\n * validation succeeded or an error message.\n * @typedef {function(value: String): Boolean|String} inquirer~Validator\n */\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/typedef/external/inquirer.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 637,
    "kind": "external",
    "name": "Inquirer",
    "externalLink": "https://github.com/sboudrias/Inquirer.js",
    "memberof": "src/typedef/external/inquirer.js",
    "static": true,
    "longname": "src/typedef/external/inquirer.js~Inquirer",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 638,
    "kind": "typedef",
    "name": "inquirer~PromptType",
    "memberof": "src/typedef/external/inquirer.js",
    "static": true,
    "longname": "src/typedef/external/inquirer.js~inquirer~PromptType",
    "access": "public",
    "description": "Must be one of: 'list', 'rawlist', 'expand', 'checkbox', 'confirm', 'input', 'password',\n'editor'.",
    "see": [
      "https://github.com/sboudrias/Inquirer.js#prompt-types"
    ],
    "type": {
      "types": [
        "String"
      ],
      "optional": false,
      "name": "inquirer~PromptType"
    }
  },
  {
    "__docId__": 639,
    "kind": "typedef",
    "name": "inquirer~Validator",
    "memberof": "src/typedef/external/inquirer.js",
    "static": true,
    "longname": "src/typedef/external/inquirer.js~inquirer~Validator",
    "access": "public",
    "description": "A function that, when called with a value, validates this value and either retunrs `true` if\nvalidation succeeded or an error message.",
    "type": {
      "types": [
        "function(value: String): Boolean",
        "String"
      ],
      "optional": false,
      "name": "inquirer~Validator"
    }
  },
  {
    "__docId__": 640,
    "kind": "file",
    "name": "src/typedef/external/node-opcua.js",
    "content": "/**\n * @external {node-opcua} http://node-opcua.github.io/api_doc/0.1.0/\n */\n\n/**\n * @external {node-opcua~NodeId} http://node-opcua.github.io/api_doc/0.1.0/classes/NodeId.html\n */\n\n/**\n * @external {node-opcua~NodeIdType} http://node-opcua.github.io/api_doc/0.1.0/classes/NodeIdType.html\n */\n\n/**\n * @external {node-opcua~OPCUAClient} http://node-opcua.github.io/api_doc/0.1.0/classes/OPCUAClient.html\n */\n\n/**\n * @external {node-opcua~ClientSession} http://node-opcua.github.io/api_doc/0.1.0/classes/ClientSession.html\n */\n\n/**\n * @external {node-opcua~ClientSubscription} http://node-opcua.github.io/api_doc/0.1.0/classes/ClientSubscription.html\n */\n\n/**\n * @external {node-opcua~DataValue} http://node-opcua.github.io/api_doc/0.1.0/classes/DataValue.html\n */\n\n/**\n * @external {node-opcua~ReferenceDescription} http://node-opcua.github.io/api_doc/0.1.0/classes/ReferenceDescription.html\n */\n\n/**\n * @external {node-opcua~Variant} http://node-opcua.github.io/api_doc/0.1.0/classes/Variant.html\n */\n\n/**\n * @external {node-opcua~DataType} https://github.com/node-opcua/node-opcua/blob/master/packages/node-opcua-variant/source/DataType_enum.ts\n */\n\n/**\n * @external {node-opcua~VariantArrayType} https://github.com/node-opcua/node-opcua/blob/master/packages/node-opcua-variant/source/VariantArrayType_enum.ts\n */\n\n/**\n * @external {node-opcua~StatusCodes} https://github.com/node-opcua/node-opcua/blob/v0.0.60/lib/raw_status_codes.js\n */\n\n/**\n * @external {node-opcua~CallMethodRequest} http://node-opcua.github.io/api_doc/0.1.0/classes/CallMethodRequest.html\n */\n\n/**\n * @external {node-opcua~ReferenceTypeId} https://github.com/node-opcua/node-opcua/blob/608771099fbfaa42195e150bdf36956affbb53e9/packages/node-opcua-constants/src/opcua_node_ids.js\n */\n\n/**\n * @external {node-opcua~NodeClass} https://github.com/node-opcua/node-opcua/blob/608771099fbfaa42195e150bdf36956affbb53e9/packages/node-opcua-data-model/schemas/NodeClass_enum.js\n */\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/typedef/external/node-opcua.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 641,
    "kind": "external",
    "name": "node-opcua",
    "externalLink": "http://node-opcua.github.io/api_doc/0.1.0/",
    "memberof": "src/typedef/external/node-opcua.js",
    "static": true,
    "longname": "src/typedef/external/node-opcua.js~node-opcua",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 642,
    "kind": "external",
    "name": "node-opcua~NodeId",
    "externalLink": "http://node-opcua.github.io/api_doc/0.1.0/classes/NodeId.html",
    "memberof": "src/typedef/external/node-opcua.js",
    "static": true,
    "longname": "src/typedef/external/node-opcua.js~node-opcua~NodeId",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 643,
    "kind": "external",
    "name": "node-opcua~NodeIdType",
    "externalLink": "http://node-opcua.github.io/api_doc/0.1.0/classes/NodeIdType.html",
    "memberof": "src/typedef/external/node-opcua.js",
    "static": true,
    "longname": "src/typedef/external/node-opcua.js~node-opcua~NodeIdType",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 644,
    "kind": "external",
    "name": "node-opcua~OPCUAClient",
    "externalLink": "http://node-opcua.github.io/api_doc/0.1.0/classes/OPCUAClient.html",
    "memberof": "src/typedef/external/node-opcua.js",
    "static": true,
    "longname": "src/typedef/external/node-opcua.js~node-opcua~OPCUAClient",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 645,
    "kind": "external",
    "name": "node-opcua~ClientSession",
    "externalLink": "http://node-opcua.github.io/api_doc/0.1.0/classes/ClientSession.html",
    "memberof": "src/typedef/external/node-opcua.js",
    "static": true,
    "longname": "src/typedef/external/node-opcua.js~node-opcua~ClientSession",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 646,
    "kind": "external",
    "name": "node-opcua~ClientSubscription",
    "externalLink": "http://node-opcua.github.io/api_doc/0.1.0/classes/ClientSubscription.html",
    "memberof": "src/typedef/external/node-opcua.js",
    "static": true,
    "longname": "src/typedef/external/node-opcua.js~node-opcua~ClientSubscription",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 647,
    "kind": "external",
    "name": "node-opcua~DataValue",
    "externalLink": "http://node-opcua.github.io/api_doc/0.1.0/classes/DataValue.html",
    "memberof": "src/typedef/external/node-opcua.js",
    "static": true,
    "longname": "src/typedef/external/node-opcua.js~node-opcua~DataValue",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 648,
    "kind": "external",
    "name": "node-opcua~ReferenceDescription",
    "externalLink": "http://node-opcua.github.io/api_doc/0.1.0/classes/ReferenceDescription.html",
    "memberof": "src/typedef/external/node-opcua.js",
    "static": true,
    "longname": "src/typedef/external/node-opcua.js~node-opcua~ReferenceDescription",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 649,
    "kind": "external",
    "name": "node-opcua~Variant",
    "externalLink": "http://node-opcua.github.io/api_doc/0.1.0/classes/Variant.html",
    "memberof": "src/typedef/external/node-opcua.js",
    "static": true,
    "longname": "src/typedef/external/node-opcua.js~node-opcua~Variant",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 650,
    "kind": "external",
    "name": "node-opcua~DataType",
    "externalLink": "https://github.com/node-opcua/node-opcua/blob/master/packages/node-opcua-variant/source/DataType_enum.ts",
    "memberof": "src/typedef/external/node-opcua.js",
    "static": true,
    "longname": "src/typedef/external/node-opcua.js~node-opcua~DataType",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 651,
    "kind": "external",
    "name": "node-opcua~VariantArrayType",
    "externalLink": "https://github.com/node-opcua/node-opcua/blob/master/packages/node-opcua-variant/source/VariantArrayType_enum.ts",
    "memberof": "src/typedef/external/node-opcua.js",
    "static": true,
    "longname": "src/typedef/external/node-opcua.js~node-opcua~VariantArrayType",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 652,
    "kind": "external",
    "name": "node-opcua~StatusCodes",
    "externalLink": "https://github.com/node-opcua/node-opcua/blob/v0.0.60/lib/raw_status_codes.js",
    "memberof": "src/typedef/external/node-opcua.js",
    "static": true,
    "longname": "src/typedef/external/node-opcua.js~node-opcua~StatusCodes",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 653,
    "kind": "external",
    "name": "node-opcua~CallMethodRequest",
    "externalLink": "http://node-opcua.github.io/api_doc/0.1.0/classes/CallMethodRequest.html",
    "memberof": "src/typedef/external/node-opcua.js",
    "static": true,
    "longname": "src/typedef/external/node-opcua.js~node-opcua~CallMethodRequest",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 654,
    "kind": "external",
    "name": "node-opcua~ReferenceTypeId",
    "externalLink": "https://github.com/node-opcua/node-opcua/blob/608771099fbfaa42195e150bdf36956affbb53e9/packages/node-opcua-constants/src/opcua_node_ids.js",
    "memberof": "src/typedef/external/node-opcua.js",
    "static": true,
    "longname": "src/typedef/external/node-opcua.js~node-opcua~ReferenceTypeId",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 655,
    "kind": "external",
    "name": "node-opcua~NodeClass",
    "externalLink": "https://github.com/node-opcua/node-opcua/blob/608771099fbfaa42195e150bdf36956affbb53e9/packages/node-opcua-data-model/schemas/NodeClass_enum.js",
    "memberof": "src/typedef/external/node-opcua.js",
    "static": true,
    "longname": "src/typedef/external/node-opcua.js~node-opcua~NodeClass",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 656,
    "kind": "file",
    "name": "src/typedef/external/node.js",
    "content": "/**\n * @external {events~Emitter} https://nodejs.org/api/events.html#events_class_eventemitter\n */\n\n/**\n * @external {fs~Stats} https://nodejs.org/api/fs.html#fs_class_fs_stats\n */\n\n/**\n * @external {util~inspect} https://nodejs.org/api/util.html#util_util_inspect_object_options\n */\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/typedef/external/node.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 657,
    "kind": "external",
    "name": "events~Emitter",
    "externalLink": "https://nodejs.org/api/events.html#events_class_eventemitter",
    "memberof": "src/typedef/external/node.js",
    "static": true,
    "longname": "src/typedef/external/node.js~events~Emitter",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 658,
    "kind": "external",
    "name": "fs~Stats",
    "externalLink": "https://nodejs.org/api/fs.html#fs_class_fs_stats",
    "memberof": "src/typedef/external/node.js",
    "static": true,
    "longname": "src/typedef/external/node.js~fs~Stats",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 659,
    "kind": "external",
    "name": "util~inspect",
    "externalLink": "https://nodejs.org/api/util.html#util_util_inspect_object_options",
    "memberof": "src/typedef/external/node.js",
    "static": true,
    "longname": "src/typedef/external/node.js~util~inspect",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 660,
    "kind": "file",
    "name": "src/typedef/external/p-queue.js",
    "content": "/**\n * @external {p-queue~PQueue} https://github.com/sindresorhus/p-queue#api\n */\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/typedef/external/p-queue.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 661,
    "kind": "external",
    "name": "p-queue~PQueue",
    "externalLink": "https://github.com/sindresorhus/p-queue#api",
    "memberof": "src/typedef/external/p-queue.js",
    "static": true,
    "longname": "src/typedef/external/p-queue.js~p-queue~PQueue",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 662,
    "kind": "file",
    "name": "src/typedef/external/sane.js",
    "content": "/**\n * @external {sane~Watcher} https://github.com/amasad/sane\n */\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/typedef/external/sane.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 663,
    "kind": "external",
    "name": "sane~Watcher",
    "externalLink": "https://github.com/amasad/sane",
    "memberof": "src/typedef/external/sane.js",
    "static": true,
    "longname": "src/typedef/external/sane.js~sane~Watcher",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 664,
    "kind": "file",
    "name": "src/typedef/external/vinyl.js",
    "content": "/**\n * @external {vinyl~File} https://github.com/gulpjs/vinyl#new-vinyloptions\n */\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/typedef/external/vinyl.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 665,
    "kind": "external",
    "name": "vinyl~File",
    "externalLink": "https://github.com/gulpjs/vinyl#new-vinyloptions",
    "memberof": "src/typedef/external/vinyl.js",
    "static": true,
    "longname": "src/typedef/external/vinyl.js~vinyl~File",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 666,
    "kind": "file",
    "name": "src/typedef/external/xml2js.js",
    "content": "/**\n * @external {xml2js~Builder} https://github.com/Leonidas-from-XIV/node-xml2js#options-for-the-builder-class\n */\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/typedef/external/xml2js.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 667,
    "kind": "external",
    "name": "xml2js~Builder",
    "externalLink": "https://github.com/Leonidas-from-XIV/node-xml2js#options-for-the-builder-class",
    "memberof": "src/typedef/external/xml2js.js",
    "static": true,
    "longname": "src/typedef/external/xml2js.js~xml2js~Builder",
    "access": "public",
    "description": ""
  },
  {
    "__docId__": 668,
    "kind": "file",
    "name": "src/util/cleanup.js",
    "content": "import readline from 'readline';\nimport Logger from 'gulplog';\nimport Session from '../lib/server/Session';\n\n/**\n * Cleans up after the app ended with the specified code or signal.\n * @param {?number} exitCode The exit code received.\n * @param {?string} signal The signal that triggered the exit.\n * @param {function()} uninstall The uninstall script to run.\n * @return {boolean} `true` if the process should continue exiting.\n */\nexport default function cleanup(exitCode, signal, uninstall) {\n  uninstall();\n\n  if (signal === 'SIGINT') {\n    readline.clearLine(process.stdout);\n    readline.cursorTo(process.stdout, 0);\n    Logger.warn('Ctrl-C');\n  }\n\n  Logger.debug('Running cleanup...');\n\n  if (Session.open.length > 0) {\n    Logger.debug('  Closing', Session.open.length, 'open sessions...');\n\n    // Ignore further gulp error messages\n    Logger.removeAllListeners('error');\n    Logger.on('error', () => {});\n\n    Session.closeOpen()\n      .then(() => process.kill(process.pid, signal))\n      .catch((e) => {\n        Logger.error('Error in cleanup', e.message);\n        process.kill(process.pid, signal);\n      });\n\n    return false;\n  }\n\n  return true;\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/util/cleanup.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 669,
    "kind": "function",
    "name": "cleanup",
    "memberof": "src/util/cleanup.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/util/cleanup.js~cleanup",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/util/cleanup.js",
    "importStyle": "cleanup",
    "description": "Cleans up after the app ended with the specified code or signal.",
    "lineNumber": 12,
    "params": [
      {
        "nullable": true,
        "types": [
          "number"
        ],
        "spread": false,
        "optional": false,
        "name": "exitCode",
        "description": "The exit code received."
      },
      {
        "nullable": true,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "signal",
        "description": "The signal that triggered the exit."
      },
      {
        "nullable": null,
        "types": [
          "function()"
        ],
        "spread": false,
        "optional": false,
        "name": "uninstall",
        "description": "The uninstall script to run."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "boolean"
      ],
      "spread": false,
      "description": "`true` if the process should continue exiting."
    }
  },
  {
    "__docId__": 670,
    "kind": "file",
    "name": "src/util/fs.js",
    "content": "import { resolve as resolvePath } from 'path';\nimport { stat } from 'fs';\n\n/**\n * Returns the {@link fs~Stats} for a path.\n * @param {string} path The path to look at.\n * @return {Promise<fs~Stats, Error>} Fulfilled with the requested stats or rejected with the error\n * that occurred.\n */\nexport function getStat(path) {\n  return new Promise((resolve, reject) => {\n    stat(resolvePath(path), (err, stats) => {\n      if (err) {\n        reject(err);\n      } else {\n        resolve(stats);\n      }\n    });\n  });\n}\n\n/**\n * Checks it a given path holds a directory and returns it's {@link fs~Stats} if found.\n * @param {string} directoryPath The path to look at.\n * @return {Promise<fs~Stats, Error>} Fulfilled with the directory's stats or rejected with the\n * error that occurred.\n */\nexport function validateDirectoryExists(directoryPath) {\n  return getStat(directoryPath).then((stats) => {\n    if (!stats.isDirectory()) {\n      throw new Error(`${resolvePath(directoryPath)} is not a directory`);\n    }\n\n    return stat;\n  });\n}\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/src/util/fs.js",
    "access": "public",
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 671,
    "kind": "function",
    "name": "getStat",
    "memberof": "src/util/fs.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/util/fs.js~getStat",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/util/fs.js",
    "importStyle": "{getStat}",
    "description": "Returns the {@link fs~Stats} for a path.",
    "lineNumber": 10,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "path",
        "description": "The path to look at."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise<fs~Stats, Error>"
      ],
      "spread": false,
      "description": "Fulfilled with the requested stats or rejected with the error\nthat occurred."
    }
  },
  {
    "__docId__": 672,
    "kind": "function",
    "name": "validateDirectoryExists",
    "memberof": "src/util/fs.js",
    "generator": false,
    "async": false,
    "static": true,
    "longname": "src/util/fs.js~validateDirectoryExists",
    "access": "public",
    "export": true,
    "importPath": "atscm/src/util/fs.js",
    "importStyle": "{validateDirectoryExists}",
    "description": "Checks it a given path holds a directory and returns it's {@link fs~Stats} if found.",
    "lineNumber": 28,
    "params": [
      {
        "nullable": null,
        "types": [
          "string"
        ],
        "spread": false,
        "optional": false,
        "name": "directoryPath",
        "description": "The path to look at."
      }
    ],
    "return": {
      "nullable": null,
      "types": [
        "Promise<fs~Stats, Error>"
      ],
      "spread": false,
      "description": "Fulfilled with the directory's stats or rejected with the\nerror that occurred."
    }
  },
  {
    "kind": "index",
    "content": "# atscm\n\n> Source code management utilities for atvise\n\n[![CircleCI](https://circleci.com/gh/atSCM/atscm.svg?style=shield)](https://circleci.com/gh/atSCM/workflows/atscm)\n[![codecov](https://codecov.io/gh/atSCM/atscm/branch/master/graph/badge.svg)](https://codecov.io/gh/atSCM/atscm)\n[![ESDoc](https://atscm.github.io/atscm/badge.svg)](https://atscm.github.io/atscm)\n\n_atscm_ is a [node.js](https://nodejs.org) based utility that stores the contents of atvise projects on the file system. This has several benefits to advanced atvise developers:\n\n- atvise project can be put under source control (e.g. using _git_)\n- source code can be edited in external editors\n- easier unit testing\n- easier source code linting / static analysis\n- source files can be preprocessed by using custom transformers: <!-- TODO: Insert links -->\n  - using alternate programming languages such as [ES2015 JavaScript](http://babeljs.io/learn-es2015/) or [TypeScript](https://www.typescriptlang.org)\n  - using alternate markup languages such as [pug](https://pugjs.org)\n  - using templating engines such as [handlebars](http://handlebarsjs.com)\n\n<!-- BEGIN overview -->\n\n## Installation\n\nPrerequisite: Install node.js (version 10 or later)\n\n<details><summary>How to check which version is installed</summary>\n\n- Make sure [node.js](https://nodejs.org) (version 10 or later) is installed by running `node --version`.\n- Make sure [npm](https://www.npmjs.com) is installed by running `npm --version`.\n\n</details>\n\n### With atscm-cli\n\n_atscm_ can be installed via [atscm-cli](https://github.com/atSCM/atscm-cli).\n\n> Run `npm install --global atscm-cli` to install _atscm-cli_ globally. _You may have to run this command as an administrator._\n\nWith [atscm-cli](https://github.com/atSCM/atscm-cli) installed run `atscm init` to create a new _atscm_ project.\n\n### With `npm init`\n\nSimply run `npm init atscm` to create a new atscm project.\n\n## Basic usage\n\n**Pulling nodes from atvise server**\n\nRunning `atscm pull` will download all nodes from atvise server into the `./src` folder inside your project.\n\nBy default only displays, serverside scripts and quickdynamics will be split into their JavaScript and SVG sources. You can specify additional transformers to use in your [Project configuration](#project-configuration) file.\n\n**Pushing source files to atvise server**\n\nRunning `atscm push` will update all nodes from the contents of your `./src` folder.\n\n**Automatically watching for changes**\n\nAfter running `atscm watch` files and atvise server nodes are watched for changes. If a file changes, the file is pushed, if a node changes this node is pulled.\n\n`atscm watch` is very useful if you want edit source files in an external editor but still have the ability to use _atvise builder_'s drag and drop functionality.\n\n<!-- END overview -->\n\n## Project configuration\n\nAn atscm project's configuration is stored inside the _Atviseproject_ file inside your project root. See the [Atviseproject class reference](https://atscm.github.io/atscm/class/src/lib/config/Atviseproject.js~Atviseproject.html) for available options.\n",
    "longname": "/home/circleci/project/packages/atscm/README.md",
    "name": "./README.md",
    "static": true,
    "access": "public"
  },
  {
    "kind": "packageJSON",
    "content": "{\n  \"name\": \"atscm\",\n  \"version\": \"1.5.2\",\n  \"description\": \"Source code management utilities for atvise\",\n  \"license\": \"MIT\",\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/atSCM/atscm.git\",\n    \"directory\": \"packages/atscm\"\n  },\n  \"author\": \"Lukas Hechenberger <lukas.hechenberger@bachmann.info>\",\n  \"homepage\": \"https://github.com/atSCM/atscm/tree/master/packages/atscm#readme\",\n  \"bugs\": {\n    \"url\": \"https://github.com/atSCM/atscm/issues\"\n  },\n  \"main\": \"out/index.js\",\n  \"engines\": {\n    \"atscm-cli\": \">=0.7.0\",\n    \"atserver\": \">=3.2.0 <=3.5.2\",\n    \"node\": \">=10.0\"\n  },\n  \"scripts\": {\n    \"build\": \"run-s compile types\",\n    \"compile\": \"babel src --out-dir out --source-maps --extensions .js,.ts\",\n    \"compile:watch\": \"npm run compile -- --watch --verbose\",\n    \"dev\": \"npm run -s compile -- --watch\",\n    \"docs\": \"esdoc -c esdoc.json\",\n    \"docs:coverage\": \"esdoc-coverage -c esdoc.json -t 80\",\n    \"prepublishOnly\": \"npm run compile && npm run docs\",\n    \"schemas\": \"run-s schemas:build schemas:format\",\n    \"schemas:build\": \"node ./scripts/build-schemas.js\",\n    \"schemas:format\": \"prettier schemas types/schemas --write\",\n    \"test\": \"npm run -s test:base -- \\\"test/**/*.spec.js\\\"\",\n    \"test:base\": \"cross-env NODE_ENV=test mocha --recursive --require ./test/prepare --timeout 20000 --exit test/src/maintenance.spec.js\",\n    \"test:coverage\": \"nyc --reporter=html npm run test:unit\",\n    \"test:docs\": \"blcl docs/api --exclude https://circleci.com/gh/atSCM/workflows/atscm\",\n    \"test:integration\": \"npm run -s test:base -- \\\"test/integration/**/*.spec.js\\\"\",\n    \"test:unit\": \"npm run -s test:base -- \\\"test/src/**/*.spec.js\\\"\",\n    \"test:watch\": \"npm test -- --watch --reporter min\",\n    \"types\": \"tsc\"\n  },\n  \"dependencies\": {\n    \"@atscm/server-scripts\": \"0.3.1\",\n    \"@babel/code-frame\": \"^7.5.5\",\n    \"browser-sync\": \"^2.26.7\",\n    \"chalk\": \"^4.0.0\",\n    \"detect-indent\": \"^6.0.0\",\n    \"fs-extra\": \"^6.0.1\",\n    \"gulp\": \"^4.0.2\",\n    \"gulp-compile-handlebars\": \"^0.6.1\",\n    \"gulp-replace\": \"1.0.0\",\n    \"gulplog\": \"^1.0.0\",\n    \"handlebars-helpers\": \"^0.10.0\",\n    \"hasha\": \"^3.0.0\",\n    \"modify-xml\": \"^1.0.0-beta.0\",\n    \"mri\": \"^1.1.4\",\n    \"node-cleanup\": \"^2.1.2\",\n    \"node-opcua\": \"0.0.60\",\n    \"p-queue\": \"^6.2.1\",\n    \"prompts\": \"^2.3.2\",\n    \"sane\": \"^2.5.2\",\n    \"semver\": \"^5.7.1\",\n    \"stream-to-promise\": \"^2.2.0\",\n    \"through2\": \"^2.0.5\",\n    \"validate-npm-package-name\": \"^3.0.0\",\n    \"vinyl\": \"^2.2.0\"\n  },\n  \"devDependencies\": {\n    \"@atscm/esdoc-typescript-plugin\": \"0.1.0\",\n    \"@babel/cli\": \"7.10.5\",\n    \"@babel/core\": \"7.11.4\",\n    \"@babel/plugin-proposal-class-properties\": \"7.10.4\",\n    \"@babel/plugin-proposal-object-rest-spread\": \"7.11.0\",\n    \"@babel/preset-env\": \"7.11.0\",\n    \"@babel/preset-typescript\": \"7.10.4\",\n    \"@babel/register\": \"7.10.5\",\n    \"@ls-age/esdoc-coverage\": \"0.1.6\",\n    \"@types/fs-extra\": \"8.1.0\",\n    \"@types/mri\": \"1.1.0\",\n    \"@types/semver\": \"7.1.0\",\n    \"babel-plugin-istanbul\": \"6.0.0\",\n    \"broken-link-checker-local\": \"0.2.1\",\n    \"buffer-replace\": \"1.0.0\",\n    \"camelcase\": \"6.2.0\",\n    \"codecov\": \"3.7.2\",\n    \"cross-env\": \"7.0.2\",\n    \"esdoc\": \"1.1.0\",\n    \"esdoc-ecmascript-proposal-plugin\": \"1.0.0\",\n    \"esdoc-standard-plugin\": \"1.0.0\",\n    \"eval\": \"0.1.4\",\n    \"istanbul-combine\": \"0.3.0\",\n    \"json-schema-to-typescript\": \"10.1.3\",\n    \"mocha\": \"8.1.2\",\n    \"mocha-circleci-reporter\": \"0.0.3\",\n    \"npm-run-all\": \"4.1.5\",\n    \"nyc\": \"15.1.0\",\n    \"proxyquire\": \"2.1.3\",\n    \"sinon\": \"9.0.3\",\n    \"typescript\": \"3.9.7\",\n    \"unexpected\": \"11.14.0\",\n    \"unexpected-sinon\": \"10.11.2\",\n    \"unexpected-stream\": \"4.0.0\",\n    \"yargs\": \"15.4.1\"\n  },\n  \"types\": \"out/types/src/index.d.ts\",\n  \"nyc\": {\n    \"all\": true,\n    \"include\": [\n      \"src/**/*.js\",\n      \"src/**/*.ts\"\n    ],\n    \"exclude\": [\n      \"res/**/*.*\"\n    ],\n    \"require\": [\n      \"@babel/register\"\n    ],\n    \"sourceMap\": false,\n    \"instrument\": false,\n    \"check-coverage\": true\n  }\n}\n",
    "longname": "/home/circleci/project/packages/atscm/package.json",
    "name": "package.json",
    "static": true,
    "access": "public"
  },
  {
    "kind": "manualIndex",
    "globalIndex": false,
    "content": null,
    "longname": "",
    "static": true,
    "access": "public"
  },
  {
    "kind": "manual",
    "longname": "/home/circleci/project/packages/atscm/docs/manual/get-started/updating.md",
    "name": "./docs/manual/get-started/updating.md",
    "content": "# Updating atscm\n\n> You can use atscm to update atscm 😀\n\n## Installing new versions\n\nSimply run `atscm update` to install the latest version available. Add the `--beta` flag to install prerelease versions. Ensure to **backup your project** before doing so.\n\n> Internally, we use [npm](https://www.npmjs.com) to install updates, which means that you can also run `npm install --save-dev atscm` instead.\n\n## Updating your atscm project\n\nWe'll do our best to follow [semantic versioning](https://semver.org), which means you shouldn't need to update your project sources between non-major releases, e.g. when updating from _1.0.0_ to _1.0.1_ or _1.1.0_.\n\nBetween major releases (e.g. from 0.7.0 to 1.0.0) we introduce changes that may break your existing project. **Follow these steps to migrate your project to a new major version of atscm:**\n\n- Backup your project _before_, e.g. with git: `git add . && git commit -m \"chore: Backup before atscm update\"`\n- Start a fresh atvise server instance and push your current project: `atscm push`\n- Update atscm: `atscm update`\n- Pull your project sources from atvise server: `atscm pull --clean`\n- Afterwards, you can commit commit the changes: `git add . && git commit -m \"chore: Update atscm\"`\n",
    "static": true,
    "access": "public"
  },
  {
    "kind": "manual",
    "longname": "/home/circleci/project/packages/atscm/docs/manual/tutorial/custom-transformer.md",
    "name": "./docs/manual/tutorial/custom-transformer.md",
    "content": "# Tutorial: Custom Transformer\n\n> tl;dr: Jump to the [tutorial-custom-transformer repository](https://github.com/atSCM/tutorial-custom-transformer) to see the results.\n\nIn this document we'll guide you through the steps necessary to implement a custom Transformer.\nOur transformer will use [Babel](http://babeljs.io) to transpile ES2015/ES6 JavaScript to plain ES5 JavaScript that works in all Browsers.\n\n## Overview\n\nCustom transformers provide an easy way to extend the build functionality of _atscm_. Basically, a transformer implements two behaviours: How atvise server nodes are mapped to files (when running `atscm pull`) and vice versa (when running `atscm push`).\n\n**Where to store transformers**\n\nBasically, transformers can be stored anywhere inside your _atscm_ project. When using a non-ES5 configuration language (such as ES2015 or TypeScript, chosen when running `atscm init`) transformers should also be written in this language. _atscm_ will handle the transpilation of your transformer code automatically. If you plan to write multiple custom transformers for your project, it is recommended to create your transformers in an own directory, e.g `./atscm`.\n\n## Step 0: Project setup\n\nIn order to have the same starting point, create a new _atscm_ project to follow this tutorial. Run `atscm init` and **pick ES2015 as configuration language**.\n\nAs for now the atvise library is written in old ES5 JavaScript, we'll ignore it in our project. Adjust your project configuration accordingly:\n\n```javascript\n// Atviseproject.babel.js\n\n...\n\nexport default class MyProject extends Atviseproject {\n  ...\n\n  static get ignoreNodes() {\n    return super.ignoreNodes\n      .concat(['ns=1;s=SYSTEM.LIBRARY.ATVISE']);\n  }\n\n}\n```\n\nNow we're ready to pull the project by running:\n\n```\natscm pull\n```\n\nWe'll use the default project files for testing later.\n\nAs suggested above, we'll store our custom transformer inside a new directory, `./atscm`. Create the directory and an empty file called _BabelTransformer.js_:\n\n```bash\nmkdir atscm\ntouch atscm/BabelTransformer.js\n```\n\nBy now you should have a project containing an `./Atviseproject.babel.js` and an empty `./atscm/BabelTransformer.js` file.\nMake sure the `./src` directory contains at least the _default Main display_ which should exist inside `./src/AGENT/DISPLAYS/Main.display`.\n\n## Step 1: Import _PartialTransformer_ class\n\nAs we don't want to implement things twice we'll subclass _atscm_'s [Transformer class](https://atscm.github.io/atscm/class/src/lib/transform/Transformer.js~Transformer.html). As our transformer shall only be used for JavaScript source files we can even use the [PartialTransformer class](https://atscm.github.io/atscm/class/src/lib/transform/PartialTransformer.js~PartialTransformer.html) which supports filtering source files out of the box. As both of these classes are exported from _atscm_'s main file, importing them is pretty straightforward. Inside the _BabelTransformer.js_ file add:\n\n```javascript\n// atscm/BabelTransformer.js\n\nimport { PartialTransformer } from 'atscm';\n```\n\n## Step 2: Create the _BabelTransformer_ class\n\nThe next step is to create and export our Transformer class:\n\n```javascript\n// atscm/BabelTransformer.js\n\nimport { PartialTransformer } from 'atscm';\n\nexport default class BabelTransformer extends PartialTransformer {}\n```\n\nWe just created a _PartialTransformer_ subclass that is exported as the file's default export. For more detailed information on ES2015's module system [take a look at the docs](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/export).\n\n## Step 3: Use _BabelTransformer_\n\nBy default, _atscm_ uses just some standard transformers. Any additional transformers must be configured to use inside the project's _Atviseproject_ file.\n\nFirst of all, we have to import our newly created _BabelTransformer_ class:\n\n```javascript\n// Atviseproject.babel.js\n\nimport { Atviseproject } from 'atscm'\nimport BabelTransformer from './atscm/BabelTransformer';\n\nexport default class MyProject extends Atviseproject { ... }\n```\n\nNow we override the _Atviseproject.useTransformers_ [getter](https://developer.mozilla.org/de/docs/Web/JavaScript/Reference/Functions/get) to use our transformer:\n\n```javascript\n// Atviseproject.babel.js\n\n...\n\nexport default class MyProject extends Atviseproject {\n  ...\n\n  static get useTransformers() {\n    return super.useTransformers\n      .concat(new BabelTransformer());\n  }\n\n}\n```\n\nThis statement tells _atscm_ to use a new _BabelTransformer_ instance **in addition to the default transformers** (`super.useTransformers`).\n\nTo verify everything worked so far run `atscm config`. Our new Transformer should show up in the _useTransformers_ section:\n\n```\n$ atscm config\n[08:38:16] Configuration at ~/custom-transformer/Atviseproject.babel.js\n{ host: '10.211.55.4',\n  port:\n   { opc: 4840,\n     http: 80 },\n  useTransformers:\n   [ DisplayTransformer<>,\n     ScriptTransformer<>,\n     BabelTransformer<> ],\n  ...\n```\n\n## Step 4: Implement _PartialTransformer#shouldBeTransformed_\n\n[PartialTransformer#shouldBeTransformed](https://atscm.github.io/atscm/class/src/lib/transform/PartialTransformer.js~PartialTransformer.html#instance-method-shouldBeTransformed) is responsible for filtering the files we want to transform. Returning `true` means the piped file will be transformed, `false` bypasses the file.\n\nIn out case we want to edit all JavaScript source files. Therefore we return true for all files with the extension `.js`. Edit _BabelTransformer.js_ accordingly:\n\n```javascript\n// atscm/BabelTransformer\n\n...\n\nexport default class BabelTransformer extends PartialTransformer {\n\n  shouldBeTransformed(file) {\n    return file.extname === '.js';\n  }\n\n}\n```\n\n## Step 5: Implement _Transformer#transformFromFilesystem_\n\nImplementing [Transformer#transformFromFilesystem](https://atscm.github.io/atscm/class/src/lib/transform/Transformer.js~Transformer.html#instance-method-transformFromFilesystem) is probably the most important part of this tutorial. In here we define the logic that actually creates ES5 code from ES2015 sources.\n\nFirst of all, we need to **install additional dependencies** required. Running\n\n```bash\nnpm install --save-dev babel-core babel-preset-2015\n```\n\nwill install [Babel](http://babeljs.io) and it's ES2015 preset. This preset ensures all ES5 compatible browsers will be able to run the resulting code.\n\nWe will also need the [node.js buffer module](https://nodejs.org/api/buffer.html). We don't need to install it, as it comes with every node installation.\n\nNext, import these modules as usual:\n\n```javascript\n// atscm/BabelTransformer.js\n\nimport { Buffer } from 'buffer';\nimport { PartialTransformer } from 'atscm';\nimport { transform } from 'babel-core';\n\n...\n```\n\nThe import order follows a pretty usual convention:\n\n1.  Core **node.js modules** (_buffer_ in our case)\n2.  Other **external modules** (_babel-core_ and _atscm_ in our case)\n3.  **Relative modules** (_./atscm/BabelTransformer.js_ inside _Atviseproject.babel.js_ in our case)\n\nNow we're ready to implement _Transformer#transformFromFilesystem_. What we're about to do is pretty simple:\n\n- We'll transpile the contents of the passed file with babels _transform_ method\n- We clone the passed file and set it's contents to a Buffer containing the resulting code\n- We pass the resulting file to other streams\n\n```javascript\nimport ...\n\nexport default class BabelTransformer extends PartialTransformer {\n\n  static shouldBeTransformed(file) { ... }\n\n  transformFromFilesystem(file, enc, callback) {\n    // Create ES5 code\n    const { code } = transform(file.contents, {\n      presets: ['es2015']\n    });\n\n    // Create new file with ES5 content\n    const result = file.clone();\n    result.contents = Buffer.from(code);\n\n    // We're done, pass the new file to other streams\n    callback(null, result);\n  }\n\n}\n```\n\n**Wow!** You just implemented your first custom transformer! Now we can write any scripts using the new ES2015 syntax.\n\n## Step 6: Test _BabelTransformer_\n\nIt's time to check if everything works as expected. Create a script file for the Main display containing ES2015 JavaScript:\n\n```javascript\n// src/AGENT/DISPLAYS/Main.display/Main.js\n\n// Class syntax\nclass Test {\n  constructor(options = {}, ...otherArgs) {\n    // Default values and rest params\n    this.options = options;\n    this.args = otherArgs.map((arg) => parseInt(arg, 10)); // Arrows and Lexical This\n  }\n}\n\nconst a = 13; // Constants\nconst { options, args } = new Test({ a }, '23'); // Enhanced Object Literals\n\nalert(`Option a: ${options.a}, args: ${args.join(', ')}`); // Template Strings\n```\n\nRun `atscm push` to upload the new display script to atvise server. Open your atvise project in your favorite browser (you may have to delete the browser cache) and if everything worked you should see an alert box containing the text \"Option a: 13, args: 23\". When you inspect the page's source you'll see the display script code was transpiled to ES5.\n\n## Step 7: Implement _Transformer#transformFromDB_\n\nAs said at the beginning, atscm transformers allow transformation from and to the filesystem. A babel transpilation is a one-way process, meaning you cannot create ES2015 source code from the resulting ES5 code. Therefore the only thing we can do when transforming from atvise server to the filesystem is to prevent an override.\n\nWe do so by implementing [Transformer#transformFromDB](https://atscm.github.io/atscm/class/src/lib/transform/Transformer.js~Transformer.html#instance-method-transformFromDB):\n\n```javascript\n// atscm/BabelTransformer.js\n...\n\nexport default class BabelTransformer extends PartialTransfromer {\n  ...\n\n  transformFromDB(file, enc, callback) {\n    // Optionally, we could print a warning here\n    callback(null); // Ignore file, remove it from the stream\n  }\n}\n```\n\nNow we can run `atscm push` without overriding our ES2015 source code.\n\n## Result\n\nThis is how your custom transformer should look now:\n\n```javascript\n// atscm/BabelTransformer.js\n\nimport { Buffer } from 'buffer';\nimport { PartialTransformer } from 'atscm';\nimport { transform } from 'babel-core';\n\nexport default class BabelTransformer extends PartialTransformer {\n  shouldBeTransformed(file) {\n    return file.extname === '.js';\n  }\n\n  transformFromFilesystem(file, enc, callback) {\n    // Create ES5 code\n    const { code } = transform(file.contents, {\n      presets: ['es2015'],\n    });\n\n    // Create new file with ES5 content\n    const result = file.clone();\n    result.contents = Buffer.from(code);\n\n    // We're done, pass the new file to other streams\n    callback(null, result);\n  }\n\n  transformFromDB(file, enc, callback) {\n    callback(null); // Ignore file, remove it from the stream\n  }\n}\n```\n\n## Conclusion\n\nWe just created a custom Transformer in no time. It transpiles ES2015 code on push and prevents overriding this code on pull.\n\nOf course there are many ways to improve the transformer, for example:\n\n- Handle options to configure how babel transpiles the source code\n\n## Further reading\n\n- [babeljs.io](http://babeljs.io/learn-es2015/) provides a nice overview of ES2015 features. You can also use the [REPL](http://babeljs.io/repl/) to try out these features.\n",
    "static": true,
    "access": "public"
  },
  {
    "kind": "manual",
    "longname": "/home/circleci/project/packages/atscm/docs/manual/advanced/id-conflicts.md",
    "name": "./docs/manual/advanced/id-conflicts.md",
    "content": "# Node ID conflicts\n\n> **Note that rename files are not available for atscm < v1.0.0.** Use `atscm update` to use the latest version\n\n## How atscm handles id conflicts\n\nLet's assume we have two atvise server nodes, _AGENT.OBJECT.conflictingnode_ and _AGENT.OBJECT.ConflictingNode_. These are valid node ids on the server, but when stored to the (case-insensitive) filesystem, the behaviour is undefined.\n\nWhen _atscm_ discovers such a name conflict it creates a _rename file_ at `./atscm/rename.json`. This file will contain a map where the conflicting ids stored against the name to use to resolve the conflict. by default _insert node name_ is used, e.g.:\n\n```json\n{\n  \"AGENT.OBJECTS.ConflictingNode\": \"insert node name\"\n}\n```\n\n## How to resolve id conflicts\n\nOnce an id conflict is recognized and added to the rename file, it is your responsibility to provide non-conflicting node names, e.g.:\n\n```json\n{\n  \"AGENT.OBJECTS.ConflictingNode\": \"ConflictingNode-renamed\"\n}\n```\n\nAfter that **run `atscm pull` again** to pull the conflicting nodes.\n",
    "static": true,
    "access": "public"
  },
  {
    "kind": "manual",
    "longname": "/home/circleci/project/packages/atscm/docs/manual/advanced/gulp-plugins.md",
    "name": "./docs/manual/advanced/gulp-plugins.md",
    "content": "# Guide: gulp.js plugins\n\n> **Please note:** This guide assumes you have a basic knowledge on how gulp.js and custom _atscm_ transformers work. You may go through [gulp's getting started guide](https://github.com/gulpjs/gulp/blob/master/docs/getting-started.md) or the [custom transformer tutorial](https://atscm.github.io/atscm/manual/tutorial/custom-transformer.html) first otherwise.\n\n_atscm_ heavily relies on the [gulp.js](http://gulpjs.com) build tool. Therefore it's pretty easy to integrate existing [gulp plugins](http://gulpjs.com/plugins/) into _atscm_ transformers.\n\n## Using _Transformer_ class\n\nBasically, the only Transformer method you have to override is [Transformer#applyToStream](https://atscm.github.io/atscm/class/src/lib/transform/Transformer.js~Transformer.html#instance-method-applyToStream). In there, you can pipe your gulp plugin just as you would do in a regular gulp project. The only difference is, that you have to handle the current transform direction as well:\n\n**A basic example:**\n\n```javascript\nimport { Transformer, TransformDirection } from 'atscm';\nimport fromDBGulpPlugin from 'gulp-plugin-to-use-from-db';\nimport fromFSGulpPlugin from 'gulp-plugin-to-use-from-fs';\n\nclass MyTransformer extends Transformer {\n  applyToStream(stream, direction) {\n    if (direction === TransformDirection.FromDB) {\n      return stream.pipe(fromDBGulpPlugin(/* plugin options */));\n    }\n\n    return stream.pipe(fromFSGulpPlugin(/* plugin options */));\n  }\n}\n```\n\n## Using _PartialTransformer_ class\n\nIn most cases you'll have to transform only parts of the piped files. This can be done by inheriting from [PartialTransfomer class](https://atscm.github.io/atscm/class/src/lib/transform/PartialTransformer.js~PartialTransformer.html):\n\n**Transforming only JavaScript files:**\n\n```javascript\nimport { PartialTransformer, TransformDirection } from 'atscm';\nimport fromDBGulpPlugin from 'gulp-plugin-to-use-from-db';\nimport fromFSGulpPlugin from 'gulp-plugin-to-use-from-fs';\n\nclass MyPartialTransformer extends PartialTransformer {\n  shouldBeTransformed(file) {\n    return file.extname === '.js';\n  }\n\n  applyToFilteredStream(stream, direction) {\n    if (direction === TransformDirection.FromDB) {\n      return stream.pipe(fromDBGulpPlugin(/* plugin options */));\n    }\n\n    return stream.pipe(fromFSGulpPlugin(/* plugin options */));\n  }\n}\n```\n\n## Conclusion\n\nUsing existing gulp plugins is probably the easiest way to use custom transformers inside an _atscm_ project. As there are **thousands of well-tested gulp-plugins** out there, you won't have to implemtent any transform logic in most cases.\n\nGive it a try!\n\n## Further reading\n\n- Take a look at [gulp's plugin page](http://gulpjs.com/plugins/) for a list of available plugins.\n",
    "static": true,
    "access": "public"
  },
  {
    "kind": "manual",
    "longname": "/home/circleci/project/packages/atscm/docs/manual/advanced/debugging.md",
    "name": "./docs/manual/advanced/debugging.md",
    "content": "# Guide: Debugging atscm\n\n_atscm_ can be easily debugged using Google Chrome's developer tools. All you have to do to attach the debugger, is to start the command line interface with the `--inspect` or `--inspect-brk` flag. For this to work you must first find the path to _atscm-cli_'s executable:\n\n```bash\nwhich atscm\n```\n\n**Note: This only works on Linux and macOS only**\n\nYou can now use this executable directly and run it with the inspector flags, e.g.:\n\n```bash\nnode --inspect-brk \"$(which atscm)\" [arguments passed to atscm]\n```\n\n[For further details on how to use the debugger, visit the offical nodejs docs on debugging.](https://nodejs.org/en/docs/guides/debugging-getting-started/)\n",
    "static": true,
    "access": "public"
  },
  {
    "kind": "manual",
    "longname": "/home/circleci/project/packages/atscm/docs/manual/advanced/error-handling.md",
    "name": "./docs/manual/advanced/error-handling.md",
    "content": "# Guide: Error handling\n\n## Adding source locations\n\nWhen a throwing an Error that was caused by client code, you should provide location info so it can be traced back to the source code.\n\nTo do so, simply add additional properties to the error object, containing the source code, the start location and (optionally) the end location.\n\n```javascript\nfunction myTransformCode() {\n  const sourceCode = 'the code transformed';\n\n  try {\n    // Do something that may throw an error...\n  } catch (error) {\n    Object.assign(error, {\n      rawLines: sourceCode, // A string containing the raw source code\n      location: {\n        start: {\n          line: 1, // The line number\n          column: 1, // The column number\n        },\n        // you could add a 'end' property here, with the same signature as 'start'\n      },\n    });\n\n    // Finally re-throw the error\n    throw error;\n  }\n}\n```\n\n**Example output: XML Parse error**\n\n```\n[13:30:28] Using gulpfile ~/Downloads/delete/atscm-330/node_modules/atscm/out/Gulpfile.js\n[13:30:28] Starting 'pull'...\n[13:30:30] 'pull' errored after 1.09 s\n[13:30:30] closing tag mismatch\n  5 |   <atv:gridconfig width=\"20\" gridstyle=\"lines\" enabled=\"false\" height=\"20\"/>\n  6 |   <atv:snapconfig width=\"10\" enabled=\"false\" height=\"10\"/>\n> 7 |  </metadata>\n    |  ^ closing tag mismatch\n  8 | </svg>\n  9 |\n   - Node: AGENT.DISPLAYS.Main\n```\n\n**Details**\n\n- [`@babel/code-frame`](https://babeljs.io/docs/en/babel-code-frame) is used to render the frame.\n",
    "static": true,
    "access": "public"
  },
  {
    "kind": "manual",
    "longname": "/home/circleci/project/packages/atscm/docs/manual/advanced/api.md",
    "name": "./docs/manual/advanced/api.md",
    "content": "# Guide: Using the API\n\n> Learn how to use the atscm API to e.g. run server serverscripts in your node application.\n> **Available since atscm v1.0.0.** Use `atscm update` to use the latest version\n\n## Installation\n\nFirst of all, make sure your project has atscm installed: Take a look at your _package.json_ file and make sure, atscm is present in the _dependencies_ or (depending on your use case) _devDependencies_ section. Otherwise, **install atscm if necessary**:\n\n```bash\n# If you need atscm as a runtime-dependency\nnpm install --save atscm\n\n# If you need atscm as a development dependency (most likely)\nnpm install --save-dev atscm\n```\n\n## Configuration\n\nSimilar to regular atscm projects, you need an _Atviseproject_ file that contains atscm's configuration. A minimal example may look like this:\n\n```js\n// Atviseproject.js\nconst { Atviseproject } = require('atscm');\n\nmodule.exports = class ApiProject extends Atviseproject {\n  // Add your configuration here, if needed.\n  // By default, atvise server is assumed to run on opc.tcp://localhost:4840\n};\n```\n\nBefore you can finally require the atscm API in your project, you have to **set the `ATSCM_CONFIG_PATH` environment variable**, pointing to your _Atviseproject_ file. You can do this in multiple ways:\n\n- You can set it in your app at runtime (_recommended_)\n\n  Adjust your app's entry file (assuming it's called _app.js_ in these examples) to set the variable **before you import atscm**:\n\n  ```js\n  // app.js\n  const { join } = require('path');\n\n  process.env.ATSCM_CONFIG_PATH = join(__dirname, '../Atviseproject.js');\n\n  // Your app comes here...\n  ```\n\n- You can set it every time you run your application:\n\n  E.g. instead of running your app with `node ./app.js` you can use `ATSCM_CONFIG_PATH=\"/my-project/Atviseproject.js\" node ./app.js`.\n\n  You can also use npm scripts so you simply have to run `npm run start`:\n\n  ```json\n  // package.json\n  {\n    \"scripts\": {\n      \"start\": \"ATSCM_CONFIG_PATH='/my-project/Atviseproject.js' node ./app.js\"\n    }\n  }\n  ```\n\n  If your running on windows, use [`cross-env`](https://www.npmjs.com/package/cross-env) to set the environment variable (don't forget `npm install cross-env`):\n\n  ```json\n  // package.json\n  {\n    \"scripts\": {\n      \"start\": \"cross-env ATSCM_CONFIG_PATH='/my-project/Atviseproject.js' node ./app.js\"\n    }\n  }\n  ```\n\n## Usage\n\nRequire `atscm/api` and call the methods you need:\n\n```js\n// Set process.env.ATSCM_CONFIG_PATH here...\n\nconst atscm = require('atscm/api');\n\n// You can use atscm here...\n```\n\n## Examples\n\n**Create an export file for a node**\n\n```js\n// app.js\n\n// Import node core modules\nconst { promises: fsp } = require('fs');\nconst { join, dirname } = require('path');\n\n// Set atscm config env variable\nprocess.env.ATSCM_CONFIG_PATH = join(__dirname, './Atviseproject.js');\n\n// Require atscm and node-opcua APIs\nconst { NodeId } = require('atscm');\nconst { callMethod } = require('atscm/api');\nconst { Variant, DataType, VariantArrayType } = require('node-opcua');\n\n// Configuration: You could also use process.argv here...\nconst nodesToExport = ['AGENT.DISPLAYS.Main'];\nconst exportPath = './out/export.xml';\n\n// Our main function\nasync function createExportFile() {\n  console.log(`Exporting nodes: ${nodesToExport.join(',')}`);\n\n  // Use the 'exportNodes' method to create an xml export on the server\n  const {\n    outputArguments: [{ value }],\n  } = await callMethod(new NodeId('AGENT.OPCUA.METHODS.exportNodes'), [\n    new Variant({\n      dataType: DataType.NodeId,\n      arrayType: VariantArrayType.Array,\n      value: nodesToExport.map((id) => new NodeId(id)),\n    }),\n  ]);\n\n  // Create the output directory if needed\n  await fsp.mkdir(dirname(exportPath), { recursive: true });\n\n  // Write the export to the file\n  await fsp.writeFile(exportPath, value);\n\n  console.log(`Export written to ${exportPath}`);\n}\n\n// Run it and catch any errors\ncreateExportFile().catch((error) => {\n  console.error(error);\n  process.exitCode = 1;\n});\n```\n\n> Note: The example assumes the Atviseproject file is located in the same directory as the app's entry file. Otherwise you have to adjust you code accordingly.\n",
    "static": true,
    "access": "public"
  },
  {
    "kind": "manual",
    "longname": "/home/circleci/project/packages/atscm/docs/manual/contribute/testing.md",
    "name": "./docs/manual/contribute/testing.md",
    "content": "# Contribute: Testing atscm\n\natscm uses both unit and integration tests. [Mocha](https://mochajs.org) is used as a test runner and [nyc](https://github.com/istanbuljs/nyc#readme) for test coverage reports.\n\n**Test scripts:**\n\n| Command                    | Description                        |\n| :------------------------- | :--------------------------------- |\n| `npm run test`             | Run all tests                      |\n| `npm run test:unit`        | Run all unit tests                 |\n| `npm run test:integration` | Run all integration tests          |\n| `npm run test:watch`       | Re-run all tests when files change |\n| `npm run test:coverage`    | Check test coverage                |\n\n## Unit tests\n\nThe unit tests are located inside `./test/src`. Test files are named after the module they test, e.g. unit tests for `./src/my/module.js` are inside `./test/src/my/module.spec.js`.\n\n## Integration tests\n\nIntegration tests are used to ensure cross-version and -platform compatibility. They are located inside `./test/integration`.\n\n### Test setups\n\nFor most integration tests, we use test setups to create the proper project structure to test against. These are XML files that can be imported to the running atserver before the tests are run. **The easiest way to create such files is with atbuilder:**\n\n- First _connect atvise builder_ to your running atserver\n- Create and _configure the node(s)_ you want to test against\n- Select theses nodes, right-click them and choose _\"Export hierarchy to XML\"_ from the context menu.\n- Save the export file to `./test/fixtures/setup`.\n\nAfter this, you can use the _importSetup_ method exported from [`./test/helpers/atscm.js`](./test/helpers/atscm.js) to import this setup. See the existing integration tests for examples.\n",
    "static": true,
    "access": "public"
  },
  {
    "kind": "manual",
    "longname": "/home/circleci/project/.github/CONTRIBUTING.md",
    "name": "../../.github/CONTRIBUTING.md",
    "content": "# Contributing\n\nWe would love for you to contribute to atSCM. As a contributor, here are the guidelines we would like you to follow:\n\n## Found a bug?\n\nIf you find a bug in the source code, you can help us by submitting an issue to this repository. Even better, you can submit a Pull Request with a fix.\n\n## Missing a feature?\n\nYou can _request_ a new feature by submitting an issue to this repository. If you would like to _implement_ a new feature, please submit an issue with a proposal for your work first, to be sure that we can use it.\n\n## Submission Guidelines\n\n### Submitting an issue\n\nBefore you submit an issue, please search the issue tracker, maybe an issue for your problem already exists and the discussion might inform you of workarounds readily available.\n\nWe can only fix an issue if we can reproduce it. To help us provide the following information in your issue description:\n\n- **The original error message:** Any console output regarding the issue. Consider running _atscm_ with verbose logging (using the command line option `-LLLL`) to get more error details.\n- **_atscm_ and _atscm-cli_ versions used:** The results of `atscm --version`.\n- **atvise server version used**\n- **_node_ and _npm_ versions used:** The results of `node --version` and `npm version`.\n- **Special project setup:** Any default overrides to your `Atviseproject.js` file, such as custom Transformers.\n\n### Submitting a Pull Request (PR)\n\nBefore you submit your Pull Request (PR) consider the following guidelines:\n\n- Search GitHub for an open or closed PR that relates to your submission. You don't want to duplicate effort.\n- Make your changes in a new git branch: Run `git checkout -b my-fix-branch master`\n- Create your patch, **including appropriate test cases**.\n- Run the full test suite and ensure all tests pass.\n- Commit your changes using a descriptive commit message that follows our commit message conventions. Adherence to these conventions is necessary because release notes are automatically generated from these messages.\n- Push your branch to GitHub and create a pull request **to merge back to the beta branch**.\n- Once we reviewed your changes, we'll merge your pull request.\n\n> **Merge strategy (Maintainers only)**\n>\n> - Accepted changes from fix/feature branches **should always be squash-merged** to beta.\n> - Once beta is stable **create a regular merge commit** to merge back to master.\n> - After merging to master, changes should be synced back to the beta branch. To do so, run:\n>   ```bash\n>   git checkout beta\n>   git fetch\n>   git rebase origin/master\n>   # Solve conflicts if any, accepting changes from master\n>   git commit -m 'chore: Update from master'\n>   git push\n>   ```\n\n## Code quality control\n\n> All files inside this project are automatically built, linted and tested by [CircleCI](https://circleci.com/gh/atSCM/atscm).\n\nBuilds will only pass if they meet the following criteria:\n\n- **No ESLint errors:** We use [ESLint](http://eslint.org) to lint our entire JavaScript code. The config used is [eslint-config-lsage](https://www.npmjs.com/package/eslint-config-lsage). Any lint errors will cause the build to fail.\n- **Test coverage >= 90%:** We use [istanbul](https://gotwarlost.github.io/istanbul/) to validate test coverage is at least 90 percent. Any commits not covered by tests will cause the build to fail.\n- **Documentation coverage >= 90%:** Our source code is documented using [ESDoc](https://esdoc.org). We will only merge if your contribution is documented as well.\n\n## Setting up the development environment\n\n> In order to meet out coding guideline it's very useful to have your development environment set up right.\n\n### Linting files\n\nYou can lint all source files by running `npm run lint`. Although most IDEs support running it directly in the editor:\n\n**Jetbrains Webstorm**\n\n[Webstorm](https://www.jetbrains.com/webstorm/) has built-in support for ESLint. Check out [their documentation](https://www.jetbrains.com/help/webstorm/2016.3/eslint.html) to set it up.\n\n**Atom**\n\n[Atom](https://atom.io) has several packages that provide support for inline ESLint validation. We recommend you to use [linter-eslint](https://atom.io/packages/linter-eslint).\n\n### Running tests\n\nOur [mocha](https://mochajs.org) tests can be run by calling `npm test`. If you want the tests to be run right after you saved your changes, then run `npm run test:watch`.\n\n**Setup needed to run tests on atvise server**\n\nPlease note, that you have to **provide a valid atvise server connection** in order to get tests against atvise server running. You can achieve that by doing one of the following:\n\n- Set environment variables `ATVISE_USERNAME` and `ATVISE_PASSWORD` to valid credentials for the public atvise demo server at [demo.ativse.com](http://185.67.228.66:8888).\n- Adapt host, ports and login credentials inside `./test/fixtures/Atviseproject.babel.js`.\n\n**Check test coverage**\n\nTest coverage can be checked by running `npm run test:coverage`.\n\n### Creating API documentation\n\nRun `npm run docs` to create [ESDoc](https://esdoc.org) API documentation.\n\n<!-- TODO: Add steps for creating good issues -->\n<!-- TODO: Add links to documentation and manuals -->\n\n## Commit Message Guideline\n\nWe have very precise rules over how our git commit messages can be formatted. This leads to more readable messages that are easy to follow when looking through the project history. But also, we use the git commit messages to **generate the changelog**.\n\n### Commit message format\n\n> tl;dr: We use an adaption of the [angular commit message convention](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-commit-message-guidelines) with the only difference that capitalized subjects are allowed.\n\nEach commit message consists of a _header_, a _body_ and a footer. The header has a special format that includes a _type_, a _scope_ and a _subject_:\n\n```\n<type>(<scope>): <subject>\n\n<body>\n\n<footer>\n```\n\nThe _header_ is mandatory and the _scope_ of the _header_ is optional. It cannot be longer than **72 characters**.\n\n**Samples**\n\n- Describe a documentation change\n\n  `docs(changelog): Update changelog for version 1.2.3`\n\n- Describes a bug fix affecting mapping\n\n  ```\n  fix(mapping): Replace invalid data type for html help documents\n\n  Prevents html help documents to have an invalid extension unter atvise server v3.1.0.\n\n  Closes #123\n  ```\n\n#### Type\n\nMust be one of the following:\n\n- **build:** Changes that affect the build system or external dependencies (example scopes: babel, npm)\n- **chore:** Maintainance tasks (example tasks: release)\n- **ci:** Changes to our CI configuration files and scripts (example scopes: circleci, appveyor, codecov)\n- **docs:** Documentation only changes\n- **feat:** A new feature\n- **fix:** A bug fix\n- **perf:** A code change that improves performance\n- **refactor:** A code change that neither fixes a bug nor adds a feature\n- **revert:** Reverts a previous commit.\n- **style:** Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)\n- **test:** Adding missing tests or correcting existing tests\n\n#### Scope\n\nThe scope should describe the feature affected. Must be lower case.\n\n#### Subject\n\nThe subject contains succinct description of the change:\n\n- Use the imperative, present tense: \"change\" not \"changed\" nor \"changes\"\n- Capitalize first letter _(The only notable difference to the [angular commit message convention](https://github.com/angular/angular/blob/master/CONTRIBUTING.md#-commit-message-guidelines))_\n- no dot (.) at the end\n\n#### Body\n\nJust as in the subject, use the imperative, present tense: \"change\" not \"changed\" nor \"changes\". The body should include the motivation for the change and contrast this with previous behavior.\n\n#### Footer\n\nThe footer should contain any information about **Breaking Changes** and is also the place to reference GitHub issues that this commit **Closes**.\n\n**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.\n\n### Commit message linting\n\nThe project is setup to use a **git hook that lints commit messages** before creating a commit. Do not bypass this hook.\n\nSee [husky's documentation on git GUI support](https://github.com/typicode/husky#git-gui-clients-support).\n",
    "static": true,
    "access": "public"
  },
  {
    "kind": "manual",
    "longname": "/home/circleci/project/packages/atscm/CHANGELOG.md",
    "name": "./CHANGELOG.md",
    "content": "<a name=\"1.5.2\"></a>\n## 1.5.2 (2021-03-23)\n\n\n### Bug Fixes\n\n* **atscm:** Support atserver 3.5.2 ([#453](https://github.com/atSCM/atscm/issues/453)) ([a9d5a3a](https://github.com/atSCM/atscm/commits/a9d5a3a))\n\n\n\n\n<a name=\"atscm-v1.5.1\"></a>\n# atscm-v1.5.1 (2021-02-19)\n\n\n### Bug Fixes\n\n* **atscm:** Add missing init dependency ([#449](https://github.com/atSCM/atscm/issues/449)) ([4ac28ba](https://github.com/atSCM/atscm/commits/4ac28ba))\n\n\n\n\n<a name=\"atscm-v1.5.0\"></a>\n# atscm-v1.5.0 (2021-02-17)\n\n\n### Features\n\n* **pull:** Create config files only if necessary ([#448](https://github.com/atSCM/atscm/issues/448)) ([90aed75](https://github.com/atSCM/atscm/commits/90aed75))\n\n\n\n\n<a name=\"atscm-v1.4.2\"></a>\n# atscm-v1.4.2 (2021-02-17)\n\n\n### Bug Fixes\n\n* **pull:** Do not pull empty display scripts ([#447](https://github.com/atSCM/atscm/issues/447)) ([9fbaba1](https://github.com/atSCM/atscm/commits/9fbaba1))\n\n\n\n\n<a name=\"atscm-v1.4.1\"></a>\n# atscm-v1.4.1 (2021-02-16)\n\n\n### Bug Fixes\n\n* **atscm:** Format init template files ([#440](https://github.com/atSCM/atscm/issues/440)) ([e0c8521](https://github.com/atSCM/atscm/commits/e0c8521))\n\n\n\n\n<a name=\"atscm-v1.4.0\"></a>\n# atscm-v1.4.0 (2021-02-15)\n\n\n### Features\n\n* **atscm:** Support for atvise server 3.5.x ([#432](https://github.com/atSCM/atscm/issues/432)) ([853e347](https://github.com/atSCM/atscm/commits/853e347))\n\n\n\n\n<a name=\"atscm-v1.3.0\"></a>\n# atscm-v1.3.0 (2021-02-11)\n\n\n### Features\n\n* **atscm:** Allow sorting of XML attributes ([#438](https://github.com/atSCM/atscm/issues/438)) ([31cf329](https://github.com/atSCM/atscm/commits/31cf329))\n\n\n\n\n<a name=\"atscm-v1.2.0\"></a>\n# atscm-v1.2.0 (2021-01-30)\n\n\n### Features\n\n* Add JSON schemas for config files ([#435](https://github.com/atSCM/atscm/issues/435)) ([fbc2fbb](https://github.com/atSCM/atscm/commits/fbc2fbb))\n\n\n\n\n<a name=\"create-atscm-v0.1.0\"></a>\n# create-atscm-v0.1.0 (2021-01-25)\n\n\n\n\n<a name=\"atscm-v1.1.3\"></a>\n# atscm-v1.1.3 (2021-01-25)\n\n\n### Bug Fixes\n\n* **init:** Rename gitignore in init template ([#428](https://github.com/atSCM/atscm/issues/428)) ([1a75245](https://github.com/atSCM/atscm/commits/1a75245))\n\n\n\n\n<a name=\"atscm-v1.1.2\"></a>\n# atscm-v1.1.2 (2021-01-18)\n\n\n### Bug Fixes\n\n* **init:** Initialize gitignore ([#427](https://github.com/atSCM/atscm/issues/427)) ([5ea887e](https://github.com/atSCM/atscm/commits/5ea887e))\n\n\n\n\n<a name=\"atscm-v1.1.1\"></a>\n# atscm-v1.1.1 (2021-01-18)\n\n\n### Bug Fixes\n\n* **push:** Allow brackets in file names ([#425](https://github.com/atSCM/atscm/issues/425)) ([3699795](https://github.com/atSCM/atscm/commits/3699795))\n\n\n\n",
    "static": true,
    "access": "public"
  },
  {
    "__docId__": 673,
    "kind": "testFile",
    "name": "test/integration/api/manuals-example.spec.js",
    "content": "import { promises as fsp } from 'fs';\nimport { join, dirname } from 'path';\nimport { Variant, DataType, VariantArrayType } from 'node-opcua';\nimport { NodeId } from '../../..';\nimport { callMethod } from '../../../api';\nimport expect from '../../expect';\nimport { tmpDir } from '../../helpers/util';\n\ndescribe('Manual API example', () => {\n  // Configuration: You could also use process.argv here...\n  const nodesToExport = ['AGENT.DISPLAYS.Main'];\n  const outDir = tmpDir('manuals-example');\n  const exportPath = join(outDir, 'export.xml');\n\n  // Our main function\n  async function createExportFile() {\n    console.log(`Exporting nodes: ${nodesToExport.join(',')}`);\n\n    // Use the 'exportNodes' method to create an xml export on the server\n    const {\n      outputArguments: [{ value }],\n    } = await callMethod(new NodeId('AGENT.OPCUA.METHODS.exportNodes'), [\n      new Variant({\n        dataType: DataType.NodeId,\n        arrayType: VariantArrayType.Array,\n        value: nodesToExport.map((id) => new NodeId(id)),\n      }),\n    ]);\n\n    // Create the output directory if needed\n    await fsp.mkdir(dirname(exportPath), { recursive: true });\n\n    // Write the export to the file\n    await fsp.writeFile(exportPath, value);\n\n    console.log(`Export written to ${exportPath}`);\n  }\n\n  it('should work as promised', async () => {\n    await expect(createExportFile(), 'to be fulfilled');\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/integration/api/manuals-example.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 674,
    "kind": "test",
    "name": "describe0",
    "testId": 0,
    "memberof": "test/integration/api/manuals-example.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/api/manuals-example.spec.js~describe0",
    "access": null,
    "description": "Manual API example",
    "lineNumber": 9
  },
  {
    "__docId__": 675,
    "kind": "test",
    "name": "it1",
    "testId": 1,
    "memberof": "test/integration/api/manuals-example.spec.js~describe0",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/api/manuals-example.spec.js~describe0.it1",
    "access": null,
    "description": "should work as promised",
    "lineNumber": 39
  },
  {
    "__docId__": 676,
    "kind": "testFile",
    "name": "test/integration/issues/issue-157.spec.js",
    "content": "import { DataType } from 'node-opcua';\nimport watch from '../../../src/tasks/watch';\nimport { importSetup, callScript } from '../../helpers/atscm';\n\ndescribe.skip('watch task', function () {\n  context('when a watched node is deleted', function () {\n    it('should not error', async function () {\n      const nodeName = await importSetup('issue-157', 'DeleteDisplay');\n      const nodeId = `AGENT.DISPLAYS.atSCM.watch.${nodeName}`;\n\n      // Start watch task\n      const { serverWatcher } = await watch({ open: false });\n\n      // Wait until deletion is recognized\n      const isTestNode = (r) => r.nodeId.value.split(nodeId).length > 1;\n      const changeCalled = new Promise((resolve, reject) => {\n        serverWatcher.on('change', (r) => {\n          if (isTestNode(r)) {\n            reject();\n          }\n        });\n\n        serverWatcher.on('delete', (r) => {\n          if (isTestNode(r)) {\n            resolve();\n          }\n        });\n      });\n\n      // Delete the node\n      await callScript('DeleteNode', {\n        nodeId: {\n          dataType: DataType.String,\n          value: nodeId,\n        },\n      });\n\n      return changeCalled;\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/integration/issues/issue-157.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 677,
    "kind": "test",
    "name": "context2",
    "testId": 2,
    "memberof": "test/integration/issues/issue-157.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-157.spec.js~context2",
    "access": null,
    "description": "when a watched node is deleted",
    "lineNumber": 6
  },
  {
    "__docId__": 678,
    "kind": "test",
    "name": "it3",
    "testId": 3,
    "memberof": "test/integration/issues/issue-157.spec.js~context2",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/issues/issue-157.spec.js~context2.it3",
    "access": null,
    "description": "should not error",
    "lineNumber": 7
  },
  {
    "__docId__": 679,
    "kind": "testFile",
    "name": "test/integration/issues/issue-170.spec.js",
    "content": "import { expectCorrectMapping } from '../../helpers/atscm';\n\ndescribe.skip('push task', function () {\n  context('when pushing SMTP servers', function () {\n    expectCorrectMapping('issue-170/smtp-server', {\n      path: 'AGENT.SMTPSERVERS',\n      name: 'TestSMTPServer',\n    });\n  });\n\n  context('when pushing node with alarm configuration', function () {\n    expectCorrectMapping('issue-170/node-with-alarmconfig', {\n      path: 'AGENT.OBJECTS',\n      name: 'TestWithAlarmConfig',\n    });\n  });\n\n  // NOTE: This only works on atvise server 3+\n  context('when pushing webserver with protected call', function () {\n    expectCorrectMapping('issue-170/webserver-with-protectedcall', {\n      path: 'AGENT.WEBACCESS',\n      name: 'http2',\n    });\n  });\n\n  context('when pushing archives with partition interval and file limit', function () {\n    expectCorrectMapping('issue-170/archive-interval-filelimit', {\n      path: 'AGENT.HISTORY',\n      name: 'TestArchive',\n    });\n  });\n\n  context('when pushing aggregate templates and functions', function () {\n    expectCorrectMapping('issue-170/aggregate-template', {\n      path: 'AGENT.HISTORY.AGGREGATETEMPLATES',\n      name: 'TestAggregateTemplate',\n    });\n  });\n\n  context('when pushing custom alarm category', function () {\n    expectCorrectMapping('issue-170/alarm-category', {\n      path: 'SYSTEM.LIBRARY.PROJECT.ALARMCATEGORIES',\n      name: 'TestAlarmCategory',\n    });\n  });\n\n  context('when pushing custom user groups', function () {\n    expectCorrectMapping('issue-170/user-and-group', {\n      path: ['SYSTEM.SECURITY.GROUPS', 'SYSTEM.SECURITY.USERS'],\n      name: ['TestGroup', 'TestUser'],\n    });\n  });\n\n  context('when pushing serverscripts in redundant project', function () {\n    expectCorrectMapping('issue-170/redundancy-serverscript', {\n      path: 'SYSTEM.LIBRARY.PROJECT.SERVERSCRIPTS',\n      name: 'LongRunningScript',\n    });\n  });\n\n  context('when pushing resources with compress properties', function () {\n    expectCorrectMapping('issue-170/compressed-node', {\n      path: 'SYSTEM.LIBRARY.PROJECT.RESOURCES',\n      name: 'CompressedNode.html',\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/integration/issues/issue-170.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 680,
    "kind": "test",
    "name": "context4",
    "testId": 4,
    "memberof": "test/integration/issues/issue-170.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-170.spec.js~context4",
    "access": null,
    "description": "when pushing SMTP servers",
    "lineNumber": 4
  },
  {
    "__docId__": 681,
    "kind": "test",
    "name": "context5",
    "testId": 5,
    "memberof": "test/integration/issues/issue-170.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-170.spec.js~context5",
    "access": null,
    "description": "when pushing node with alarm configuration",
    "lineNumber": 11
  },
  {
    "__docId__": 682,
    "kind": "test",
    "name": "context6",
    "testId": 6,
    "memberof": "test/integration/issues/issue-170.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-170.spec.js~context6",
    "access": null,
    "description": "when pushing webserver with protected call",
    "lineNumber": 19
  },
  {
    "__docId__": 683,
    "kind": "test",
    "name": "context7",
    "testId": 7,
    "memberof": "test/integration/issues/issue-170.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-170.spec.js~context7",
    "access": null,
    "description": "when pushing archives with partition interval and file limit",
    "lineNumber": 26
  },
  {
    "__docId__": 684,
    "kind": "test",
    "name": "context8",
    "testId": 8,
    "memberof": "test/integration/issues/issue-170.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-170.spec.js~context8",
    "access": null,
    "description": "when pushing aggregate templates and functions",
    "lineNumber": 33
  },
  {
    "__docId__": 685,
    "kind": "test",
    "name": "context9",
    "testId": 9,
    "memberof": "test/integration/issues/issue-170.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-170.spec.js~context9",
    "access": null,
    "description": "when pushing custom alarm category",
    "lineNumber": 40
  },
  {
    "__docId__": 686,
    "kind": "test",
    "name": "context10",
    "testId": 10,
    "memberof": "test/integration/issues/issue-170.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-170.spec.js~context10",
    "access": null,
    "description": "when pushing custom user groups",
    "lineNumber": 47
  },
  {
    "__docId__": 687,
    "kind": "test",
    "name": "context11",
    "testId": 11,
    "memberof": "test/integration/issues/issue-170.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-170.spec.js~context11",
    "access": null,
    "description": "when pushing serverscripts in redundant project",
    "lineNumber": 54
  },
  {
    "__docId__": 688,
    "kind": "test",
    "name": "context12",
    "testId": 12,
    "memberof": "test/integration/issues/issue-170.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-170.spec.js~context12",
    "access": null,
    "description": "when pushing resources with compress properties",
    "lineNumber": 61
  },
  {
    "__docId__": 689,
    "kind": "testFile",
    "name": "test/integration/issues/issue-239.spec.js",
    "content": "import { expectCorrectMapping } from '../../helpers/atscm';\n\ndescribe('Issue #239 (https://github.com/atSCM/atscm/issues/239)', function () {\n  context('Should not add empty newlines after pull and push', function () {\n    expectCorrectMapping('issue-239', {\n      path: 'AGENT.DISPLAYS',\n      name: 'Issue-239',\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/integration/issues/issue-239.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 690,
    "kind": "test",
    "name": "describe13",
    "testId": 13,
    "memberof": "test/integration/issues/issue-239.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-239.spec.js~describe13",
    "access": null,
    "description": "Issue #239 (https://github.com/atSCM/atscm/issues/239)",
    "lineNumber": 3
  },
  {
    "__docId__": 691,
    "kind": "test",
    "name": "context14",
    "testId": 14,
    "memberof": "test/integration/issues/issue-239.spec.js~describe13",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/issues/issue-239.spec.js~describe13.context14",
    "access": null,
    "description": "Should not add empty newlines after pull and push",
    "lineNumber": 4
  },
  {
    "__docId__": 692,
    "kind": "testFile",
    "name": "test/integration/issues/issue-253.spec.js",
    "content": "import { expectCorrectMapping } from '../../helpers/atscm';\n\ndescribe('Issue #253 (https://github.com/atSCM/atscm/issues/253)', function () {\n  context('Umlauts should be mapped correctly after pull and push', function () {\n    expectCorrectMapping('issue-253', {\n      path: 'AGENT.DISPLAYS',\n      name: 'Issue-253',\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/integration/issues/issue-253.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 693,
    "kind": "test",
    "name": "describe15",
    "testId": 15,
    "memberof": "test/integration/issues/issue-253.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-253.spec.js~describe15",
    "access": null,
    "description": "Issue #253 (https://github.com/atSCM/atscm/issues/253)",
    "lineNumber": 3
  },
  {
    "__docId__": 694,
    "kind": "test",
    "name": "context16",
    "testId": 16,
    "memberof": "test/integration/issues/issue-253.spec.js~describe15",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/issues/issue-253.spec.js~describe15.context16",
    "access": null,
    "description": "Umlauts should be mapped correctly after pull and push",
    "lineNumber": 4
  },
  {
    "__docId__": 695,
    "kind": "testFile",
    "name": "test/integration/issues/issue-265.spec.js",
    "content": "import Logger from 'gulplog';\nimport { outputJson, readJson } from 'fs-extra';\nimport expect from '../../expect';\nimport { importSetup, pull, deleteNode } from '../../helpers/atscm';\nimport { tmpDir } from '../../helpers/util';\n\ndescribe('Issue #265 (https://github.com/atSCM/atscm/issues/265)', function () {\n  const renamePath = './atscm/rename.json';\n  const setup = 'issue-265';\n  const originalName = 'conflicting-nodes';\n\n  let nodeIds;\n\n  const catchErrorLog = () => {};\n\n  before('reset renames, import setup and pull conflicting nodes', async function () {\n    Logger.on('error', () => catchErrorLog);\n    await outputJson(renamePath, {});\n\n    const nodeNames = await importSetup(setup, originalName);\n    const nodePaths = ['AGENT.OBJECTS'];\n    nodeIds = nodeNames.map((nodeName, i) => `${nodePaths[i]}.${nodeName}`);\n    const destination = tmpDir(setup.replace(/\\//g, '-'));\n\n    await pull(\n      nodeIds.map((nodeId) => `ns=1;s=${nodeId}`),\n      destination\n    );\n  });\n\n  it('should not create duplicate entries in rename.json', async function () {\n    const renames = await readJson(renamePath);\n\n    expect(Object.keys(renames), 'to equal', [`${nodeIds[0]}.Parent`]);\n  });\n\n  after('delete tmp node', function () {\n    Logger.removeListener('error', () => catchErrorLog);\n\n    // Delete the pushed node\n    return Promise.all(nodeIds.map((n) => deleteNode(n)));\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/integration/issues/issue-265.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 696,
    "kind": "test",
    "name": "describe17",
    "testId": 17,
    "memberof": "test/integration/issues/issue-265.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-265.spec.js~describe17",
    "access": null,
    "description": "Issue #265 (https://github.com/atSCM/atscm/issues/265)",
    "lineNumber": 7
  },
  {
    "__docId__": 697,
    "kind": "test",
    "name": "it18",
    "testId": 18,
    "memberof": "test/integration/issues/issue-265.spec.js~describe17",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/issues/issue-265.spec.js~describe17.it18",
    "access": null,
    "description": "should not create duplicate entries in rename.json",
    "lineNumber": 31
  },
  {
    "__docId__": 698,
    "kind": "testFile",
    "name": "test/integration/issues/issue-290.spec.js",
    "content": "import { expectCorrectMapping } from '../../helpers/atscm';\n\ndescribe('Issue #290 (https://github.com/atSCM/atscm/issues/290)', function () {\n  context('User group references should be mapped correctly', function () {\n    expectCorrectMapping('issue-290', {\n      path: 'SYSTEM',\n      name: 'SECURITY-Test',\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/integration/issues/issue-290.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 699,
    "kind": "test",
    "name": "describe19",
    "testId": 19,
    "memberof": "test/integration/issues/issue-290.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-290.spec.js~describe19",
    "access": null,
    "description": "Issue #290 (https://github.com/atSCM/atscm/issues/290)",
    "lineNumber": 3
  },
  {
    "__docId__": 700,
    "kind": "test",
    "name": "context20",
    "testId": 20,
    "memberof": "test/integration/issues/issue-290.spec.js~describe19",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/issues/issue-290.spec.js~describe19.context20",
    "access": null,
    "description": "User group references should be mapped correctly",
    "lineNumber": 4
  },
  {
    "__docId__": 701,
    "kind": "testFile",
    "name": "test/integration/issues/issue-319.spec.js",
    "content": "import { expectCorrectMapping } from '../../helpers/atscm';\n\ndescribe('Issue #319 (https://github.com/atSCM/atscm/issues/319)', function () {\n  context('Mapping relative node parameters', function () {\n    expectCorrectMapping('issue-319', {\n      path: 'AGENT.OBJECTS',\n      name: 'Test-319',\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/integration/issues/issue-319.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 702,
    "kind": "test",
    "name": "describe21",
    "testId": 21,
    "memberof": "test/integration/issues/issue-319.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-319.spec.js~describe21",
    "access": null,
    "description": "Issue #319 (https://github.com/atSCM/atscm/issues/319)",
    "lineNumber": 3
  },
  {
    "__docId__": 703,
    "kind": "test",
    "name": "context22",
    "testId": 22,
    "memberof": "test/integration/issues/issue-319.spec.js~describe21",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/issues/issue-319.spec.js~describe21.context22",
    "access": null,
    "description": "Mapping relative node parameters",
    "lineNumber": 4
  },
  {
    "__docId__": 704,
    "kind": "testFile",
    "name": "test/integration/issues/issue-330.spec.js",
    "content": "import expect from '../../expect';\nimport { importSetup, pull, deleteNode } from '../../helpers/atscm';\nimport { tmpDir } from '../../helpers/util';\n\ndescribe('Issue #330 (https://github.com/atSCM/atscm/issues/330)', function () {\n  const originalNames = ['Header'];\n  const nodePaths = ['AGENT.DISPLAYS.HEADER'];\n\n  function getNodeIds(nodeNames) {\n    return nodeNames.map((nodeName, i) => {\n      const path = nodePaths[i];\n      const divider = path.match(/RESOURCES/) ? '/' : '.';\n      return `${path}${divider}${nodeName}`;\n    });\n  }\n\n  context('when pulling XML with `>` in attribute value', function () {\n    const setup = 'issue-330/original';\n    let nodeNames;\n    let nodeIds;\n    let destination;\n\n    before('Import setup', async function () {\n      nodeNames = await importSetup(setup, ...originalNames);\n      nodeIds = getNodeIds(nodeNames);\n      destination = tmpDir(setup.replace(/\\//g, '-'));\n    });\n\n    it('should not error', function () {\n      return expect(\n        pull(\n          nodeIds.map((nodeId) => `ns=1;s=${nodeId}`),\n          destination\n        ),\n        'to be fulfilled'\n      );\n    });\n\n    after('delete tmp node', function () {\n      // Delete the pushed node\n      return Promise.all(nodeIds.map((n) => deleteNode(n)));\n    });\n  });\n\n  context('when attribute is renamed', function () {\n    const setup = 'issue-330/fixed';\n    let nodeNames;\n    let nodeIds;\n    let destination;\n\n    before('Import setup', async function () {\n      nodeNames = await importSetup(setup, ...originalNames);\n      nodeIds = getNodeIds(nodeNames);\n      destination = tmpDir(setup.replace(/\\//g, '-'));\n    });\n\n    it('should not error', function () {\n      return expect(\n        pull(\n          nodeIds.map((nodeId) => `ns=1;s=${nodeId}`),\n          destination\n        ),\n        'to be fulfilled'\n      );\n    });\n\n    after('delete tmp node', function () {\n      // Delete the pushed node\n      return Promise.all(nodeIds.map((n) => deleteNode(n)));\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/integration/issues/issue-330.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 705,
    "kind": "test",
    "name": "describe23",
    "testId": 23,
    "memberof": "test/integration/issues/issue-330.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-330.spec.js~describe23",
    "access": null,
    "description": "Issue #330 (https://github.com/atSCM/atscm/issues/330)",
    "lineNumber": 5
  },
  {
    "__docId__": 706,
    "kind": "test",
    "name": "context24",
    "testId": 24,
    "memberof": "test/integration/issues/issue-330.spec.js~describe23",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/issues/issue-330.spec.js~describe23.context24",
    "access": null,
    "description": "when pulling XML with `>` in attribute value",
    "lineNumber": 17
  },
  {
    "__docId__": 707,
    "kind": "test",
    "name": "it25",
    "testId": 25,
    "memberof": "test/integration/issues/issue-330.spec.js~describe23.context24",
    "testDepth": 2,
    "static": true,
    "longname": "test/integration/issues/issue-330.spec.js~describe23.context24.it25",
    "access": null,
    "description": "should not error",
    "lineNumber": 29
  },
  {
    "__docId__": 708,
    "kind": "test",
    "name": "context26",
    "testId": 26,
    "memberof": "test/integration/issues/issue-330.spec.js~describe23",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/issues/issue-330.spec.js~describe23.context26",
    "access": null,
    "description": "when attribute is renamed",
    "lineNumber": 45
  },
  {
    "__docId__": 709,
    "kind": "test",
    "name": "it27",
    "testId": 27,
    "memberof": "test/integration/issues/issue-330.spec.js~describe23.context26",
    "testDepth": 2,
    "static": true,
    "longname": "test/integration/issues/issue-330.spec.js~describe23.context26.it27",
    "access": null,
    "description": "should not error",
    "lineNumber": 57
  },
  {
    "__docId__": 710,
    "kind": "testFile",
    "name": "test/integration/issues/issue-345.spec.js",
    "content": "import Logger from 'gulplog';\nimport { spy } from 'sinon';\nimport { readdir } from 'fs-extra';\nimport expect from '../../expect';\nimport { tmpDir } from '../../helpers/util';\nimport { importSetup, pull, deleteNode } from '../../helpers/atscm';\n\ndescribe('Issue #345 (https://github.com/atSCM/atscm/issues/345)', function () {\n  const setup = 'issue-345';\n  let nodeIds;\n\n  it('pull should not error on empty script', async function () {\n    const nodeNames = await importSetup(setup, 'EmptyScript');\n    const nodePaths = ['SYSTEM.LIBRARY.PROJECT.MENUSCRIPTS'];\n    nodeIds = nodeNames.map((nodeName, i) => {\n      const path = nodePaths[i];\n      const divider = path.match(/RESOURCES/) ? '/' : '.';\n      return `${path}${divider}${nodeName}`;\n    });\n    const destination = tmpDir(setup.replace(/\\//g, '-'));\n\n    const warnSpy = spy();\n    Logger.on('warn', warnSpy);\n\n    // Run atscm pull\n    await pull(\n      nodeIds.map((nodeId) => `ns=1;s=${nodeId}`),\n      destination\n    );\n\n    // No files should be pulled, ...\n    await expect(() => readdir(destination), 'to be rejected with', { code: 'ENOENT' });\n\n    // ... instead, a warning should be displayed\n    expect(warnSpy, 'was called once');\n    return expect(warnSpy, 'to have a call satisfying', { args: [/is empty/] });\n  });\n\n  after(() => nodeIds.forEach((id) => deleteNode(id)));\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/integration/issues/issue-345.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 711,
    "kind": "test",
    "name": "describe28",
    "testId": 28,
    "memberof": "test/integration/issues/issue-345.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-345.spec.js~describe28",
    "access": null,
    "description": "Issue #345 (https://github.com/atSCM/atscm/issues/345)",
    "lineNumber": 8
  },
  {
    "__docId__": 712,
    "kind": "test",
    "name": "it29",
    "testId": 29,
    "memberof": "test/integration/issues/issue-345.spec.js~describe28",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/issues/issue-345.spec.js~describe28.it29",
    "access": null,
    "description": "pull should not error on empty script",
    "lineNumber": 12
  },
  {
    "__docId__": 713,
    "kind": "testFile",
    "name": "test/integration/issues/issue-354.spec.js",
    "content": "import { expectCorrectMapping } from '../../helpers/atscm';\n\ndescribe('Issue #354 (https://github.com/atSCM/atscm/issues/354)', function () {\n  context('Object type modelling rules', function () {\n    expectCorrectMapping('issue-354', {\n      path: ['ObjectTypes.PROJECT', 'ObjectTypes.PROJECT'],\n      name: ['MyObjectType1', 'MyObjectType2'],\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/integration/issues/issue-354.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 714,
    "kind": "test",
    "name": "describe30",
    "testId": 30,
    "memberof": "test/integration/issues/issue-354.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-354.spec.js~describe30",
    "access": null,
    "description": "Issue #354 (https://github.com/atSCM/atscm/issues/354)",
    "lineNumber": 3
  },
  {
    "__docId__": 715,
    "kind": "test",
    "name": "context31",
    "testId": 31,
    "memberof": "test/integration/issues/issue-354.spec.js~describe30",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/issues/issue-354.spec.js~describe30.context31",
    "access": null,
    "description": "Object type modelling rules",
    "lineNumber": 4
  },
  {
    "__docId__": 716,
    "kind": "testFile",
    "name": "test/integration/issues/issue-46.spec.js",
    "content": "import { EOL } from 'os';\nimport expect from '../../expect';\nimport { TransformDirection } from '../../../src/lib/transform/Transformer';\nimport XMLTransformer from '../../../src/lib/transform/XMLTransformer';\n\ndescribe('XMLTransformer', function () {\n  it('should keep element order', async function () {\n    const testContents = `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<svg version=\"1.2\" xmlns=\"http://www.w3.org/2000/svg\" width=\"1280\" height=\"680\">\n  <text>text1</text>\n  <rect width=\"200\" height=\"200\" x=\"160\" y=\"16\"/>\n  <text>text2</text>\n</svg>`\n      .split('\\n')\n      .join(EOL); // Multi line string templates are always LF\n    const testFile = { value: { value: Buffer.from(testContents) } };\n    const transformer = new XMLTransformer({\n      direction: TransformDirection.FromDB, // just to have os-native newlines\n    });\n\n    const decoded = transformer.decodeContents(testFile);\n    const encoded = transformer.encodeContents(decoded);\n\n    expect(encoded, 'to equal', testContents);\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/integration/issues/issue-46.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 717,
    "kind": "test",
    "name": "describe32",
    "testId": 32,
    "memberof": "test/integration/issues/issue-46.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/issues/issue-46.spec.js~describe32",
    "access": null,
    "description": "XMLTransformer",
    "lineNumber": 6
  },
  {
    "__docId__": 718,
    "kind": "test",
    "name": "it33",
    "testId": 33,
    "memberof": "test/integration/issues/issue-46.spec.js~describe32",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/issues/issue-46.spec.js~describe32.it33",
    "access": null,
    "description": "should keep element order",
    "lineNumber": 7
  },
  {
    "__docId__": 719,
    "kind": "testFile",
    "name": "test/integration/mapping.spec.js",
    "content": "import { expectCorrectMapping } from '../helpers/atscm';\n\ndescribe('Mapping', function () {\n  context.skip('when resource directory with dot in name', function () {\n    expectCorrectMapping('mapping/dot-in-dirname', {\n      path: 'SYSTEM.LIBRARY.PROJECT.RESOURCES/DataTables/Bootstrap-4-4.0.0/css',\n      name: 'bootstrap.min.css',\n    });\n  });\n\n  context('a display containing a folder', function () {\n    expectCorrectMapping('mapping/folder-in-display', {\n      path: 'AGENT.DISPLAYS',\n      name: 'FolderInDisplay',\n    });\n  });\n\n  context('a display containing a display with the same name', function () {\n    expectCorrectMapping('mapping/child-display-with-same-name', {\n      path: 'AGENT.DISPLAYS',\n      name: 'ChildWithSameName',\n    });\n  });\n\n  context('a variable array', function () {\n    expectCorrectMapping('mapping/test-array-values', {\n      path: 'AGENT.OBJECTS',\n      name: 'InvalidArrayValue',\n    });\n  });\n\n  context('a 64bit variable value', function () {\n    expectCorrectMapping('mapping/int64', {\n      path: 'AGENT.OBJECTS',\n      name: 'TestCreateInt64',\n    });\n  });\n\n  context('a node with a historical configuration', function () {\n    expectCorrectMapping('mapping/historical-config', {\n      path: 'AGENT.OBJECTS',\n      name: 'TestHistoryConfig',\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/integration/mapping.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 720,
    "kind": "test",
    "name": "describe34",
    "testId": 34,
    "memberof": "test/integration/mapping.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/mapping.spec.js~describe34",
    "access": null,
    "description": "Mapping",
    "lineNumber": 3
  },
  {
    "__docId__": 721,
    "kind": "test",
    "name": "context35",
    "testId": 35,
    "memberof": "test/integration/mapping.spec.js~describe34",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/mapping.spec.js~describe34.context35",
    "access": null,
    "description": "a display containing a folder",
    "lineNumber": 11
  },
  {
    "__docId__": 722,
    "kind": "test",
    "name": "context36",
    "testId": 36,
    "memberof": "test/integration/mapping.spec.js~describe34",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/mapping.spec.js~describe34.context36",
    "access": null,
    "description": "a display containing a display with the same name",
    "lineNumber": 18
  },
  {
    "__docId__": 723,
    "kind": "test",
    "name": "context37",
    "testId": 37,
    "memberof": "test/integration/mapping.spec.js~describe34",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/mapping.spec.js~describe34.context37",
    "access": null,
    "description": "a variable array",
    "lineNumber": 25
  },
  {
    "__docId__": 724,
    "kind": "test",
    "name": "context38",
    "testId": 38,
    "memberof": "test/integration/mapping.spec.js~describe34",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/mapping.spec.js~describe34.context38",
    "access": null,
    "description": "a 64bit variable value",
    "lineNumber": 32
  },
  {
    "__docId__": 725,
    "kind": "test",
    "name": "context39",
    "testId": 39,
    "memberof": "test/integration/mapping.spec.js~describe34",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/mapping.spec.js~describe34.context39",
    "access": null,
    "description": "a node with a historical configuration",
    "lineNumber": 39
  },
  {
    "__docId__": 726,
    "kind": "testFile",
    "name": "test/integration/tasks/init.spec.js",
    "content": "import expect from 'unexpected';\nimport { spy } from 'sinon';\nimport proxyquire from 'proxyquire';\nimport { obj as createStream } from 'through2';\nimport { src } from 'gulp';\nimport handlebars from 'gulp-compile-handlebars';\nimport { transform as babelTransform } from '@babel/core';\nimport { transpileModule as tsTransform } from 'typescript';\nimport evaluate from 'eval';\nimport pkg from '../../../package.json';\nimport Atviseproject from '../../../src/lib/config/Atviseproject';\n\nconst destSpy = spy((c, e, cb) => cb(null));\nconst srcSpy = spy((c, e, cb) => cb(null, c));\n\nconst gulpStub = {\n  src: (...args) => src(...args).pipe(createStream(srcSpy)),\n  dest: () => createStream(destSpy),\n};\n\nconst handlebarsSpy = spy(handlebars);\n\nconst InitTask = proxyquire('../../../src/init/InitTask', {\n  gulp: gulpStub,\n  handlebars: {\n    default: handlebarsSpy,\n  },\n}).default;\n\n/** @test {InitTask} */\ndescribe('InitTask', function () {\n  const baseConfig = {\n    name: 'unit-testing',\n    atviseHost: 'localhost',\n    atvisePortOpc: 4840,\n    atvisePortHttp: 80,\n    modulePackage: pkg,\n  };\n\n  function optionsForLang(lang) {\n    return Object.assign({ configLang: lang }, baseConfig);\n  }\n\n  beforeEach(() => {\n    srcSpy.resetHistory();\n    destSpy.resetHistory();\n    handlebarsSpy.resetHistory();\n  });\n\n  function expectValidConfig(lang, transform) {\n    it(`should create valid ${lang} config`, function () {\n      return InitTask.run(optionsForLang(lang)).then(() => {\n        const createdFiles = destSpy.args.map((args) => args[0]);\n\n        // Expect config file is created\n        const configs = createdFiles.filter((file) => file.relative.match(/Atviseproject/));\n        expect(configs, 'to have length', 1);\n\n        // Expect code can be transpiled\n        const configCode = configs[0].contents.toString();\n        let resultingCode;\n        expect(\n          () =>\n            (resultingCode = transform(configCode, createdFiles).replace(\n              /require\\(['|\"]atscm['|\"]\\)/,\n              \"require('../../../')\"\n            )),\n          'not to throw'\n        );\n\n        // Expect transpiled code to be runnable\n        let config;\n        expect(() => (config = evaluate(resultingCode, true).default), 'not to throw');\n\n        // Expect config to extend Atviseproject\n        expect(config, 'to have properties', Object.getOwnPropertyNames(Atviseproject));\n        expect(config.name, 'to equal', 'UnitTesting');\n        expect(config.host, 'to equal', baseConfig.atviseHost);\n        expect(config.port.opc, 'to equal', baseConfig.atvisePortOpc);\n        expect(config.port.http, 'to equal', baseConfig.atvisePortHttp);\n      });\n    });\n  }\n\n  expectValidConfig('es2015', (code, createdFiles) => {\n    const rcs = createdFiles.filter((file) => file.relative.match(/.babelrc/));\n\n    expect(rcs, 'to have length', 1);\n\n    const rc = JSON.parse(rcs[0].contents.toString());\n\n    return babelTransform(code, rc).code;\n  });\n\n  expectValidConfig('es5', (code) => code);\n\n  expectValidConfig('ts', (code, createdFiles) => {\n    const rcs = createdFiles.filter((file) => file.relative.match(/tsconfig.json/));\n\n    expect(rcs, 'to have length', 1);\n\n    const rc = JSON.parse(rcs[0].contents.toString());\n\n    return tsTransform(code, rc).outputText;\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/integration/tasks/init.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 727,
    "kind": "test",
    "name": "describe40",
    "testId": 40,
    "memberof": "test/integration/tasks/init.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/tasks/init.spec.js~describe40",
    "access": null,
    "description": "InitTask",
    "lineNumber": 31,
    "testTargets": [
      "InitTask"
    ]
  },
  {
    "__docId__": 728,
    "kind": "test",
    "name": "it41",
    "testId": 41,
    "memberof": "test/integration/tasks/init.spec.js~describe40",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/tasks/init.spec.js~describe40.it41",
    "access": null,
    "lineNumber": 51
  },
  {
    "__docId__": 729,
    "kind": "testFile",
    "name": "test/integration/tasks/pull.spec.js",
    "content": "import { join } from 'path';\nimport expect from 'unexpected';\nimport proxyquire from 'proxyquire';\nimport { copy, outputJson, outputFile, readdir, remove } from 'fs-extra';\nimport { tmpDir } from '../../helpers/util';\n\nconst runPull = proxyquire('../../../src/tasks/pull', {\n  '../lib/server/NodeBrowser': {\n    default: class PullStub {\n      async browse() {\n        return false;\n      }\n    },\n  },\n}).default;\n\ndescribe('pull task', function () {\n  context('with the `--clean` flag', function () {\n    const projectDir = tmpDir('pull-clean');\n    const sourceDir = join(projectDir, 'src');\n    const testFile = join(sourceDir, 'file-that-exists.txt');\n\n    const originalCwd = process.cwd();\n\n    before(() =>\n      Promise.all([\n        copy(\n          join(__dirname, '../../fixtures/Atviseproject.babel.js'),\n          join(projectDir, 'Atviseproject.babel.js')\n        ),\n        outputJson(join(projectDir, 'package.json'), {}),\n        outputFile(testFile, 'Testing...'),\n      ]).then(() => process.chdir(projectDir))\n    );\n\n    it('should empty the source directory first', function () {\n      return expect(readdir(sourceDir), 'when fulfilled', 'not to be empty')\n        .then(() => runPull({ clean: true }))\n        .then(() => expect(readdir(sourceDir), 'when fulfilled', 'to be empty'));\n    });\n\n    after(() => {\n      process.chdir(originalCwd);\n      return remove(projectDir);\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/integration/tasks/pull.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 730,
    "kind": "test",
    "name": "describe42",
    "testId": 42,
    "memberof": "test/integration/tasks/pull.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/integration/tasks/pull.spec.js~describe42",
    "access": null,
    "description": "pull task",
    "lineNumber": 17
  },
  {
    "__docId__": 731,
    "kind": "test",
    "name": "context43",
    "testId": 43,
    "memberof": "test/integration/tasks/pull.spec.js~describe42",
    "testDepth": 1,
    "static": true,
    "longname": "test/integration/tasks/pull.spec.js~describe42.context43",
    "access": null,
    "description": "with the `--clean` flag",
    "lineNumber": 18
  },
  {
    "__docId__": 732,
    "kind": "test",
    "name": "it44",
    "testId": 44,
    "memberof": "test/integration/tasks/pull.spec.js~describe42.context43",
    "testDepth": 2,
    "static": true,
    "longname": "test/integration/tasks/pull.spec.js~describe42.context43.it44",
    "access": null,
    "description": "should empty the source directory first",
    "lineNumber": 36
  },
  {
    "__docId__": 733,
    "kind": "testFile",
    "name": "test/src/Gulpfile.spec.js",
    "content": "import expect from 'unexpected';\nimport { spy } from 'sinon';\nimport proxyquire from 'proxyquire';\nimport * as tasks from '../../src/Gulpfile';\n\ndescribe('Gulpfile', function () {\n  it('should export description for all tasks', function () {\n    Object.keys(tasks).forEach((name) => {\n      const desc = tasks[name].description;\n\n      expect(desc, 'to be defined');\n      expect(desc, 'not to be empty');\n    });\n  });\n\n  it('should register cleanupHandler', function () {\n    const nodeCleanup = spy();\n\n    const orgLog = console.log; // eslint-disable-line no-console\n    process.env.NODE_ENV = 'production';\n    proxyquire('../../src/Gulpfile', {\n      'node-cleanup': nodeCleanup,\n    });\n    process.env.NODE_ENV = 'test';\n    console.log = orgLog; // eslint-disable-line no-console\n\n    expect(nodeCleanup.calledOnce, 'to be', true);\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/Gulpfile.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 734,
    "kind": "test",
    "name": "describe45",
    "testId": 45,
    "memberof": "test/src/Gulpfile.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/Gulpfile.spec.js~describe45",
    "access": null,
    "description": "Gulpfile",
    "lineNumber": 6
  },
  {
    "__docId__": 735,
    "kind": "test",
    "name": "it46",
    "testId": 46,
    "memberof": "test/src/Gulpfile.spec.js~describe45",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/Gulpfile.spec.js~describe45.it46",
    "access": null,
    "description": "should export description for all tasks",
    "lineNumber": 7
  },
  {
    "__docId__": 736,
    "kind": "test",
    "name": "it47",
    "testId": 47,
    "memberof": "test/src/Gulpfile.spec.js~describe45",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/Gulpfile.spec.js~describe45.it47",
    "access": null,
    "description": "should register cleanupHandler",
    "lineNumber": 16
  },
  {
    "__docId__": 737,
    "kind": "testFile",
    "name": "test/src/config/ProjectConfig.spec.js",
    "content": "import expect from 'unexpected';\nimport TestConfig from '../../fixtures/Atviseproject.babel';\nimport ProjectConfig from '../../../src/config/ProjectConfig';\n\n/** @test {ProjectConfig} */\ndescribe('ProjectConfig', function () {\n  const orgValues = {};\n\n  function setEnv(key, value) {\n    if (value === undefined) {\n      delete process.env[key];\n    } else {\n      process.env[key] = value;\n    }\n  }\n\n  afterEach(function () {\n    Object.keys(orgValues).forEach((key) => setEnv(key, orgValues[key]));\n  });\n\n  function checkOverride(desc, values, check) {\n    const envVarNames = Object.keys(values);\n\n    envVarNames.forEach((name) => {\n      if (!orgValues[name]) {\n        orgValues[name] = process.env[name];\n      }\n    });\n\n    it(`should ${desc}`, function () {\n      envVarNames.forEach((name) => setEnv(name, values[name]));\n\n      check();\n    });\n  }\n\n  function checkDefault(name, check) {\n    checkOverride(\n      `should use default without ${name}`,\n      {\n        [name]: undefined,\n      },\n      check\n    );\n  }\n\n  checkOverride(\n    'use ATSCM_PROJECT__HOST if provided',\n    {\n      ATSCM_PROJECT__HOST: '1.2.3.4',\n    },\n    function () {\n      expect(ProjectConfig.host, 'to equal', '1.2.3.4');\n    }\n  );\n\n  checkOverride(\n    'use ATSCM_PROJECT__PORT__OPC if provided',\n    {\n      ATSCM_PROJECT__PORT__OPC: '1234',\n    },\n    function () {\n      expect(ProjectConfig.port.opc, 'to equal', 1234);\n    }\n  );\n\n  checkOverride(\n    'use ATSCM_PROJECT__PORT__HTTP if provided',\n    {\n      ATSCM_PROJECT__PORT__HTTP: '1234',\n    },\n    function () {\n      expect(ProjectConfig.port.http, 'to equal', 1234);\n    }\n  );\n\n  checkOverride(\n    'use ATSCM_PROJECT__LOGIN__USERNAME if provided',\n    {\n      ATSCM_PROJECT__LOGIN__USERNAME: 'username',\n    },\n    function () {\n      expect(ProjectConfig.login.username, 'to equal', 'username');\n    }\n  );\n\n  checkOverride(\n    'use ATSCM_PROJECT__LOGIN__PASSWORD if provided',\n    {\n      ATSCM_PROJECT__LOGIN__PASSWORD: 'password',\n    },\n    function () {\n      expect(ProjectConfig.login.password, 'to equal', 'password');\n    }\n  );\n\n  checkDefault('ATSCM_PROJECT__HOST', () =>\n    expect(ProjectConfig.host, 'to equal', TestConfig.host)\n  );\n\n  checkDefault('ATSCM_PROJECT__PORT__OPC', () =>\n    expect(ProjectConfig.port.opc, 'to equal', TestConfig.port.opc)\n  );\n\n  checkDefault('ATSCM_PROJECT__PORT__HTTP', () =>\n    expect(ProjectConfig.port.http, 'to equal', TestConfig.port.http)\n  );\n\n  checkDefault('ATSCM_PROJECT__LOGIN__USERNAME', () =>\n    expect(ProjectConfig.login, 'to equal', TestConfig.login)\n  );\n\n  checkDefault('ATSCM_PROJECT__LOGIN__PASSWORD', () =>\n    expect(ProjectConfig.login, 'to equal', TestConfig.login)\n  );\n\n  describe('.isExternal', function () {\n    it('should return true for ids not included in .nodes', function () {\n      expect(ProjectConfig.isExternal('Somewhere.Else'), 'to be', true);\n    });\n\n    it('should return true for ignored ids', function () {\n      // NOTE: AGENT.OPCUA.server_url is ignored by .ServerRelatedNodes\n      expect(ProjectConfig.isExternal('AGENT.OPCUA.server_url'), 'to be', true);\n    });\n\n    it('should return false for included nodes', function () {\n      expect(ProjectConfig.isExternal('AGENT.DISPLAYS.Default'), 'to be', false);\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/config/ProjectConfig.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 738,
    "kind": "test",
    "name": "describe48",
    "testId": 48,
    "memberof": "test/src/config/ProjectConfig.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/config/ProjectConfig.spec.js~describe48",
    "access": null,
    "description": "ProjectConfig",
    "lineNumber": 6,
    "testTargets": [
      "ProjectConfig"
    ]
  },
  {
    "__docId__": 739,
    "kind": "test",
    "name": "it49",
    "testId": 49,
    "memberof": "test/src/config/ProjectConfig.spec.js~describe48",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/config/ProjectConfig.spec.js~describe48.it49",
    "access": null,
    "lineNumber": 30
  },
  {
    "__docId__": 740,
    "kind": "test",
    "name": "describe50",
    "testId": 50,
    "memberof": "test/src/config/ProjectConfig.spec.js~describe48",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/config/ProjectConfig.spec.js~describe48.describe50",
    "access": null,
    "description": ".isExternal",
    "lineNumber": 117
  },
  {
    "__docId__": 741,
    "kind": "test",
    "name": "it51",
    "testId": 51,
    "memberof": "test/src/config/ProjectConfig.spec.js~describe48.describe50",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/config/ProjectConfig.spec.js~describe48.describe50.it51",
    "access": null,
    "description": "should return true for ids not included in .nodes",
    "lineNumber": 118
  },
  {
    "__docId__": 742,
    "kind": "test",
    "name": "it52",
    "testId": 52,
    "memberof": "test/src/config/ProjectConfig.spec.js~describe48.describe50",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/config/ProjectConfig.spec.js~describe48.describe50.it52",
    "access": null,
    "description": "should return true for ignored ids",
    "lineNumber": 122
  },
  {
    "__docId__": 743,
    "kind": "test",
    "name": "it53",
    "testId": 53,
    "memberof": "test/src/config/ProjectConfig.spec.js~describe48.describe50",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/config/ProjectConfig.spec.js~describe48.describe50.it53",
    "access": null,
    "description": "should return false for included nodes",
    "lineNumber": 127
  },
  {
    "__docId__": 744,
    "kind": "testFile",
    "name": "test/src/index.spec.js",
    "content": "import expect from 'unexpected';\nimport * as globalExports from '../../src/index';\nimport Atviseproject from '../../src/lib/config/Atviseproject';\nimport NodeId from '../../src/lib/model/opcua/NodeId';\nimport Transformer, { TransformDirection } from '../../src/lib/transform/Transformer';\nimport PartialTransformer from '../../src/lib/transform/PartialTransformer';\nimport SplittingTransformer from '../../src/lib/transform/SplittingTransformer';\nimport DisplayTransformer from '../../src/transform/DisplayTransformer';\nimport ScriptTransformer from '../../src/transform/ScriptTransformer';\n\ndescribe('atscm module', function () {\n  /** @test {Atviseproject} */\n  it('should export Atviseproject class', function () {\n    expect(globalExports.Atviseproject, 'to be', Atviseproject);\n  });\n\n  /** @test {NodeId} */\n  it('should export NodeId class', function () {\n    expect(globalExports.NodeId, 'to be', NodeId);\n  });\n\n  /** @test {Transformer} */\n  it('should export Transformer class', function () {\n    expect(globalExports.Transformer, 'to be', Transformer);\n  });\n\n  /** @test {TransformDirection} */\n  it('should export TransformDirection enum', function () {\n    expect(globalExports.TransformDirection, 'to be', TransformDirection);\n  });\n\n  /** @test {PartialTransformer} */\n  it('should export PartialTransformer class', function () {\n    expect(globalExports.PartialTransformer, 'to be', PartialTransformer);\n  });\n\n  /** @test {SplittingTransformer} */\n  it('should export SplittingTransformer class', function () {\n    expect(globalExports.SplittingTransformer, 'to be', SplittingTransformer);\n  });\n\n  /** @test {DisplayTransformer} */\n  it('should export DisplayTransformer class', function () {\n    expect(globalExports.DisplayTransformer, 'to be', DisplayTransformer);\n  });\n\n  /** @test {ScriptTransformer} */\n  it('should export ScriptTransformer class', function () {\n    expect(globalExports.ScriptTransformer, 'to be', ScriptTransformer);\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/index.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 745,
    "kind": "test",
    "name": "describe54",
    "testId": 54,
    "memberof": "test/src/index.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/index.spec.js~describe54",
    "access": null,
    "description": "atscm module",
    "lineNumber": 11
  },
  {
    "__docId__": 746,
    "kind": "test",
    "name": "it55",
    "testId": 55,
    "memberof": "test/src/index.spec.js~describe54",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/index.spec.js~describe54.it55",
    "access": null,
    "description": "should export Atviseproject class",
    "lineNumber": 13,
    "testTargets": [
      "Atviseproject"
    ]
  },
  {
    "__docId__": 747,
    "kind": "test",
    "name": "it56",
    "testId": 56,
    "memberof": "test/src/index.spec.js~describe54",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/index.spec.js~describe54.it56",
    "access": null,
    "description": "should export NodeId class",
    "lineNumber": 18,
    "testTargets": [
      "NodeId"
    ]
  },
  {
    "__docId__": 748,
    "kind": "test",
    "name": "it57",
    "testId": 57,
    "memberof": "test/src/index.spec.js~describe54",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/index.spec.js~describe54.it57",
    "access": null,
    "description": "should export Transformer class",
    "lineNumber": 23,
    "testTargets": [
      "Transformer"
    ]
  },
  {
    "__docId__": 749,
    "kind": "test",
    "name": "it58",
    "testId": 58,
    "memberof": "test/src/index.spec.js~describe54",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/index.spec.js~describe54.it58",
    "access": null,
    "description": "should export TransformDirection enum",
    "lineNumber": 28,
    "testTargets": [
      "TransformDirection"
    ]
  },
  {
    "__docId__": 750,
    "kind": "test",
    "name": "it59",
    "testId": 59,
    "memberof": "test/src/index.spec.js~describe54",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/index.spec.js~describe54.it59",
    "access": null,
    "description": "should export PartialTransformer class",
    "lineNumber": 33,
    "testTargets": [
      "PartialTransformer"
    ]
  },
  {
    "__docId__": 751,
    "kind": "test",
    "name": "it60",
    "testId": 60,
    "memberof": "test/src/index.spec.js~describe54",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/index.spec.js~describe54.it60",
    "access": null,
    "description": "should export SplittingTransformer class",
    "lineNumber": 38,
    "testTargets": [
      "SplittingTransformer"
    ]
  },
  {
    "__docId__": 752,
    "kind": "test",
    "name": "it61",
    "testId": 61,
    "memberof": "test/src/index.spec.js~describe54",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/index.spec.js~describe54.it61",
    "access": null,
    "description": "should export DisplayTransformer class",
    "lineNumber": 43,
    "testTargets": [
      "DisplayTransformer"
    ]
  },
  {
    "__docId__": 753,
    "kind": "test",
    "name": "it62",
    "testId": 62,
    "memberof": "test/src/index.spec.js~describe54",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/index.spec.js~describe54.it62",
    "access": null,
    "description": "should export ScriptTransformer class",
    "lineNumber": 48,
    "testTargets": [
      "ScriptTransformer"
    ]
  },
  {
    "__docId__": 754,
    "kind": "testFile",
    "name": "test/src/init/InitTask.spec.js",
    "content": "import { readdirSync } from 'fs';\nimport { join, isAbsolute, basename } from 'path';\nimport expect from 'unexpected';\nimport { spy } from 'sinon';\nimport proxyquire from 'proxyquire';\nimport { obj as createStream } from 'through2';\nimport { src } from 'gulp';\nimport handlebars from 'gulp-compile-handlebars';\nimport { ConfigLangs } from '../../../src/init/Options';\n\nconst destSpy = spy((c, e, cb) => cb(null));\nconst srcSpy = spy((c, e, cb) => cb(null, c));\n\nconst gulpStub = {\n  src: (...args) => src(...args).pipe(createStream(srcSpy)),\n  dest: () => createStream(destSpy),\n};\n\nconst handlebarsSpy = spy(handlebars);\n\nconst InitTask = proxyquire('../../../src/init/InitTask', {\n  gulp: gulpStub,\n  handlebars: {\n    default: handlebarsSpy,\n  },\n}).default;\n\n/** @test {InitTask} */\ndescribe('InitTask', function () {\n  beforeEach(() => {\n    srcSpy.resetHistory();\n    destSpy.resetHistory();\n    handlebarsSpy.resetHistory();\n  });\n\n  /** @test {InitTask.filesToHandle} */\n  describe('.filesToHandle', function () {\n    it('should return array of absolute paths', function () {\n      expect(InitTask.filesToHandle('es2015'), 'to have items satisfying', 'to be a', 'string');\n      expect(\n        InitTask.filesToHandle('es2015'),\n        'to have items satisfying',\n        expect.it('when passed as parameter to', isAbsolute, 'to equal', true)\n      );\n    });\n  });\n\n  /** @test {InitTask.run} */\n  describe('.run', function () {\n    it('should handle all general files', function () {\n      const files = readdirSync(join(__dirname, '../../../res/init/templates/general'));\n      const renamedFiles = files.map((f) => (f === 'gitignore' ? '.gitignore' : f));\n\n      return InitTask.run({ configLang: 'es2015', name: 'test' }).then(() => {\n        expect(srcSpy.callCount, 'to be greater than', 0);\n\n        const handled = srcSpy.args.map((args) => args[0]);\n        const resulting = destSpy.args.map((args) => args[0]);\n        expect(handled, 'to have values satisfying', 'to have properties', { _isVinyl: true });\n\n        expect(\n          resulting.map((f) => basename(f.history[0])),\n          'to contain',\n          ...files\n        );\n        expect(\n          resulting.map((f) => f.relative),\n          'to contain',\n          ...renamedFiles\n        );\n      });\n    });\n\n    it('should not escape author field in package.json (#52)', function () {\n      const author = 'Sample name <mail@example.com>';\n\n      return InitTask.run({ configLang: 'es2015', author, name: 'test' }).then(() => {\n        expect(srcSpy.callCount, 'to be greater than', 0);\n\n        const pkgOut = destSpy.args\n          .map((args) => args[0])\n          .filter((f) => f.relative === 'package.json')[0]\n          .contents.toString();\n\n        expect(JSON.parse(pkgOut).author, 'to equal', author);\n      });\n    });\n\n    function expectHandlingLangFiles(configLang) {\n      const files = readdirSync(join(__dirname, '../../../res/init/templates/lang', configLang));\n\n      it(`should handle ${configLang} files`, function () {\n        return InitTask.run({ configLang, name: 'test' }).then(() => {\n          const handled = srcSpy.args.map((args) => args[0].relative);\n          const resulting = destSpy.args.map((args) => args[0].relative);\n\n          expect(handled, 'to contain', ...files);\n          expect(resulting, 'to contain', ...files);\n        });\n      });\n    }\n\n    // Check if all lang files are handled for all config langs\n    Object.keys(ConfigLangs).forEach((l) => expectHandlingLangFiles(ConfigLangs[l]));\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/init/InitTask.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 755,
    "kind": "test",
    "name": "describe63",
    "testId": 63,
    "memberof": "test/src/init/InitTask.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/init/InitTask.spec.js~describe63",
    "access": null,
    "description": "InitTask",
    "lineNumber": 29,
    "testTargets": [
      "InitTask"
    ]
  },
  {
    "__docId__": 756,
    "kind": "test",
    "name": "describe64",
    "testId": 64,
    "memberof": "test/src/init/InitTask.spec.js~describe63",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/init/InitTask.spec.js~describe63.describe64",
    "access": null,
    "description": ".filesToHandle",
    "lineNumber": 37,
    "testTargets": [
      "InitTask.filesToHandle"
    ]
  },
  {
    "__docId__": 757,
    "kind": "test",
    "name": "it65",
    "testId": 65,
    "memberof": "test/src/init/InitTask.spec.js~describe63.describe64",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/init/InitTask.spec.js~describe63.describe64.it65",
    "access": null,
    "description": "should return array of absolute paths",
    "lineNumber": 38
  },
  {
    "__docId__": 758,
    "kind": "test",
    "name": "describe66",
    "testId": 66,
    "memberof": "test/src/init/InitTask.spec.js~describe63",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/init/InitTask.spec.js~describe63.describe66",
    "access": null,
    "description": ".run",
    "lineNumber": 49,
    "testTargets": [
      "InitTask.run"
    ]
  },
  {
    "__docId__": 759,
    "kind": "test",
    "name": "it67",
    "testId": 67,
    "memberof": "test/src/init/InitTask.spec.js~describe63.describe66",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/init/InitTask.spec.js~describe63.describe66.it67",
    "access": null,
    "description": "should handle all general files",
    "lineNumber": 50
  },
  {
    "__docId__": 760,
    "kind": "test",
    "name": "it68",
    "testId": 68,
    "memberof": "test/src/init/InitTask.spec.js~describe63.describe66",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/init/InitTask.spec.js~describe63.describe66.it68",
    "access": null,
    "description": "should not escape author field in package.json (#52)",
    "lineNumber": 74
  },
  {
    "__docId__": 761,
    "kind": "test",
    "name": "it69",
    "testId": 69,
    "memberof": "test/src/init/InitTask.spec.js~describe63.describe66",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/init/InitTask.spec.js~describe63.describe66.it69",
    "access": null,
    "lineNumber": 92
  },
  {
    "__docId__": 762,
    "kind": "testFile",
    "name": "test/src/init/Options.spec.js",
    "content": "import expect from 'unexpected';\nimport InitOptionsAsArray, { InitOptions } from '../../../src/init/Options';\nimport InitOption from '../../../src/lib/init/Option';\n\n/** @test {InitOptions} */\ndescribe('InitOptions', function () {\n  it('should contain InitOptions stored against names', function () {\n    Object.keys(InitOptions).forEach((key) => {\n      expect(key, 'to be a', 'string');\n      expect(InitOptions[key], 'to be a', InitOption);\n    });\n  });\n\n  /** @test {InitOptions.atviseUser} */\n  describe('.atviseUser', function () {\n    it('should only be asked if using login', function () {\n      expect(InitOptions.atviseUser.when({ useLogin: false }), 'to equal', false);\n      expect(InitOptions.atviseUser.when({ useLogin: true }), 'to equal', true);\n    });\n  });\n\n  /** @test {InitOptions.atvisePassword} */\n  describe('.atvisePassword', function () {\n    it('should only be asked if using login', function () {\n      expect(InitOptions.atvisePassword.when({ useLogin: false }), 'to equal', false);\n      expect(InitOptions.atvisePassword.when({ useLogin: true }), 'to equal', true);\n    });\n  });\n});\n\n/** @test {InitOptionsAsArray} */\ndescribe('InitOptionsAsArray', function () {\n  it('should contain all InitOptions', function () {\n    InitOptionsAsArray.forEach((opt) => {\n      expect(InitOptions[opt.name], 'to be defined');\n      expect(opt, 'to have properties', InitOptions[opt.name]);\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/init/Options.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 763,
    "kind": "test",
    "name": "describe70",
    "testId": 70,
    "memberof": "test/src/init/Options.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/init/Options.spec.js~describe70",
    "access": null,
    "description": "InitOptions",
    "lineNumber": 6,
    "testTargets": [
      "InitOptions"
    ]
  },
  {
    "__docId__": 764,
    "kind": "test",
    "name": "it71",
    "testId": 71,
    "memberof": "test/src/init/Options.spec.js~describe70",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/init/Options.spec.js~describe70.it71",
    "access": null,
    "description": "should contain InitOptions stored against names",
    "lineNumber": 7
  },
  {
    "__docId__": 765,
    "kind": "test",
    "name": "describe72",
    "testId": 72,
    "memberof": "test/src/init/Options.spec.js~describe70",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/init/Options.spec.js~describe70.describe72",
    "access": null,
    "description": ".atviseUser",
    "lineNumber": 15,
    "testTargets": [
      "InitOptions.atviseUser"
    ]
  },
  {
    "__docId__": 766,
    "kind": "test",
    "name": "it73",
    "testId": 73,
    "memberof": "test/src/init/Options.spec.js~describe70.describe72",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/init/Options.spec.js~describe70.describe72.it73",
    "access": null,
    "description": "should only be asked if using login",
    "lineNumber": 16
  },
  {
    "__docId__": 767,
    "kind": "test",
    "name": "describe74",
    "testId": 74,
    "memberof": "test/src/init/Options.spec.js~describe70",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/init/Options.spec.js~describe70.describe74",
    "access": null,
    "description": ".atvisePassword",
    "lineNumber": 23,
    "testTargets": [
      "InitOptions.atvisePassword"
    ]
  },
  {
    "__docId__": 768,
    "kind": "test",
    "name": "it75",
    "testId": 75,
    "memberof": "test/src/init/Options.spec.js~describe70.describe74",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/init/Options.spec.js~describe70.describe74.it75",
    "access": null,
    "description": "should only be asked if using login",
    "lineNumber": 24
  },
  {
    "__docId__": 769,
    "kind": "test",
    "name": "describe76",
    "testId": 76,
    "memberof": "test/src/init/Options.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/init/Options.spec.js~describe76",
    "access": null,
    "description": "InitOptionsAsArray",
    "lineNumber": 32,
    "testTargets": [
      "InitOptionsAsArray"
    ]
  },
  {
    "__docId__": 770,
    "kind": "test",
    "name": "it77",
    "testId": 77,
    "memberof": "test/src/init/Options.spec.js~describe76",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/init/Options.spec.js~describe76.it77",
    "access": null,
    "description": "should contain all InitOptions",
    "lineNumber": 33
  },
  {
    "__docId__": 771,
    "kind": "testFile",
    "name": "test/src/init/OptionsValidator.spec.js",
    "content": "import expect from 'unexpected';\nimport Validator from '../../../src/init/OptionsValidator';\n\n/** @test {InitOptionsValidator} */\ndescribe('InitOptionsValidator', function () {\n  /** @test {InitOptionsValidator.name} */\n  describe('.name', function () {\n    it('should fail for empty names', function () {\n      expect(Validator.name(''), 'to match', /must be greater than zero/);\n    });\n\n    it('should fail with capital letters', function () {\n      expect(Validator.name('atSCM'), 'to match', /can no longer contain capital letters/);\n    });\n\n    it('should fail with non-url-safe characters', function () {\n      expect(Validator.name('#asdf'), 'to match', /URL-friendly characters/);\n    });\n\n    it('should fail with names starting with . or _', function () {\n      expect(Validator.name('_atscm'), 'to match', /cannot start with an underscore/);\n      expect(Validator.name('.atscm'), 'to match', /cannot start with a period/);\n    });\n\n    it('should fail with leading or trailing spaces', function () {\n      expect(Validator.name(' atscm'), 'to match', /cannot contain leading or trailing spaces/);\n      expect(Validator.name('atscm '), 'to match', /cannot contain leading or trailing spaces/);\n    });\n\n    it('should fail with core nodejs module name', function () {\n      expect(Validator.name('http'), 'to match', /is a core module name/);\n    });\n\n    it('should fail with blacklisted name', function () {\n      expect(Validator.name('node_modules'), 'to match', /is a blacklisted name/);\n    });\n\n    it(\"should fail with 'atscm'\", function () {\n      expect(Validator.name('atscm'), 'to match', /is not allowed/);\n    });\n\n    it('should fail with names longer than 214 characters', function () {\n      expect(Validator.name('a'.repeat(215)), 'to match', /can no longer contain more than 214/);\n    });\n\n    it('should work for valid package names', function () {\n      expect(Validator.name('project-name'), 'to be', true);\n    });\n\n    it('should work for scoped package names', function () {\n      expect(Validator.name('@project/name'), 'to be', true);\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/init/OptionsValidator.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 772,
    "kind": "test",
    "name": "describe78",
    "testId": 78,
    "memberof": "test/src/init/OptionsValidator.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/init/OptionsValidator.spec.js~describe78",
    "access": null,
    "description": "InitOptionsValidator",
    "lineNumber": 5,
    "testTargets": [
      "InitOptionsValidator"
    ]
  },
  {
    "__docId__": 773,
    "kind": "test",
    "name": "describe79",
    "testId": 79,
    "memberof": "test/src/init/OptionsValidator.spec.js~describe78",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/init/OptionsValidator.spec.js~describe78.describe79",
    "access": null,
    "description": ".name",
    "lineNumber": 7,
    "testTargets": [
      "InitOptionsValidator.name"
    ]
  },
  {
    "__docId__": 774,
    "kind": "test",
    "name": "it80",
    "testId": 80,
    "memberof": "test/src/init/OptionsValidator.spec.js~describe78.describe79",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/init/OptionsValidator.spec.js~describe78.describe79.it80",
    "access": null,
    "description": "should fail for empty names",
    "lineNumber": 8
  },
  {
    "__docId__": 775,
    "kind": "test",
    "name": "it81",
    "testId": 81,
    "memberof": "test/src/init/OptionsValidator.spec.js~describe78.describe79",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/init/OptionsValidator.spec.js~describe78.describe79.it81",
    "access": null,
    "description": "should fail with capital letters",
    "lineNumber": 12
  },
  {
    "__docId__": 776,
    "kind": "test",
    "name": "it82",
    "testId": 82,
    "memberof": "test/src/init/OptionsValidator.spec.js~describe78.describe79",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/init/OptionsValidator.spec.js~describe78.describe79.it82",
    "access": null,
    "description": "should fail with non-url-safe characters",
    "lineNumber": 16
  },
  {
    "__docId__": 777,
    "kind": "test",
    "name": "it83",
    "testId": 83,
    "memberof": "test/src/init/OptionsValidator.spec.js~describe78.describe79",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/init/OptionsValidator.spec.js~describe78.describe79.it83",
    "access": null,
    "description": "should fail with names starting with . or _",
    "lineNumber": 20
  },
  {
    "__docId__": 778,
    "kind": "test",
    "name": "it84",
    "testId": 84,
    "memberof": "test/src/init/OptionsValidator.spec.js~describe78.describe79",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/init/OptionsValidator.spec.js~describe78.describe79.it84",
    "access": null,
    "description": "should fail with leading or trailing spaces",
    "lineNumber": 25
  },
  {
    "__docId__": 779,
    "kind": "test",
    "name": "it85",
    "testId": 85,
    "memberof": "test/src/init/OptionsValidator.spec.js~describe78.describe79",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/init/OptionsValidator.spec.js~describe78.describe79.it85",
    "access": null,
    "description": "should fail with core nodejs module name",
    "lineNumber": 30
  },
  {
    "__docId__": 780,
    "kind": "test",
    "name": "it86",
    "testId": 86,
    "memberof": "test/src/init/OptionsValidator.spec.js~describe78.describe79",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/init/OptionsValidator.spec.js~describe78.describe79.it86",
    "access": null,
    "description": "should fail with blacklisted name",
    "lineNumber": 34
  },
  {
    "__docId__": 781,
    "kind": "test",
    "name": "it87",
    "testId": 87,
    "memberof": "test/src/init/OptionsValidator.spec.js~describe78.describe79",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/init/OptionsValidator.spec.js~describe78.describe79.it87",
    "access": null,
    "description": "should fail with 'atscm'",
    "lineNumber": 38
  },
  {
    "__docId__": 782,
    "kind": "test",
    "name": "it88",
    "testId": 88,
    "memberof": "test/src/init/OptionsValidator.spec.js~describe78.describe79",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/init/OptionsValidator.spec.js~describe78.describe79.it88",
    "access": null,
    "description": "should fail with names longer than 214 characters",
    "lineNumber": 42
  },
  {
    "__docId__": 783,
    "kind": "test",
    "name": "it89",
    "testId": 89,
    "memberof": "test/src/init/OptionsValidator.spec.js~describe78.describe79",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/init/OptionsValidator.spec.js~describe78.describe79.it89",
    "access": null,
    "description": "should work for valid package names",
    "lineNumber": 46
  },
  {
    "__docId__": 784,
    "kind": "test",
    "name": "it90",
    "testId": 90,
    "memberof": "test/src/init/OptionsValidator.spec.js~describe78.describe79",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/init/OptionsValidator.spec.js~describe78.describe79.it90",
    "access": null,
    "description": "should work for scoped package names",
    "lineNumber": 50
  },
  {
    "__docId__": 785,
    "kind": "testFile",
    "name": "test/src/lib/config/Atviseproject.spec.js",
    "content": "import expect from 'unexpected';\nimport Atviseproject from '../../../../src/lib/config/Atviseproject';\nimport NodeId from '../../../../src/lib/model/opcua/NodeId';\n\n/** @test {Atviseproject} */\ndescribe('Atviseproject', function () {\n  function expectNodeIds(arr) {\n    it('should contain NodeIds', function () {\n      arr.forEach((id) => expect(id, 'to be a', NodeId));\n    });\n  }\n\n  /** @test {Atviseproject.login} */\n  describe('.login', function () {\n    it('should default to false', function () {\n      expect(Atviseproject.login, 'to equal', false);\n    });\n  });\n\n  /** @test {Atviseproject.nodes} */\n  describe('.nodes', function () {\n    expectNodeIds(Atviseproject.nodes);\n  });\n\n  /** @test {Atviseproject.nodesToWatch} */\n  describe('.nodesToWatch', function () {\n    expectNodeIds(Atviseproject.nodesToWatch);\n  });\n\n  /** @test {Atviseproject.EditorRelatedNodes} */\n  describe('.EditorRelatedNodes', function () {\n    expectNodeIds(Atviseproject.EditorRelatedNodes);\n  });\n\n  /** @test {Atviseproject.ServerRelatedNodes} */\n  describe('.ServerRelatedNodes', function () {\n    expectNodeIds(Atviseproject.ServerRelatedNodes);\n  });\n\n  /** @test {Atviseproject.EditorRelatedNodes} */\n  describe('.ignoreNodes', function () {\n    expectNodeIds(Atviseproject.ignoreNodes);\n\n    it('should contain Atviseproject.EditorRelatedNodes', function () {\n      expect(Atviseproject.ignoreNodes, 'to contain', ...Atviseproject.EditorRelatedNodes);\n    });\n\n    it('should contain Atviseproject.ServerRelatedNodes', function () {\n      expect(Atviseproject.ignoreNodes, 'to contain', ...Atviseproject.ServerRelatedNodes);\n    });\n  });\n\n  /** @test {Atviseproject.inspect} */\n  describe('.inspect', function () {\n    it('should return the properties to print', function () {\n      expect(Atviseproject.inspect(), 'to have properties', [\n        'host',\n        'port',\n        'useTransformers',\n        'nodes',\n        'nodesToWatch',\n        'ignoreNodes',\n      ]);\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/config/Atviseproject.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 786,
    "kind": "test",
    "name": "describe91",
    "testId": 91,
    "memberof": "test/src/lib/config/Atviseproject.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/config/Atviseproject.spec.js~describe91",
    "access": null,
    "description": "Atviseproject",
    "lineNumber": 6,
    "testTargets": [
      "Atviseproject"
    ]
  },
  {
    "__docId__": 787,
    "kind": "test",
    "name": "it92",
    "testId": 92,
    "memberof": "test/src/lib/config/Atviseproject.spec.js~describe91",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/config/Atviseproject.spec.js~describe91.it92",
    "access": null,
    "description": "should contain NodeIds",
    "lineNumber": 8
  },
  {
    "__docId__": 788,
    "kind": "test",
    "name": "describe93",
    "testId": 93,
    "memberof": "test/src/lib/config/Atviseproject.spec.js~describe91",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/config/Atviseproject.spec.js~describe91.describe93",
    "access": null,
    "description": ".login",
    "lineNumber": 14,
    "testTargets": [
      "Atviseproject.login"
    ]
  },
  {
    "__docId__": 789,
    "kind": "test",
    "name": "it94",
    "testId": 94,
    "memberof": "test/src/lib/config/Atviseproject.spec.js~describe91.describe93",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/config/Atviseproject.spec.js~describe91.describe93.it94",
    "access": null,
    "description": "should default to false",
    "lineNumber": 15
  },
  {
    "__docId__": 790,
    "kind": "test",
    "name": "describe95",
    "testId": 95,
    "memberof": "test/src/lib/config/Atviseproject.spec.js~describe91",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/config/Atviseproject.spec.js~describe91.describe95",
    "access": null,
    "description": ".nodes",
    "lineNumber": 21,
    "testTargets": [
      "Atviseproject.nodes"
    ]
  },
  {
    "__docId__": 791,
    "kind": "test",
    "name": "describe96",
    "testId": 96,
    "memberof": "test/src/lib/config/Atviseproject.spec.js~describe91",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/config/Atviseproject.spec.js~describe91.describe96",
    "access": null,
    "description": ".nodesToWatch",
    "lineNumber": 26,
    "testTargets": [
      "Atviseproject.nodesToWatch"
    ]
  },
  {
    "__docId__": 792,
    "kind": "test",
    "name": "describe97",
    "testId": 97,
    "memberof": "test/src/lib/config/Atviseproject.spec.js~describe91",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/config/Atviseproject.spec.js~describe91.describe97",
    "access": null,
    "description": ".EditorRelatedNodes",
    "lineNumber": 31,
    "testTargets": [
      "Atviseproject.EditorRelatedNodes"
    ]
  },
  {
    "__docId__": 793,
    "kind": "test",
    "name": "describe98",
    "testId": 98,
    "memberof": "test/src/lib/config/Atviseproject.spec.js~describe91",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/config/Atviseproject.spec.js~describe91.describe98",
    "access": null,
    "description": ".ServerRelatedNodes",
    "lineNumber": 36,
    "testTargets": [
      "Atviseproject.ServerRelatedNodes"
    ]
  },
  {
    "__docId__": 794,
    "kind": "test",
    "name": "describe99",
    "testId": 99,
    "memberof": "test/src/lib/config/Atviseproject.spec.js~describe91",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/config/Atviseproject.spec.js~describe91.describe99",
    "access": null,
    "description": ".ignoreNodes",
    "lineNumber": 41,
    "testTargets": [
      "Atviseproject.EditorRelatedNodes"
    ]
  },
  {
    "__docId__": 795,
    "kind": "test",
    "name": "it100",
    "testId": 100,
    "memberof": "test/src/lib/config/Atviseproject.spec.js~describe91.describe99",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/config/Atviseproject.spec.js~describe91.describe99.it100",
    "access": null,
    "description": "should contain Atviseproject.EditorRelatedNodes",
    "lineNumber": 44
  },
  {
    "__docId__": 796,
    "kind": "test",
    "name": "it101",
    "testId": 101,
    "memberof": "test/src/lib/config/Atviseproject.spec.js~describe91.describe99",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/config/Atviseproject.spec.js~describe91.describe99.it101",
    "access": null,
    "description": "should contain Atviseproject.ServerRelatedNodes",
    "lineNumber": 48
  },
  {
    "__docId__": 797,
    "kind": "test",
    "name": "describe102",
    "testId": 102,
    "memberof": "test/src/lib/config/Atviseproject.spec.js~describe91",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/config/Atviseproject.spec.js~describe91.describe102",
    "access": null,
    "description": ".inspect",
    "lineNumber": 54,
    "testTargets": [
      "Atviseproject.inspect"
    ]
  },
  {
    "__docId__": 798,
    "kind": "test",
    "name": "it103",
    "testId": 103,
    "memberof": "test/src/lib/config/Atviseproject.spec.js~describe91.describe102",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/config/Atviseproject.spec.js~describe91.describe102.it103",
    "access": null,
    "description": "should return the properties to print",
    "lineNumber": 55
  },
  {
    "__docId__": 799,
    "kind": "testFile",
    "name": "test/src/lib/gulp/ImportStream.spec.js",
    "content": "import { join, sep as separator } from 'path';\nimport { DataType, NodeId } from 'node-opcua';\nimport { src } from 'gulp';\nimport { obj as createTransformStream } from 'through2';\nimport replace from 'buffer-replace';\nimport expect from '../../../expect';\nimport ImportStream from '../../../../src/lib/gulp/ImportStream';\nimport Session from '../../../../src/lib/server/Session';\n\n/** @test {ImportStream} */\ndescribe('ImportStream', function () {\n  /** @test {ImportStream#methodId} */\n  describe('#methodId', function () {\n    it('should return importNodes method id', function () {\n      expect(\n        ImportStream.prototype.methodId.toString(),\n        'to equal',\n        'ns=1;s=AGENT.OPCUA.METHODS.importNodes'\n      );\n    });\n  });\n\n  /** @test {ImportStream#inputArguments} */\n  describe('#inputArguments', function () {\n    it('should contain global scope argument', function () {\n      const [scope] = ImportStream.prototype.inputArguments({});\n\n      expect(scope.value, 'to be a', NodeId);\n      expect(scope.value.namespace, 'to equal', 0);\n      expect(scope.value.value, 'to equal', 0);\n    });\n\n    it('should contain file contents', function () {\n      const contents = 'test';\n      const fileArg = ImportStream.prototype.inputArguments({ contents })[1];\n\n      expect(fileArg.value, 'to equal', contents);\n      expect(fileArg.dataType, 'to equal', DataType.XmlElement);\n    });\n  });\n\n  /** @test {ImportStream#processErrorMessage} */\n  describe('#processErrorMessage', function () {\n    it('should prefix file path', function () {\n      const path = 'TestPath';\n\n      return expect(\n        ImportStream.prototype.processErrorMessage,\n        'when called with',\n        [{ path }],\n        'to begin with',\n        'Error importing file'\n      );\n    });\n\n    it('should print path relative to project directory', function () {\n      const relative = ['path', 'to', 'file'].join(separator);\n\n      return expect(\n        ImportStream.prototype.processErrorMessage,\n        'when called with',\n        [{ relative }],\n        'to end with',\n        relative\n      );\n    });\n  });\n\n  /** @test {ImportStream#handleOutputArguments} */\n  describe('#handleOutputArguments', function () {\n    it('should error if import failed', function () {\n      return expect(\n        (cb) => ImportStream.prototype.handleOutputArguments({}, [{ value: false }], cb),\n        'to call the callback with error',\n        'Import failed'\n      );\n    });\n\n    it('should error without status', function () {\n      return expect(\n        (cb) => ImportStream.prototype.handleOutputArguments({}, undefined, cb),\n        'to call the callback with error',\n        'Import failed'\n      );\n    });\n\n    it('should not error if import succeeded', function () {\n      return expect(\n        (cb) => ImportStream.prototype.handleOutputArguments({}, [{ value: true }], cb),\n        'to call the callback without error'\n      );\n    });\n  });\n\n  /** @test {ImportStream#processChunk} */\n  describe('#processChunk', function () {\n    it('should create new nodes on success', async function () {\n      const nodeName = `TestNode-${Date.now()}`;\n      const fixturePath = join(__dirname, '../../../fixtures/TestImport.xml');\n      const replaceStream = createTransformStream((file, enc, callback) => {\n        callback(\n          null,\n          Object.assign(file, {\n            contents: replace(file.contents, 'TestNode', nodeName),\n          })\n        );\n      });\n      const importStream = new ImportStream();\n\n      // eslint-disable-next-line no-console\n      console.log(`Importing test node: ${nodeName}`);\n\n      await expect(\n        src(fixturePath).pipe(replaceStream).pipe(importStream),\n        'to yield objects satisfying',\n        []\n      );\n\n      const session = await Session.create();\n\n      const [value] = await expect(\n        (cb) => session.readVariableValue([`ns=1;s=AGENT.OBJECTS.${nodeName}`], cb),\n        'to call the callback without error'\n      );\n\n      return expect(value[0].value.value, 'to equal', 13);\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/gulp/ImportStream.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 800,
    "kind": "test",
    "name": "describe104",
    "testId": 104,
    "memberof": "test/src/lib/gulp/ImportStream.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/gulp/ImportStream.spec.js~describe104",
    "access": null,
    "description": "ImportStream",
    "lineNumber": 11,
    "testTargets": [
      "ImportStream"
    ]
  },
  {
    "__docId__": 801,
    "kind": "test",
    "name": "describe105",
    "testId": 105,
    "memberof": "test/src/lib/gulp/ImportStream.spec.js~describe104",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe105",
    "access": null,
    "description": "#methodId",
    "lineNumber": 13,
    "testTargets": [
      "ImportStream#methodId"
    ]
  },
  {
    "__docId__": 802,
    "kind": "test",
    "name": "it106",
    "testId": 106,
    "memberof": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe105",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe105.it106",
    "access": null,
    "description": "should return importNodes method id",
    "lineNumber": 14
  },
  {
    "__docId__": 803,
    "kind": "test",
    "name": "describe107",
    "testId": 107,
    "memberof": "test/src/lib/gulp/ImportStream.spec.js~describe104",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe107",
    "access": null,
    "description": "#inputArguments",
    "lineNumber": 24,
    "testTargets": [
      "ImportStream#inputArguments"
    ]
  },
  {
    "__docId__": 804,
    "kind": "test",
    "name": "it108",
    "testId": 108,
    "memberof": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe107",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe107.it108",
    "access": null,
    "description": "should contain global scope argument",
    "lineNumber": 25
  },
  {
    "__docId__": 805,
    "kind": "test",
    "name": "it109",
    "testId": 109,
    "memberof": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe107",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe107.it109",
    "access": null,
    "description": "should contain file contents",
    "lineNumber": 33
  },
  {
    "__docId__": 806,
    "kind": "test",
    "name": "describe110",
    "testId": 110,
    "memberof": "test/src/lib/gulp/ImportStream.spec.js~describe104",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe110",
    "access": null,
    "description": "#processErrorMessage",
    "lineNumber": 43,
    "testTargets": [
      "ImportStream#processErrorMessage"
    ]
  },
  {
    "__docId__": 807,
    "kind": "test",
    "name": "it111",
    "testId": 111,
    "memberof": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe110",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe110.it111",
    "access": null,
    "description": "should prefix file path",
    "lineNumber": 44
  },
  {
    "__docId__": 808,
    "kind": "test",
    "name": "it112",
    "testId": 112,
    "memberof": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe110",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe110.it112",
    "access": null,
    "description": "should print path relative to project directory",
    "lineNumber": 56
  },
  {
    "__docId__": 809,
    "kind": "test",
    "name": "describe113",
    "testId": 113,
    "memberof": "test/src/lib/gulp/ImportStream.spec.js~describe104",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe113",
    "access": null,
    "description": "#handleOutputArguments",
    "lineNumber": 70,
    "testTargets": [
      "ImportStream#handleOutputArguments"
    ]
  },
  {
    "__docId__": 810,
    "kind": "test",
    "name": "it114",
    "testId": 114,
    "memberof": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe113",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe113.it114",
    "access": null,
    "description": "should error if import failed",
    "lineNumber": 71
  },
  {
    "__docId__": 811,
    "kind": "test",
    "name": "it115",
    "testId": 115,
    "memberof": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe113",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe113.it115",
    "access": null,
    "description": "should error without status",
    "lineNumber": 79
  },
  {
    "__docId__": 812,
    "kind": "test",
    "name": "it116",
    "testId": 116,
    "memberof": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe113",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe113.it116",
    "access": null,
    "description": "should not error if import succeeded",
    "lineNumber": 87
  },
  {
    "__docId__": 813,
    "kind": "test",
    "name": "describe117",
    "testId": 117,
    "memberof": "test/src/lib/gulp/ImportStream.spec.js~describe104",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe117",
    "access": null,
    "description": "#processChunk",
    "lineNumber": 96,
    "testTargets": [
      "ImportStream#processChunk"
    ]
  },
  {
    "__docId__": 814,
    "kind": "test",
    "name": "it118",
    "testId": 118,
    "memberof": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe117",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/gulp/ImportStream.spec.js~describe104.describe117.it118",
    "access": null,
    "description": "should create new nodes on success",
    "lineNumber": 97
  },
  {
    "__docId__": 815,
    "kind": "testFile",
    "name": "test/src/lib/gulp/PullStream.spec.js",
    "content": "import { Stream, PassThrough } from 'stream';\nimport Logger from 'gulplog';\nimport { spy } from 'sinon';\nimport proxyquire from 'proxyquire';\nimport { DataType, StatusCodes, Variant, NodeClass } from 'node-opcua';\nimport { obj as createTransformSteam } from 'through2';\nimport expect from '../../../expect';\nimport ReadStream from '../../../../src/lib/server/NodeStream';\nimport { TransformDirection } from '../../../../src/lib/transform/Transformer';\nimport { ServerNode } from '../../../../src/lib/model/Node';\n\nconst StubTransformer = {\n  applyTransformers: spy((stream) => stream),\n};\n\nconst readline = {\n  clearLine: spy().named('readline.clearLine'),\n  moveCursor: spy().named('readline.moveCursor'),\n};\n\nconst PullStream = proxyquire('../../../../src/lib/gulp/PullStream', {\n  readline,\n  './dest': {\n    default: () => createTransformSteam(),\n  },\n  '../transform/Transformer': {\n    _esModule: true,\n    default: StubTransformer,\n  },\n}).default;\n\nclass StubReadStream extends ReadStream {\n  processChunk(\n    {\n      nodeId,\n      references = {},\n      dataType = DataType.XmlElement,\n      value = '<svg></svg>',\n      nodeClass = NodeClass.Variable,\n    },\n    handleErrors\n  ) {\n    handleErrors(null, StatusCodes.Good, (done) => {\n      this.push({\n        nodeId,\n        value: new Variant({\n          dataType,\n          value,\n        }),\n        nodeClass,\n        references,\n        mtime: new Date(),\n      });\n      done();\n    });\n  }\n}\n\n/** @test {PullStream} */\ndescribe('PullStream', function () {\n  /** @test {PullStream#constructor} */\n  describe('#constructor', function () {\n    let logListener;\n\n    beforeEach(() => {\n      StubTransformer.applyTransformers.resetHistory();\n      readline.clearLine.resetHistory();\n      readline.moveCursor.resetHistory();\n\n      if (logListener) {\n        Logger.removeListener('info', logListener);\n      }\n    });\n\n    it('should return a stream', function () {\n      const stream = new PullStream(new PassThrough({ objectMode: true }));\n      expect(stream, 'to be a', Stream);\n      stream.end();\n\n      expect(stream, 'to yield objects satisfying', 'to have length', 0);\n    });\n\n    it('should apply transformers from db', function () {\n      const readStream = new PassThrough({ objectMode: true });\n      const stream = new PullStream(readStream);\n\n      readStream.write(\n        new ServerNode({\n          name: 'Main',\n          parent: null,\n          nodeClass: NodeClass.Variable,\n        })\n      );\n      readStream.end();\n\n      return expect(stream, 'to yield objects satisfying', [expect.it('to be a', ServerNode)]).then(\n        () => {\n          expect(StubTransformer.applyTransformers.calledOnce, 'to be', true);\n          expect(\n            StubTransformer.applyTransformers.lastCall.args[2],\n            'to be',\n            TransformDirection.FromDB\n          );\n        }\n      );\n    });\n\n    it.skip('should print progress', function () {\n      const stream = new PullStream(Object.assign(new StubReadStream(), { _processed: 12 }));\n\n      setTimeout(() => stream.end(), 1200);\n\n      logListener = spy().named('logListener');\n      Logger.on('info', logListener);\n\n      return expect(stream, 'to yield objects satisfying', 'to have length', 0).then(() => {\n        // expect(logListener, 'was called once');\n        expect(logListener.lastCall, 'to satisfy', [/Pulled: 12 \\([0-9.]+ ops\\/s\\)/]);\n        expect(readline.clearLine, 'was called once');\n        expect(readline.moveCursor, 'was called once');\n      });\n    });\n\n    it.skip('should work without log listeners', function () {\n      const stream = new PullStream(new StubReadStream());\n\n      setTimeout(() => stream.end(), 1200);\n\n      return expect(stream, 'to yield objects satisfying', 'to have length', 0).then(() => {\n        expect(readline.clearLine, 'was not called');\n        expect(readline.moveCursor, 'was not called');\n      });\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/gulp/PullStream.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 816,
    "kind": "test",
    "name": "describe119",
    "testId": 119,
    "memberof": "test/src/lib/gulp/PullStream.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/gulp/PullStream.spec.js~describe119",
    "access": null,
    "description": "PullStream",
    "lineNumber": 60,
    "testTargets": [
      "PullStream"
    ]
  },
  {
    "__docId__": 817,
    "kind": "test",
    "name": "describe120",
    "testId": 120,
    "memberof": "test/src/lib/gulp/PullStream.spec.js~describe119",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/gulp/PullStream.spec.js~describe119.describe120",
    "access": null,
    "description": "#constructor",
    "lineNumber": 62,
    "testTargets": [
      "PullStream#constructor"
    ]
  },
  {
    "__docId__": 818,
    "kind": "test",
    "name": "it121",
    "testId": 121,
    "memberof": "test/src/lib/gulp/PullStream.spec.js~describe119.describe120",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/gulp/PullStream.spec.js~describe119.describe120.it121",
    "access": null,
    "description": "should return a stream",
    "lineNumber": 75
  },
  {
    "__docId__": 819,
    "kind": "test",
    "name": "it122",
    "testId": 122,
    "memberof": "test/src/lib/gulp/PullStream.spec.js~describe119.describe120",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/gulp/PullStream.spec.js~describe119.describe120.it122",
    "access": null,
    "description": "should apply transformers from db",
    "lineNumber": 83
  },
  {
    "__docId__": 820,
    "kind": "testFile",
    "name": "test/src/lib/gulp/PushStream.spec.js",
    "content": "import { Stream } from 'stream';\nimport { spy } from 'sinon';\nimport proxyquire from 'proxyquire';\nimport { obj as createTransformStream } from 'through2';\nimport File from 'vinyl';\nimport Logger from 'gulplog';\nimport expect from '../../../expect';\nimport { TransformDirection } from '../../../../src/lib/transform/Transformer';\n\nconst StubTransformer = {\n  applyTransformers: spy((stream) => stream),\n};\n\nconst readline = {\n  clearLine: spy().named('readline.clearLine'),\n  moveCursor: spy().named('readline.moveCursor'),\n};\n\nconst PushStream = proxyquire('../../../../src/lib/gulp/PushStream', {\n  readline,\n  '../server/WriteStream': {\n    _esModule: true,\n    default: class WriteStream {\n      constructor() {\n        return Object.assign(createTransformStream(), {\n          opsPerSecond: 13.2,\n          _processed: 12,\n        });\n      }\n    },\n  },\n  '../transform/Transformer': {\n    _esModule: true,\n    default: StubTransformer,\n  },\n}).default;\n\n/** @test {PushStream} */\ndescribe('PushStream', function () {\n  /** @test {PushStream#constructor} */\n  describe('#constructor', function () {\n    let logListener;\n\n    beforeEach(() => {\n      StubTransformer.applyTransformers.resetHistory();\n      readline.clearLine.resetHistory();\n      readline.moveCursor.resetHistory();\n\n      if (logListener) {\n        Logger.removeListener('info', logListener);\n      }\n    });\n\n    it('should return a stream', function () {\n      const stream = new PushStream(createTransformStream());\n      expect(stream, 'to be a', Stream);\n      stream.end();\n\n      return expect(stream, 'to yield objects satisfying', 'to have length', 0);\n    });\n\n    it.skip('should apply transformers from db', function () {\n      const srcStream = createTransformStream();\n      const stream = new PushStream(srcStream);\n\n      srcStream.write(\n        new File({\n          path: 'src/AGENT/DISPLAYS/Main.display',\n          base: 'src',\n        })\n      );\n      srcStream.end();\n\n      return expect(stream, 'to yield objects satisfying', 'to have length', 0).then(() => {\n        expect(StubTransformer.applyTransformers.calledOnce, 'to be', true);\n        expect(\n          StubTransformer.applyTransformers.lastCall.args[2],\n          'to be',\n          TransformDirection.FromFilesystem\n        );\n      });\n    });\n\n    it.skip('should print progress', function () {\n      const stream = new PushStream(createTransformStream());\n\n      setTimeout(() => stream.end(), 1200);\n\n      logListener = spy().named('logListener');\n      Logger.on('info', logListener);\n\n      return expect(stream, 'to yield objects satisfying', 'to have length', 0).then(() => {\n        expect(logListener, 'was called once');\n        expect(logListener.lastCall, 'to satisfy', [/Pushed: 12 \\([0-9.]+ ops\\/s\\)/]);\n        expect(readline.clearLine, 'was called once');\n        expect(readline.moveCursor, 'was called once');\n      });\n    });\n\n    it('should work without log listeners', function () {\n      const stream = new PushStream(createTransformStream());\n\n      setTimeout(() => stream.end(), 1200);\n\n      return expect(stream, 'to yield objects satisfying', 'to have length', 0).then(() => {\n        expect(readline.clearLine, 'was not called');\n        expect(readline.moveCursor, 'was not called');\n      });\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/gulp/PushStream.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 821,
    "kind": "test",
    "name": "describe123",
    "testId": 123,
    "memberof": "test/src/lib/gulp/PushStream.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/gulp/PushStream.spec.js~describe123",
    "access": null,
    "description": "PushStream",
    "lineNumber": 39,
    "testTargets": [
      "PushStream"
    ]
  },
  {
    "__docId__": 822,
    "kind": "test",
    "name": "describe124",
    "testId": 124,
    "memberof": "test/src/lib/gulp/PushStream.spec.js~describe123",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/gulp/PushStream.spec.js~describe123.describe124",
    "access": null,
    "description": "#constructor",
    "lineNumber": 41,
    "testTargets": [
      "PushStream#constructor"
    ]
  },
  {
    "__docId__": 823,
    "kind": "test",
    "name": "it125",
    "testId": 125,
    "memberof": "test/src/lib/gulp/PushStream.spec.js~describe123.describe124",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/gulp/PushStream.spec.js~describe123.describe124.it125",
    "access": null,
    "description": "should return a stream",
    "lineNumber": 54
  },
  {
    "__docId__": 824,
    "kind": "test",
    "name": "it126",
    "testId": 126,
    "memberof": "test/src/lib/gulp/PushStream.spec.js~describe123.describe124",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/gulp/PushStream.spec.js~describe123.describe124.it126",
    "access": null,
    "description": "should work without log listeners",
    "lineNumber": 100
  },
  {
    "__docId__": 825,
    "kind": "testFile",
    "name": "test/src/lib/helpers/Object.spec.js",
    "content": "import expect from '../../../expect';\nimport { reverse } from '../../../../src/lib/helpers/Object';\n\n/** @test {reverse} */\ndescribe('reverse', function () {\n  it('should return an object with keys and values switched', function () {\n    expect(reverse({ a: 1, 2: 'b' }), 'to equal', { 1: 'a', b: '2' });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/helpers/Object.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 826,
    "kind": "test",
    "name": "describe127",
    "testId": 127,
    "memberof": "test/src/lib/helpers/Object.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/helpers/Object.spec.js~describe127",
    "access": null,
    "description": "reverse",
    "lineNumber": 5,
    "testTargets": [
      "reverse"
    ]
  },
  {
    "__docId__": 827,
    "kind": "test",
    "name": "it128",
    "testId": 128,
    "memberof": "test/src/lib/helpers/Object.spec.js~describe127",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/helpers/Object.spec.js~describe127.it128",
    "access": null,
    "description": "should return an object with keys and values switched",
    "lineNumber": 6
  },
  {
    "__docId__": 828,
    "kind": "testFile",
    "name": "test/src/lib/helpers/async.spec.js",
    "content": "import expect from '../../../expect';\nimport { delay, promisified } from '../../../../src/lib/helpers/async';\n\n/** @test {delay} */\ndescribe('delay', function () {\n  it('should resolve after duration', function () {\n    return expect(() => delay(100), 'to be fulfilled');\n  });\n});\n\n/** @test {promisified} */\ndescribe('promisified', function () {\n  it('should be fulfilled when async function calls callback', function () {\n    return expect(\n      promisified((cb) => process.nextTick(cb)),\n      'to be fulfilled'\n    );\n  });\n\n  it('should be rejected when async function fails', function () {\n    function failingAsync(callback) {\n      process.nextTick(() => {\n        callback(new Error('Oops'));\n      });\n    }\n\n    return expect(\n      promisified((cb) => failingAsync(cb)),\n      'to be rejected with',\n      'Oops'\n    );\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/helpers/async.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 829,
    "kind": "test",
    "name": "describe129",
    "testId": 129,
    "memberof": "test/src/lib/helpers/async.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/helpers/async.spec.js~describe129",
    "access": null,
    "description": "delay",
    "lineNumber": 5,
    "testTargets": [
      "delay"
    ]
  },
  {
    "__docId__": 830,
    "kind": "test",
    "name": "it130",
    "testId": 130,
    "memberof": "test/src/lib/helpers/async.spec.js~describe129",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/helpers/async.spec.js~describe129.it130",
    "access": null,
    "description": "should resolve after duration",
    "lineNumber": 6
  },
  {
    "__docId__": 831,
    "kind": "test",
    "name": "describe131",
    "testId": 131,
    "memberof": "test/src/lib/helpers/async.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/helpers/async.spec.js~describe131",
    "access": null,
    "description": "promisified",
    "lineNumber": 12,
    "testTargets": [
      "promisified"
    ]
  },
  {
    "__docId__": 832,
    "kind": "test",
    "name": "it132",
    "testId": 132,
    "memberof": "test/src/lib/helpers/async.spec.js~describe131",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/helpers/async.spec.js~describe131.it132",
    "access": null,
    "description": "should be fulfilled when async function calls callback",
    "lineNumber": 13
  },
  {
    "__docId__": 833,
    "kind": "test",
    "name": "it133",
    "testId": 133,
    "memberof": "test/src/lib/helpers/async.spec.js~describe131",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/helpers/async.spec.js~describe131.it133",
    "access": null,
    "description": "should be rejected when async function fails",
    "lineNumber": 20
  },
  {
    "__docId__": 834,
    "kind": "testFile",
    "name": "test/src/lib/init/Options.spec.js",
    "content": "import expect from 'unexpected';\nimport InitOption from '../../../../src/lib/init/Option';\n\n/** @test {InitOption} */\ndescribe('InitOption', function () {\n  it('should throw when run without arguments', function () {\n    expect(() => new InitOption(), 'to throw', 'message or options required');\n  });\n\n  /** @test {InitOption#constructor} */\n  describe('#constructor', function () {\n    context('when run with string, string', function () {\n      it('should throw error for empty message', function () {\n        expect(() => new InitOption(''), 'to throw error', 'message is required');\n      });\n\n      it('should work with message only', function () {\n        let opt;\n\n        expect(() => (opt = new InitOption('message')), 'not to throw');\n        expect(opt.message, 'to match', /message/);\n        expect(opt.default, 'to be', undefined);\n      });\n\n      it('should set default type', function () {\n        expect(new InitOption('message').type, 'to equal', InitOption.DefaultType);\n      });\n\n      it('should add `?` to message', function () {\n        expect(new InitOption('message').message, 'to equal', 'message?');\n      });\n\n      it('should store default if given', function () {\n        expect(new InitOption('message', 'default').default, 'to equal', 'default');\n      });\n    });\n\n    context('when run with object', function () {\n      it('should throw error for missing message', function () {\n        expect(() => new InitOption({}), 'to throw error', 'message is required');\n      });\n\n      it('should throw error for empty message', function () {\n        expect(() => new InitOption({ message: '' }), 'to throw error', 'message is required');\n      });\n\n      it('should add `?` to message', function () {\n        expect(new InitOption({ message: 'message' }).message, 'to equal', 'message?');\n      });\n\n      it('should set default type', function () {\n        expect(new InitOption({ message: 'message' }).type, 'to equal', InitOption.DefaultType);\n      });\n\n      it('should store type, message, default and validate', function () {\n        const opts = {\n          type: 'test',\n          message: 'message',\n          default: 'default',\n          validate: () => true,\n        };\n\n        const result = Object.assign({}, opts, { message: `${opts.message}?` });\n\n        expect(new InitOption(opts), 'to have properties', result);\n      });\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/init/Options.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 835,
    "kind": "test",
    "name": "describe134",
    "testId": 134,
    "memberof": "test/src/lib/init/Options.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/init/Options.spec.js~describe134",
    "access": null,
    "description": "InitOption",
    "lineNumber": 5,
    "testTargets": [
      "InitOption"
    ]
  },
  {
    "__docId__": 836,
    "kind": "test",
    "name": "it135",
    "testId": 135,
    "memberof": "test/src/lib/init/Options.spec.js~describe134",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/init/Options.spec.js~describe134.it135",
    "access": null,
    "description": "should throw when run without arguments",
    "lineNumber": 6
  },
  {
    "__docId__": 837,
    "kind": "test",
    "name": "describe136",
    "testId": 136,
    "memberof": "test/src/lib/init/Options.spec.js~describe134",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/init/Options.spec.js~describe134.describe136",
    "access": null,
    "description": "#constructor",
    "lineNumber": 11,
    "testTargets": [
      "InitOption#constructor"
    ]
  },
  {
    "__docId__": 838,
    "kind": "test",
    "name": "context137",
    "testId": 137,
    "memberof": "test/src/lib/init/Options.spec.js~describe134.describe136",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/init/Options.spec.js~describe134.describe136.context137",
    "access": null,
    "description": "when run with string, string",
    "lineNumber": 12
  },
  {
    "__docId__": 839,
    "kind": "test",
    "name": "it138",
    "testId": 138,
    "memberof": "test/src/lib/init/Options.spec.js~describe134.describe136.context137",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/init/Options.spec.js~describe134.describe136.context137.it138",
    "access": null,
    "description": "should throw error for empty message",
    "lineNumber": 13
  },
  {
    "__docId__": 840,
    "kind": "test",
    "name": "it139",
    "testId": 139,
    "memberof": "test/src/lib/init/Options.spec.js~describe134.describe136.context137",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/init/Options.spec.js~describe134.describe136.context137.it139",
    "access": null,
    "description": "should work with message only",
    "lineNumber": 17
  },
  {
    "__docId__": 841,
    "kind": "test",
    "name": "it140",
    "testId": 140,
    "memberof": "test/src/lib/init/Options.spec.js~describe134.describe136.context137",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/init/Options.spec.js~describe134.describe136.context137.it140",
    "access": null,
    "description": "should set default type",
    "lineNumber": 25
  },
  {
    "__docId__": 842,
    "kind": "test",
    "name": "it141",
    "testId": 141,
    "memberof": "test/src/lib/init/Options.spec.js~describe134.describe136.context137",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/init/Options.spec.js~describe134.describe136.context137.it141",
    "access": null,
    "description": "should add `?` to message",
    "lineNumber": 29
  },
  {
    "__docId__": 843,
    "kind": "test",
    "name": "it142",
    "testId": 142,
    "memberof": "test/src/lib/init/Options.spec.js~describe134.describe136.context137",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/init/Options.spec.js~describe134.describe136.context137.it142",
    "access": null,
    "description": "should store default if given",
    "lineNumber": 33
  },
  {
    "__docId__": 844,
    "kind": "test",
    "name": "context143",
    "testId": 143,
    "memberof": "test/src/lib/init/Options.spec.js~describe134.describe136",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/init/Options.spec.js~describe134.describe136.context143",
    "access": null,
    "description": "when run with object",
    "lineNumber": 38
  },
  {
    "__docId__": 845,
    "kind": "test",
    "name": "it144",
    "testId": 144,
    "memberof": "test/src/lib/init/Options.spec.js~describe134.describe136.context143",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/init/Options.spec.js~describe134.describe136.context143.it144",
    "access": null,
    "description": "should throw error for missing message",
    "lineNumber": 39
  },
  {
    "__docId__": 846,
    "kind": "test",
    "name": "it145",
    "testId": 145,
    "memberof": "test/src/lib/init/Options.spec.js~describe134.describe136.context143",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/init/Options.spec.js~describe134.describe136.context143.it145",
    "access": null,
    "description": "should throw error for empty message",
    "lineNumber": 43
  },
  {
    "__docId__": 847,
    "kind": "test",
    "name": "it146",
    "testId": 146,
    "memberof": "test/src/lib/init/Options.spec.js~describe134.describe136.context143",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/init/Options.spec.js~describe134.describe136.context143.it146",
    "access": null,
    "description": "should add `?` to message",
    "lineNumber": 47
  },
  {
    "__docId__": 848,
    "kind": "test",
    "name": "it147",
    "testId": 147,
    "memberof": "test/src/lib/init/Options.spec.js~describe134.describe136.context143",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/init/Options.spec.js~describe134.describe136.context143.it147",
    "access": null,
    "description": "should set default type",
    "lineNumber": 51
  },
  {
    "__docId__": 849,
    "kind": "test",
    "name": "it148",
    "testId": 148,
    "memberof": "test/src/lib/init/Options.spec.js~describe134.describe136.context143",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/init/Options.spec.js~describe134.describe136.context143.it148",
    "access": null,
    "description": "should store type, message, default and validate",
    "lineNumber": 55
  },
  {
    "__docId__": 850,
    "kind": "testFile",
    "name": "test/src/lib/model/opcua/NodeId.spec.js",
    "content": "import { join } from 'path';\nimport expect from 'unexpected';\nimport { spy } from 'sinon';\nimport { NodeId as OpcNodeId } from 'node-opcua';\nimport NodeId from '../../../../../src/lib/model/opcua/NodeId';\n\n/** @test {NodeId} */\ndescribe('NodeId', function () {\n  const path = join('AGENT/DISPLAYS/Main');\n  const id = 'AGENT.DISPLAYS.Main';\n\n  /** @test {NodeId#constructor} */\n  describe('#constructor', function () {\n    function expectType(type, ...args) {\n      expect(new NodeId(...args).identifierType, 'to equal', type);\n    }\n\n    context('when called with value only', function () {\n      it('should work', function () {\n        expect(() => new NodeId('AGENT.DISPLAYS'), 'not to throw');\n      });\n\n      it('should set namespace to 1', function () {\n        expect(new NodeId('AGENT.DISPLAYS').namespace, 'to equal', 1);\n      });\n\n      it('should set indentifierType to string if string is passed', function () {\n        expectType(NodeId.NodeIdType.STRING, 'AGENT.DISPLAYS');\n      });\n\n      it('should set indentifierType to number if number is passed', function () {\n        expectType(NodeId.NodeIdType.NUMERIC, 123);\n      });\n    });\n\n    context('when called with a nodeid string', function () {\n      it('should work', function () {\n        expect(() => new NodeId('ns=1;s=AGENT.DISPLAYS'), 'not to throw');\n      });\n\n      it('should get namespace from string', function () {\n        expect(new NodeId('ns=13;s=AGENT.DISPLAYS').namespace, 'to equal', 13);\n      });\n\n      it('should get identifierType from string', function () {\n        expectType(NodeId.NodeIdType.STRING, 'ns=1;s=AGENT.DISPLAYS');\n        expectType(NodeId.NodeIdType.NUMERIC, 'ns=1;i=13');\n        // FIXME: Missing tests for type GUID\n        expectType(NodeId.NodeIdType.BYTESTRING, 'ns=1;b=13Ac');\n      });\n    });\n\n    context('when called with type, value, namespace', function () {\n      it('should work', function () {\n        expect(() => new NodeId(NodeId.NodeIdType.STRING, 'AGENT.DISPLAYS', 1), 'not to throw');\n      });\n\n      it('should set namespace to 1 if omitted', function () {\n        expect(() => new NodeId(NodeId.NodeIdType.STRING, 'AGENT.DISPLAYS'), 'not to throw');\n        expect(new NodeId(NodeId.NodeIdType.STRING, 'AGENT.DISPLAYS').namespace, 'to equal', 1);\n      });\n    });\n\n    it(\"should extend node-opcua's NodeId\", function () {\n      expect(new NodeId(NodeId.NodeIdType.NUMERIC, 123, 1), 'to be a', OpcNodeId);\n    });\n  });\n\n  /** @test {NodeId#fromFilePath} */\n  describe('#fromFilePath', function () {\n    it('should return a NodeId', function () {\n      expect(NodeId.fromFilePath(path), 'to be a', NodeId);\n    });\n\n    it('should return file path again', function () {\n      const nodeId = NodeId.fromFilePath(path);\n      expect(nodeId.filePath, 'to be a', 'string');\n      expect(join(nodeId.filePath), 'to equal', path);\n    });\n\n    it('should work with resource paths', function () {\n      expect(\n        NodeId.fromFilePath(\n          join('SYSTEM/LIBRARY/ATVISE/RESOURCES/timer/imgs_glossy/top-separator.gif')\n        ).value,\n        'to equal',\n        'SYSTEM.LIBRARY.ATVISE.RESOURCES/timer/imgs_glossy/top-separator.gif'\n      );\n    });\n\n    it('should work with multi extension resource paths', function () {\n      expect(\n        NodeId.fromFilePath(join('SYSTEM/LIBRARY/PROJECT/RESOURCES/styles/bootstrap.min.css'))\n          .value,\n        'to equal',\n        'SYSTEM.LIBRARY.PROJECT.RESOURCES/styles/bootstrap.min.css'\n      );\n    });\n\n    it('should unescape slashes', function () {\n      return expect(\n        NodeId.fromFilePath(join('test/no%2Ffolder')).value,\n        'to equal',\n        'test.no/folder'\n      );\n    });\n  });\n\n  /** @test {NodeId#filePath} */\n  describe('#filePath', function () {\n    it('should return a valid file path', function () {\n      const nodeId = new NodeId(NodeId.NodeIdType.STRING, id, 1);\n\n      expect(nodeId.filePath, 'to be a', 'string');\n      expect(join(nodeId.filePath), 'to equal', path);\n    });\n\n    it('should handle resource paths', function () {\n      const nodeId = new NodeId(NodeId.NodeIdType.STRING, 'SYSTEM.LIBRARY.RESOURCES/dir/test.e', 1);\n\n      expect(nodeId.filePath, 'to be a', 'string');\n      expect(nodeId.filePath, 'to equal', 'SYSTEM/LIBRARY/RESOURCES/dir/test.e');\n    });\n\n    it('should escape slashes', function () {\n      return expect(\n        new NodeId('AGENT.OBJECTS.Test/node').filePath,\n        'to equal',\n        'AGENT/OBJECTS/Test%2Fnode'\n      );\n    });\n  });\n\n  /** @test {_lastSeparator} */\n  describe('#_lastSeparator', function () {\n    it('should return null for non-string node ids', function () {\n      expect(new NodeId(NodeId.NodeIdType.NUMERIC, 123, 1)._lastSeparator, 'to be', null);\n    });\n\n    it('should return `/` for resource paths', function () {\n      expect(new NodeId(NodeId.NodeIdType.STRING, 'Test/Resource', 1)._lastSeparator, 'to be', '/');\n    });\n\n    it('should return `.` for regular node ids', function () {\n      expect(new NodeId(NodeId.NodeIdType.STRING, 'Test.Node', 1)._lastSeparator, 'to be', '.');\n    });\n  });\n\n  /** @test {NodeId#parent} */\n  describe('#parent', function () {\n    it('should return null for non-string node ids', function () {\n      const child = new NodeId(NodeId.NodeIdType.NUMERIC, 123, 1);\n      const parent = child.parent;\n\n      expect(parent, 'to be', null);\n    });\n\n    it('should inherit identifier type', function () {\n      const child = new NodeId(NodeId.NodeIdType.STRING, 'AGENT.DISPLAYS.Main', 13);\n      const parent = child.parent;\n\n      expect(parent.identifierType, 'to equal', NodeId.NodeIdType.STRING);\n    });\n\n    it('should inherit namespace', function () {\n      const child = new NodeId(NodeId.NodeIdType.STRING, 'AGENT.DISPLAYS.Main', 13);\n      const parent = child.parent;\n\n      expect(parent.namespace, 'to equal', 13);\n    });\n\n    it('should return parent nodes for dot separated node ids', function () {\n      const child = new NodeId(NodeId.NodeIdType.STRING, 'AGENT.DISPLAYS.Main', 13);\n      const parent = child.parent;\n\n      expect(parent.value, 'to equal', 'AGENT.DISPLAYS');\n    });\n\n    it('should return parent nodes for slash separated node ids', function () {\n      const child = new NodeId(NodeId.NodeIdType.STRING, 'SYSTEM.LIBRARY.RESOURCES/dir/test.e', 13);\n      const parent = child.parent;\n\n      expect(parent.value, 'to equal', 'SYSTEM.LIBRARY.RESOURCES/dir');\n    });\n  });\n\n  /** @test {NodeId#isChildOf} */\n  describe('#isChildOf', function () {\n    it('should return false for non-string ids', function () {\n      const invalid = new NodeId(NodeId.NodeIdType.NUMERIC, 123, 13);\n      const valid = new NodeId(NodeId.NodeIdType.STRING, 'Node.Path', 13);\n\n      expect(invalid.isChildOf(valid), 'to be false');\n      expect(valid.isChildOf(invalid), 'to be false');\n    });\n\n    it('should return false for different namespaces', function () {\n      const first = new NodeId(NodeId.NodeIdType.STRING, 'Path.To.Node', 1);\n      const second = new NodeId(NodeId.NodeIdType.STRING, 'Path.To', 2);\n\n      expect(first.isChildOf(second), 'to be false');\n    });\n\n    it('should return false for same nodes values', function () {\n      const first = new NodeId(NodeId.NodeIdType.STRING, 'Path.To.Node', 1);\n      const second = new NodeId(NodeId.NodeIdType.STRING, 'Path.To.Node', 1);\n\n      expect(first.isChildOf(second), 'to be false');\n    });\n\n    it('should return false for similar node values', function () {\n      const base = new NodeId(NodeId.NodeIdType.STRING, 'Path.To.Node', 1);\n      const postfixed = new NodeId(NodeId.NodeIdType.STRING, 'Path.To.Node1', 1);\n      const prefixed = new NodeId(NodeId.NodeIdType.STRING, 'Another.Path.To.Node', 1);\n\n      expect(base.isChildOf(postfixed), 'to be false');\n      expect(postfixed.isChildOf(base), 'to be false');\n\n      expect(base.isChildOf(prefixed), 'to be false');\n      expect(prefixed.isChildOf(base), 'to be false');\n    });\n\n    it('should return true for real parents', function () {\n      const first = new NodeId(NodeId.NodeIdType.STRING, 'Path.To.Node', 1);\n      const second = new NodeId(NodeId.NodeIdType.STRING, 'Path.To', 1);\n\n      expect(first.isChildOf(second), 'to be true');\n    });\n\n    it('should return true for parent resource nodes', function () {\n      const first = new NodeId(NodeId.NodeIdType.STRING, 'Path/to/Node', 1);\n      const second = new NodeId(NodeId.NodeIdType.STRING, 'Path/to', 1);\n\n      expect(first.isChildOf(second), 'to be true');\n    });\n\n    it('should return true for resource child nodes', function () {\n      const first = new NodeId(NodeId.NodeIdType.STRING, 'Path/to/Node.html.Translate', 1);\n      const second = new NodeId(NodeId.NodeIdType.STRING, 'Path/to/Node.html', 1);\n\n      expect(first.isChildOf(second), 'to be true');\n    });\n  });\n\n  /** @test {NodeId#browseName} */\n  describe('#browseName', function () {\n    it('should return null for non-string node ids', function () {\n      const node = new NodeId(NodeId.NodeIdType.NUMERIC, 123, 1);\n\n      expect(node.browseName, 'to be', null);\n    });\n\n    it('should return the last node path component', function () {\n      const node = new NodeId(NodeId.NodeIdType.STRING, 'Path.to.node', 1);\n      expect(node.browseName, 'to be', 'node');\n    });\n\n    it('should return the last resource path component', function () {\n      const node = new NodeId(NodeId.NodeIdType.STRING, 'Path/to/Node', 1);\n      expect(node.browseName, 'to be', 'Node');\n    });\n  });\n\n  /** @test {NodeId#inspect} */\n  describe('#inspect', function () {\n    const opts = {\n      stylize: spy((t) => t),\n    };\n\n    beforeEach(() => opts.stylize.resetHistory());\n\n    it('should return \"namespace value\"', function () {\n      const nodeId = new NodeId(NodeId.NodeIdType.STRING, 'AGENT.DISPLAYS', 1);\n\n      expect(nodeId.inspect(0, opts), 'to match', /1 AGENT\\.DISPLAYS/);\n    });\n\n    it('should style string id as string', function () {\n      new NodeId(NodeId.NodeIdType.STRING, 'AGENT.DISPLAYS', 1).inspect(0, opts);\n\n      expect(opts.stylize.calledTwice, 'to be true');\n      expect(opts.stylize.lastCall.args, 'to equal', ['AGENT.DISPLAYS', 'string']);\n    });\n\n    it('should style numeric id as number', function () {\n      new NodeId(NodeId.NodeIdType.NUMERIC, 123, 1).inspect(0, opts);\n\n      expect(opts.stylize.calledTwice, 'to be true');\n      expect(opts.stylize.lastCall.args, 'to equal', [123, 'number']);\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/model/opcua/NodeId.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 851,
    "kind": "test",
    "name": "describe149",
    "testId": 149,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149",
    "access": null,
    "description": "NodeId",
    "lineNumber": 8,
    "testTargets": [
      "NodeId"
    ]
  },
  {
    "__docId__": 852,
    "kind": "test",
    "name": "describe150",
    "testId": 150,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150",
    "access": null,
    "description": "#constructor",
    "lineNumber": 13,
    "testTargets": [
      "NodeId#constructor"
    ]
  },
  {
    "__docId__": 853,
    "kind": "test",
    "name": "context151",
    "testId": 151,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context151",
    "access": null,
    "description": "when called with value only",
    "lineNumber": 18
  },
  {
    "__docId__": 854,
    "kind": "test",
    "name": "it152",
    "testId": 152,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context151",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context151.it152",
    "access": null,
    "description": "should work",
    "lineNumber": 19
  },
  {
    "__docId__": 855,
    "kind": "test",
    "name": "it153",
    "testId": 153,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context151",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context151.it153",
    "access": null,
    "description": "should set namespace to 1",
    "lineNumber": 23
  },
  {
    "__docId__": 856,
    "kind": "test",
    "name": "it154",
    "testId": 154,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context151",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context151.it154",
    "access": null,
    "description": "should set indentifierType to string if string is passed",
    "lineNumber": 27
  },
  {
    "__docId__": 857,
    "kind": "test",
    "name": "it155",
    "testId": 155,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context151",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context151.it155",
    "access": null,
    "description": "should set indentifierType to number if number is passed",
    "lineNumber": 31
  },
  {
    "__docId__": 858,
    "kind": "test",
    "name": "context156",
    "testId": 156,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context156",
    "access": null,
    "description": "when called with a nodeid string",
    "lineNumber": 36
  },
  {
    "__docId__": 859,
    "kind": "test",
    "name": "it157",
    "testId": 157,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context156",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context156.it157",
    "access": null,
    "description": "should work",
    "lineNumber": 37
  },
  {
    "__docId__": 860,
    "kind": "test",
    "name": "it158",
    "testId": 158,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context156",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context156.it158",
    "access": null,
    "description": "should get namespace from string",
    "lineNumber": 41
  },
  {
    "__docId__": 861,
    "kind": "test",
    "name": "it159",
    "testId": 159,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context156",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context156.it159",
    "access": null,
    "description": "should get identifierType from string",
    "lineNumber": 45
  },
  {
    "__docId__": 862,
    "kind": "test",
    "name": "context160",
    "testId": 160,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context160",
    "access": null,
    "description": "when called with type, value, namespace",
    "lineNumber": 53
  },
  {
    "__docId__": 863,
    "kind": "test",
    "name": "it161",
    "testId": 161,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context160",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context160.it161",
    "access": null,
    "description": "should work",
    "lineNumber": 54
  },
  {
    "__docId__": 864,
    "kind": "test",
    "name": "it162",
    "testId": 162,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context160",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.context160.it162",
    "access": null,
    "description": "should set namespace to 1 if omitted",
    "lineNumber": 58
  },
  {
    "__docId__": 865,
    "kind": "test",
    "name": "it163",
    "testId": 163,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe150.it163",
    "access": null,
    "description": "should extend node-opcua's NodeId",
    "lineNumber": 64
  },
  {
    "__docId__": 866,
    "kind": "test",
    "name": "describe164",
    "testId": 164,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe164",
    "access": null,
    "description": "#fromFilePath",
    "lineNumber": 70,
    "testTargets": [
      "NodeId#fromFilePath"
    ]
  },
  {
    "__docId__": 867,
    "kind": "test",
    "name": "it165",
    "testId": 165,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe164",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe164.it165",
    "access": null,
    "description": "should return a NodeId",
    "lineNumber": 71
  },
  {
    "__docId__": 868,
    "kind": "test",
    "name": "it166",
    "testId": 166,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe164",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe164.it166",
    "access": null,
    "description": "should return file path again",
    "lineNumber": 75
  },
  {
    "__docId__": 869,
    "kind": "test",
    "name": "it167",
    "testId": 167,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe164",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe164.it167",
    "access": null,
    "description": "should work with resource paths",
    "lineNumber": 81
  },
  {
    "__docId__": 870,
    "kind": "test",
    "name": "it168",
    "testId": 168,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe164",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe164.it168",
    "access": null,
    "description": "should work with multi extension resource paths",
    "lineNumber": 91
  },
  {
    "__docId__": 871,
    "kind": "test",
    "name": "it169",
    "testId": 169,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe164",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe164.it169",
    "access": null,
    "description": "should unescape slashes",
    "lineNumber": 100
  },
  {
    "__docId__": 872,
    "kind": "test",
    "name": "describe170",
    "testId": 170,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe170",
    "access": null,
    "description": "#filePath",
    "lineNumber": 110,
    "testTargets": [
      "NodeId#filePath"
    ]
  },
  {
    "__docId__": 873,
    "kind": "test",
    "name": "it171",
    "testId": 171,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe170",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe170.it171",
    "access": null,
    "description": "should return a valid file path",
    "lineNumber": 111
  },
  {
    "__docId__": 874,
    "kind": "test",
    "name": "it172",
    "testId": 172,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe170",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe170.it172",
    "access": null,
    "description": "should handle resource paths",
    "lineNumber": 118
  },
  {
    "__docId__": 875,
    "kind": "test",
    "name": "it173",
    "testId": 173,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe170",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe170.it173",
    "access": null,
    "description": "should escape slashes",
    "lineNumber": 125
  },
  {
    "__docId__": 876,
    "kind": "test",
    "name": "describe174",
    "testId": 174,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe174",
    "access": null,
    "description": "#_lastSeparator",
    "lineNumber": 135,
    "testTargets": [
      "_lastSeparator"
    ]
  },
  {
    "__docId__": 877,
    "kind": "test",
    "name": "it175",
    "testId": 175,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe174",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe174.it175",
    "access": null,
    "description": "should return null for non-string node ids",
    "lineNumber": 136
  },
  {
    "__docId__": 878,
    "kind": "test",
    "name": "it176",
    "testId": 176,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe174",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe174.it176",
    "access": null,
    "description": "should return `/` for resource paths",
    "lineNumber": 140
  },
  {
    "__docId__": 879,
    "kind": "test",
    "name": "it177",
    "testId": 177,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe174",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe174.it177",
    "access": null,
    "description": "should return `.` for regular node ids",
    "lineNumber": 144
  },
  {
    "__docId__": 880,
    "kind": "test",
    "name": "describe178",
    "testId": 178,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe178",
    "access": null,
    "description": "#parent",
    "lineNumber": 150,
    "testTargets": [
      "NodeId#parent"
    ]
  },
  {
    "__docId__": 881,
    "kind": "test",
    "name": "it179",
    "testId": 179,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe178",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe178.it179",
    "access": null,
    "description": "should return null for non-string node ids",
    "lineNumber": 151
  },
  {
    "__docId__": 882,
    "kind": "test",
    "name": "it180",
    "testId": 180,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe178",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe178.it180",
    "access": null,
    "description": "should inherit identifier type",
    "lineNumber": 158
  },
  {
    "__docId__": 883,
    "kind": "test",
    "name": "it181",
    "testId": 181,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe178",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe178.it181",
    "access": null,
    "description": "should inherit namespace",
    "lineNumber": 165
  },
  {
    "__docId__": 884,
    "kind": "test",
    "name": "it182",
    "testId": 182,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe178",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe178.it182",
    "access": null,
    "description": "should return parent nodes for dot separated node ids",
    "lineNumber": 172
  },
  {
    "__docId__": 885,
    "kind": "test",
    "name": "it183",
    "testId": 183,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe178",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe178.it183",
    "access": null,
    "description": "should return parent nodes for slash separated node ids",
    "lineNumber": 179
  },
  {
    "__docId__": 886,
    "kind": "test",
    "name": "describe184",
    "testId": 184,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe184",
    "access": null,
    "description": "#isChildOf",
    "lineNumber": 188,
    "testTargets": [
      "NodeId#isChildOf"
    ]
  },
  {
    "__docId__": 887,
    "kind": "test",
    "name": "it185",
    "testId": 185,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe184",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe184.it185",
    "access": null,
    "description": "should return false for non-string ids",
    "lineNumber": 189
  },
  {
    "__docId__": 888,
    "kind": "test",
    "name": "it186",
    "testId": 186,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe184",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe184.it186",
    "access": null,
    "description": "should return false for different namespaces",
    "lineNumber": 197
  },
  {
    "__docId__": 889,
    "kind": "test",
    "name": "it187",
    "testId": 187,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe184",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe184.it187",
    "access": null,
    "description": "should return false for same nodes values",
    "lineNumber": 204
  },
  {
    "__docId__": 890,
    "kind": "test",
    "name": "it188",
    "testId": 188,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe184",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe184.it188",
    "access": null,
    "description": "should return false for similar node values",
    "lineNumber": 211
  },
  {
    "__docId__": 891,
    "kind": "test",
    "name": "it189",
    "testId": 189,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe184",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe184.it189",
    "access": null,
    "description": "should return true for real parents",
    "lineNumber": 223
  },
  {
    "__docId__": 892,
    "kind": "test",
    "name": "it190",
    "testId": 190,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe184",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe184.it190",
    "access": null,
    "description": "should return true for parent resource nodes",
    "lineNumber": 230
  },
  {
    "__docId__": 893,
    "kind": "test",
    "name": "it191",
    "testId": 191,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe184",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe184.it191",
    "access": null,
    "description": "should return true for resource child nodes",
    "lineNumber": 237
  },
  {
    "__docId__": 894,
    "kind": "test",
    "name": "describe192",
    "testId": 192,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe192",
    "access": null,
    "description": "#browseName",
    "lineNumber": 246,
    "testTargets": [
      "NodeId#browseName"
    ]
  },
  {
    "__docId__": 895,
    "kind": "test",
    "name": "it193",
    "testId": 193,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe192",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe192.it193",
    "access": null,
    "description": "should return null for non-string node ids",
    "lineNumber": 247
  },
  {
    "__docId__": 896,
    "kind": "test",
    "name": "it194",
    "testId": 194,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe192",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe192.it194",
    "access": null,
    "description": "should return the last node path component",
    "lineNumber": 253
  },
  {
    "__docId__": 897,
    "kind": "test",
    "name": "it195",
    "testId": 195,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe192",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe192.it195",
    "access": null,
    "description": "should return the last resource path component",
    "lineNumber": 258
  },
  {
    "__docId__": 898,
    "kind": "test",
    "name": "describe196",
    "testId": 196,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe196",
    "access": null,
    "description": "#inspect",
    "lineNumber": 265,
    "testTargets": [
      "NodeId#inspect"
    ]
  },
  {
    "__docId__": 899,
    "kind": "test",
    "name": "it197",
    "testId": 197,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe196",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe196.it197",
    "access": null,
    "description": "should return \"namespace value\"",
    "lineNumber": 272
  },
  {
    "__docId__": 900,
    "kind": "test",
    "name": "it198",
    "testId": 198,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe196",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe196.it198",
    "access": null,
    "description": "should style string id as string",
    "lineNumber": 278
  },
  {
    "__docId__": 901,
    "kind": "test",
    "name": "it199",
    "testId": 199,
    "memberof": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe196",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/model/opcua/NodeId.spec.js~describe149.describe196.it199",
    "access": null,
    "description": "should style numeric id as number",
    "lineNumber": 285
  },
  {
    "__docId__": 902,
    "kind": "testFile",
    "name": "test/src/lib/model/opcua/ReverseReferenceTypeIds.spec.js",
    "content": "import { ReferenceTypeIds } from 'node-opcua';\nimport expect from '../../../../expect';\nimport ReverseReferenceTypeIds from '../../../../../src/lib/model/opcua/ReverseReferenceTypeIds';\n\n/* @test {ReverseReferenceTypeIds} */\ndescribe('ReverseReferenceTypeIds', function () {\n  it('should export values for all node-opcua~ReferenceTypeIds', function () {\n    Object.entries(ReferenceTypeIds).forEach(([key, value]) => {\n      expect(ReverseReferenceTypeIds[value], 'to be defined');\n      expect(ReverseReferenceTypeIds[value], 'to equal', key);\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/model/opcua/ReverseReferenceTypeIds.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 903,
    "kind": "test",
    "name": "describe200",
    "testId": 200,
    "memberof": "test/src/lib/model/opcua/ReverseReferenceTypeIds.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/model/opcua/ReverseReferenceTypeIds.spec.js~describe200",
    "access": null,
    "description": "ReverseReferenceTypeIds",
    "lineNumber": 6
  },
  {
    "__docId__": 904,
    "kind": "test",
    "name": "it201",
    "testId": 201,
    "memberof": "test/src/lib/model/opcua/ReverseReferenceTypeIds.spec.js~describe200",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/model/opcua/ReverseReferenceTypeIds.spec.js~describe200.it201",
    "access": null,
    "description": "should export values for all node-opcua~ReferenceTypeIds",
    "lineNumber": 7
  },
  {
    "__docId__": 905,
    "kind": "testFile",
    "name": "test/src/lib/regexp.spec.js",
    "content": "import expect from 'unexpected';\nimport { escapeForRegExp } from '../../../src/lib/regexp';\n\ndescribe('regex helpers', function () {\n  describe('excapeForRegExp', function () {\n    it('should escape special characters', function () {\n      const regExp = new RegExp(`^${escapeForRegExp('test.json')}$`);\n      expect('test.json', 'to match', regExp);\n      expect('testxjson', 'not to match', regExp);\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/regexp.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 906,
    "kind": "test",
    "name": "describe202",
    "testId": 202,
    "memberof": "test/src/lib/regexp.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/regexp.spec.js~describe202",
    "access": null,
    "description": "regex helpers",
    "lineNumber": 4
  },
  {
    "__docId__": 907,
    "kind": "test",
    "name": "describe203",
    "testId": 203,
    "memberof": "test/src/lib/regexp.spec.js~describe202",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/regexp.spec.js~describe202.describe203",
    "access": null,
    "description": "excapeForRegExp",
    "lineNumber": 5
  },
  {
    "__docId__": 908,
    "kind": "test",
    "name": "it204",
    "testId": 204,
    "memberof": "test/src/lib/regexp.spec.js~describe202.describe203",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/regexp.spec.js~describe202.describe203.it204",
    "access": null,
    "description": "should escape special characters",
    "lineNumber": 6
  },
  {
    "__docId__": 909,
    "kind": "testFile",
    "name": "test/src/lib/server/AddReferencesStream.spec.js",
    "content": "import { StatusCodes } from 'node-opcua';\nimport expect from '../../../expect';\nimport NodeId from '../../../../src/lib/model/opcua/NodeId';\nimport AddReferencesStream from '../../../../src/lib/server/AddReferencesStream';\nimport { ReferenceTypeIds } from '../../../../src/lib/model/Node';\n\n/** @test {AddReferencesStream} */\ndescribe('AddReferencesStream', function () {\n  /** @test {AddReferencesStream#scriptId} */\n  describe('#scriptId', function () {\n    it(\"should return the AddReferences script's id\", function () {\n      expect(\n        AddReferencesStream.prototype.scriptId.value,\n        'to equal',\n        'SYSTEM.LIBRARY.ATVISE.SERVERSCRIPTS.atscm.AddReferences'\n      );\n    });\n  });\n\n  /** @test {AddReferencesStream#scriptParameters} */\n  describe('#scriptParameters', function () {\n    it('should return null without references', function () {\n      expect(\n        AddReferencesStream.prototype.scriptParameters({ references: new Map() }),\n        'to be',\n        null\n      );\n    });\n\n    it('should return null witout additional references', function () {\n      expect(\n        AddReferencesStream.prototype.scriptParameters({\n          references: new Map([\n            [ReferenceTypeIds.toParent, new Set([1])],\n            [ReferenceTypeIds.HasTypeDefinition, new Set([2])],\n            [ReferenceTypeIds.HasModellingRule, new Set([3])],\n          ]),\n        }),\n        'to be',\n        null\n      );\n    });\n\n    it('should return JSON string for additional references', function () {\n      expect(\n        AddReferencesStream.prototype.scriptParameters({\n          references: new Map([\n            [ReferenceTypeIds.toParent, new Set([1])],\n            [ReferenceTypeIds.HasTypeDefinition, new Set([2])],\n            [ReferenceTypeIds.HasModellingRule, new Set([3])],\n            [\n              ReferenceTypeIds.HasComponent,\n              new Set(['SYSTEM.LIBRARY.ATVISE.ALARMCATEGORIES.Error']),\n            ],\n          ]),\n        }),\n        'to satisfy',\n        {\n          paramObjString: {\n            // eslint-disable-next-line max-len\n            value:\n              '{\"references\":[{\"referenceIdValue\":47,\"items\":[\"ns=1;s=SYSTEM.LIBRARY.ATVISE.ALARMCATEGORIES.Error\"]}]}',\n          },\n        }\n      );\n    });\n  });\n\n  /** @test {AddReferencesStream#processErrorMessage} */\n  describe('#processErrorMessage', function () {\n    it('should decorate the error message', function () {\n      expect(\n        AddReferencesStream.prototype.processErrorMessage({\n          nodeId: new NodeId('ns=1;s=AGENT.OBJECTS.Test'),\n        }),\n        'to contain',\n        'AGENT.OBJECTS.Test',\n        'adding references'\n      );\n    });\n  });\n\n  /** @test {AddReferencesStream#handleOutputArguments} */\n  describe('#handleOutputArguments', function () {\n    it('should error with bad status codes', function () {\n      return expect(\n        AddReferencesStream.prototype.handleOutputArguments.bind(null, {}, [\n          { value: StatusCodes.Bad },\n          { value: 'Something bad happened' },\n        ]),\n        'to call the callback with error',\n        'Something bad happened'\n      );\n    });\n\n    it('should retry when script had failures', async function () {\n      const stream = new AddReferencesStream();\n      const file = { nodeId: new NodeId('AGENT.OBJECTS.Failing') };\n      const handleOutput = AddReferencesStream.prototype.handleOutputArguments.bind(stream, file, [\n        { value: StatusCodes.Good },\n        {},\n        {},\n        {\n          value: [{ value: [new NodeId('A.Referenced.Node')] }],\n        },\n      ]);\n\n      // The first time adding references fails is ignored\n      await expect(handleOutput, 'to call the callback without error');\n\n      // and pushed to the retry stack\n      expect(Array.from(stream._retry.values()), 'to equal', ['AGENT.OBJECTS.Failing']);\n\n      // The second time it should fail.\n      await expect(\n        handleOutput,\n        'to call the callback with error',\n        /Failed to create reference.+A.Referenced.Node/i\n      );\n    });\n\n    it('should continue without failures', function () {\n      return expect(\n        AddReferencesStream.prototype.handleOutputArguments.bind(null, {}, [\n          { value: StatusCodes.Good },\n          {},\n          {},\n          {\n            value: [{ value: [] }],\n          },\n        ]),\n        'to call the callback without error'\n      );\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/server/AddReferencesStream.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 910,
    "kind": "test",
    "name": "describe205",
    "testId": 205,
    "memberof": "test/src/lib/server/AddReferencesStream.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/AddReferencesStream.spec.js~describe205",
    "access": null,
    "description": "AddReferencesStream",
    "lineNumber": 8,
    "testTargets": [
      "AddReferencesStream"
    ]
  },
  {
    "__docId__": 911,
    "kind": "test",
    "name": "describe206",
    "testId": 206,
    "memberof": "test/src/lib/server/AddReferencesStream.spec.js~describe205",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe206",
    "access": null,
    "description": "#scriptId",
    "lineNumber": 10,
    "testTargets": [
      "AddReferencesStream#scriptId"
    ]
  },
  {
    "__docId__": 912,
    "kind": "test",
    "name": "it207",
    "testId": 207,
    "memberof": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe206",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe206.it207",
    "access": null,
    "description": "should return the AddReferences script's id",
    "lineNumber": 11
  },
  {
    "__docId__": 913,
    "kind": "test",
    "name": "describe208",
    "testId": 208,
    "memberof": "test/src/lib/server/AddReferencesStream.spec.js~describe205",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe208",
    "access": null,
    "description": "#scriptParameters",
    "lineNumber": 21,
    "testTargets": [
      "AddReferencesStream#scriptParameters"
    ]
  },
  {
    "__docId__": 914,
    "kind": "test",
    "name": "it209",
    "testId": 209,
    "memberof": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe208",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe208.it209",
    "access": null,
    "description": "should return null without references",
    "lineNumber": 22
  },
  {
    "__docId__": 915,
    "kind": "test",
    "name": "it210",
    "testId": 210,
    "memberof": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe208",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe208.it210",
    "access": null,
    "description": "should return null witout additional references",
    "lineNumber": 30
  },
  {
    "__docId__": 916,
    "kind": "test",
    "name": "it211",
    "testId": 211,
    "memberof": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe208",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe208.it211",
    "access": null,
    "description": "should return JSON string for additional references",
    "lineNumber": 44
  },
  {
    "__docId__": 917,
    "kind": "test",
    "name": "describe212",
    "testId": 212,
    "memberof": "test/src/lib/server/AddReferencesStream.spec.js~describe205",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe212",
    "access": null,
    "description": "#processErrorMessage",
    "lineNumber": 70,
    "testTargets": [
      "AddReferencesStream#processErrorMessage"
    ]
  },
  {
    "__docId__": 918,
    "kind": "test",
    "name": "it213",
    "testId": 213,
    "memberof": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe212",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe212.it213",
    "access": null,
    "description": "should decorate the error message",
    "lineNumber": 71
  },
  {
    "__docId__": 919,
    "kind": "test",
    "name": "describe214",
    "testId": 214,
    "memberof": "test/src/lib/server/AddReferencesStream.spec.js~describe205",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe214",
    "access": null,
    "description": "#handleOutputArguments",
    "lineNumber": 84,
    "testTargets": [
      "AddReferencesStream#handleOutputArguments"
    ]
  },
  {
    "__docId__": 920,
    "kind": "test",
    "name": "it215",
    "testId": 215,
    "memberof": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe214",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe214.it215",
    "access": null,
    "description": "should error with bad status codes",
    "lineNumber": 85
  },
  {
    "__docId__": 921,
    "kind": "test",
    "name": "it216",
    "testId": 216,
    "memberof": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe214",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe214.it216",
    "access": null,
    "description": "should retry when script had failures",
    "lineNumber": 96
  },
  {
    "__docId__": 922,
    "kind": "test",
    "name": "it217",
    "testId": 217,
    "memberof": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe214",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AddReferencesStream.spec.js~describe205.describe214.it217",
    "access": null,
    "description": "should continue without failures",
    "lineNumber": 122
  },
  {
    "__docId__": 923,
    "kind": "testFile",
    "name": "test/src/lib/server/AtviseFile.spec.js",
    "content": "import { Buffer } from 'buffer';\nimport { stub, spy } from 'sinon';\nimport File from 'vinyl';\nimport { DataType, VariantArrayType, NodeClass } from 'node-opcua';\nimport expect from '../../../expect';\nimport AtviseFile from '../../../../src/lib/server/AtviseFile';\nimport AtviseTypes from '../../../../src/lib/server/Types';\nimport NodeId from '../../../../src/lib/model/opcua/NodeId';\n\n/** @test {AtviseFile} */\ndescribe('AtviseFile', function () {\n  /** @test {AtviseFile#constructor} */\n  describe('#constructor', function () {\n    it('should create a vinyl instance', function () {\n      const file = new AtviseFile();\n\n      expect(file, 'to be a', File);\n    });\n  });\n\n  const tests = [\n    {\n      name: 'should store variables with their data type as an extension',\n      nodeId: new NodeId('ns=1;s=AGENT.OBJECTS.Test'),\n      dataType: DataType.UInt16,\n      typeDefinition: new NodeId(NodeId.NodeIdType.NUMERIC, 62, 0),\n      arrayType: VariantArrayType.Scalar,\n      filePath: 'AGENT/OBJECTS/Test.uint16',\n    },\n    {\n      name: 'should store variable arrays with their data type as an extension',\n      nodeId: new NodeId('ns=1;s=AGENT.OBJECTS.Test'),\n      dataType: DataType.UInt16,\n      typeDefinition: new NodeId(NodeId.NodeIdType.NUMERIC, 62, 0),\n      arrayType: VariantArrayType.Array,\n      filePath: 'AGENT/OBJECTS/Test.uint16.array',\n    },\n    {\n      name: 'should store variable matrices with their data type as an extension',\n      nodeId: new NodeId('ns=1;s=AGENT.OBJECTS.Test'),\n      dataType: DataType.UInt16,\n      typeDefinition: new NodeId(NodeId.NodeIdType.NUMERIC, 62, 0),\n      arrayType: VariantArrayType.Matrix,\n      filePath: 'AGENT/OBJECTS/Test.uint16.matrix',\n    },\n    {\n      name: 'should store property variables with their data type as an extension',\n      nodeId: new NodeId('ns=1;s=AGENT.OBJECTS.Test.property'),\n      dataType: DataType.UInt16,\n      typeDefinition: new NodeId(NodeId.NodeIdType.NUMERIC, 68, 0),\n      arrayType: VariantArrayType.Scalar,\n      filePath: 'AGENT/OBJECTS/Test/property.prop.uint16',\n    },\n    {\n      name: 'should store html help documents with a \".help.html\" extension',\n      nodeId: new NodeId('ns=1;s=AGENT.DISPLAYS.Test.en'),\n      dataType: DataType.ByteString,\n      typeDefinition: new NodeId('VariableTypes.ATVISE.HtmlHelp'),\n      arrayType: VariantArrayType.Scalar,\n      filePath: 'AGENT/DISPLAYS/Test/en.help.html',\n    },\n    {\n      name: 'should store quickdynamics with a \".qd.xml\" extension',\n      nodeId: new NodeId('ns=1;s=SYSTEM.LIBRARY.PROJECT.QUICKDYNAMICS.Test'),\n      dataType: DataType.XmlElement,\n      typeDefinition: new NodeId('VariableTypes.ATVISE.QuickDynamic'),\n      arrayType: VariantArrayType.Scalar,\n      filePath: 'SYSTEM/LIBRARY/PROJECT/QUICKDYNAMICS/Test.qd.xml',\n    },\n    {\n      name: 'should store scripts with a \".script.xml\" extension',\n      nodeId: new NodeId('ns=1;s=SYSTEM.LIBRARY.PROJECT.SERVERSCRIPTS.Test'),\n      dataType: DataType.XmlElement,\n      typeDefinition: new NodeId('VariableTypes.ATVISE.ScriptCode'),\n      arrayType: VariantArrayType.Scalar,\n      filePath: 'SYSTEM/LIBRARY/PROJECT/SERVERSCRIPTS/Test.script.xml',\n    },\n    {\n      name: 'should store displays with a \".display.xml\" extension',\n      nodeId: new NodeId('ns=1;s=AGENT.DISPLAYS.Test'),\n      dataType: DataType.XmlElement,\n      typeDefinition: new NodeId('VariableTypes.ATVISE.Display'),\n      arrayType: VariantArrayType.Scalar,\n      filePath: 'AGENT/DISPLAYS/Test.display.xml',\n    },\n    {\n      name: 'should store translation tables with a \".locs.xml\" extension',\n      nodeId: new NodeId('ns=1;s=SYSTEM.LIBRARY.PROJECT.de'),\n      dataType: DataType.XmlElement,\n      typeDefinition: new NodeId('VariableTypes.ATVISE.TranslationTable'),\n      arrayType: VariantArrayType.Scalar,\n      filePath: 'SYSTEM/LIBRARY/PROJECT/de.locs.xml',\n    },\n    {\n      name: 'should store custom resources with their original extension',\n      nodeId: new NodeId('ns=1;s=SYSTEM.LIBRARY.PROJECT.RESOURCES/Test.md'),\n      dataType: DataType.ByteString,\n      typeDefinition: new NodeId('VariableTypes.ATVISE.Resource.OctetStream'),\n      arrayType: VariantArrayType.Scalar,\n      filePath: 'SYSTEM/LIBRARY/PROJECT/RESOURCES/Test.md',\n    },\n  ].concat(\n    AtviseTypes.filter((t) => t.constructor.name === 'AtviseResourceType').map((t) => ({\n      name: `should store ${t.typeDefinition.value} resources with their original extension`,\n      nodeId: new NodeId(`ns=1;s=SYSTEM.LIBRARY.PROJECT.RESOURCES/Test.${t.identifier}`),\n      dataType: DataType.ByteString,\n      typeDefinition: new NodeId(t.typeDefinition.value),\n      arrayType: VariantArrayType.Scalar,\n      filePath: `SYSTEM/LIBRARY/PROJECT/RESOURCES/Test.${t.identifier}`,\n    }))\n  );\n\n  /** @test {AtviseFile.pathForReadResult} */\n  describe('.pathForReadResult', function () {\n    it('should store non-variables as .{nodeClass}.json', function () {\n      expect(\n        AtviseFile.pathForReadResult({\n          nodeId: new NodeId('Path.To.Node'),\n          nodeClass: NodeClass.Object,\n        }),\n        'to equal',\n        'Path/To/Node/.Object.json'\n      );\n    });\n\n    tests.forEach((test) => {\n      it(test.name, function () {\n        expect(\n          AtviseFile.pathForReadResult({\n            nodeId: test.nodeId,\n            nodeClass: NodeClass.Variable,\n            value: {\n              $dataType: test.dataType,\n              $arrayType: test.arrayType,\n            },\n            references: {\n              HasTypeDefinition: [test.typeDefinition],\n            },\n          }),\n          'to equal',\n          test.filePath\n        );\n      });\n    });\n\n    it('should store custom typed variables with a \".var\" extension', function () {\n      expect(\n        AtviseFile.pathForReadResult({\n          nodeId: new NodeId('AGENT.OBJECTS.CustomVar'),\n          nodeClass: NodeClass.Variable,\n          value: {\n            $dataType: DataType.Boolean,\n            $arrayType: VariantArrayType.Scalar,\n          },\n          references: {\n            HasTypeDefinition: [new NodeId('VariableTypes.Project.CustomType')],\n          },\n        }),\n        'to equal',\n        'AGENT/OBJECTS/CustomVar.var.bool'\n      );\n    });\n  });\n\n  /** @test {AtviseFile.encodeValue} */\n  describe('.encodeValue', function () {\n    it('should return empty buffer for null', function () {\n      expect(AtviseFile.encodeValue({ value: null }), 'to equal', Buffer.from(''));\n    });\n\n    it('should store timestamp as string for DateTime values', function () {\n      const now = new Date();\n\n      expect(\n        AtviseFile.encodeValue({ value: now }, DataType.DateTime, VariantArrayType.Scalar),\n        'to equal',\n        Buffer.from(now.toJSON())\n      );\n    });\n\n    it('should store JSON encoded bytes for UInt64 values', function () {\n      expect(\n        AtviseFile.encodeValue({ value: [1, 2] }, DataType.UInt64, VariantArrayType.Scalar),\n        'to equal',\n        Buffer.from(JSON.stringify([1, 2], null, '  '))\n      );\n    });\n\n    it('should use trimmed string value if no special encoder is used', function () {\n      const value = 'string\\n ';\n\n      expect(\n        AtviseFile.encodeValue({ value }, DataType.String, VariantArrayType.Scalar),\n        'to equal',\n        Buffer.from('string')\n      );\n    });\n\n    it('should convert typed array', function () {\n      expect(\n        AtviseFile.encodeValue(\n          { value: new Uint16Array([1, 2]) },\n          DataType.UInt16,\n          VariantArrayType.Array\n        ).toString(),\n        'to equal',\n        JSON.stringify([1, 2], null, '  ')\n      );\n    });\n\n    context('with an array passed', function () {\n      it('should JSON encode standard values', function () {\n        const value = ['test', 'another'];\n\n        return expect(\n          AtviseFile.encodeValue({ value }, DataType.String, VariantArrayType.Array),\n          'to equal',\n          Buffer.from(JSON.stringify(value, null, '  '))\n        );\n      });\n\n      it('should JSON encode special encoded values', function () {\n        const value = [[0, 1]];\n\n        return expect(\n          AtviseFile.encodeValue({ value }, DataType.Int64, VariantArrayType.Array),\n          'to equal',\n          Buffer.from(JSON.stringify([[0, 1]], null, '  '))\n        );\n      });\n\n      it('should JSON encode null values', function () {\n        const value = [null];\n\n        return expect(\n          AtviseFile.encodeValue({ value }, DataType.String, VariantArrayType.Array),\n          'to equal',\n          Buffer.from(JSON.stringify(value, null, '  '))\n        );\n      });\n    });\n  });\n\n  /** @test {AtviseFile.decodeValue} */\n  describe('.decodeValue', function () {\n    it('should forward null', function () {\n      expect(AtviseFile.decodeValue(null), 'to equal', null);\n    });\n\n    function testDecoderForDataType(dataType, rawValue, expectedValue) {\n      it(`decoder for ${dataType} should work`, function () {\n        expect(\n          AtviseFile.decodeValue(Buffer.from(rawValue), dataType, VariantArrayType.Scalar),\n          'to satisfy',\n          expectedValue\n        );\n      });\n    }\n\n    const now = new Date();\n    now.setMilliseconds(0);\n\n    [\n      [DataType.Boolean, 'false', false],\n      [DataType.Boolean, 'true', true],\n      [DataType.String, 'test', 'test'],\n      [DataType.NodeId, 'ns=1;s=AGENT.DISPLAYS.Main', new NodeId('AGENT.DISPLAYS.Main')],\n      [DataType.DateTime, now.toString(), now],\n      ...[\n        // Long int types\n        DataType.Int64,\n        DataType.UInt64,\n      ].map((type) => [type, JSON.stringify([1, 2], null, '  '), [1, 2]]),\n      ...[\n        // Int types\n        DataType.SByte,\n        DataType.Byte,\n        DataType.Int16,\n        DataType.UInt16,\n        DataType.Int32,\n        DataType.UInt32,\n      ].map((type) => [type, '13', 13]),\n      ...[\n        // float types\n        DataType.Float,\n        DataType.Double,\n      ].map((type) => [type, '13.5', 13.5]),\n    ].forEach((t) => testDecoderForDataType(...t));\n\n    it('should forward binary buffer for ByteString', function () {\n      const buffer = Buffer.from('test');\n      expect(\n        AtviseFile.decodeValue(buffer, DataType.ByteString, VariantArrayType.Scalar),\n        'to equal',\n        buffer\n      );\n    });\n\n    it(\"should throw if an array variable's value is scalar\", function () {\n      const value = 24;\n      return expect(\n        () => AtviseFile.decodeValue(value, DataType.Int16, VariantArrayType.Array),\n        'to throw',\n        /not an array/i\n      );\n    });\n\n    context('with an array passed', function () {\n      it('should JSON decode standard values', function () {\n        const value = ['<xml />', '<xml />'];\n        const buffer = Buffer.from(JSON.stringify(value));\n        expect(\n          AtviseFile.decodeValue(buffer, DataType.XmlElement, VariantArrayType.Array),\n          'to equal',\n          value\n        );\n      });\n\n      it('should JSON decode special encoded values', function () {\n        const value = [[0, 1]];\n        const buffer = Buffer.from(JSON.stringify(value));\n        expect(\n          AtviseFile.decodeValue(buffer, DataType.UInt64, VariantArrayType.Array),\n          'to equal',\n          [[0, 1]]\n        );\n      });\n\n      it('should JSON decode null values', function () {\n        const value = [null];\n        const buffer = Buffer.from(JSON.stringify(value));\n        expect(\n          AtviseFile.decodeValue(buffer, DataType.String, VariantArrayType.Array),\n          'to equal',\n          value\n        );\n      });\n    });\n  });\n\n  /** @test {AtviseFile.normalizeMtime} */\n  describe('.normalizeMtime', function () {\n    it('should return original without milliseconds', function () {\n      const org = new Date();\n      org.setMilliseconds(0);\n\n      expect(AtviseFile.normalizeMtime(org), 'to equal', org);\n    });\n\n    it('should remove milliseconds if provided', function () {\n      const org = new Date();\n      org.setMilliseconds(500);\n\n      expect(AtviseFile.normalizeMtime(org).getMilliseconds(), 'to equal', 0);\n    });\n  });\n\n  /** @test {AtviseFile.fromReadResult} */\n  describe('.fromReadResult', function () {\n    it('should fail for variable without value', function () {\n      expect(\n        () =>\n          AtviseFile.fromReadResult({\n            nodeClass: NodeClass.Variable,\n          }),\n        'to throw',\n        'no value'\n      );\n    });\n\n    it('should return a new instance with valid readResult', function () {\n      const nodeId = new NodeId('AGENT.DISPLAYS.Main');\n\n      expect(\n        AtviseFile.fromReadResult({\n          nodeId,\n          nodeClass: NodeClass.Variable,\n          value: {\n            value: '<svg></svg>',\n            $dataType: DataType.XmlElement,\n            $arrayType: VariantArrayType.Scalar,\n          },\n          references: {\n            HasTypeDefinition: [new NodeId('VariableTypes.ATVISE.Display')],\n          },\n          mtime: new Date(),\n        }),\n        'to be a',\n        AtviseFile\n      );\n    });\n\n    it('should use undefined as mtime if not provided', function () {\n      const nodeId = new NodeId('AGENT.DISPLAYS.Main');\n\n      const file = AtviseFile.fromReadResult({\n        nodeId,\n        nodeClass: NodeClass.Variable,\n        value: {\n          value: '<svg></svg>',\n          $dataType: DataType.XmlElement,\n          $arrayType: VariantArrayType.Scalar,\n        },\n        references: {\n          HasTypeDefinition: [new NodeId('VariableTypes.ATVISE.Display')],\n        },\n      });\n\n      expect(file, 'to be a', AtviseFile);\n      expect(file.stat.mtime, 'to be', undefined);\n    });\n\n    it('should store JSON-encoded references if not a variable-node', function () {\n      const nodeId = new NodeId('AGENT');\n      const references = {\n        HasTypeDefinition: [new NodeId('ns=1;s=ObjectTypes.ATVISE.Server.Local')],\n      };\n\n      const file = AtviseFile.fromReadResult({\n        nodeId,\n        nodeClass: NodeClass.Object,\n        references,\n      });\n\n      expect(file, 'to be a', AtviseFile);\n      expect(file._dataType, 'to be', undefined);\n      expect(file._arrayType, 'to be', undefined);\n      expect(file.stat.mtime, 'to be', undefined);\n      expect(JSON.parse(file.contents.toString()), 'to equal', {\n        references: {\n          HasTypeDefinition: [references.HasTypeDefinition[0].toString()],\n        },\n      });\n    });\n\n    it('should sort references in JSON file', function () {\n      const nodeId = new NodeId('AGENT');\n      const references = {\n        HasTypeDefinition: [new NodeId('ns=1;s=ObjectTypes.ATVISE.Server.Local')],\n        toParent: 'HasComponent',\n        HasModellingRule: [new NodeId('ns=1;i=78')],\n      };\n\n      const file = AtviseFile.fromReadResult({\n        nodeId,\n        nodeClass: NodeClass.Object,\n        references,\n      });\n\n      expect(\n        file.contents.toString(),\n        'to equal',\n        `{\n  \"references\": {\n    \"HasModellingRule\": [\n      \"ns=1;i=78\"\n    ],\n    \"HasTypeDefinition\": [\n      \"ns=1;s=ObjectTypes.ATVISE.Server.Local\"\n    ],\n    \"toParent\": \"HasComponent\"\n  }\n}`\n      );\n    });\n  });\n\n  /** @test {AtviseFile#_getMetadata} */\n  describe('#_getMetadata', function () {\n    tests.forEach((test) => {\n      it(test.name, function () {\n        const file = new AtviseFile({ path: test.filePath });\n\n        expect(() => file._getMetadata(), 'not to throw');\n        if (test.dataType) {\n          expect(file._dataType, 'to equal', test.dataType);\n        }\n        expect(file._arrayType, 'to equal', test.arrayType);\n        expect(file._references, 'to be an object');\n        expect(file._references, 'to have property', 'HasTypeDefinition');\n        expect(file._references.HasTypeDefinition[0], 'to equal', test.typeDefinition);\n      });\n    });\n\n    it('should use dirname extensions if filename has no extensions', function () {\n      const file = new AtviseFile({ path: 'dir.display/file' });\n      expect(() => file._getMetadata(), 'not to throw');\n      expect(\n        file._references.HasTypeDefinition[0],\n        'to equal',\n        new NodeId('VariableTypes.ATVISE.Display')\n      );\n    });\n\n    it('should not get tripped up by multiple dots in dirname if filename has no extensions', function () {\n      const file = new AtviseFile({ path: 'dir.with.multiple.dots.display/file' });\n      expect(() => file._getMetadata(), 'not to throw');\n      expect(\n        file._references.HasTypeDefinition[0],\n        'to equal',\n        new NodeId('VariableTypes.ATVISE.Display')\n      );\n    });\n\n    it('should parse contents for non-variable nodes', function () {\n      const references = {\n        HasTypeDefinition: ['ns=1;s=Type.Definition'],\n      };\n\n      const file = new AtviseFile({\n        path: './path/to/object/.Object.json',\n        contents: Buffer.from(JSON.stringify({ references })),\n      });\n\n      expect(() => file._getMetadata(), 'not to throw');\n      expect(\n        file._references.HasTypeDefinition[0],\n        'to equal',\n        new NodeId('ns=1;s=Type.Definition')\n      );\n    });\n  });\n\n  function testMetaGetter(name) {\n    beforeEach(() => stub(AtviseFile.prototype, '_getMetadata').callsFake(() => {}));\n    afterEach(() => AtviseFile.prototype._getMetadata.restore());\n\n    it('should call _getMetadata if not present', function () {\n      const file = new AtviseFile({ path: 'path' });\n      expect(file[`_${name}`], 'to be', undefined);\n\n      const val = file[name];\n\n      expect(val, 'to be', undefined);\n      expect(AtviseFile.prototype._getMetadata.calledOnce, 'to be', true);\n    });\n\n    it('should return stored value if present', function () {\n      const value = 'value';\n      const file = new AtviseFile({\n        path: 'path',\n        [`_${name}`]: value,\n      });\n\n      expect(file[name], 'to be', value);\n      expect(AtviseFile.prototype._getMetadata, 'was not called');\n    });\n  }\n\n  /** @test {AtviseFile#dataType} */\n  describe('#nodeClass', function () {\n    testMetaGetter('nodeClass');\n  });\n\n  /** @test {AtviseFile#dataType} */\n  describe('#dataType', function () {\n    testMetaGetter('dataType');\n  });\n\n  /** @test {AtviseFile#arrayType} */\n  describe('#arrayType', function () {\n    testMetaGetter('arrayType');\n  });\n\n  /** @test {AtviseFile#typeDefinition} */\n  describe('#typeDefinition', function () {\n    it('should call _getMetadata if not present', function () {\n      const file = new AtviseFile({\n        path: 'path',\n      });\n      expect(file._references, 'to be', undefined);\n\n      spy(file, '_getMetadata');\n\n      expect(() => file.typeDefinition, 'not to throw');\n\n      expect(file._getMetadata, 'was called once');\n    });\n\n    it('should return stored value if present', function () {\n      const value = 'value';\n      const file = new AtviseFile({\n        path: 'path',\n        _references: {\n          HasTypeDefinition: [value],\n        },\n      });\n\n      spy(file, '_getMetadata');\n\n      expect(file.typeDefinition, 'to be', value);\n      expect(file._getMetadata, 'was not called');\n    });\n\n    it('should default to ns=0;i=0 for non-variable nodes', function () {\n      const file = new AtviseFile({\n        path: 'path/.Object.json',\n        contents: Buffer.from(JSON.stringify({ references: {} })),\n      });\n\n      expect(file.typeDefinition, 'to equal', new NodeId('ns=0;i=0'));\n    });\n  });\n\n  /** @test {AtviseFile#isDisplay} */\n  describe('#isDisplay', function () {\n    it('should return true for AtviseFiles with correct TypeDefinition', function () {\n      expect(\n        new AtviseFile({\n          path: './src/test/path',\n          _references: {\n            HasTypeDefinition: [new NodeId('VariableTypes.ATVISE.Display')],\n          },\n        }).isDisplay,\n        'to be true'\n      );\n    });\n  });\n\n  /** @test {AtviseFile#isScript} */\n  describe('#isScript', function () {\n    it('should return true for AtviseFiles with correct TypeDefinition', function () {\n      expect(\n        new AtviseFile({\n          path: './src/test/path',\n          _references: {\n            HasTypeDefinition: [new NodeId('VariableTypes.ATVISE.ScriptCode')],\n          },\n        }).isScript,\n        'to be true'\n      );\n    });\n  });\n\n  /** @test {AtviseFile#isQuickDynamic} */\n  describe('#isQuickDynamic', function () {\n    it('should return true for AtviseFiles with correct TypeDefinition', function () {\n      expect(\n        new AtviseFile({\n          path: './src/test/path',\n          _references: {\n            HasTypeDefinition: [new NodeId('VariableTypes.ATVISE.QuickDynamic')],\n          },\n        }).isQuickDynamic,\n        'to be true'\n      );\n    });\n  });\n\n  /** @test {AtivseFile#value} */\n  describe('#value', function () {\n    const val = Buffer.from('test');\n\n    before(() => {\n      stub(AtviseFile, 'decodeValue').callsFake(() => true);\n      stub(AtviseFile, 'encodeValue').callsFake(() => val);\n    });\n\n    after(() => {\n      AtviseFile.decodeValue.restore();\n      AtviseFile.encodeValue.restore();\n    });\n\n    context('when used as getter', function () {\n      it('should return decodedValue', function () {\n        const file = new AtviseFile({ path: 'path.ext' });\n\n        expect(file.value, 'to equal', true);\n        expect(AtviseFile.decodeValue.calledOnce, 'to be true');\n      });\n    });\n\n    context('when used as setter', function () {\n      it('should set encoded value as contents', function () {\n        const file = new AtviseFile({ path: 'path.ext' });\n        file.value = 13;\n\n        expect(AtviseFile.encodeValue.calledOnce, 'to be true');\n        expect(file.contents, 'to equal', val);\n      });\n    });\n  });\n\n  /** @test {AtivseFile#createNodeValue} */\n  describe('#createNodeValue', function () {\n    it('should return #value for non-datetime nodes', function () {\n      expect(\n        new AtviseFile({\n          path: 'AGENT/OBJECTS/Test.bool',\n          contents: Buffer.from('true'),\n        }).createNodeValue,\n        'to equal',\n        true\n      );\n    });\n\n    it('should return timestamp for datetime nodes', function () {\n      const date = new Date();\n      date.setMilliseconds(0);\n\n      expect(\n        new AtviseFile({\n          path: 'AGENT/OBJECTS/Test.datetime',\n          contents: Buffer.from(date.toString()),\n        }).createNodeValue,\n        'to equal',\n        date.valueOf()\n      );\n    });\n  });\n\n  /** @test {AtviseFile#nodeId} */\n  describe('#nodeId', function () {\n    it('should return id for directory with non-variable file', function () {\n      expect(\n        new AtviseFile({\n          path: 'SYSTEM/LIBRARY/PROJECT/.Object.json',\n          contents: Buffer.from(JSON.stringify({})),\n        }).nodeId.value,\n        'to equal',\n        'SYSTEM.LIBRARY.PROJECT'\n      );\n    });\n\n    it('should keep extensions for resources', function () {\n      expect(\n        new AtviseFile({ path: 'SYSTEM/LIBRARY/PROJECT/RESOURCES/example.js' }).nodeId.value,\n        'to equal',\n        'SYSTEM.LIBRARY.PROJECT.RESOURCES/example.js'\n      );\n    });\n\n    it('should remove extension for non-atvise types', function () {\n      expect(\n        new AtviseFile({ path: 'AGENT/OBJECTS/Test.bool' }).nodeId.value,\n        'to equal',\n        'AGENT.OBJECTS.Test'\n      );\n    });\n  });\n\n  /** @test {AtviseFile#clone} */\n  describe('#clone', function () {\n    it('should return a file again', function () {\n      expect(\n        new AtviseFile({\n          path: 'path/to/name.display.xml',\n          _arrayType: VariantArrayType.Matrix,\n        }).clone(),\n        'to be a',\n        AtviseFile\n      );\n    });\n\n    it('should return file with the same array type', function () {\n      expect(\n        new AtviseFile({\n          path: 'path/to/name.display.xml',\n          _arrayType: VariantArrayType.Matrix,\n        }).clone()._arrayType,\n        'to equal',\n        VariantArrayType.Matrix\n      );\n    });\n  });\n\n  /** @test {AtviseFile.read} */\n  describe('.read', function () {\n    it('should fail without path', function () {\n      return expect(AtviseFile.read(), 'to be rejected with', 'options.path is required');\n    });\n\n    it('should forward read errors', function () {\n      return expect(\n        AtviseFile.read({\n          path: 'does/not/exist',\n        }),\n        'to be rejected with',\n        /no such file/\n      );\n    });\n\n    it('should return AtviseFile if read succeeds', function () {\n      return expect(\n        AtviseFile.read({\n          path: `${__filename}`,\n        }),\n        'when fulfilled',\n        'to be a',\n        AtviseFile\n      );\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/server/AtviseFile.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 924,
    "kind": "test",
    "name": "describe218",
    "testId": 218,
    "memberof": "test/src/lib/server/AtviseFile.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "access": null,
    "description": "AtviseFile",
    "lineNumber": 11,
    "testTargets": [
      "AtviseFile"
    ]
  },
  {
    "__docId__": 925,
    "kind": "test",
    "name": "describe219",
    "testId": 219,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe219",
    "access": null,
    "description": "#constructor",
    "lineNumber": 13,
    "testTargets": [
      "AtviseFile#constructor"
    ]
  },
  {
    "__docId__": 926,
    "kind": "test",
    "name": "it220",
    "testId": 220,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe219",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe219.it220",
    "access": null,
    "description": "should create a vinyl instance",
    "lineNumber": 14
  },
  {
    "__docId__": 927,
    "kind": "test",
    "name": "describe221",
    "testId": 221,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe221",
    "access": null,
    "description": ".pathForReadResult",
    "lineNumber": 114,
    "testTargets": [
      "AtviseFile.pathForReadResult"
    ]
  },
  {
    "__docId__": 928,
    "kind": "test",
    "name": "it222",
    "testId": 222,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe221",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe221.it222",
    "access": null,
    "description": "should store non-variables as .{nodeClass}.json",
    "lineNumber": 115
  },
  {
    "__docId__": 929,
    "kind": "test",
    "name": "it223",
    "testId": 223,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe221",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe221.it223",
    "access": null,
    "lineNumber": 127
  },
  {
    "__docId__": 930,
    "kind": "test",
    "name": "it224",
    "testId": 224,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe221",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe221.it224",
    "access": null,
    "description": "should store custom typed variables with a \".var\" extension",
    "lineNumber": 146
  },
  {
    "__docId__": 931,
    "kind": "test",
    "name": "describe225",
    "testId": 225,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225",
    "access": null,
    "description": ".encodeValue",
    "lineNumber": 166,
    "testTargets": [
      "AtviseFile.encodeValue"
    ]
  },
  {
    "__docId__": 932,
    "kind": "test",
    "name": "it226",
    "testId": 226,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225.it226",
    "access": null,
    "description": "should return empty buffer for null",
    "lineNumber": 167
  },
  {
    "__docId__": 933,
    "kind": "test",
    "name": "it227",
    "testId": 227,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225.it227",
    "access": null,
    "description": "should store timestamp as string for DateTime values",
    "lineNumber": 171
  },
  {
    "__docId__": 934,
    "kind": "test",
    "name": "it228",
    "testId": 228,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225.it228",
    "access": null,
    "description": "should store JSON encoded bytes for UInt64 values",
    "lineNumber": 181
  },
  {
    "__docId__": 935,
    "kind": "test",
    "name": "it229",
    "testId": 229,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225.it229",
    "access": null,
    "description": "should use trimmed string value if no special encoder is used",
    "lineNumber": 189
  },
  {
    "__docId__": 936,
    "kind": "test",
    "name": "it230",
    "testId": 230,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225.it230",
    "access": null,
    "description": "should convert typed array",
    "lineNumber": 199
  },
  {
    "__docId__": 937,
    "kind": "test",
    "name": "context231",
    "testId": 231,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225.context231",
    "access": null,
    "description": "with an array passed",
    "lineNumber": 211
  },
  {
    "__docId__": 938,
    "kind": "test",
    "name": "it232",
    "testId": 232,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225.context231",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225.context231.it232",
    "access": null,
    "description": "should JSON encode standard values",
    "lineNumber": 212
  },
  {
    "__docId__": 939,
    "kind": "test",
    "name": "it233",
    "testId": 233,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225.context231",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225.context231.it233",
    "access": null,
    "description": "should JSON encode special encoded values",
    "lineNumber": 222
  },
  {
    "__docId__": 940,
    "kind": "test",
    "name": "it234",
    "testId": 234,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225.context231",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe225.context231.it234",
    "access": null,
    "description": "should JSON encode null values",
    "lineNumber": 232
  },
  {
    "__docId__": 941,
    "kind": "test",
    "name": "describe235",
    "testId": 235,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe235",
    "access": null,
    "description": ".decodeValue",
    "lineNumber": 245,
    "testTargets": [
      "AtviseFile.decodeValue"
    ]
  },
  {
    "__docId__": 942,
    "kind": "test",
    "name": "it236",
    "testId": 236,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe235",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe235.it236",
    "access": null,
    "description": "should forward null",
    "lineNumber": 246
  },
  {
    "__docId__": 943,
    "kind": "test",
    "name": "it237",
    "testId": 237,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe235",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe235.it237",
    "access": null,
    "lineNumber": 251
  },
  {
    "__docId__": 944,
    "kind": "test",
    "name": "it238",
    "testId": 238,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe235",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe235.it238",
    "access": null,
    "description": "should forward binary buffer for ByteString",
    "lineNumber": 290
  },
  {
    "__docId__": 945,
    "kind": "test",
    "name": "it239",
    "testId": 239,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe235",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe235.it239",
    "access": null,
    "description": "should throw if an array variable's value is scalar",
    "lineNumber": 299
  },
  {
    "__docId__": 946,
    "kind": "test",
    "name": "context240",
    "testId": 240,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe235",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe235.context240",
    "access": null,
    "description": "with an array passed",
    "lineNumber": 308
  },
  {
    "__docId__": 947,
    "kind": "test",
    "name": "it241",
    "testId": 241,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe235.context240",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe235.context240.it241",
    "access": null,
    "description": "should JSON decode standard values",
    "lineNumber": 309
  },
  {
    "__docId__": 948,
    "kind": "test",
    "name": "it242",
    "testId": 242,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe235.context240",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe235.context240.it242",
    "access": null,
    "description": "should JSON decode special encoded values",
    "lineNumber": 319
  },
  {
    "__docId__": 949,
    "kind": "test",
    "name": "it243",
    "testId": 243,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe235.context240",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe235.context240.it243",
    "access": null,
    "description": "should JSON decode null values",
    "lineNumber": 329
  },
  {
    "__docId__": 950,
    "kind": "test",
    "name": "describe244",
    "testId": 244,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe244",
    "access": null,
    "description": ".normalizeMtime",
    "lineNumber": 342,
    "testTargets": [
      "AtviseFile.normalizeMtime"
    ]
  },
  {
    "__docId__": 951,
    "kind": "test",
    "name": "it245",
    "testId": 245,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe244",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe244.it245",
    "access": null,
    "description": "should return original without milliseconds",
    "lineNumber": 343
  },
  {
    "__docId__": 952,
    "kind": "test",
    "name": "it246",
    "testId": 246,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe244",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe244.it246",
    "access": null,
    "description": "should remove milliseconds if provided",
    "lineNumber": 350
  },
  {
    "__docId__": 953,
    "kind": "test",
    "name": "describe247",
    "testId": 247,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe247",
    "access": null,
    "description": ".fromReadResult",
    "lineNumber": 359,
    "testTargets": [
      "AtviseFile.fromReadResult"
    ]
  },
  {
    "__docId__": 954,
    "kind": "test",
    "name": "it248",
    "testId": 248,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe247",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe247.it248",
    "access": null,
    "description": "should fail for variable without value",
    "lineNumber": 360
  },
  {
    "__docId__": 955,
    "kind": "test",
    "name": "it249",
    "testId": 249,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe247",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe247.it249",
    "access": null,
    "description": "should return a new instance with valid readResult",
    "lineNumber": 371
  },
  {
    "__docId__": 956,
    "kind": "test",
    "name": "it250",
    "testId": 250,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe247",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe247.it250",
    "access": null,
    "description": "should use undefined as mtime if not provided",
    "lineNumber": 393
  },
  {
    "__docId__": 957,
    "kind": "test",
    "name": "it251",
    "testId": 251,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe247",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe247.it251",
    "access": null,
    "description": "should store JSON-encoded references if not a variable-node",
    "lineNumber": 413
  },
  {
    "__docId__": 958,
    "kind": "test",
    "name": "it252",
    "testId": 252,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe247",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe247.it252",
    "access": null,
    "description": "should sort references in JSON file",
    "lineNumber": 436
  },
  {
    "__docId__": 959,
    "kind": "test",
    "name": "describe253",
    "testId": 253,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe253",
    "access": null,
    "description": "#_getMetadata",
    "lineNumber": 469,
    "testTargets": [
      "AtviseFile#_getMetadata"
    ]
  },
  {
    "__docId__": 960,
    "kind": "test",
    "name": "it254",
    "testId": 254,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe253",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe253.it254",
    "access": null,
    "lineNumber": 471
  },
  {
    "__docId__": 961,
    "kind": "test",
    "name": "it255",
    "testId": 255,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe253",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe253.it255",
    "access": null,
    "description": "should use dirname extensions if filename has no extensions",
    "lineNumber": 485
  },
  {
    "__docId__": 962,
    "kind": "test",
    "name": "it256",
    "testId": 256,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe253",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe253.it256",
    "access": null,
    "description": "should not get tripped up by multiple dots in dirname if filename has no extensions",
    "lineNumber": 495
  },
  {
    "__docId__": 963,
    "kind": "test",
    "name": "it257",
    "testId": 257,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe253",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe253.it257",
    "access": null,
    "description": "should parse contents for non-variable nodes",
    "lineNumber": 505
  },
  {
    "__docId__": 964,
    "kind": "test",
    "name": "it258",
    "testId": 258,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.it258",
    "access": null,
    "description": "should call _getMetadata if not present",
    "lineNumber": 528
  },
  {
    "__docId__": 965,
    "kind": "test",
    "name": "it259",
    "testId": 259,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.it259",
    "access": null,
    "description": "should return stored value if present",
    "lineNumber": 538
  },
  {
    "__docId__": 966,
    "kind": "test",
    "name": "describe260",
    "testId": 260,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe260",
    "access": null,
    "description": "#nodeClass",
    "lineNumber": 551,
    "testTargets": [
      "AtviseFile#dataType"
    ]
  },
  {
    "__docId__": 967,
    "kind": "test",
    "name": "describe261",
    "testId": 261,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe261",
    "access": null,
    "description": "#dataType",
    "lineNumber": 556,
    "testTargets": [
      "AtviseFile#dataType"
    ]
  },
  {
    "__docId__": 968,
    "kind": "test",
    "name": "describe262",
    "testId": 262,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe262",
    "access": null,
    "description": "#arrayType",
    "lineNumber": 561,
    "testTargets": [
      "AtviseFile#arrayType"
    ]
  },
  {
    "__docId__": 969,
    "kind": "test",
    "name": "describe263",
    "testId": 263,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe263",
    "access": null,
    "description": "#typeDefinition",
    "lineNumber": 566,
    "testTargets": [
      "AtviseFile#typeDefinition"
    ]
  },
  {
    "__docId__": 970,
    "kind": "test",
    "name": "it264",
    "testId": 264,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe263",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe263.it264",
    "access": null,
    "description": "should call _getMetadata if not present",
    "lineNumber": 567
  },
  {
    "__docId__": 971,
    "kind": "test",
    "name": "it265",
    "testId": 265,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe263",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe263.it265",
    "access": null,
    "description": "should return stored value if present",
    "lineNumber": 580
  },
  {
    "__docId__": 972,
    "kind": "test",
    "name": "it266",
    "testId": 266,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe263",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe263.it266",
    "access": null,
    "description": "should default to ns=0;i=0 for non-variable nodes",
    "lineNumber": 595
  },
  {
    "__docId__": 973,
    "kind": "test",
    "name": "describe267",
    "testId": 267,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe267",
    "access": null,
    "description": "#isDisplay",
    "lineNumber": 606,
    "testTargets": [
      "AtviseFile#isDisplay"
    ]
  },
  {
    "__docId__": 974,
    "kind": "test",
    "name": "it268",
    "testId": 268,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe267",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe267.it268",
    "access": null,
    "description": "should return true for AtviseFiles with correct TypeDefinition",
    "lineNumber": 607
  },
  {
    "__docId__": 975,
    "kind": "test",
    "name": "describe269",
    "testId": 269,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe269",
    "access": null,
    "description": "#isScript",
    "lineNumber": 621,
    "testTargets": [
      "AtviseFile#isScript"
    ]
  },
  {
    "__docId__": 976,
    "kind": "test",
    "name": "it270",
    "testId": 270,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe269",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe269.it270",
    "access": null,
    "description": "should return true for AtviseFiles with correct TypeDefinition",
    "lineNumber": 622
  },
  {
    "__docId__": 977,
    "kind": "test",
    "name": "describe271",
    "testId": 271,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe271",
    "access": null,
    "description": "#isQuickDynamic",
    "lineNumber": 636,
    "testTargets": [
      "AtviseFile#isQuickDynamic"
    ]
  },
  {
    "__docId__": 978,
    "kind": "test",
    "name": "it272",
    "testId": 272,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe271",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe271.it272",
    "access": null,
    "description": "should return true for AtviseFiles with correct TypeDefinition",
    "lineNumber": 637
  },
  {
    "__docId__": 979,
    "kind": "test",
    "name": "describe273",
    "testId": 273,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe273",
    "access": null,
    "description": "#value",
    "lineNumber": 651,
    "testTargets": [
      "AtivseFile#value"
    ]
  },
  {
    "__docId__": 980,
    "kind": "test",
    "name": "context274",
    "testId": 274,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe273",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe273.context274",
    "access": null,
    "description": "when used as getter",
    "lineNumber": 664
  },
  {
    "__docId__": 981,
    "kind": "test",
    "name": "it275",
    "testId": 275,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe273.context274",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe273.context274.it275",
    "access": null,
    "description": "should return decodedValue",
    "lineNumber": 665
  },
  {
    "__docId__": 982,
    "kind": "test",
    "name": "context276",
    "testId": 276,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe273",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe273.context276",
    "access": null,
    "description": "when used as setter",
    "lineNumber": 673
  },
  {
    "__docId__": 983,
    "kind": "test",
    "name": "it277",
    "testId": 277,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe273.context276",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe273.context276.it277",
    "access": null,
    "description": "should set encoded value as contents",
    "lineNumber": 674
  },
  {
    "__docId__": 984,
    "kind": "test",
    "name": "describe278",
    "testId": 278,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe278",
    "access": null,
    "description": "#createNodeValue",
    "lineNumber": 685,
    "testTargets": [
      "AtivseFile#createNodeValue"
    ]
  },
  {
    "__docId__": 985,
    "kind": "test",
    "name": "it279",
    "testId": 279,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe278",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe278.it279",
    "access": null,
    "description": "should return #value for non-datetime nodes",
    "lineNumber": 686
  },
  {
    "__docId__": 986,
    "kind": "test",
    "name": "it280",
    "testId": 280,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe278",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe278.it280",
    "access": null,
    "description": "should return timestamp for datetime nodes",
    "lineNumber": 697
  },
  {
    "__docId__": 987,
    "kind": "test",
    "name": "describe281",
    "testId": 281,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe281",
    "access": null,
    "description": "#nodeId",
    "lineNumber": 713,
    "testTargets": [
      "AtviseFile#nodeId"
    ]
  },
  {
    "__docId__": 988,
    "kind": "test",
    "name": "it282",
    "testId": 282,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe281",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe281.it282",
    "access": null,
    "description": "should return id for directory with non-variable file",
    "lineNumber": 714
  },
  {
    "__docId__": 989,
    "kind": "test",
    "name": "it283",
    "testId": 283,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe281",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe281.it283",
    "access": null,
    "description": "should keep extensions for resources",
    "lineNumber": 725
  },
  {
    "__docId__": 990,
    "kind": "test",
    "name": "it284",
    "testId": 284,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe281",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe281.it284",
    "access": null,
    "description": "should remove extension for non-atvise types",
    "lineNumber": 733
  },
  {
    "__docId__": 991,
    "kind": "test",
    "name": "describe285",
    "testId": 285,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe285",
    "access": null,
    "description": "#clone",
    "lineNumber": 743,
    "testTargets": [
      "AtviseFile#clone"
    ]
  },
  {
    "__docId__": 992,
    "kind": "test",
    "name": "it286",
    "testId": 286,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe285",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe285.it286",
    "access": null,
    "description": "should return a file again",
    "lineNumber": 744
  },
  {
    "__docId__": 993,
    "kind": "test",
    "name": "it287",
    "testId": 287,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe285",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe285.it287",
    "access": null,
    "description": "should return file with the same array type",
    "lineNumber": 755
  },
  {
    "__docId__": 994,
    "kind": "test",
    "name": "describe288",
    "testId": 288,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe288",
    "access": null,
    "description": ".read",
    "lineNumber": 768,
    "testTargets": [
      "AtviseFile.read"
    ]
  },
  {
    "__docId__": 995,
    "kind": "test",
    "name": "it289",
    "testId": 289,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe288",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe288.it289",
    "access": null,
    "description": "should fail without path",
    "lineNumber": 769
  },
  {
    "__docId__": 996,
    "kind": "test",
    "name": "it290",
    "testId": 290,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe288",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe288.it290",
    "access": null,
    "description": "should forward read errors",
    "lineNumber": 773
  },
  {
    "__docId__": 997,
    "kind": "test",
    "name": "it291",
    "testId": 291,
    "memberof": "test/src/lib/server/AtviseFile.spec.js~describe218.describe288",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/AtviseFile.spec.js~describe218.describe288.it291",
    "access": null,
    "description": "should return AtviseFile if read succeeds",
    "lineNumber": 783
  },
  {
    "__docId__": 998,
    "kind": "testFile",
    "name": "test/src/lib/server/CreateNodeStream.spec.js",
    "content": "import {\n  DataType,\n  NodeClass,\n  Variant,\n  VariantArrayType,\n  StatusCodes,\n  NodeId as OpcNodeId,\n} from 'node-opcua';\nimport { spy } from 'sinon';\nimport Logger from 'gulplog';\nimport expect from '../../../expect';\nimport CreateNodeStream from '../../../../src/lib/server/CreateNodeStream';\nimport AtviseFile from '../../../../src/lib/server/AtviseFile';\nimport Session from '../../../../src/lib/server/Session';\nimport NodeId from '../../../../src/lib/model/opcua/NodeId';\nimport { FileNode } from '../../../../src/lib/gulp/src';\n\n/** @test {CreateNodeStream} */\ndescribe('CreateNodeStream', function () {\n  /** @test {CreateNodeStream#scriptId} */\n  describe('#scriptId', function () {\n    it('should return the atscm CreateNode script', function () {\n      return expect(\n        new CreateNodeStream().scriptId,\n        'to equal',\n        new NodeId('ns=1;s=SYSTEM.LIBRARY.ATVISE.SERVERSCRIPTS.atscm.CreateNode')\n      );\n    });\n  });\n\n  /** @test {CreateNodeStream#scriptParameters} */\n  describe('#scriptParameters', function () {\n    it.skip('should return a single JSON encoded parameter', function () {\n      const file = new FileNode({\n        name: 'Test',\n        parent: null,\n        nodeClass: 'Variable',\n        nodeId: 'AGENT.OBJECTS.Testing',\n        referneces: {\n          HasTypeDefinition: 'VariableTypes.Project.Test',\n        },\n        dataType: DataType.String,\n        arrayType: VariantArrayType.Scalar,\n      });\n\n      this.value.value = 'Just testing...';\n\n      const params = new CreateNodeStream().scriptParameters(file);\n\n      expect(params, 'to only have keys', ['paramObjString']);\n      expect(params.paramObjString, 'to only have keys', ['dataType', 'value']);\n      expect(params.paramObjString.dataType, 'to equal', DataType.String);\n      expect(params.paramObjString.value, 'to be a string');\n      expect(() => JSON.parse(params.paramObjString.value), 'not to throw');\n    });\n\n    it.skip('should include nodeId, parentNodeId, nodeClass, typeDefinition and browseName', () => {\n      const typeDefId = new NodeId('Type.Def.Id');\n      const file = new AtviseFile({\n        path: './src/path/to/node/.Object.json',\n        base: './src/',\n        contents: Buffer.from(\n          JSON.stringify({\n            references: {\n              HasTypeDefinition: [typeDefId],\n            },\n          })\n        ),\n      });\n\n      const params = new CreateNodeStream().scriptParameters(file);\n      const decoded = JSON.parse(params.paramObjString.value);\n\n      expect(decoded.nodeId, 'to equal', 'ns=1;s=path.to.node');\n      expect(decoded.parentNodeId, 'to equal', 'ns=1;s=path.to');\n      expect(decoded.nodeClass, 'to equal', NodeClass.Object.value);\n      expect(decoded.typeDefinition, 'to equal', typeDefId.value);\n      expect(decoded.browseName, 'to equal', 'node');\n      expect(decoded.dataType, 'to be undefined');\n      expect(decoded.valueRank, 'to be undefined');\n      expect(decoded.value, 'to be undefined');\n    });\n\n    it.skip('should include dataType, arrayType and value for variables', function () {\n      const file = new AtviseFile({\n        path: './src/AGENT/OBJECTS/Test.prop.float.array',\n        base: './src/',\n        contents: Buffer.from('[0.13,14]'),\n      });\n\n      const params = new CreateNodeStream().scriptParameters(file);\n      const decoded = JSON.parse(params.paramObjString.value);\n\n      expect(decoded.nodeId, 'to equal', 'ns=1;s=AGENT.OBJECTS.Test');\n      expect(decoded.parentNodeId, 'to equal', 'ns=1;s=AGENT.OBJECTS');\n      expect(decoded.nodeClass, 'to equal', NodeClass.Variable.value);\n      expect(decoded.typeDefinition, 'to equal', 68); // Property\n      expect(decoded.browseName, 'to equal', 'Test');\n      expect(decoded.dataType, 'to equal', DataType.Float.value);\n      expect(decoded.valueRank, 'to equal', VariantArrayType.Array.value);\n      expect(decoded.value, 'to equal', [0.13, 14]);\n    });\n  });\n\n  /** @test {CreateNodeStream#processErrorMessage} */\n  describe('#processErrorMessage', function () {\n    it('should tell which node failed to create', function () {\n      return expect(\n        CreateNodeStream.prototype.processErrorMessage,\n        'when called with',\n        [{ nodeId: new NodeId('Failed.to.create') }],\n        'to match',\n        /creating node/i\n      );\n    });\n  });\n\n  /** @test {CreateNodeStream#handleOutputArguments} */\n  describe('#handleOutputArguments', function () {\n    it('should forward script errors', function () {\n      const stream = new CreateNodeStream();\n\n      return expect(\n        (cb) =>\n          stream.handleOutputArguments(\n            {},\n            [{ value: StatusCodes.Bad }, { value: 'Test error' }],\n            cb\n          ),\n        'to call the callback with error',\n        'Test error'\n      );\n    });\n\n    it('should warn if creating the node failed', async function () {\n      const stream = new CreateNodeStream();\n\n      const warnSpy = spy();\n      Logger.on('warn', warnSpy);\n\n      await expect(\n        (cb) =>\n          stream.handleOutputArguments(\n            { nodeId: 'Test' },\n            [{ value: StatusCodes.Good }, {}, {}, { value: [{ value: false }, { value: true }] }],\n            cb\n          ),\n        'to call the callback without error'\n      );\n\n      expect(warnSpy, 'was called once');\n      return expect(warnSpy, 'to have a call satisfying', { args: [/Failed to create.*Test/] });\n    });\n\n    it('should log if a node was created', async function () {\n      const stream = new CreateNodeStream();\n\n      const debugSpy = spy();\n      Logger.on('debug', debugSpy);\n\n      await expect(\n        (cb) =>\n          stream.handleOutputArguments(\n            { nodeId: 'Test' },\n            [{ value: StatusCodes.Good }, {}, {}, { value: [{ value: true }, { value: false }] }],\n            cb\n          ),\n        'to call the callback without error'\n      );\n\n      expect(debugSpy, 'was called once');\n      return expect(debugSpy, 'to have a call satisfying', { args: [/Created node.*Test/] });\n    });\n\n    it.skip('should log if node already existed', async function () {\n      const stream = new CreateNodeStream();\n\n      const debugSpy = spy();\n      Logger.on('debug', debugSpy);\n\n      await expect(\n        (cb) =>\n          stream.handleOutputArguments(\n            { nodeId: 'Test' },\n            [{ value: StatusCodes.Good }, {}, {}, { value: [{ value: false }, { value: false }] }],\n            cb\n          ),\n        'to call the callback without error'\n      );\n\n      expect(debugSpy, 'was called once');\n      return expect(debugSpy, 'to have a call satisfying', { args: [/already exists/] });\n    });\n  });\n\n  /** @test {CreateNodeStream#processChunk} */\n  describe.skip('#processChunk', function () {\n    const testTime = Date.now();\n    const testFolderNodePath = `src/AGENT/OBJECTS/TestCreate-${testTime}`;\n    const nodeIdBase = `AGENT.OBJECTS.TestCreate-${testTime}`;\n\n    before('create test node folder', function () {\n      const stream = new CreateNodeStream();\n\n      return expect(\n        [\n          new FileNode({\n            path: `${testFolderNodePath}/.Object.json`,\n            base: './src',\n            contents: Buffer.from(\n              JSON.stringify({\n                references: {\n                  HasTypeDefinition: ['ns=0;i=61'],\n                },\n              })\n            ),\n          }),\n        ],\n        'when piped through',\n        stream,\n        'to yield objects satisfying',\n        'to have length',\n        1\n      );\n    });\n\n    const dateValue = new Date();\n    dateValue.setMilliseconds(0);\n\n    const tests = [\n      {\n        nodeClass: NodeClass.Variable,\n        value: {\n          value: true,\n          dataType: DataType.Boolean,\n          arrayType: VariantArrayType.Scalar,\n        },\n      },\n      {\n        nodeClass: NodeClass.Variable,\n        value: {\n          value: 3,\n          dataType: DataType.Int16,\n          arrayType: VariantArrayType.Scalar,\n        },\n      },\n      {\n        nodeClass: NodeClass.Variable,\n        value: {\n          value: 1.0,\n          dataType: DataType.Float,\n          arrayType: VariantArrayType.Scalar,\n        },\n      },\n      {\n        nodeClass: NodeClass.Variable,\n        value: {\n          value: 'Test',\n          dataType: DataType.String,\n          arrayType: VariantArrayType.Scalar,\n        },\n      },\n      {\n        nodeClass: NodeClass.Variable,\n        value: {\n          value: dateValue,\n          dataType: DataType.DateTime,\n          arrayType: VariantArrayType.Scalar,\n        },\n      },\n      {\n        nodeClass: NodeClass.Variable,\n        value: {\n          value: '<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><test />',\n          dataType: DataType.XmlElement,\n          arrayType: VariantArrayType.Scalar,\n        },\n      },\n      {\n        nodeClass: NodeClass.Variable,\n        value: {\n          value: new OpcNodeId(NodeId.NodeIdType.STRING, 'Testing'),\n          dataType: DataType.NodeId,\n          arrayType: VariantArrayType.Scalar,\n        },\n      },\n    ];\n\n    tests.forEach(({ nodeClass, value }) => {\n      it(`should be able to create ${value.dataType.key} ${nodeClass.key}s`, async function () {\n        const stream = new CreateNodeStream();\n\n        const nodeId = new NodeId(`${nodeIdBase}.Test${value.dataType.key}`);\n\n        const variant = new Variant(value);\n\n        expect(variant.isValid(), 'to be', true);\n\n        const file = AtviseFile.fromReadResult({\n          nodeId,\n          nodeClass,\n          value: variant,\n          mtime: new Date(),\n          references: {\n            HasTypeDefinition: [new NodeId('ns=0;i=62')],\n          },\n        });\n\n        await expect([file], 'when piped through', stream, 'to yield objects satisfying', [file]);\n\n        const session = await Session.create();\n\n        const [[{ value: readValue }]] = await expect(\n          (cb) => session.readVariableValue([nodeId.toString()], cb),\n          'to call the callback without error'\n        );\n\n        expect(readValue, 'to equal', variant);\n      });\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/server/CreateNodeStream.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 999,
    "kind": "test",
    "name": "describe292",
    "testId": 292,
    "memberof": "test/src/lib/server/CreateNodeStream.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/CreateNodeStream.spec.js~describe292",
    "access": null,
    "description": "CreateNodeStream",
    "lineNumber": 19,
    "testTargets": [
      "CreateNodeStream"
    ]
  },
  {
    "__docId__": 1000,
    "kind": "test",
    "name": "describe293",
    "testId": 293,
    "memberof": "test/src/lib/server/CreateNodeStream.spec.js~describe292",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/CreateNodeStream.spec.js~describe292.describe293",
    "access": null,
    "description": "#scriptId",
    "lineNumber": 21,
    "testTargets": [
      "CreateNodeStream#scriptId"
    ]
  },
  {
    "__docId__": 1001,
    "kind": "test",
    "name": "it294",
    "testId": 294,
    "memberof": "test/src/lib/server/CreateNodeStream.spec.js~describe292.describe293",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/CreateNodeStream.spec.js~describe292.describe293.it294",
    "access": null,
    "description": "should return the atscm CreateNode script",
    "lineNumber": 22
  },
  {
    "__docId__": 1002,
    "kind": "test",
    "name": "describe295",
    "testId": 295,
    "memberof": "test/src/lib/server/CreateNodeStream.spec.js~describe292",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/CreateNodeStream.spec.js~describe292.describe295",
    "access": null,
    "description": "#scriptParameters",
    "lineNumber": 32,
    "testTargets": [
      "CreateNodeStream#scriptParameters"
    ]
  },
  {
    "__docId__": 1003,
    "kind": "test",
    "name": "describe296",
    "testId": 296,
    "memberof": "test/src/lib/server/CreateNodeStream.spec.js~describe292",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/CreateNodeStream.spec.js~describe292.describe296",
    "access": null,
    "description": "#processErrorMessage",
    "lineNumber": 106,
    "testTargets": [
      "CreateNodeStream#processErrorMessage"
    ]
  },
  {
    "__docId__": 1004,
    "kind": "test",
    "name": "it297",
    "testId": 297,
    "memberof": "test/src/lib/server/CreateNodeStream.spec.js~describe292.describe296",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/CreateNodeStream.spec.js~describe292.describe296.it297",
    "access": null,
    "description": "should tell which node failed to create",
    "lineNumber": 107
  },
  {
    "__docId__": 1005,
    "kind": "test",
    "name": "describe298",
    "testId": 298,
    "memberof": "test/src/lib/server/CreateNodeStream.spec.js~describe292",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/CreateNodeStream.spec.js~describe292.describe298",
    "access": null,
    "description": "#handleOutputArguments",
    "lineNumber": 119,
    "testTargets": [
      "CreateNodeStream#handleOutputArguments"
    ]
  },
  {
    "__docId__": 1006,
    "kind": "test",
    "name": "it299",
    "testId": 299,
    "memberof": "test/src/lib/server/CreateNodeStream.spec.js~describe292.describe298",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/CreateNodeStream.spec.js~describe292.describe298.it299",
    "access": null,
    "description": "should forward script errors",
    "lineNumber": 120
  },
  {
    "__docId__": 1007,
    "kind": "test",
    "name": "it300",
    "testId": 300,
    "memberof": "test/src/lib/server/CreateNodeStream.spec.js~describe292.describe298",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/CreateNodeStream.spec.js~describe292.describe298.it300",
    "access": null,
    "description": "should warn if creating the node failed",
    "lineNumber": 135
  },
  {
    "__docId__": 1008,
    "kind": "test",
    "name": "it301",
    "testId": 301,
    "memberof": "test/src/lib/server/CreateNodeStream.spec.js~describe292.describe298",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/CreateNodeStream.spec.js~describe292.describe298.it301",
    "access": null,
    "description": "should log if a node was created",
    "lineNumber": 155
  },
  {
    "__docId__": 1009,
    "kind": "test",
    "name": "it302",
    "testId": 302,
    "memberof": "test/src/lib/server/CreateNodeStream.spec.js~describe292",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/CreateNodeStream.spec.js~describe292.it302",
    "access": null,
    "lineNumber": 290
  },
  {
    "__docId__": 1010,
    "kind": "testFile",
    "name": "test/src/lib/server/NodeStream.spec.js",
    "content": "import { resolveNodeId, StatusCodes, NodeClass, ReferenceTypeIds } from 'node-opcua';\nimport { spy } from 'sinon';\nimport Logger from 'gulplog';\nimport expect from '../../../expect';\nimport { waitForEvent } from '../../../helpers/Emitter';\nimport NodeStream from '../../../../src/lib/server/NodeStream';\nimport NodeId from '../../../../src/lib/model/opcua/NodeId';\n\nclass StubNodeStream extends NodeStream {\n  _transform(chunk, enc, callback) {\n    callback(null, chunk);\n  }\n}\n\nclass NoWriteNodeStream extends StubNodeStream {\n  // eslint-disable-next-line @typescript-eslint/no-empty-function\n  _writeNodesToBrowse() {}\n}\n\nclass NonRecursive extends NodeStream {\n  processChunk(chunk, handleErrors) {\n    setImmediate(() => {\n      handleErrors(null, StatusCodes.Good, (done) => {\n        this.push(chunk);\n        done();\n      });\n    });\n  }\n}\n\n/** @test {NodeStream} */\ndescribe.skip('NodeStream', function () {\n  const testNodes = [new NodeId('ns=1;s=AGENT.DISPLAYS'), new NodeId('ns=1;s=AGENT.OBJECTS')];\n\n  function referenceTypeId(referenceType) {\n    return new NodeId(NodeId.NodeIdType.NUMERIC, referenceType);\n  }\n\n  /** @test {NodeStream#constructor} */\n  describe('#constructor', function () {\n    it('should fail without nodesToBrowse', function () {\n      expect(() => new NodeStream(), 'to throw', /nodesToBrowse is required/);\n    });\n\n    it('should throw with invalid ignoreNodes', function () {\n      expect(\n        () => new NodeStream(testNodes, { ignoreNodes: 'test' }),\n        'to throw',\n        /ignoreNodes must be an array/\n      );\n    });\n\n    it('should store \"recursive\" option', function () {\n      expect(new NoWriteNodeStream(testNodes, { recursive: false }).recursive, 'to be', false);\n    });\n\n    it('should create ignoredRexExp', function () {\n      expect(\n        new NoWriteNodeStream(testNodes, {\n          ignoreNodes: [new NodeId('Test.Node')],\n        }).ignoredRegExp,\n        'to equal',\n        /^(ns=1;s=Test.Node)/\n      );\n    });\n\n    it('should warn on ignored nodes', function (done) {\n      Logger.once('warn', (message) => {\n        expect(message, 'to match', /ignored/);\n        done();\n      });\n\n      expect(\n        new NoWriteNodeStream(testNodes, {\n          ignoreNodes: [testNodes[0]],\n        }),\n        'to be defined'\n      );\n    });\n\n    it('should error without nodes to browse', function () {\n      expect(\n        () => new StubNodeStream(testNodes, { ignoreNodes: testNodes }),\n        'to throw error',\n        /Nothing to browse/\n      );\n    });\n\n    /* it('should listen to drained events', function() {\n      expect((new StubNodeStream(testNodes)).listenerCount('drained'), 'to equal', 1);\n    }); */\n  });\n\n  /* @test {NodeStream#_writeNodesToBrowse} */\n  describe('#_writeNodesToBrowse', function () {\n    it('should forward read errors', function () {\n      const stream = new StubNodeStream(testNodes);\n\n      stream.prependOnceListener('session-open', () => {\n        stream.session.read = (_, cb) => cb(new Error('Read error'));\n      });\n\n      return expect(stream, 'to error with', 'Read error');\n    });\n\n    it('should error on bad status code', function () {\n      const node = new NodeId('Does.Not.Exist');\n      const stream = new StubNodeStream([testNodes[0], node, testNodes[1]]);\n\n      return expect(stream, 'to error with', new RegExp(`^Error reading ${node}`));\n    });\n\n    it('should write read results', async function () {\n      const stream = new NonRecursive(testNodes);\n\n      spy(stream, 'write');\n\n      await expect(stream, 'to yield objects satisfying', 'to have length', 2);\n\n      return expect(stream.write, 'was called times', 2);\n    });\n\n    it('should call #end on drained', async function () {\n      const stream = new NonRecursive(testNodes);\n\n      spy(stream, 'end');\n\n      await waitForEvent(stream, 'initial-read-complete');\n      await waitForEvent(stream, 'drained');\n\n      return expect(stream.end, 'was called once');\n    });\n  });\n\n  /** @test {NodeStream#processErrorMessage} */\n  describe('#processErrorMessage', function () {\n    it('should decorate error message', function () {\n      const nodeId = resolveNodeId('ns=1;s=AGENT.DISPLAYS.Main');\n      expect(NodeStream.prototype.processErrorMessage({ nodeId }), 'to contain', nodeId.toString());\n    });\n  });\n\n  /** @test {NodeStream#processChunk} */\n  describe('#processChunk', function () {\n    it('should forward browse errors', function () {\n      const stream = new NodeStream(testNodes).prependOnceListener('session-open', () => {\n        stream.session.browse = (options, callback) => {\n          callback(new Error('Browse error'));\n        };\n      });\n\n      return expect(stream, 'to error with', /Browse error/);\n    });\n\n    it('should emit error without results', function () {\n      const stream = new NodeStream(testNodes).prependOnceListener('session-open', () => {\n        stream.session.browse = (options, callback) => {\n          callback(null, null);\n        };\n      });\n\n      return expect(stream, 'to error with', /No results/);\n    });\n\n    it('should emit error with empty results', function () {\n      const stream = new NodeStream(testNodes).prependOnceListener('session-open', () => {\n        stream.session.browse = (options, callback) => {\n          callback(null, []);\n        };\n      });\n\n      return expect(stream, 'to error with', /No results/);\n    });\n\n    it('should emit error with empty results after initial write', function () {\n      const stream = new NodeStream(testNodes).prependOnceListener('initial-read-complete', () => {\n        stream.session.browse = (options, callback) => {\n          callback(null, []);\n        };\n      });\n\n      return expect(stream, 'to error with', /No results/);\n    });\n\n    it('should not push parent nodes', function () {\n      const stream = new NodeStream(testNodes, { recursive: false }).prependOnceListener(\n        'session-open',\n        () => {\n          stream.session.browse = (options, callback) => {\n            callback(null, [\n              {\n                statusCode: StatusCodes.Good,\n                references: [\n                  {\n                    referenceTypeId: referenceTypeId(ReferenceTypeIds.HasComponent), // anything valid\n                    $nodeClass: NodeClass.Variable,\n                    nodeId: new NodeId('ns=1;s=AGENT'),\n                  },\n                ],\n              },\n            ]);\n          };\n        }\n      );\n\n      return expect(stream, 'to yield objects satisfying', 'to have length', testNodes.length);\n    });\n\n    it('should not push ignored nodes', function () {\n      const stream = new NodeStream(testNodes, {\n        recursive: false,\n        ignoreNodes: [new NodeId('ns=1;s=AGENT.DISPLAYS.Main')],\n      }).prependOnceListener('session-open', () => {\n        stream.session.browse = (options, callback) => {\n          callback(null, [\n            {\n              statusCode: StatusCodes.Good,\n              references: [\n                {\n                  referenceTypeId: referenceTypeId(ReferenceTypeIds.HasComponent),\n                  $nodeClass: NodeClass.Variable,\n                  nodeId: new NodeId('ns=1;s=AGENT.DISPLAYS.Main'),\n                },\n              ],\n            },\n          ]);\n        };\n      });\n\n      return expect(stream, 'to yield objects satisfying', 'to have length', testNodes.length);\n    });\n\n    it('should push nodes to browse', async function () {\n      const stream = new NodeStream(testNodes, { recursive: false });\n\n      return expect(\n        stream,\n        'to yield objects satisfying',\n        'to have items satisfying',\n        (item, i) => {\n          expect(item, 'to have property', 'nodeId', testNodes[i]);\n          expect(item, 'to have property', 'nodeClass', NodeClass.Object);\n        }\n      );\n    });\n\n    it('should browse discovered nodes', async function () {\n      const stream = new NodeStream([testNodes[0]]).prependOnceListener('session-open', () => {\n        stream.session.browse = (options, callback) => {\n          callback(null, [\n            {\n              statusCode: StatusCodes.Good,\n              references: [\n                {\n                  referenceTypeId: referenceTypeId(ReferenceTypeIds.HasComponent),\n                  $nodeClass: NodeClass.Object,\n                  nodeId: new NodeId('ns=1;s=AGENT.DISPLAYS.MAIN'),\n                },\n              ],\n            },\n          ]);\n        };\n      });\n\n      return expect(stream, 'to yield objects satisfying', 'to have length', 2);\n    });\n\n    it('should push discovered object nodes', function () {\n      const stream = new NodeStream(testNodes).prependOnceListener('session-open', () => {\n        stream.session.browse = (options, callback) => {\n          callback(null, [\n            {\n              statusCode: StatusCodes.Good,\n              references: [\n                {\n                  referenceTypeId: referenceTypeId(ReferenceTypeIds.HasComponent),\n                  $nodeClass: NodeClass.Object,\n                  nodeId: new NodeId('ns=1;s=AGENT.DISPLAYS.MAIN'),\n                },\n              ],\n            },\n          ]);\n        };\n      });\n\n      return expect(stream, 'to yield objects satisfying', 'to have length', 3);\n    });\n\n    it('should push discovered variable nodes', async function () {\n      const stream = new NodeStream(testNodes).prependOnceListener('session-open', () => {\n        stream.session.browse = (options, callback) => {\n          callback(null, [\n            {\n              statusCode: StatusCodes.Good,\n              references: [\n                {\n                  referenceTypeId: referenceTypeId(ReferenceTypeIds.HasComponent),\n                  $nodeClass: NodeClass.Variable,\n                  nodeId: new NodeId('ns=1;s=AGENT.DISPLAYS.Main'),\n                },\n              ],\n            },\n          ]);\n        };\n      });\n\n      spy(stream, 'write');\n\n      await expect(stream, 'to yield objects satisfying', 'to have length', 3);\n\n      return expect(stream.write, 'was called times', 3);\n    });\n\n    it('should write discovered nodes if recursive', function () {\n      let called = 0;\n      const stream = new NodeStream([testNodes[0]], { recursive: true }).prependOnceListener(\n        'session-open',\n        () => {\n          stream.session.browse = (options, callback) => {\n            if (called === 2) {\n              callback(null, [\n                {\n                  statusCode: StatusCodes.Good,\n                  references: [],\n                },\n              ]);\n            } else {\n              called++;\n\n              callback(null, [\n                {\n                  statusCode: StatusCodes.Good,\n                  references: [\n                    {\n                      referenceTypeId: referenceTypeId(ReferenceTypeIds.HasComponent),\n                      $nodeClass: NodeClass.Variable,\n                      nodeId: new NodeId('ns=1;s=AGENT.DISPLAYS.Main'),\n                    },\n                    {\n                      referenceTypeId: referenceTypeId(ReferenceTypeIds.HasComponent),\n                      $nodeClass: NodeClass.Object,\n                      nodeId: new NodeId('ns=1;s=AGENT.DISPLAYS.MAIN'),\n                    },\n                  ],\n                },\n              ]);\n            }\n          };\n        }\n      );\n\n      spy(stream, 'write');\n\n      return expect(stream, 'to yield objects satisfying', 'to have length', 3).then(() =>\n        expect(stream.write, 'was called times', 3)\n      );\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/server/NodeStream.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1011,
    "kind": "test",
    "name": "describe303",
    "testId": 303,
    "memberof": "test/src/lib/server/NodeStream.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe303",
    "access": null,
    "description": "#constructor",
    "lineNumber": 40,
    "testTargets": [
      "NodeStream#constructor"
    ]
  },
  {
    "__docId__": 1012,
    "kind": "test",
    "name": "it304",
    "testId": 304,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe303",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe303.it304",
    "access": null,
    "description": "should fail without nodesToBrowse",
    "lineNumber": 41
  },
  {
    "__docId__": 1013,
    "kind": "test",
    "name": "it305",
    "testId": 305,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe303",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe303.it305",
    "access": null,
    "description": "should throw with invalid ignoreNodes",
    "lineNumber": 45
  },
  {
    "__docId__": 1014,
    "kind": "test",
    "name": "it306",
    "testId": 306,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe303",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe303.it306",
    "access": null,
    "description": "should store \"recursive\" option",
    "lineNumber": 53
  },
  {
    "__docId__": 1015,
    "kind": "test",
    "name": "it307",
    "testId": 307,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe303",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe303.it307",
    "access": null,
    "description": "should create ignoredRexExp",
    "lineNumber": 57
  },
  {
    "__docId__": 1016,
    "kind": "test",
    "name": "it308",
    "testId": 308,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe303",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe303.it308",
    "access": null,
    "description": "should warn on ignored nodes",
    "lineNumber": 67
  },
  {
    "__docId__": 1017,
    "kind": "test",
    "name": "it309",
    "testId": 309,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe303",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe303.it309",
    "access": null,
    "description": "should error without nodes to browse",
    "lineNumber": 81
  },
  {
    "__docId__": 1018,
    "kind": "test",
    "name": "describe310",
    "testId": 310,
    "memberof": "test/src/lib/server/NodeStream.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe310",
    "access": null,
    "description": "#_writeNodesToBrowse",
    "lineNumber": 95
  },
  {
    "__docId__": 1019,
    "kind": "test",
    "name": "it311",
    "testId": 311,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe310",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe310.it311",
    "access": null,
    "description": "should forward read errors",
    "lineNumber": 96
  },
  {
    "__docId__": 1020,
    "kind": "test",
    "name": "it312",
    "testId": 312,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe310",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe310.it312",
    "access": null,
    "description": "should error on bad status code",
    "lineNumber": 106
  },
  {
    "__docId__": 1021,
    "kind": "test",
    "name": "it313",
    "testId": 313,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe310",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe310.it313",
    "access": null,
    "description": "should write read results",
    "lineNumber": 113
  },
  {
    "__docId__": 1022,
    "kind": "test",
    "name": "it314",
    "testId": 314,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe310",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe310.it314",
    "access": null,
    "description": "should call #end on drained",
    "lineNumber": 123
  },
  {
    "__docId__": 1023,
    "kind": "test",
    "name": "describe315",
    "testId": 315,
    "memberof": "test/src/lib/server/NodeStream.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe315",
    "access": null,
    "description": "#processErrorMessage",
    "lineNumber": 136,
    "testTargets": [
      "NodeStream#processErrorMessage"
    ]
  },
  {
    "__docId__": 1024,
    "kind": "test",
    "name": "it316",
    "testId": 316,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe315",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe315.it316",
    "access": null,
    "description": "should decorate error message",
    "lineNumber": 137
  },
  {
    "__docId__": 1025,
    "kind": "test",
    "name": "describe317",
    "testId": 317,
    "memberof": "test/src/lib/server/NodeStream.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe317",
    "access": null,
    "description": "#processChunk",
    "lineNumber": 144,
    "testTargets": [
      "NodeStream#processChunk"
    ]
  },
  {
    "__docId__": 1026,
    "kind": "test",
    "name": "it318",
    "testId": 318,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe317",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe317.it318",
    "access": null,
    "description": "should forward browse errors",
    "lineNumber": 145
  },
  {
    "__docId__": 1027,
    "kind": "test",
    "name": "it319",
    "testId": 319,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe317",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe317.it319",
    "access": null,
    "description": "should emit error without results",
    "lineNumber": 155
  },
  {
    "__docId__": 1028,
    "kind": "test",
    "name": "it320",
    "testId": 320,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe317",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe317.it320",
    "access": null,
    "description": "should emit error with empty results",
    "lineNumber": 165
  },
  {
    "__docId__": 1029,
    "kind": "test",
    "name": "it321",
    "testId": 321,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe317",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe317.it321",
    "access": null,
    "description": "should emit error with empty results after initial write",
    "lineNumber": 175
  },
  {
    "__docId__": 1030,
    "kind": "test",
    "name": "it322",
    "testId": 322,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe317",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe317.it322",
    "access": null,
    "description": "should not push parent nodes",
    "lineNumber": 185
  },
  {
    "__docId__": 1031,
    "kind": "test",
    "name": "it323",
    "testId": 323,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe317",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe317.it323",
    "access": null,
    "description": "should not push ignored nodes",
    "lineNumber": 209
  },
  {
    "__docId__": 1032,
    "kind": "test",
    "name": "it324",
    "testId": 324,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe317",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe317.it324",
    "access": null,
    "description": "should push nodes to browse",
    "lineNumber": 233
  },
  {
    "__docId__": 1033,
    "kind": "test",
    "name": "it325",
    "testId": 325,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe317",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe317.it325",
    "access": null,
    "description": "should browse discovered nodes",
    "lineNumber": 247
  },
  {
    "__docId__": 1034,
    "kind": "test",
    "name": "it326",
    "testId": 326,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe317",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe317.it326",
    "access": null,
    "description": "should push discovered object nodes",
    "lineNumber": 268
  },
  {
    "__docId__": 1035,
    "kind": "test",
    "name": "it327",
    "testId": 327,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe317",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe317.it327",
    "access": null,
    "description": "should push discovered variable nodes",
    "lineNumber": 289
  },
  {
    "__docId__": 1036,
    "kind": "test",
    "name": "it328",
    "testId": 328,
    "memberof": "test/src/lib/server/NodeStream.spec.js~describe317",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/NodeStream.spec.js~describe317.it328",
    "access": null,
    "description": "should write discovered nodes if recursive",
    "lineNumber": 314
  },
  {
    "__docId__": 1037,
    "kind": "testFile",
    "name": "test/src/lib/server/QueueStream.spec.js",
    "content": "import { StatusCodes } from 'node-opcua';\nimport { spy, stub } from 'sinon';\nimport expect from '../../../expect';\nimport QueueStream from '../../../../src/lib/server/QueueStream';\n\nfunction fakeQueueStream(\n  err = null,\n  status = StatusCodes.Good,\n  onSuccess = (done) => done(),\n  options = {}\n) {\n  return new (class FakeQueueStream extends QueueStream {\n    processErrorMessage(chunk) {\n      return `Error processing ${chunk}`;\n    }\n    processChunk(chunk, handle) {\n      handle(err, status, onSuccess);\n    }\n  })(options);\n}\n\n/** @test {QueueStream} */\ndescribe('QueueStream', function () {\n  /** @test {QueueStream#constructor} */\n  describe('#constructor', function () {\n    it('should work without options', function () {\n      expect(() => new QueueStream(), 'not to throw');\n    });\n\n    it('should store maxParallel option', function () {\n      expect(new QueueStream({ maxParallel: 99 })._maxParallel, 'to equal', 99);\n    });\n\n    it('should store start date', function () {\n      expect(new QueueStream()._start, 'to be a', 'number');\n    });\n\n    it('should listen for processed-chunk events', function () {\n      expect(new QueueStream().listenerCount('processed-chunk'), 'to be', 1);\n    });\n  });\n\n  /** @test {QueueStream#hasPending} */\n  describe('#hasPending', function () {\n    it('should return true if there are queued operations', function () {\n      const stream = new QueueStream();\n      stream._queued.push({});\n\n      expect(stream.hasPending, 'to be', true);\n    });\n\n    it('should return true if there are running operations', function () {\n      const stream = new QueueStream();\n      stream._processing = 1;\n\n      expect(stream.hasPending, 'to be', true);\n    });\n\n    it('should return false otherwise', function () {\n      expect(new QueueStream().hasPending, 'to be', false);\n    });\n  });\n\n  /** @test {QueueStream#queueEmpty} */\n  describe('#queueEmpty', function () {\n    it('should return true if not operations are queued', function () {\n      expect(new QueueStream().queueEmpty, 'to be', true);\n    });\n\n    it('should return false if there are queued operations', function () {\n      const stream = new QueueStream();\n      stream._queued.push({});\n\n      expect(stream.queueEmpty, 'to be', false);\n    });\n  });\n\n  /** @test {QueueStream#processed} */\n  describe('#processed', function () {\n    it('should return the number of processed items', function () {\n      const stream = new QueueStream();\n      stream._processed = 13;\n\n      expect(stream.processed, 'to equal', 13);\n    });\n  });\n\n  /** @test {QueueStream#opsPerSecond} */\n  describe('#opsPerSecond', function () {\n    it('should return 0 right after creating the stream', function () {\n      expect(new QueueStream().opsPerSecond, 'to be', 0);\n    });\n\n    it('should return the number of processed items after one second', function () {\n      const stream = new QueueStream();\n      stream._start -= 1000;\n      stream._processed = 13;\n\n      expect(stream.opsPerSecond, 'to be close to', 13, 0.5);\n    });\n  });\n\n  /** @test {QueueStream#processErrorMessage} */\n  describe('#processErrorMessage', function () {\n    it('should throw if not overridden', function () {\n      expect(() => new QueueStream().processErrorMessage({}), 'to throw', /must be implemented/);\n    });\n  });\n\n  /** @test {QueueStream#processChunk} */\n  describe('#processChunk', function () {\n    it('should throw if not overridden', function () {\n      expect(\n        (cb) => new QueueStream().processChunk({}, cb),\n        'to call the callback with error',\n        /must be implemented/\n      );\n    });\n  });\n\n  /** @test {QueueStream#_processChunk} */\n  describe('#_processChunk', function () {\n    it('should increase #_processing', function () {\n      const stream = fakeQueueStream();\n\n      expect(stream._processing, 'to equal', 0);\n      stream._processChunk('item');\n      expect(stream._processing, 'to equal', 0);\n    });\n\n    it('should emit processed-chunk event', function () {\n      const stream = fakeQueueStream();\n      const listener = spy();\n      stream.on('processed-chunk', listener);\n\n      stream._processChunk('item');\n      expect(listener, 'was called once');\n      expect(listener.lastCall.args[0], 'to equal', 'item');\n    });\n\n    it('should emit errors', function () {\n      const stream = fakeQueueStream(new Error('Test'));\n      const listener = spy();\n      stream.on('error', listener);\n\n      stream._processChunk('item');\n      expect(listener, 'was called once');\n      expect(listener.lastCall, 'to satisfy', [/Error processing item: Test/]);\n    });\n\n    it('should emit error on invalid status', function () {\n      const stream = fakeQueueStream(null, StatusCodes.BadAggregateInvalidInputs);\n\n      const listener = spy();\n      stream.on('error', listener);\n\n      stream._processChunk('item');\n      expect(listener, 'was called once');\n      expect(listener.lastCall, 'to satisfy', [/invalid data inputs/]);\n    });\n  });\n\n  /** @test {QueueStream#_enqueueChunk} */\n  describe('#_enqueueChunk', function () {\n    it('should call _processChunk if allowed', function () {\n      const stream = fakeQueueStream();\n      stub(stream, '_processChunk');\n\n      stream._enqueueChunk('item');\n      expect(stream._processChunk, 'was called once');\n      expect(stream._processChunk.lastCall, 'to satisfy', ['item']);\n    });\n\n    it('should add chunk to queue if maxParallel is reached', function () {\n      const stream = fakeQueueStream();\n      stream._processing = stream._maxParallel;\n\n      stream._enqueueChunk('item');\n      expect(stream._queued, 'to have length', 1);\n      expect(stream._queued, 'to contain', 'item');\n    });\n  });\n\n  /** @test {QueueStream#_transform} */\n  describe('#_transform', function () {\n    it('should wait for session to open', function () {\n      const stream = fakeQueueStream();\n      stub(stream, '_enqueueChunk');\n\n      stream._transform('item', 'utf8', () => {});\n      expect(stream._enqueueChunk, 'was not called');\n    });\n\n    it('should enqueue item once session is open', function (done) {\n      const stream = fakeQueueStream();\n      stub(stream, '_enqueueChunk');\n\n      stream.once('session-open', () => {\n        stream._transform('item', 'utf8', () => {});\n        expect(stream._enqueueChunk, 'was called once');\n        expect(stream._enqueueChunk.lastCall, 'to satisfy', ['item']);\n        done();\n      });\n    });\n  });\n\n  /** @test {QueueStream#_flush} */\n  describe('#_flush', function () {\n    it('should wait for queue to drain', function () {\n      const stream = fakeQueueStream();\n      stream._processing = 1;\n      const listener = spy();\n      stream._flush(listener);\n\n      expect(listener, 'was not called');\n\n      stream.emit('drained');\n      expect(listener, 'was called once');\n    });\n\n    it('should flush instantly if queue is empty', function () {\n      const stream = fakeQueueStream();\n      const listener = spy();\n      stream._flush(listener);\n\n      expect(listener, 'was called once');\n    });\n  });\n\n  context('when chunk has been processed', function () {\n    context('and queue is empty', function () {\n      it('should emit drained if not processing any items', function () {\n        const stream = new QueueStream();\n        const listener = spy();\n        stream.on('drained', listener);\n\n        stream.emit('processed-chunk');\n        expect(listener, 'was called once');\n      });\n\n      it('should not emit drained if processing an items', function () {\n        const stream = new QueueStream();\n        stream._processing = 1;\n        const listener = spy();\n        stream.on('drained', listener);\n\n        stream.emit('processed-chunk');\n        expect(listener, 'was not called');\n      });\n    });\n\n    context('and queue is not empty', function () {\n      it('should call _processChunk with queued chunk', function () {\n        const stream = new QueueStream();\n        const item = {};\n        stub(stream, '_processChunk');\n        stream._queued = [item];\n\n        stream.emit('processed-chunk');\n        expect(stream._processChunk, 'was called once');\n        expect(stream._processChunk, 'was called with', item);\n      });\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/server/QueueStream.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1038,
    "kind": "test",
    "name": "describe329",
    "testId": 329,
    "memberof": "test/src/lib/server/QueueStream.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329",
    "access": null,
    "description": "QueueStream",
    "lineNumber": 23,
    "testTargets": [
      "QueueStream"
    ]
  },
  {
    "__docId__": 1039,
    "kind": "test",
    "name": "describe330",
    "testId": 330,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe330",
    "access": null,
    "description": "#constructor",
    "lineNumber": 25,
    "testTargets": [
      "QueueStream#constructor"
    ]
  },
  {
    "__docId__": 1040,
    "kind": "test",
    "name": "it331",
    "testId": 331,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe330",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe330.it331",
    "access": null,
    "description": "should work without options",
    "lineNumber": 26
  },
  {
    "__docId__": 1041,
    "kind": "test",
    "name": "it332",
    "testId": 332,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe330",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe330.it332",
    "access": null,
    "description": "should store maxParallel option",
    "lineNumber": 30
  },
  {
    "__docId__": 1042,
    "kind": "test",
    "name": "it333",
    "testId": 333,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe330",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe330.it333",
    "access": null,
    "description": "should store start date",
    "lineNumber": 34
  },
  {
    "__docId__": 1043,
    "kind": "test",
    "name": "it334",
    "testId": 334,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe330",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe330.it334",
    "access": null,
    "description": "should listen for processed-chunk events",
    "lineNumber": 38
  },
  {
    "__docId__": 1044,
    "kind": "test",
    "name": "describe335",
    "testId": 335,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe335",
    "access": null,
    "description": "#hasPending",
    "lineNumber": 44,
    "testTargets": [
      "QueueStream#hasPending"
    ]
  },
  {
    "__docId__": 1045,
    "kind": "test",
    "name": "it336",
    "testId": 336,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe335",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe335.it336",
    "access": null,
    "description": "should return true if there are queued operations",
    "lineNumber": 45
  },
  {
    "__docId__": 1046,
    "kind": "test",
    "name": "it337",
    "testId": 337,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe335",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe335.it337",
    "access": null,
    "description": "should return true if there are running operations",
    "lineNumber": 52
  },
  {
    "__docId__": 1047,
    "kind": "test",
    "name": "it338",
    "testId": 338,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe335",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe335.it338",
    "access": null,
    "description": "should return false otherwise",
    "lineNumber": 59
  },
  {
    "__docId__": 1048,
    "kind": "test",
    "name": "describe339",
    "testId": 339,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe339",
    "access": null,
    "description": "#queueEmpty",
    "lineNumber": 65,
    "testTargets": [
      "QueueStream#queueEmpty"
    ]
  },
  {
    "__docId__": 1049,
    "kind": "test",
    "name": "it340",
    "testId": 340,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe339",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe339.it340",
    "access": null,
    "description": "should return true if not operations are queued",
    "lineNumber": 66
  },
  {
    "__docId__": 1050,
    "kind": "test",
    "name": "it341",
    "testId": 341,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe339",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe339.it341",
    "access": null,
    "description": "should return false if there are queued operations",
    "lineNumber": 70
  },
  {
    "__docId__": 1051,
    "kind": "test",
    "name": "describe342",
    "testId": 342,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe342",
    "access": null,
    "description": "#processed",
    "lineNumber": 79,
    "testTargets": [
      "QueueStream#processed"
    ]
  },
  {
    "__docId__": 1052,
    "kind": "test",
    "name": "it343",
    "testId": 343,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe342",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe342.it343",
    "access": null,
    "description": "should return the number of processed items",
    "lineNumber": 80
  },
  {
    "__docId__": 1053,
    "kind": "test",
    "name": "describe344",
    "testId": 344,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe344",
    "access": null,
    "description": "#opsPerSecond",
    "lineNumber": 89,
    "testTargets": [
      "QueueStream#opsPerSecond"
    ]
  },
  {
    "__docId__": 1054,
    "kind": "test",
    "name": "it345",
    "testId": 345,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe344",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe344.it345",
    "access": null,
    "description": "should return 0 right after creating the stream",
    "lineNumber": 90
  },
  {
    "__docId__": 1055,
    "kind": "test",
    "name": "it346",
    "testId": 346,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe344",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe344.it346",
    "access": null,
    "description": "should return the number of processed items after one second",
    "lineNumber": 94
  },
  {
    "__docId__": 1056,
    "kind": "test",
    "name": "describe347",
    "testId": 347,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe347",
    "access": null,
    "description": "#processErrorMessage",
    "lineNumber": 104,
    "testTargets": [
      "QueueStream#processErrorMessage"
    ]
  },
  {
    "__docId__": 1057,
    "kind": "test",
    "name": "it348",
    "testId": 348,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe347",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe347.it348",
    "access": null,
    "description": "should throw if not overridden",
    "lineNumber": 105
  },
  {
    "__docId__": 1058,
    "kind": "test",
    "name": "describe349",
    "testId": 349,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe349",
    "access": null,
    "description": "#processChunk",
    "lineNumber": 111,
    "testTargets": [
      "QueueStream#processChunk"
    ]
  },
  {
    "__docId__": 1059,
    "kind": "test",
    "name": "it350",
    "testId": 350,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe349",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe349.it350",
    "access": null,
    "description": "should throw if not overridden",
    "lineNumber": 112
  },
  {
    "__docId__": 1060,
    "kind": "test",
    "name": "describe351",
    "testId": 351,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe351",
    "access": null,
    "description": "#_processChunk",
    "lineNumber": 122,
    "testTargets": [
      "QueueStream#_processChunk"
    ]
  },
  {
    "__docId__": 1061,
    "kind": "test",
    "name": "it352",
    "testId": 352,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe351",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe351.it352",
    "access": null,
    "description": "should increase #_processing",
    "lineNumber": 123
  },
  {
    "__docId__": 1062,
    "kind": "test",
    "name": "it353",
    "testId": 353,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe351",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe351.it353",
    "access": null,
    "description": "should emit processed-chunk event",
    "lineNumber": 131
  },
  {
    "__docId__": 1063,
    "kind": "test",
    "name": "it354",
    "testId": 354,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe351",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe351.it354",
    "access": null,
    "description": "should emit errors",
    "lineNumber": 141
  },
  {
    "__docId__": 1064,
    "kind": "test",
    "name": "it355",
    "testId": 355,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe351",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe351.it355",
    "access": null,
    "description": "should emit error on invalid status",
    "lineNumber": 151
  },
  {
    "__docId__": 1065,
    "kind": "test",
    "name": "describe356",
    "testId": 356,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe356",
    "access": null,
    "description": "#_enqueueChunk",
    "lineNumber": 164,
    "testTargets": [
      "QueueStream#_enqueueChunk"
    ]
  },
  {
    "__docId__": 1066,
    "kind": "test",
    "name": "it357",
    "testId": 357,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe356",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe356.it357",
    "access": null,
    "description": "should call _processChunk if allowed",
    "lineNumber": 165
  },
  {
    "__docId__": 1067,
    "kind": "test",
    "name": "it358",
    "testId": 358,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe356",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe356.it358",
    "access": null,
    "description": "should add chunk to queue if maxParallel is reached",
    "lineNumber": 174
  },
  {
    "__docId__": 1068,
    "kind": "test",
    "name": "describe359",
    "testId": 359,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe359",
    "access": null,
    "description": "#_transform",
    "lineNumber": 185,
    "testTargets": [
      "QueueStream#_transform"
    ]
  },
  {
    "__docId__": 1069,
    "kind": "test",
    "name": "it360",
    "testId": 360,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe359",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe359.it360",
    "access": null,
    "description": "should wait for session to open",
    "lineNumber": 186
  },
  {
    "__docId__": 1070,
    "kind": "test",
    "name": "it361",
    "testId": 361,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe359",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe359.it361",
    "access": null,
    "description": "should enqueue item once session is open",
    "lineNumber": 194
  },
  {
    "__docId__": 1071,
    "kind": "test",
    "name": "describe362",
    "testId": 362,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe362",
    "access": null,
    "description": "#_flush",
    "lineNumber": 208,
    "testTargets": [
      "QueueStream#_flush"
    ]
  },
  {
    "__docId__": 1072,
    "kind": "test",
    "name": "it363",
    "testId": 363,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe362",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe362.it363",
    "access": null,
    "description": "should wait for queue to drain",
    "lineNumber": 209
  },
  {
    "__docId__": 1073,
    "kind": "test",
    "name": "it364",
    "testId": 364,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.describe362",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.describe362.it364",
    "access": null,
    "description": "should flush instantly if queue is empty",
    "lineNumber": 221
  },
  {
    "__docId__": 1074,
    "kind": "test",
    "name": "context365",
    "testId": 365,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.context365",
    "access": null,
    "description": "when chunk has been processed",
    "lineNumber": 230
  },
  {
    "__docId__": 1075,
    "kind": "test",
    "name": "context366",
    "testId": 366,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.context365",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.context365.context366",
    "access": null,
    "description": "and queue is empty",
    "lineNumber": 231
  },
  {
    "__docId__": 1076,
    "kind": "test",
    "name": "it367",
    "testId": 367,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.context365.context366",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.context365.context366.it367",
    "access": null,
    "description": "should emit drained if not processing any items",
    "lineNumber": 232
  },
  {
    "__docId__": 1077,
    "kind": "test",
    "name": "it368",
    "testId": 368,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.context365.context366",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.context365.context366.it368",
    "access": null,
    "description": "should not emit drained if processing an items",
    "lineNumber": 241
  },
  {
    "__docId__": 1078,
    "kind": "test",
    "name": "context369",
    "testId": 369,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.context365",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.context365.context369",
    "access": null,
    "description": "and queue is not empty",
    "lineNumber": 252
  },
  {
    "__docId__": 1079,
    "kind": "test",
    "name": "it370",
    "testId": 370,
    "memberof": "test/src/lib/server/QueueStream.spec.js~describe329.context365.context369",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/QueueStream.spec.js~describe329.context365.context369.it370",
    "access": null,
    "description": "should call _processChunk with queued chunk",
    "lineNumber": 253
  },
  {
    "__docId__": 1080,
    "kind": "testFile",
    "name": "test/src/lib/server/Session.spec.js",
    "content": "import { spy } from 'sinon';\nimport proxyquire from 'proxyquire';\nimport { StatusCodes } from 'node-opcua';\nimport { ClientSession, OPCUAClient } from 'node-opcua/lib/client/opcua_client';\nimport Logger from 'gulplog';\nimport expect from '../../../expect';\nimport Session from '../../../../src/lib/server/Session';\nimport ProjectConfig from '../../../../src/config/ProjectConfig';\n\nfunction sessionWithLogin(login) {\n  return proxyquire('../../../../src/lib/server/Session', {\n    '../../config/ProjectConfig': {\n      default: {\n        host: ProjectConfig.host,\n        port: ProjectConfig.port,\n        login,\n        timeout: ProjectConfig.timeout,\n      },\n    },\n  }).default;\n}\n\nconst FailingClientSession = proxyquire('../../../../src/lib/server/Session', {\n  'node-opcua/lib/client/opcua_client': {\n    OPCUAClient: class StubClient {\n      connect(endpoint, cb) {\n        cb(new Error('Client.create error'));\n      }\n    },\n  },\n}).default;\n\nconst FailingSession = proxyquire('../../../../src/lib/server/Session', {\n  'node-opcua/lib/client/opcua_client': {\n    OPCUAClient: class StubClient extends OPCUAClient {\n      createSession(login, callback) {\n        callback(new Error('Client.createSession error'));\n      }\n    },\n  },\n}).default;\n\n/** @test {Session} */\ndescribe('Session', function () {\n  /** @test {Session.create} */\n  describe('.create', function () {\n    it('should create a new ClientSession', function () {\n      return expect(Session.create(), 'to be fulfilled')\n        .then((session) => {\n          expect(session, 'to be a', ClientSession);\n          return session;\n        })\n        .then((session) => Session.close(session));\n    });\n\n    it('should store newly created session', function () {\n      return expect(Session.create(), 'to be fulfilled')\n        .then((session) => {\n          expect(Session.open, 'to contain', session);\n          return session;\n        })\n        .then((session) => Session.close(session));\n    });\n\n    it('should fail with invalid credentials', function () {\n      return Promise.all([\n        // Missing username\n        expect(\n          sessionWithLogin({\n            username: false,\n            password: 'invalid password',\n          }).create(),\n          'to be rejected with',\n          /Invalid login/\n        ),\n\n        // Missing password\n        expect(\n          sessionWithLogin({\n            username: 'invalid username',\n            password: false,\n          }).create(),\n          'to be rejected with',\n          /Invalid login/\n        ),\n\n        // Invalid credentials\n        expect(\n          sessionWithLogin({\n            username: 'invalid username',\n            password: 'invalid password',\n          }).create(),\n          'to be rejected with',\n          /Invalid login/\n        ),\n      ]);\n    });\n\n    it('should forward Client.create errors', function () {\n      return expect(FailingClientSession.create(), 'to be rejected with', 'Client.create error');\n    });\n\n    it('should forward non-login errors', function () {\n      return expect(FailingSession.create(), 'to be rejected with', /Client\\.createSession error/);\n    });\n  });\n\n  /** @test {Session.close} */\n  describe('.close', function () {\n    it('should fail without session', function () {\n      return expect(() => Session.close(), 'to be rejected with', 'session is required');\n    });\n\n    it('should return if session is already closed', function () {\n      return expect(Session.create(), 'to be fulfilled')\n        .then((session) => expect(Session.close(session), 'to be fulfilled'))\n        .then((session) => expect(Session.close(session), 'to be fulfilled'));\n    });\n\n    it('should wait for session to close if already closing', function () {\n      return expect(Session.create(), 'to be fulfilled')\n        .then((session) => {\n          spy(session, 'close');\n          return session;\n        })\n        .then((session) =>\n          expect(Promise.all([Session.close(session), Session.close(session)]), 'to be fulfilled')\n        )\n        .then((sessions) => {\n          expect(sessions, 'to have length', 2);\n        });\n    });\n\n    it.skip('should warn if session does not exist', function () {\n      const logListener = spy();\n      Logger.on('debug', logListener);\n\n      const session = new ClientSession();\n      session._client = {\n        closeSession(sess, del, callback) {\n          const err = new Error();\n          err.response = {\n            responseHeader: {\n              serviceResult: StatusCodes.BadSessionIdInvalid,\n            },\n          };\n\n          callback(err);\n        },\n      };\n\n      return expect(Session.close(session), 'to be fulfilled').then(() => {\n        expect(logListener, 'was called once');\n        expect(logListener.lastCall, 'to satisfy', [/close a session that does not exist/]);\n      });\n    });\n\n    it('should do nothing if client is not connected', function () {\n      return expect(Session.create(), 'to be fulfilled')\n        .then(\n          (session) =>\n            new Promise((resolve, reject) => {\n              session._client.disconnect((err) => {\n                if (err) {\n                  reject(err);\n                } else {\n                  resolve(session);\n                }\n              });\n            })\n        )\n        .then((session) => expect(Session.close(session), 'to be fulfilled'));\n    });\n\n    it('should ignore errors closing session', function () {\n      const session = new ClientSession();\n      session._client = {\n        closeSession(sess, del, callback) {\n          callback(new Error('Test error'));\n        },\n        disconnect(cb) {\n          cb();\n        },\n      };\n\n      return expect(Session.close(session), 'to be fulfilled');\n    });\n\n    it('should ignore errors disconnecting client', function () {\n      const session = new ClientSession();\n      session._client = {\n        closeSession(sess, del, callback) {\n          callback(null);\n        },\n        disconnect(callback) {\n          callback(new Error('Test client error'));\n        },\n      };\n\n      return expect(Session.close(session), 'to be fulfilled');\n    });\n  });\n\n  /** @test {Session.closeOpen} */\n  describe('.closeOpen', function () {\n    it('should return if no sessions are open', function () {\n      return expect(Session.closeOpen(), 'to be fulfilled with', []);\n    });\n\n    it('should close open sessions', function () {\n      expect(Session.open, 'to have length', 0);\n      return expect(Session.create(), 'to be fulfilled').then((session) =>\n        expect(Session.closeOpen(), 'to be fulfilled with', [session])\n      );\n    });\n\n    it('should wait for opening sessions to open before closing', function () {\n      let session;\n      Session.create().then((sess) => (session = sess));\n\n      return expect(Session.closeOpen(), 'to be fulfilled').then((sessions) => {\n        expect(sessions, 'to equal', [session]);\n      });\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/server/Session.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1081,
    "kind": "test",
    "name": "describe371",
    "testId": 371,
    "memberof": "test/src/lib/server/Session.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371",
    "access": null,
    "description": "Session",
    "lineNumber": 44,
    "testTargets": [
      "Session"
    ]
  },
  {
    "__docId__": 1082,
    "kind": "test",
    "name": "describe372",
    "testId": 372,
    "memberof": "test/src/lib/server/Session.spec.js~describe371",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371.describe372",
    "access": null,
    "description": ".create",
    "lineNumber": 46,
    "testTargets": [
      "Session.create"
    ]
  },
  {
    "__docId__": 1083,
    "kind": "test",
    "name": "it373",
    "testId": 373,
    "memberof": "test/src/lib/server/Session.spec.js~describe371.describe372",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371.describe372.it373",
    "access": null,
    "description": "should create a new ClientSession",
    "lineNumber": 47
  },
  {
    "__docId__": 1084,
    "kind": "test",
    "name": "it374",
    "testId": 374,
    "memberof": "test/src/lib/server/Session.spec.js~describe371.describe372",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371.describe372.it374",
    "access": null,
    "description": "should store newly created session",
    "lineNumber": 56
  },
  {
    "__docId__": 1085,
    "kind": "test",
    "name": "it375",
    "testId": 375,
    "memberof": "test/src/lib/server/Session.spec.js~describe371.describe372",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371.describe372.it375",
    "access": null,
    "description": "should fail with invalid credentials",
    "lineNumber": 65
  },
  {
    "__docId__": 1086,
    "kind": "test",
    "name": "it376",
    "testId": 376,
    "memberof": "test/src/lib/server/Session.spec.js~describe371.describe372",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371.describe372.it376",
    "access": null,
    "description": "should forward Client.create errors",
    "lineNumber": 99
  },
  {
    "__docId__": 1087,
    "kind": "test",
    "name": "it377",
    "testId": 377,
    "memberof": "test/src/lib/server/Session.spec.js~describe371.describe372",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371.describe372.it377",
    "access": null,
    "description": "should forward non-login errors",
    "lineNumber": 103
  },
  {
    "__docId__": 1088,
    "kind": "test",
    "name": "describe378",
    "testId": 378,
    "memberof": "test/src/lib/server/Session.spec.js~describe371",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371.describe378",
    "access": null,
    "description": ".close",
    "lineNumber": 109,
    "testTargets": [
      "Session.close"
    ]
  },
  {
    "__docId__": 1089,
    "kind": "test",
    "name": "it379",
    "testId": 379,
    "memberof": "test/src/lib/server/Session.spec.js~describe371.describe378",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371.describe378.it379",
    "access": null,
    "description": "should fail without session",
    "lineNumber": 110
  },
  {
    "__docId__": 1090,
    "kind": "test",
    "name": "it380",
    "testId": 380,
    "memberof": "test/src/lib/server/Session.spec.js~describe371.describe378",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371.describe378.it380",
    "access": null,
    "description": "should return if session is already closed",
    "lineNumber": 114
  },
  {
    "__docId__": 1091,
    "kind": "test",
    "name": "it381",
    "testId": 381,
    "memberof": "test/src/lib/server/Session.spec.js~describe371.describe378",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371.describe378.it381",
    "access": null,
    "description": "should wait for session to close if already closing",
    "lineNumber": 120
  },
  {
    "__docId__": 1092,
    "kind": "test",
    "name": "it382",
    "testId": 382,
    "memberof": "test/src/lib/server/Session.spec.js~describe371.describe378",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371.describe378.it382",
    "access": null,
    "description": "should do nothing if client is not connected",
    "lineNumber": 158
  },
  {
    "__docId__": 1093,
    "kind": "test",
    "name": "it383",
    "testId": 383,
    "memberof": "test/src/lib/server/Session.spec.js~describe371.describe378",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371.describe378.it383",
    "access": null,
    "description": "should ignore errors closing session",
    "lineNumber": 175
  },
  {
    "__docId__": 1094,
    "kind": "test",
    "name": "it384",
    "testId": 384,
    "memberof": "test/src/lib/server/Session.spec.js~describe371.describe378",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371.describe378.it384",
    "access": null,
    "description": "should ignore errors disconnecting client",
    "lineNumber": 189
  },
  {
    "__docId__": 1095,
    "kind": "test",
    "name": "describe385",
    "testId": 385,
    "memberof": "test/src/lib/server/Session.spec.js~describe371",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371.describe385",
    "access": null,
    "description": ".closeOpen",
    "lineNumber": 205,
    "testTargets": [
      "Session.closeOpen"
    ]
  },
  {
    "__docId__": 1096,
    "kind": "test",
    "name": "it386",
    "testId": 386,
    "memberof": "test/src/lib/server/Session.spec.js~describe371.describe385",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371.describe385.it386",
    "access": null,
    "description": "should return if no sessions are open",
    "lineNumber": 206
  },
  {
    "__docId__": 1097,
    "kind": "test",
    "name": "it387",
    "testId": 387,
    "memberof": "test/src/lib/server/Session.spec.js~describe371.describe385",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371.describe385.it387",
    "access": null,
    "description": "should close open sessions",
    "lineNumber": 210
  },
  {
    "__docId__": 1098,
    "kind": "test",
    "name": "it388",
    "testId": 388,
    "memberof": "test/src/lib/server/Session.spec.js~describe371.describe385",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Session.spec.js~describe371.describe385.it388",
    "access": null,
    "description": "should wait for opening sessions to open before closing",
    "lineNumber": 217
  },
  {
    "__docId__": 1099,
    "kind": "testFile",
    "name": "test/src/lib/server/Stream.spec.js",
    "content": "import { Stream as CoreStream } from 'stream';\nimport proxyquire from 'proxyquire';\nimport { spy } from 'sinon';\nimport { ClientSession } from 'node-opcua';\nimport expect from '../../../expect';\nimport Stream from '../../../../src/lib/server/Stream';\nimport Session from '../../../../src/lib/server/Session';\n\n/** @test {Stream} */\ndescribe('Stream', function () {\n  /** @test {Stream#constructor} */\n  describe('#constructor', function () {\n    it('should return a stream', function () {\n      expect(new Stream(), 'to be a', CoreStream);\n    });\n\n    it('should emit \"session-open\" once session is open', function (done) {\n      const stream = new Stream();\n\n      stream.on('session-open', (session) => {\n        expect(stream.session, 'to be defined');\n        expect(stream.session, 'to be a', ClientSession);\n        expect(session, 'to be', stream.session);\n\n        done();\n      });\n    });\n\n    it('should forward session connect errors', function (done) {\n      const FailingStream = proxyquire('../../../../src/lib/server/Stream', {\n        './Session': {\n          _esModule: true,\n          default: class FailingSession {\n            static create() {\n              return Promise.reject(new Error('Failed'));\n            }\n          },\n        },\n      }).default;\n\n      new FailingStream().on('error', (err) => {\n        expect(err, 'to have message', 'Failed');\n        done();\n      });\n    });\n\n    it('should close session on end', function () {\n      const stream = new Stream();\n\n      stream.once('session-open', () => {\n        spy(Session, 'close');\n\n        stream.end();\n      });\n\n      return expect(stream, 'to yield objects satisfying', 'to have length', 0).then(() => {\n        expect(Session.close, 'was called once');\n      });\n    });\n\n    it('should be endable even if session was not opened yet', function (done) {\n      const stream = new Stream();\n      const listener = spy();\n\n      stream\n        .on('error', listener)\n        .on('end', () => {\n          expect(listener.callCount, 'to equal', 0);\n          done();\n        })\n        .on('data', () => {}); // unpause readable stream\n\n      stream.end();\n    });\n\n    it('should forward errors occurring while closing session', function (done) {\n      const FailingStream = proxyquire('../../../../src/lib/server/Stream', {\n        './Session': {\n          _esModule: true,\n          default: class FailingStream extends Session {\n            static close() {\n              return Promise.reject(new Error('Failed'));\n            }\n          },\n        },\n      }).default;\n\n      const stream = new FailingStream()\n        .on('error', (err) => {\n          expect(err, 'to have message', 'Failed');\n          done();\n        })\n        .on('data', () => {}) // unpause readable stream\n        .once('session-open', () => stream.end());\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/server/Stream.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1100,
    "kind": "test",
    "name": "describe389",
    "testId": 389,
    "memberof": "test/src/lib/server/Stream.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/Stream.spec.js~describe389",
    "access": null,
    "description": "Stream",
    "lineNumber": 10,
    "testTargets": [
      "Stream"
    ]
  },
  {
    "__docId__": 1101,
    "kind": "test",
    "name": "describe390",
    "testId": 390,
    "memberof": "test/src/lib/server/Stream.spec.js~describe389",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Stream.spec.js~describe389.describe390",
    "access": null,
    "description": "#constructor",
    "lineNumber": 12,
    "testTargets": [
      "Stream#constructor"
    ]
  },
  {
    "__docId__": 1102,
    "kind": "test",
    "name": "it391",
    "testId": 391,
    "memberof": "test/src/lib/server/Stream.spec.js~describe389.describe390",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Stream.spec.js~describe389.describe390.it391",
    "access": null,
    "description": "should return a stream",
    "lineNumber": 13
  },
  {
    "__docId__": 1103,
    "kind": "test",
    "name": "it392",
    "testId": 392,
    "memberof": "test/src/lib/server/Stream.spec.js~describe389.describe390",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Stream.spec.js~describe389.describe390.it392",
    "access": null,
    "description": "should emit \"session-open\" once session is open",
    "lineNumber": 17
  },
  {
    "__docId__": 1104,
    "kind": "test",
    "name": "it393",
    "testId": 393,
    "memberof": "test/src/lib/server/Stream.spec.js~describe389.describe390",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Stream.spec.js~describe389.describe390.it393",
    "access": null,
    "description": "should forward session connect errors",
    "lineNumber": 29
  },
  {
    "__docId__": 1105,
    "kind": "test",
    "name": "it394",
    "testId": 394,
    "memberof": "test/src/lib/server/Stream.spec.js~describe389.describe390",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Stream.spec.js~describe389.describe390.it394",
    "access": null,
    "description": "should close session on end",
    "lineNumber": 47
  },
  {
    "__docId__": 1106,
    "kind": "test",
    "name": "it395",
    "testId": 395,
    "memberof": "test/src/lib/server/Stream.spec.js~describe389.describe390",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Stream.spec.js~describe389.describe390.it395",
    "access": null,
    "description": "should be endable even if session was not opened yet",
    "lineNumber": 61
  },
  {
    "__docId__": 1107,
    "kind": "test",
    "name": "it396",
    "testId": 396,
    "memberof": "test/src/lib/server/Stream.spec.js~describe389.describe390",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Stream.spec.js~describe389.describe390.it396",
    "access": null,
    "description": "should forward errors occurring while closing session",
    "lineNumber": 76
  },
  {
    "__docId__": 1108,
    "kind": "testFile",
    "name": "test/src/lib/server/WaitingStream.spec.js",
    "content": "import Emitter from 'events';\nimport { spy } from 'sinon';\nimport expect from '../../../expect';\nimport WaitingStream, { waitForDependencies } from '../../../../src/lib/server/WaitingStream';\nimport QueueStream from '../../../../src/lib/server/QueueStream';\nimport NodeId from '../../../../src/lib/model/opcua/NodeId';\n\nclass StubStream extends Emitter {\n  constructor() {\n    super();\n\n    this.spies = {\n      _enqueueChunk: spy(),\n      _flush: spy(),\n    };\n  }\n\n  _enqueueChunk(...args) {\n    this.spies._enqueueChunk(...args);\n    this.emit('processed-chunk', ...args);\n  }\n\n  _flush(callback) {\n    this.spies._flush(callback);\n\n    callback(null);\n  }\n}\n\nclass NoDeps extends waitForDependencies(StubStream) {\n  dependenciesFor() {\n    return [];\n  }\n}\n\nclass WithDeps extends waitForDependencies(StubStream) {\n  constructor(deps = [new NodeId('Testing')]) {\n    super();\n    this._deps = deps;\n  }\n\n  dependenciesFor() {\n    const deps = this._deps;\n\n    this._deps = [];\n\n    return deps;\n  }\n}\n\n/** @test {WaitingStream} */\ndescribe('WaitingStream', function () {\n  /** @test {WaitingStream#constructor} */\n  describe('#constructor', function () {\n    it('should return a QueueStream, mixed with waitForDependencies', function () {\n      const stream = new WaitingStream();\n\n      expect(stream, 'to be a', QueueStream);\n      expect(stream.dependenciesFor, 'to be defined');\n    });\n  });\n\n  /** @test {WaitingStream#dependenciesFor} */\n  describe('#dependenciesFor', function () {\n    it('should throw if not overridden', function () {\n      return expect(WaitingStream.prototype.dependenciesFor, 'to throw', /must be implemented/);\n    });\n  });\n\n  /** @test {WaitingStream#_enqueueChunk} */\n  describe('#_enqueueChunk', function () {\n    context('when a dependency-free file is pushed', function () {\n      it('should just call super', function () {\n        const stream = new NoDeps();\n        stream._enqueueChunk({ nodeId: new NodeId('chunk') });\n\n        return expect(stream.spies._enqueueChunk, 'was called once');\n      });\n    });\n\n    context('when a file with dependencies is pushed', function () {\n      it('should not call super', function () {\n        const stream = new WithDeps();\n        stream._enqueueChunk({ nodeId: new NodeId('Source') });\n\n        return expect(stream.spies._enqueueChunk, 'was not called');\n      });\n\n      it('should add it to the dependencies map', function () {\n        const stream = new WithDeps();\n        const chunk = { nodeId: new NodeId('Source') };\n        stream._enqueueChunk(chunk);\n\n        expect(stream._waitingFor['ns=1;s=Testing'], 'to be defined');\n        expect(stream._waitingFor['ns=1;s=Testing'], 'to have an item satisfying', 'to be', chunk);\n      });\n\n      it('should ignore system types', function () {\n        const stream = new WithDeps([new NodeId(NodeId.NodeIdType.STRING, 'System', 0)]);\n        stream._enqueueChunk({ nodeId: new NodeId('Source') });\n\n        expect(stream._waitingFor['ns=1;s=Testing'], 'to be undefined');\n        return expect(stream.spies._enqueueChunk, 'was called');\n      });\n\n      it('should ignore atserver types', function () {\n        const stream = new WithDeps([new NodeId('VariableTypes.ATVISE.Display')]);\n        stream._enqueueChunk({ nodeId: new NodeId('Source') });\n\n        expect(stream._waitingFor['ns=1;s=Testing'], 'to be undefined');\n        return expect(stream.spies._enqueueChunk, 'was called');\n      });\n\n      it('should ignore already processed nodes', function () {\n        const dep = new NodeId('TestDep');\n        const stream = new WithDeps([dep]);\n        stream._finishedProcessing[dep.toString()] = true;\n        stream._enqueueChunk({ nodeId: new NodeId('Source') });\n\n        expect(stream._waitingFor['ns=1;s=Testing'], 'to be undefined');\n        return expect(stream.spies._enqueueChunk, 'was called');\n      });\n\n      it('should process files once dependencies are finished', function (done) {\n        const dep = new NodeId('TestDep');\n        const dep2 = new NodeId('TestDep2');\n        const source = new NodeId('Source');\n        const stream = new WithDeps([dep, dep2]);\n\n        stream._enqueueChunk({ nodeId: source });\n        expect(stream.spies._enqueueChunk, 'was not called');\n\n        stream._enqueueChunk({ nodeId: dep });\n        expect(stream.spies._enqueueChunk, 'was called once');\n\n        stream.once('processed-chunk', async ({ nodeId }) => {\n          try {\n            await expect(nodeId, 'to be', source);\n            await expect(stream.spies._enqueueChunk, 'to have calls satisfying', [\n              { args: [{ nodeId: dep }] },\n              { args: [{ nodeId: dep2 }] },\n              { args: [{ nodeId: source }] },\n            ]);\n            done();\n          } catch (e) {\n            done(e);\n          }\n        });\n\n        stream._enqueueChunk({ nodeId: dep2 });\n      });\n    });\n  });\n\n  /** @test {WaitingStream#_flush} */\n  describe('#_flush', function () {\n    context('without pending operations', function () {\n      it('should call super', function () {\n        const stream = new NoDeps();\n        stream._flush(() => {});\n        return expect(stream.spies._flush, 'was called once');\n      });\n    });\n\n    context('with pending operations', function () {\n      it('should try to process dependents', function () {\n        const stream = new WithDeps([new NodeId('Dep')]);\n        stream._enqueueChunk({ nodeId: new NodeId('Depending') });\n\n        return expect((cb) => stream._flush(cb), 'to call the callback without error');\n      });\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/server/WaitingStream.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1109,
    "kind": "test",
    "name": "describe397",
    "testId": 397,
    "memberof": "test/src/lib/server/WaitingStream.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397",
    "access": null,
    "description": "WaitingStream",
    "lineNumber": 52,
    "testTargets": [
      "WaitingStream"
    ]
  },
  {
    "__docId__": 1110,
    "kind": "test",
    "name": "describe398",
    "testId": 398,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe398",
    "access": null,
    "description": "#constructor",
    "lineNumber": 54,
    "testTargets": [
      "WaitingStream#constructor"
    ]
  },
  {
    "__docId__": 1111,
    "kind": "test",
    "name": "it399",
    "testId": 399,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397.describe398",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe398.it399",
    "access": null,
    "description": "should return a QueueStream, mixed with waitForDependencies",
    "lineNumber": 55
  },
  {
    "__docId__": 1112,
    "kind": "test",
    "name": "describe400",
    "testId": 400,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe400",
    "access": null,
    "description": "#dependenciesFor",
    "lineNumber": 64,
    "testTargets": [
      "WaitingStream#dependenciesFor"
    ]
  },
  {
    "__docId__": 1113,
    "kind": "test",
    "name": "it401",
    "testId": 401,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397.describe400",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe400.it401",
    "access": null,
    "description": "should throw if not overridden",
    "lineNumber": 65
  },
  {
    "__docId__": 1114,
    "kind": "test",
    "name": "describe402",
    "testId": 402,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402",
    "access": null,
    "description": "#_enqueueChunk",
    "lineNumber": 71,
    "testTargets": [
      "WaitingStream#_enqueueChunk"
    ]
  },
  {
    "__docId__": 1115,
    "kind": "test",
    "name": "context403",
    "testId": 403,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402.context403",
    "access": null,
    "description": "when a dependency-free file is pushed",
    "lineNumber": 72
  },
  {
    "__docId__": 1116,
    "kind": "test",
    "name": "it404",
    "testId": 404,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402.context403",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402.context403.it404",
    "access": null,
    "description": "should just call super",
    "lineNumber": 73
  },
  {
    "__docId__": 1117,
    "kind": "test",
    "name": "context405",
    "testId": 405,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402.context405",
    "access": null,
    "description": "when a file with dependencies is pushed",
    "lineNumber": 81
  },
  {
    "__docId__": 1118,
    "kind": "test",
    "name": "it406",
    "testId": 406,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402.context405",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402.context405.it406",
    "access": null,
    "description": "should not call super",
    "lineNumber": 82
  },
  {
    "__docId__": 1119,
    "kind": "test",
    "name": "it407",
    "testId": 407,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402.context405",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402.context405.it407",
    "access": null,
    "description": "should add it to the dependencies map",
    "lineNumber": 89
  },
  {
    "__docId__": 1120,
    "kind": "test",
    "name": "it408",
    "testId": 408,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402.context405",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402.context405.it408",
    "access": null,
    "description": "should ignore system types",
    "lineNumber": 98
  },
  {
    "__docId__": 1121,
    "kind": "test",
    "name": "it409",
    "testId": 409,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402.context405",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402.context405.it409",
    "access": null,
    "description": "should ignore atserver types",
    "lineNumber": 106
  },
  {
    "__docId__": 1122,
    "kind": "test",
    "name": "it410",
    "testId": 410,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402.context405",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402.context405.it410",
    "access": null,
    "description": "should ignore already processed nodes",
    "lineNumber": 114
  },
  {
    "__docId__": 1123,
    "kind": "test",
    "name": "it411",
    "testId": 411,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402.context405",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe402.context405.it411",
    "access": null,
    "description": "should process files once dependencies are finished",
    "lineNumber": 124
  },
  {
    "__docId__": 1124,
    "kind": "test",
    "name": "describe412",
    "testId": 412,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe412",
    "access": null,
    "description": "#_flush",
    "lineNumber": 156,
    "testTargets": [
      "WaitingStream#_flush"
    ]
  },
  {
    "__docId__": 1125,
    "kind": "test",
    "name": "context413",
    "testId": 413,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397.describe412",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe412.context413",
    "access": null,
    "description": "without pending operations",
    "lineNumber": 157
  },
  {
    "__docId__": 1126,
    "kind": "test",
    "name": "it414",
    "testId": 414,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397.describe412.context413",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe412.context413.it414",
    "access": null,
    "description": "should call super",
    "lineNumber": 158
  },
  {
    "__docId__": 1127,
    "kind": "test",
    "name": "context415",
    "testId": 415,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397.describe412",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe412.context415",
    "access": null,
    "description": "with pending operations",
    "lineNumber": 165
  },
  {
    "__docId__": 1128,
    "kind": "test",
    "name": "it416",
    "testId": 416,
    "memberof": "test/src/lib/server/WaitingStream.spec.js~describe397.describe412.context415",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/WaitingStream.spec.js~describe397.describe412.context415.it416",
    "access": null,
    "description": "should try to process dependents",
    "lineNumber": 166
  },
  {
    "__docId__": 1129,
    "kind": "testFile",
    "name": "test/src/lib/server/Watcher.spec.js",
    "content": "import Emitter from 'events';\nimport { spy, stub } from 'sinon';\nimport proxyquire from 'proxyquire';\nimport { resolveNodeId, NodeClass } from 'node-opcua';\nimport { ctor as throughStreamClass } from 'through2';\nimport expect from '../../../expect';\nimport Watcher, { SubscribeStream } from '../../../../src/lib/server/Watcher';\n\nclass StubMonitoredItem extends Emitter {\n  constructor(error = false) {\n    super();\n\n    // Simulate first notification or error\n    setTimeout(() => this.emit(error ? 'err' : 'changed', error || {}), 10);\n  }\n}\n\nconst StubWatcher = proxyquire('../../../../src/lib/server/Watcher', {\n  './NodeStream': {\n    __esModule: true,\n    default: class ServerStream extends throughStreamClass({ objectMode: true }) {\n      constructor() {\n        super();\n\n        setTimeout(() => this.end(), 10);\n      }\n    },\n  },\n}).default;\n\nconst FailingSubscribeStream = proxyquire('../../../../src/lib/server/Watcher', {\n  'node-opcua/lib/client/client_subscription': {\n    ClientSubscription: class StubClientSubscription extends Emitter {\n      constructor() {\n        super();\n\n        this.monitor = spy(() => new StubMonitoredItem());\n\n        setTimeout(() => this.emit('failure', new Error('ClientSubscription failure')), 10);\n      }\n    },\n  },\n}).SubscribeStream;\n\n/** @test {SubscribeStream} */\ndescribe.skip('SubscribeStream', function () {\n  /** @test {SubscribeStream#constructor} */\n  describe('#constructor', function () {\n    it('should apply keepSessionAlive option', function () {\n      const stream = new SubscribeStream();\n      stream.end();\n\n      expect(stream._keepSessionAlive, 'to be', true);\n    });\n\n    it('should not track changes instantly', function () {\n      const stream = new SubscribeStream();\n      stream.end();\n\n      expect(new SubscribeStream()._trackChanges, 'to be', false);\n    });\n\n    context('once session is opened', function () {\n      it('should create subscription once session is opened', function (done) {\n        const stream = new SubscribeStream();\n        spy(stream, 'createSubscription');\n\n        stream.once('session-open', () => {\n          expect(stream.createSubscription, 'was called once');\n          done();\n        });\n      });\n    });\n  });\n\n  /** @test {SubscribeStream#createSubscription} */\n  describe('#createSubscription', function () {\n    it('should forward errors while creating subscription', function () {\n      const stream = new FailingSubscribeStream();\n\n      return expect(stream, 'to error with', /ClientSubscription failure/);\n    });\n\n    it('should emit `subscription-started`', function (done) {\n      const stream = new SubscribeStream();\n\n      stream.on('subscription-started', () => done());\n    });\n\n    it('should set subscription property', function (done) {\n      const stream = new SubscribeStream();\n\n      stream.on('subscription-started', (subscription) => {\n        expect(stream.subscription, 'to be defined');\n        expect(stream.subscription, 'to be', subscription);\n        done();\n      });\n    });\n  });\n\n  /** @test {SubscribeStream#processErrorMessage} */\n  describe('#processErrorMessage', function () {\n    it('should contain node id', function () {\n      const nodeId = resolveNodeId('ns=1;s=AGENT.DISPLAYS.Main');\n      expect(\n        SubscribeStream.prototype.processErrorMessage({ nodeId }),\n        'to contain',\n        nodeId.toString()\n      );\n    });\n  });\n\n  /** @test {SubscribeStream#processChunk} */\n  describe('#processChunk', function () {\n    it('should call ClientSubscription#monitor', function () {\n      const stream = new SubscribeStream();\n      const nodeId = resolveNodeId('ns=1;s=AGENT.DISPLAYS.Main');\n\n      stream.once('subscription-started', (subscription) => {\n        stub(subscription, 'monitor').callsFake(() => new StubMonitoredItem());\n      });\n\n      return expect(\n        [\n          {\n            specialNodeId: nodeId,\n            nodeClass: NodeClass.Variable,\n          },\n        ],\n        'when piped through',\n        stream,\n        'to yield objects satisfying',\n        'to have length',\n        0\n      ).then(() => {\n        expect(stream.subscription.monitor, 'was called once');\n        expect(stream.subscription.monitor.lastCall.args[0], 'to have properties', { nodeId });\n      });\n    });\n\n    it('should forward MonitoredItem errors', function () {\n      const stream = new SubscribeStream();\n      const nodeId = resolveNodeId('ns=1;s=AGENT.DISPLAYS.Main');\n\n      stream.once('subscription-started', (subscription) => {\n        stub(subscription, 'monitor').callsFake(\n          () => new StubMonitoredItem(new Error('item error'))\n        );\n      });\n\n      return expect(\n        [\n          {\n            nodeId,\n            nodeClass: NodeClass.Variable,\n          },\n        ],\n        'when piped through',\n        stream,\n        'to error with',\n        /item error/\n      );\n    });\n\n    it('should forward MonitoredItem errors when given as string', function () {\n      const stream = new SubscribeStream();\n      const nodeId = resolveNodeId('ns=1;s=AGENT.DISPLAYS.Main');\n\n      stream.once('subscription-started', (subscription) => {\n        stub(subscription, 'monitor').callsFake(() => new StubMonitoredItem('item error'));\n      });\n\n      return expect(\n        [\n          {\n            nodeId,\n            nodeClass: NodeClass.Variable,\n          },\n        ],\n        'when piped through',\n        stream,\n        'to error with',\n        /item error/\n      );\n    });\n\n    it('should forward change events', function () {\n      const stream = new SubscribeStream();\n      const nodeId = resolveNodeId('ns=1;s=AGENT.DISPLAYS.Main');\n      const listener = spy();\n      stream.on('change', listener);\n\n      const changeData = {\n        value: 'value',\n        serverTimestamp: new Date(),\n      };\n\n      let item;\n\n      stream.once('subscription-started', (subscription) => {\n        stub(subscription, 'monitor').callsFake(() => {\n          item = new StubMonitoredItem(false);\n          return item;\n        });\n      });\n\n      return expect(\n        [\n          {\n            nodeId,\n            nodeClass: NodeClass.Variable,\n            references: {},\n          },\n        ],\n        'when piped through',\n        stream,\n        'to yield objects satisfying',\n        'to have length',\n        0\n      )\n        .then(() => item.emit('changed', changeData))\n        .then(() => {\n          expect(listener, 'was called once');\n          expect(listener.lastCall, 'to satisfy', [\n            {\n              nodeId,\n              value: changeData.value,\n              references: {},\n              mtime: changeData.serverTimestamp,\n            },\n          ]);\n        });\n    });\n\n    it('should emit delete events without a value', function () {\n      const stream = new SubscribeStream();\n      const nodeId = resolveNodeId('ns=1;s=AGENT.DISPLAYS.Main');\n      const listener = spy();\n      stream.on('delete', listener);\n\n      const event = {\n        serverTimestamp: new Date(),\n      };\n\n      let item;\n\n      stream.once('subscription-started', (subscription) => {\n        stub(subscription, 'monitor').callsFake(() => {\n          item = new StubMonitoredItem(false);\n          return item;\n        });\n      });\n\n      return expect(\n        [\n          {\n            nodeId,\n            nodeClass: NodeClass.Variable,\n            references: {},\n          },\n        ],\n        'when piped through',\n        stream,\n        'to yield objects satisfying',\n        'to have length',\n        0\n      )\n        .then(() => item.emit('changed', event))\n        .then(() => {\n          expect(listener, 'was called once');\n          expect(listener.lastCall, 'to satisfy', [\n            {\n              nodeId,\n              references: {},\n            },\n          ]);\n        });\n    });\n  });\n\n  /** @test {SubscribeStream#_transform} */\n  describe('#_transform', function () {\n    it('should skip non-variable nodes', function (done) {\n      const stream = new SubscribeStream();\n      stub(stream, '_enqueueChunk').callsFake(() => {});\n      stream.once('subscription-started', (subscription) => {\n        expect(stream.subscription, 'to be', subscription);\n\n        stream._transform({ nodeClass: NodeClass.Object }, 'utf8', () => {});\n\n        expect(stream._enqueueChunk, 'was not called');\n        done();\n      });\n    });\n\n    const chunk = { nodeId: 'chunk', nodeClass: NodeClass.Variable };\n\n    it('should call enqueue immediately if subscription started', function (done) {\n      const stream = new SubscribeStream();\n      stub(stream, '_enqueueChunk').callsFake(() => {});\n      stream.once('subscription-started', (subscription) => {\n        expect(stream.subscription, 'to be', subscription);\n\n        stream._transform(chunk, 'utf8', () => {});\n\n        expect(stream._enqueueChunk, 'was called once');\n        expect(stream._enqueueChunk.lastCall, 'to satisfy', [chunk]);\n        done();\n      });\n    });\n\n    it('should wait for subscription to start before calling enqueue', function (done) {\n      const stream = new SubscribeStream();\n      stub(stream, '_enqueueChunk').callsFake(() => {});\n      stream._transform(chunk, 'utf8', () => {});\n\n      expect(stream._enqueueChunk, 'was not called');\n      stream.once('subscription-started', () => {\n        expect(stream._enqueueChunk, 'was called once');\n        expect(stream._enqueueChunk.lastCall, 'to satisfy', [chunk]);\n        done();\n      });\n    });\n  });\n});\n\n/** @test {Watcher} */\ndescribe.skip('Watcher', function () {\n  /** @test {Watcher#constructor} */\n  describe('#constructor', function () {\n    it('should work without arguments', function () {\n      let watcher;\n      expect(() => (watcher = new StubWatcher()), 'not to throw');\n\n      watcher.close();\n    });\n\n    it('should emit ready event once subscribe stream finished', function (done) {\n      const watcher = new Watcher([resolveNodeId('ns=1;s=AGENT.DISPLAYS.Main')]);\n\n      watcher.once('ready', () => {\n        watcher.close();\n        done();\n      });\n    });\n\n    it.skip('should forward change events', function (done) {\n      const watcher = new Watcher([resolveNodeId('ns=1;s=AGENT.DISPLAYS.Main')]);\n\n      watcher.on('ready', () => {\n        const event = {};\n\n        watcher.on('change', (e) => {\n          expect(e, 'to be', event);\n          watcher.close();\n          done();\n        });\n\n        watcher._subscribeStream.emit('change', event);\n      });\n    });\n\n    it.skip('should forward NodeStream errors', function (done) {\n      const watcher = new Watcher([resolveNodeId('ns=1;s=AGENT.DISPLAYS.Main')]);\n\n      watcher.on('error', (err) => {\n        expect(err, 'to have message', 'Test');\n        done();\n      });\n\n      watcher.on('ready', () => watcher._nodeStream.emit('error', new Error('Test')));\n    });\n\n    it.skip('should forward SubscribeStream errors', function (done) {\n      const watcher = new Watcher([resolveNodeId('ns=1;s=AGENT.DISPLAYS.Main')]);\n\n      watcher.on('error', (err) => {\n        expect(err, 'to have message', 'Test');\n        done();\n      });\n\n      watcher.on('ready', () => watcher._subscribeStream.emit('error', new Error('Test')));\n    });\n  });\n\n  /** @test {Watcher#close} */\n  describe('#close', function () {\n    it('should forward errors', function (done) {\n      const watcher = new Watcher([resolveNodeId('ns=1;s=AGENT.DISPLAYS.Main')]);\n\n      watcher.on('error', (err) => {\n        expect(err, 'to have message', 'session is required');\n        done();\n      });\n\n      watcher.on('ready', () => {\n        watcher._session = {};\n\n        watcher.close();\n      });\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/server/Watcher.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1130,
    "kind": "test",
    "name": "describe417",
    "testId": 417,
    "memberof": "test/src/lib/server/Watcher.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe417",
    "access": null,
    "description": "#constructor",
    "lineNumber": 48,
    "testTargets": [
      "SubscribeStream#constructor"
    ]
  },
  {
    "__docId__": 1131,
    "kind": "test",
    "name": "it418",
    "testId": 418,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe417",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe417.it418",
    "access": null,
    "description": "should apply keepSessionAlive option",
    "lineNumber": 49
  },
  {
    "__docId__": 1132,
    "kind": "test",
    "name": "it419",
    "testId": 419,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe417",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe417.it419",
    "access": null,
    "description": "should not track changes instantly",
    "lineNumber": 56
  },
  {
    "__docId__": 1133,
    "kind": "test",
    "name": "context420",
    "testId": 420,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe417",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe417.context420",
    "access": null,
    "description": "once session is opened",
    "lineNumber": 63
  },
  {
    "__docId__": 1134,
    "kind": "test",
    "name": "it421",
    "testId": 421,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe417.context420",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe417.context420.it421",
    "access": null,
    "description": "should create subscription once session is opened",
    "lineNumber": 64
  },
  {
    "__docId__": 1135,
    "kind": "test",
    "name": "describe422",
    "testId": 422,
    "memberof": "test/src/lib/server/Watcher.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe422",
    "access": null,
    "description": "#createSubscription",
    "lineNumber": 77,
    "testTargets": [
      "SubscribeStream#createSubscription"
    ]
  },
  {
    "__docId__": 1136,
    "kind": "test",
    "name": "it423",
    "testId": 423,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe422",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe422.it423",
    "access": null,
    "description": "should forward errors while creating subscription",
    "lineNumber": 78
  },
  {
    "__docId__": 1137,
    "kind": "test",
    "name": "it424",
    "testId": 424,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe422",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe422.it424",
    "access": null,
    "description": "should emit `subscription-started`",
    "lineNumber": 84
  },
  {
    "__docId__": 1138,
    "kind": "test",
    "name": "it425",
    "testId": 425,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe422",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe422.it425",
    "access": null,
    "description": "should set subscription property",
    "lineNumber": 90
  },
  {
    "__docId__": 1139,
    "kind": "test",
    "name": "describe426",
    "testId": 426,
    "memberof": "test/src/lib/server/Watcher.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe426",
    "access": null,
    "description": "#processErrorMessage",
    "lineNumber": 102,
    "testTargets": [
      "SubscribeStream#processErrorMessage"
    ]
  },
  {
    "__docId__": 1140,
    "kind": "test",
    "name": "it427",
    "testId": 427,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe426",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe426.it427",
    "access": null,
    "description": "should contain node id",
    "lineNumber": 103
  },
  {
    "__docId__": 1141,
    "kind": "test",
    "name": "describe428",
    "testId": 428,
    "memberof": "test/src/lib/server/Watcher.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe428",
    "access": null,
    "description": "#processChunk",
    "lineNumber": 114,
    "testTargets": [
      "SubscribeStream#processChunk"
    ]
  },
  {
    "__docId__": 1142,
    "kind": "test",
    "name": "it429",
    "testId": 429,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe428",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe428.it429",
    "access": null,
    "description": "should call ClientSubscription#monitor",
    "lineNumber": 115
  },
  {
    "__docId__": 1143,
    "kind": "test",
    "name": "it430",
    "testId": 430,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe428",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe428.it430",
    "access": null,
    "description": "should forward MonitoredItem errors",
    "lineNumber": 141
  },
  {
    "__docId__": 1144,
    "kind": "test",
    "name": "it431",
    "testId": 431,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe428",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe428.it431",
    "access": null,
    "description": "should forward MonitoredItem errors when given as string",
    "lineNumber": 165
  },
  {
    "__docId__": 1145,
    "kind": "test",
    "name": "it432",
    "testId": 432,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe428",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe428.it432",
    "access": null,
    "description": "should forward change events",
    "lineNumber": 187
  },
  {
    "__docId__": 1146,
    "kind": "test",
    "name": "it433",
    "testId": 433,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe428",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe428.it433",
    "access": null,
    "description": "should emit delete events without a value",
    "lineNumber": 235
  },
  {
    "__docId__": 1147,
    "kind": "test",
    "name": "describe434",
    "testId": 434,
    "memberof": "test/src/lib/server/Watcher.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe434",
    "access": null,
    "description": "#_transform",
    "lineNumber": 282,
    "testTargets": [
      "SubscribeStream#_transform"
    ]
  },
  {
    "__docId__": 1148,
    "kind": "test",
    "name": "it435",
    "testId": 435,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe434",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe434.it435",
    "access": null,
    "description": "should skip non-variable nodes",
    "lineNumber": 283
  },
  {
    "__docId__": 1149,
    "kind": "test",
    "name": "it436",
    "testId": 436,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe434",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe434.it436",
    "access": null,
    "description": "should call enqueue immediately if subscription started",
    "lineNumber": 298
  },
  {
    "__docId__": 1150,
    "kind": "test",
    "name": "it437",
    "testId": 437,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe434",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe434.it437",
    "access": null,
    "description": "should wait for subscription to start before calling enqueue",
    "lineNumber": 312
  },
  {
    "__docId__": 1151,
    "kind": "test",
    "name": "describe438",
    "testId": 438,
    "memberof": "test/src/lib/server/Watcher.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe438",
    "access": null,
    "description": "#constructor",
    "lineNumber": 330,
    "testTargets": [
      "Watcher#constructor"
    ]
  },
  {
    "__docId__": 1152,
    "kind": "test",
    "name": "it439",
    "testId": 439,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe438",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe438.it439",
    "access": null,
    "description": "should work without arguments",
    "lineNumber": 331
  },
  {
    "__docId__": 1153,
    "kind": "test",
    "name": "it440",
    "testId": 440,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe438",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe438.it440",
    "access": null,
    "description": "should emit ready event once subscribe stream finished",
    "lineNumber": 338
  },
  {
    "__docId__": 1154,
    "kind": "test",
    "name": "describe441",
    "testId": 441,
    "memberof": "test/src/lib/server/Watcher.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe441",
    "access": null,
    "description": "#close",
    "lineNumber": 387,
    "testTargets": [
      "Watcher#close"
    ]
  },
  {
    "__docId__": 1155,
    "kind": "test",
    "name": "it442",
    "testId": 442,
    "memberof": "test/src/lib/server/Watcher.spec.js~describe441",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/Watcher.spec.js~describe441.it442",
    "access": null,
    "description": "should forward errors",
    "lineNumber": 388
  },
  {
    "__docId__": 1156,
    "kind": "testFile",
    "name": "test/src/lib/server/WriteStream.spec.js",
    "content": "import { spy } from 'sinon';\nimport { StatusCodes, NodeClass } from 'node-opcua';\nimport Logger from 'gulplog';\nimport expect from '../../../expect';\nimport _WriteStream from '../../../../src/lib/server/WriteStream';\nimport _CreateNodeStream from '../../../../src/lib/server/CreateNodeStream';\nimport AtviseFile from '../../../../src/lib/server/AtviseFile';\nimport NodeId from '../../../../src/lib/model/opcua/NodeId';\n\nclass CreateNodeStream extends _CreateNodeStream {\n  processChunk(file, handleErrors) {\n    setTimeout(() => {\n      handleErrors(null, StatusCodes.Good, (done) => done());\n    }, 10);\n  }\n}\n\n// Ignore dependencies in tests\nclass WriteStream extends _WriteStream {\n  dependenciesFor() {\n    return [];\n  }\n}\n\n/** @test {WriteStream} */\ndescribe('WriteStream', function () {\n  /** @test {WriteStream#processErrorMessage} */\n  describe('#processErrorMessage', function () {\n    it('should include nodeId', function () {\n      expect(\n        WriteStream.prototype.processErrorMessage(\n          new AtviseFile({\n            path: 'src/AGENT/DISPLAYS/Main.display',\n            base: 'src',\n          })\n        ),\n        'to contain',\n        'AGENT.DISPLAYS.Main'\n      );\n    });\n  });\n\n  /** @test {WriteStream#processChunk} */\n  describe('#processChunk', function () {\n    it('should forward errors', function () {\n      const stream = new WriteStream(new CreateNodeStream());\n\n      stream.prependOnceListener('session-open', () => {\n        stream.session.writeSingleNode = (nodeId, value, callback) => callback(new Error('Test'));\n      });\n\n      return expect(\n        [\n          {\n            nodeId: new NodeId('ns=1;s=AGENT.DISPLAYS.Main'),\n            typeDefinition: new NodeId('VariableTypes.ATVISE.Display', 0),\n            nodeClass: NodeClass.Variable,\n          },\n        ],\n        'when piped through',\n        stream,\n        'to error with',\n        /Test/\n      );\n    });\n\n    it('should forward synchronous errors', function () {\n      const stream = new WriteStream(new CreateNodeStream());\n\n      stream.prependOnceListener('session-open', () => {\n        stream.session.writeSingleNode = () => {\n          throw new Error('Sync test');\n        };\n      });\n\n      return expect(\n        [\n          {\n            nodeId: new NodeId('ns=1;s=AGENT.DISPLAYS.Main'),\n            typeDefinition: new NodeId('ns=1;s=VariableTypes.ATVISE.Display'),\n            nodeClass: NodeClass.Variable,\n          },\n        ],\n        'when piped through',\n        stream,\n        'to error with',\n        /Sync test/\n      );\n    });\n\n    it('should warn if access is denied', function () {\n      const stream = new WriteStream(new CreateNodeStream());\n\n      stream.prependOnceListener('session-open', () => {\n        stream.session.writeSingleNode = (nodeId, value, callback) =>\n          callback(null, StatusCodes.BadUserAccessDenied);\n      });\n\n      const warnSpy = spy();\n      Logger.on('warn', warnSpy);\n\n      return expect(\n        [\n          {\n            nodeId: new NodeId('ns=1;s=AGENT.DISPLAYS.Main'),\n            typeDefinition: new NodeId('ns=1;s=VariableTypes.ATVISE.Display'),\n            nodeClass: NodeClass.Variable,\n          },\n        ],\n        'when piped through',\n        stream,\n        'to yield objects satisfying',\n        'to have length',\n        0\n      )\n        .then(() => expect(warnSpy, 'was called once'))\n        .then(() => expect(warnSpy.lastCall, 'to satisfy', [/opened in atvise builder/]));\n    });\n\n    it('should push non-variable files', function () {\n      const createStream = new CreateNodeStream();\n      const stream = new WriteStream(createStream);\n      stream.pipe(createStream);\n\n      stream.prependOnceListener('session-open', () => {\n        stream.session.writeSingleNode = (nodeId, value, callback) =>\n          callback(null, StatusCodes.Good);\n      });\n\n      const file = {\n        nodeId: new NodeId('ns=1;s=AGENT.DISPLAYS'),\n        typeDefinition: new NodeId('ns=0;i=61'),\n        nodeClass: NodeClass.Object,\n      };\n      return expect([file], 'when piped through', stream, 'to yield objects satisfying', [\n        expect.it('to be', file),\n      ]);\n    });\n\n    it('should push files where no node can be found', function () {\n      const createStream = new CreateNodeStream();\n      const stream = new WriteStream(createStream);\n      stream.pipe(createStream);\n\n      stream.prependOnceListener('session-open', () => {\n        stream.session.writeSingleNode = (nodeId, value, callback) =>\n          callback(null, StatusCodes.BadNodeIdUnknown);\n      });\n\n      const file = {\n        nodeId: new NodeId('ns=1;s=AGENT.DISPLAYS.Main'),\n        typeDefinition: new NodeId('ns=1;s=VariableTypes.ATVISE.Display'),\n        nodeClass: NodeClass.Variable,\n      };\n      return expect([file], 'when piped through', stream, 'to yield objects satisfying', [\n        expect.it('to be', file),\n      ]);\n    });\n\n    it('should push files with good status to add references stream', async function () {\n      const pushToAddRefsStream = spy();\n      const stream = new WriteStream(new CreateNodeStream(), {\n        push: pushToAddRefsStream,\n      });\n\n      stream.prependOnceListener('session-open', () => {\n        stream.session.writeSingleNode = (nodeId, value, callback) =>\n          callback(null, StatusCodes.Good);\n      });\n\n      const file = {\n        nodeId: new NodeId('ns=1;s=AGENT.DISPLAYS.Main'),\n        typeDefinition: new NodeId('ns=1;s=VariableTypes.ATVISE.Display'),\n        nodeClass: NodeClass.Variable,\n      };\n      await expect(\n        [file],\n        'when piped through',\n        stream,\n        'to yield objects satisfying',\n        'to have length',\n        0\n      );\n\n      return expect(pushToAddRefsStream, 'was called once');\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/server/WriteStream.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1157,
    "kind": "test",
    "name": "describe443",
    "testId": 443,
    "memberof": "test/src/lib/server/WriteStream.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/WriteStream.spec.js~describe443",
    "access": null,
    "description": "WriteStream",
    "lineNumber": 26,
    "testTargets": [
      "WriteStream"
    ]
  },
  {
    "__docId__": 1158,
    "kind": "test",
    "name": "describe444",
    "testId": 444,
    "memberof": "test/src/lib/server/WriteStream.spec.js~describe443",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/WriteStream.spec.js~describe443.describe444",
    "access": null,
    "description": "#processErrorMessage",
    "lineNumber": 28,
    "testTargets": [
      "WriteStream#processErrorMessage"
    ]
  },
  {
    "__docId__": 1159,
    "kind": "test",
    "name": "it445",
    "testId": 445,
    "memberof": "test/src/lib/server/WriteStream.spec.js~describe443.describe444",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/WriteStream.spec.js~describe443.describe444.it445",
    "access": null,
    "description": "should include nodeId",
    "lineNumber": 29
  },
  {
    "__docId__": 1160,
    "kind": "test",
    "name": "describe446",
    "testId": 446,
    "memberof": "test/src/lib/server/WriteStream.spec.js~describe443",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/WriteStream.spec.js~describe443.describe446",
    "access": null,
    "description": "#processChunk",
    "lineNumber": 44,
    "testTargets": [
      "WriteStream#processChunk"
    ]
  },
  {
    "__docId__": 1161,
    "kind": "test",
    "name": "it447",
    "testId": 447,
    "memberof": "test/src/lib/server/WriteStream.spec.js~describe443.describe446",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/WriteStream.spec.js~describe443.describe446.it447",
    "access": null,
    "description": "should forward errors",
    "lineNumber": 45
  },
  {
    "__docId__": 1162,
    "kind": "test",
    "name": "it448",
    "testId": 448,
    "memberof": "test/src/lib/server/WriteStream.spec.js~describe443.describe446",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/WriteStream.spec.js~describe443.describe446.it448",
    "access": null,
    "description": "should forward synchronous errors",
    "lineNumber": 67
  },
  {
    "__docId__": 1163,
    "kind": "test",
    "name": "it449",
    "testId": 449,
    "memberof": "test/src/lib/server/WriteStream.spec.js~describe443.describe446",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/WriteStream.spec.js~describe443.describe446.it449",
    "access": null,
    "description": "should warn if access is denied",
    "lineNumber": 91
  },
  {
    "__docId__": 1164,
    "kind": "test",
    "name": "it450",
    "testId": 450,
    "memberof": "test/src/lib/server/WriteStream.spec.js~describe443.describe446",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/WriteStream.spec.js~describe443.describe446.it450",
    "access": null,
    "description": "should push non-variable files",
    "lineNumber": 120
  },
  {
    "__docId__": 1165,
    "kind": "test",
    "name": "it451",
    "testId": 451,
    "memberof": "test/src/lib/server/WriteStream.spec.js~describe443.describe446",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/WriteStream.spec.js~describe443.describe446.it451",
    "access": null,
    "description": "should push files where no node can be found",
    "lineNumber": 140
  },
  {
    "__docId__": 1166,
    "kind": "test",
    "name": "it452",
    "testId": 452,
    "memberof": "test/src/lib/server/WriteStream.spec.js~describe443.describe446",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/WriteStream.spec.js~describe443.describe446.it452",
    "access": null,
    "description": "should push files with good status to add references stream",
    "lineNumber": 160
  },
  {
    "__docId__": 1167,
    "kind": "testFile",
    "name": "test/src/lib/server/scripts/CallMethodStream.spec.js",
    "content": "import { DataType } from 'node-opcua';\nimport expect from '../../../../expect';\nimport CallMethodStream from '../../../../../src/lib/server/scripts/CallMethodStream';\nimport NodeId from '../../../../../src/lib/model/opcua/NodeId';\n\nclass InvalidMethodStub extends CallMethodStream {\n  get methodId() {\n    return new NodeId(NodeId.NodeIdType.STRING, 'path.to.unknown.method', 1);\n  }\n}\n\nclass ValidMethodStub extends CallMethodStream {\n  get methodId() {\n    return new NodeId(NodeId.NodeIdType.STRING, 'AGENT.OPCUA.METHODS.importNodes', 1);\n  }\n\n  inputArguments(file) {\n    return [\n      {\n        dataType: DataType.NodeId,\n        value: new NodeId(NodeId.NodeIdType.NUMERIC, 0, 0),\n      },\n      {\n        dataType: DataType.XmlElement,\n        value: file.contents,\n      },\n    ];\n  }\n}\n\n/** @test {CallMethodStream} */\ndescribe('CallMethodStream', function () {\n  /** @test {CallMethodStream#methodId} */\n  describe('#methodId', function () {\n    it('throws an error if not overridden', function () {\n      return expect(\n        () => CallMethodStream.prototype.methodId,\n        'to throw error',\n        /must be implemented/i\n      );\n    });\n  });\n\n  /** @test {CallMethodStream#methodBaseId} */\n  describe('#methodBaseId', function () {\n    it(\"defaults to the method's parent id\", function () {\n      const base = InvalidMethodStub.prototype.methodBaseId;\n\n      expect(base, 'to be a', NodeId);\n      expect(base.value, 'to equal', 'path.to.unknown');\n      expect(base.namespace, 'to equal', 1);\n    });\n  });\n\n  /** @test {CallMethodStream#inputArguments} */\n  describe('#inputArguments', function () {\n    it('defaults to an empty array', function () {\n      const args = CallMethodStream.prototype.inputArguments({});\n\n      expect(args, 'to equal', []);\n    });\n  });\n\n  /** @test {CallMethodStream#callRequest} */\n  describe('#callRequest', function () {\n    it('uses #methodId, #baseMethodId and #inputArguments', function () {\n      const request = InvalidMethodStub.prototype.callRequest({});\n\n      expect(request, 'to be an object');\n      expect(request.methodId, 'to equal', InvalidMethodStub.prototype.methodId);\n      expect(request.objectId, 'to equal', InvalidMethodStub.prototype.methodBaseId);\n      expect(request.inputArguments, 'to equal', InvalidMethodStub.prototype.inputArguments({}));\n    });\n  });\n\n  /** @test {CallMethodStream#handleOutputArguments} */\n  describe('#handleOutputArguments', function () {\n    it('throws if not overridden', function () {\n      return expect(\n        CallMethodStream.prototype.handleOutputArguments,\n        'to throw error',\n        /must be implemented/i\n      );\n    });\n  });\n\n  /** @test {CallMethodStream#processErrorMessage} */\n  describe('#processErrorMessage', function () {\n    context('processed message', function () {\n      const message = InvalidMethodStub.prototype.processErrorMessage({\n        relative: 'relative/path',\n      });\n\n      it('should include methodId', function () {\n        expect(message, 'to contain', 'path.to.unknown.method');\n      });\n\n      it('should include relative file path', function () {\n        expect(message, 'to contain', 'relative/path');\n      });\n    });\n  });\n\n  /** @test {CallMethodStream#processChunk} */\n  describe('#processChunk', function () {\n    it('should handle synchronous errors', function () {\n      const stream = new CallMethodStream();\n\n      return expect([{}], 'when piped through', stream, 'to error').then((error) => {\n        expect(error.message, 'to match', /must be implemented/i);\n      });\n    });\n\n    it('should handle asynchronous errors', function () {\n      const stream = new InvalidMethodStub();\n\n      stream.once('session-open', () => {\n        stream.session.close(() => {});\n      });\n\n      return expect([{}], 'when piped through', stream, 'to error').then((error) => {\n        expect(error.message, 'to contain', 'BadSessionIdInvalid');\n      });\n    });\n\n    it('should report bad status codes', function () {\n      const importStream = new InvalidMethodStub();\n\n      return expect([{}], 'when piped through', importStream, 'to error').then((error) => {\n        expect(error.message, 'to contain', 'does not exist in the server address space');\n      });\n    });\n\n    it('should report non-unsuccessful operations', async function () {\n      const importStream = new ValidMethodStub();\n\n      importStream.handleOutputArguments = function (file, args, callback) {\n        callback(new Error('Test error'));\n      };\n\n      const error = await expect(\n        [{ contents: Buffer.from('invalid') }],\n        'when piped through',\n        importStream,\n        'to error'\n      );\n\n      expect(error.message, 'to end with', 'Test error');\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/server/scripts/CallMethodStream.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1168,
    "kind": "test",
    "name": "describe453",
    "testId": 453,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453",
    "access": null,
    "description": "CallMethodStream",
    "lineNumber": 32,
    "testTargets": [
      "CallMethodStream"
    ]
  },
  {
    "__docId__": 1169,
    "kind": "test",
    "name": "describe454",
    "testId": 454,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe454",
    "access": null,
    "description": "#methodId",
    "lineNumber": 34,
    "testTargets": [
      "CallMethodStream#methodId"
    ]
  },
  {
    "__docId__": 1170,
    "kind": "test",
    "name": "it455",
    "testId": 455,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe454",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe454.it455",
    "access": null,
    "description": "throws an error if not overridden",
    "lineNumber": 35
  },
  {
    "__docId__": 1171,
    "kind": "test",
    "name": "describe456",
    "testId": 456,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe456",
    "access": null,
    "description": "#methodBaseId",
    "lineNumber": 45,
    "testTargets": [
      "CallMethodStream#methodBaseId"
    ]
  },
  {
    "__docId__": 1172,
    "kind": "test",
    "name": "it457",
    "testId": 457,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe456",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe456.it457",
    "access": null,
    "description": "defaults to the method's parent id",
    "lineNumber": 46
  },
  {
    "__docId__": 1173,
    "kind": "test",
    "name": "describe458",
    "testId": 458,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe458",
    "access": null,
    "description": "#inputArguments",
    "lineNumber": 56,
    "testTargets": [
      "CallMethodStream#inputArguments"
    ]
  },
  {
    "__docId__": 1174,
    "kind": "test",
    "name": "it459",
    "testId": 459,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe458",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe458.it459",
    "access": null,
    "description": "defaults to an empty array",
    "lineNumber": 57
  },
  {
    "__docId__": 1175,
    "kind": "test",
    "name": "describe460",
    "testId": 460,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe460",
    "access": null,
    "description": "#callRequest",
    "lineNumber": 65,
    "testTargets": [
      "CallMethodStream#callRequest"
    ]
  },
  {
    "__docId__": 1176,
    "kind": "test",
    "name": "it461",
    "testId": 461,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe460",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe460.it461",
    "access": null,
    "description": "uses #methodId, #baseMethodId and #inputArguments",
    "lineNumber": 66
  },
  {
    "__docId__": 1177,
    "kind": "test",
    "name": "describe462",
    "testId": 462,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe462",
    "access": null,
    "description": "#handleOutputArguments",
    "lineNumber": 77,
    "testTargets": [
      "CallMethodStream#handleOutputArguments"
    ]
  },
  {
    "__docId__": 1178,
    "kind": "test",
    "name": "it463",
    "testId": 463,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe462",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe462.it463",
    "access": null,
    "description": "throws if not overridden",
    "lineNumber": 78
  },
  {
    "__docId__": 1179,
    "kind": "test",
    "name": "describe464",
    "testId": 464,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe464",
    "access": null,
    "description": "#processErrorMessage",
    "lineNumber": 88,
    "testTargets": [
      "CallMethodStream#processErrorMessage"
    ]
  },
  {
    "__docId__": 1180,
    "kind": "test",
    "name": "context465",
    "testId": 465,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe464",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe464.context465",
    "access": null,
    "description": "processed message",
    "lineNumber": 89
  },
  {
    "__docId__": 1181,
    "kind": "test",
    "name": "it466",
    "testId": 466,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe464.context465",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe464.context465.it466",
    "access": null,
    "description": "should include methodId",
    "lineNumber": 94
  },
  {
    "__docId__": 1182,
    "kind": "test",
    "name": "it467",
    "testId": 467,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe464.context465",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe464.context465.it467",
    "access": null,
    "description": "should include relative file path",
    "lineNumber": 98
  },
  {
    "__docId__": 1183,
    "kind": "test",
    "name": "describe468",
    "testId": 468,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe468",
    "access": null,
    "description": "#processChunk",
    "lineNumber": 105,
    "testTargets": [
      "CallMethodStream#processChunk"
    ]
  },
  {
    "__docId__": 1184,
    "kind": "test",
    "name": "it469",
    "testId": 469,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe468",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe468.it469",
    "access": null,
    "description": "should handle synchronous errors",
    "lineNumber": 106
  },
  {
    "__docId__": 1185,
    "kind": "test",
    "name": "it470",
    "testId": 470,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe468",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe468.it470",
    "access": null,
    "description": "should handle asynchronous errors",
    "lineNumber": 114
  },
  {
    "__docId__": 1186,
    "kind": "test",
    "name": "it471",
    "testId": 471,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe468",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe468.it471",
    "access": null,
    "description": "should report bad status codes",
    "lineNumber": 126
  },
  {
    "__docId__": 1187,
    "kind": "test",
    "name": "it472",
    "testId": 472,
    "memberof": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe468",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallMethodStream.spec.js~describe453.describe468.it472",
    "access": null,
    "description": "should report non-unsuccessful operations",
    "lineNumber": 134
  },
  {
    "__docId__": 1188,
    "kind": "testFile",
    "name": "test/src/lib/server/scripts/CallScriptStream.spec.js",
    "content": "import { DataType } from 'node-opcua';\nimport expect from '../../../../expect';\nimport CallScriptStream from '../../../../../src/lib/server/scripts/CallScriptStream';\nimport NodeId from '../../../../../src/lib/model/opcua/NodeId';\n\nclass StubImplementation extends CallScriptStream {\n  get scriptId() {\n    return new NodeId('ns=1;s=SYSTEM.LIBRARY.ATVISE.SERVERSCRIPTS.Stub');\n  }\n}\n\nclass StubAtscmImplementation extends CallScriptStream {\n  get scriptId() {\n    return new NodeId('ns=1;s=SYSTEM.LIBRARY.ATVISE.SERVERSCRIPTS.atscm.Stub');\n  }\n}\n\nclass WithParams extends StubImplementation {\n  scriptParameters(file) {\n    // eslint-disable-line no-unused-vars\n    return {\n      filename: {\n        dataType: DataType.String,\n        value: file.stem,\n      },\n    };\n  }\n}\n\n/** @test {CallScriptStream} */\ndescribe('CallScriptStream', function () {\n  /** @test {CallScriptStream#methodId} */\n  describe('#methodId', function () {\n    it(\"should return the callScript method's id\", function () {\n      return expect(\n        CallScriptStream.prototype.methodId.value,\n        'to equal',\n        'AGENT.SCRIPT.METHODS.callScript'\n      );\n    });\n  });\n\n  /** @test {CallScriptStream#scriptId} */\n  describe('#scriptId', function () {\n    it('should throw if not overridden', function () {\n      return expect(() => CallScriptStream.prototype.scriptId, 'to throw', /must be implemented/i);\n    });\n  });\n\n  /** @test {CallScriptStream#scriptParameters} */\n  describe('#scriptParameters', function () {\n    it('should return an empty object if not overridden', function () {\n      return expect(\n        CallScriptStream.prototype.scriptParameters,\n        'when called with',\n        [{}],\n        'to equal',\n        {}\n      );\n    });\n  });\n\n  /** @test {CallScriptStream#inputArguments} */\n  describe('#inputArguments', function () {\n    it('should return an array of node-opcua~Variants', function () {\n      const stream = new StubImplementation();\n\n      return expect(\n        () => stream.inputArguments({}),\n        'when called with',\n        [{}],\n        'to have items satisfying',\n        expect.it((item) => {\n          expect(item, 'to be an object');\n          expect(item, 'to have property', 'dataType');\n          expect(item, 'to have property', 'value');\n        })\n      );\n    });\n\n    it('should return names and values from #scriptParameters', function () {\n      const stream = new WithParams();\n      const file = { stem: 'test' };\n      const [{ value: paramNames }, { value: paramValues }] = stream.inputArguments(file).slice(2);\n\n      expect(paramNames, 'to equal', ['filename']);\n      expect(paramValues, 'to equal', [\n        {\n          dataType: DataType.String,\n          value: 'test',\n        },\n      ]);\n    });\n  });\n\n  /** @test {CallScriptStream#processErrorMessage} */\n  describe('#processErrorMessage', function () {\n    it(\"should include the file's name\", function () {\n      return expect(\n        (f) => new StubImplementation().processErrorMessage(f),\n        'when called with',\n        [{ relative: './path/file' }],\n        'to end with',\n        './path/file'\n      );\n    });\n\n    it(\"should include the called script's id\", function () {\n      return expect(\n        (f) => new StubImplementation().processErrorMessage(f),\n        'when called with',\n        [{ relative: './path/file' }],\n        'to contain',\n        'SYSTEM.LIBRARY.ATVISE.SERVERSCRIPTS.Stub'\n      );\n    });\n  });\n\n  /** @test {CallScriptStream#processChunk} */\n  describe('#processChunk', function () {\n    it('should process as usual if not called on atscm script', function () {\n      const stream = new StubImplementation();\n\n      return expect(\n        [{ relative: 'relative/path', nodeId: new NodeId('Stub') }],\n        'when piped through',\n        stream,\n        'to error with',\n        /Error running script/\n      );\n    });\n\n    it(\"should suggest running 'atscm import' if atscm script is missing\", function () {\n      const stream = new StubAtscmImplementation();\n\n      return expect(\n        [{ relative: 'relative/path', nodeId: new NodeId('Stub') }],\n        'when piped through',\n        stream,\n        'to error with',\n        /Did you forget to run 'atscm import'?/\n      );\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/server/scripts/CallScriptStream.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1189,
    "kind": "test",
    "name": "describe473",
    "testId": 473,
    "memberof": "test/src/lib/server/scripts/CallScriptStream.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473",
    "access": null,
    "description": "CallScriptStream",
    "lineNumber": 31,
    "testTargets": [
      "CallScriptStream"
    ]
  },
  {
    "__docId__": 1190,
    "kind": "test",
    "name": "describe474",
    "testId": 474,
    "memberof": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe474",
    "access": null,
    "description": "#methodId",
    "lineNumber": 33,
    "testTargets": [
      "CallScriptStream#methodId"
    ]
  },
  {
    "__docId__": 1191,
    "kind": "test",
    "name": "it475",
    "testId": 475,
    "memberof": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe474",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe474.it475",
    "access": null,
    "description": "should return the callScript method's id",
    "lineNumber": 34
  },
  {
    "__docId__": 1192,
    "kind": "test",
    "name": "describe476",
    "testId": 476,
    "memberof": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe476",
    "access": null,
    "description": "#scriptId",
    "lineNumber": 44,
    "testTargets": [
      "CallScriptStream#scriptId"
    ]
  },
  {
    "__docId__": 1193,
    "kind": "test",
    "name": "it477",
    "testId": 477,
    "memberof": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe476",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe476.it477",
    "access": null,
    "description": "should throw if not overridden",
    "lineNumber": 45
  },
  {
    "__docId__": 1194,
    "kind": "test",
    "name": "describe478",
    "testId": 478,
    "memberof": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe478",
    "access": null,
    "description": "#scriptParameters",
    "lineNumber": 51,
    "testTargets": [
      "CallScriptStream#scriptParameters"
    ]
  },
  {
    "__docId__": 1195,
    "kind": "test",
    "name": "it479",
    "testId": 479,
    "memberof": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe478",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe478.it479",
    "access": null,
    "description": "should return an empty object if not overridden",
    "lineNumber": 52
  },
  {
    "__docId__": 1196,
    "kind": "test",
    "name": "describe480",
    "testId": 480,
    "memberof": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe480",
    "access": null,
    "description": "#inputArguments",
    "lineNumber": 64,
    "testTargets": [
      "CallScriptStream#inputArguments"
    ]
  },
  {
    "__docId__": 1197,
    "kind": "test",
    "name": "it481",
    "testId": 481,
    "memberof": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe480",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe480.it481",
    "access": null,
    "description": "should return an array of node-opcua~Variants",
    "lineNumber": 65
  },
  {
    "__docId__": 1198,
    "kind": "test",
    "name": "it482",
    "testId": 482,
    "memberof": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe480",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe480.it482",
    "access": null,
    "description": "should return names and values from #scriptParameters",
    "lineNumber": 81
  },
  {
    "__docId__": 1199,
    "kind": "test",
    "name": "describe483",
    "testId": 483,
    "memberof": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe483",
    "access": null,
    "description": "#processErrorMessage",
    "lineNumber": 97,
    "testTargets": [
      "CallScriptStream#processErrorMessage"
    ]
  },
  {
    "__docId__": 1200,
    "kind": "test",
    "name": "it484",
    "testId": 484,
    "memberof": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe483",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe483.it484",
    "access": null,
    "description": "should include the file's name",
    "lineNumber": 98
  },
  {
    "__docId__": 1201,
    "kind": "test",
    "name": "it485",
    "testId": 485,
    "memberof": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe483",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe483.it485",
    "access": null,
    "description": "should include the called script's id",
    "lineNumber": 108
  },
  {
    "__docId__": 1202,
    "kind": "test",
    "name": "describe486",
    "testId": 486,
    "memberof": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe486",
    "access": null,
    "description": "#processChunk",
    "lineNumber": 120,
    "testTargets": [
      "CallScriptStream#processChunk"
    ]
  },
  {
    "__docId__": 1203,
    "kind": "test",
    "name": "it487",
    "testId": 487,
    "memberof": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe486",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe486.it487",
    "access": null,
    "description": "should process as usual if not called on atscm script",
    "lineNumber": 121
  },
  {
    "__docId__": 1204,
    "kind": "test",
    "name": "it488",
    "testId": 488,
    "memberof": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe486",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/server/scripts/CallScriptStream.spec.js~describe473.describe486.it488",
    "access": null,
    "description": "should suggest running 'atscm import' if atscm script is missing",
    "lineNumber": 133
  },
  {
    "__docId__": 1205,
    "kind": "testFile",
    "name": "test/src/lib/transform/PartialTransformer.spec.js",
    "content": "import { obj as createStream } from 'through2';\nimport { spy } from 'sinon';\nimport expect from '../../../expect';\nimport { TransformDirection } from '../../../../src/lib/transform/Transformer';\nimport PartialTransformer from '../../../../src/lib/transform/PartialTransformer';\n\n/** @test {PartialTransformer} */\ndescribe('PartialTransformer', function () {\n  /** @test {PartialTransformer#shouldBeTransformed} */\n  describe('#shouldBeTransformed', function () {\n    it('should throw if not overridden', function () {\n      expect(\n        () => PartialTransformer.prototype.shouldBeTransformed({}),\n        'to throw',\n        /must be implemented/\n      );\n    });\n  });\n\n  /** @test {PartialTransformer#_transform} */\n  describe.skip('#_transform', function () {\n    it('should pass original file if shouldBeTransformed returns false', function () {\n      const transformer = new PartialTransformer();\n      transformer.shouldBeTransformed = () => false;\n      const file = {};\n\n      expect((cb) => transformer._transform(file, 'utf8', cb), 'to call the callback').then(\n        (args) => {\n          expect(args[0], 'to be falsy');\n          expect(args[1], 'to be', file);\n        }\n      );\n    });\n\n    it('should call super if shouldBeTransformed returns true', function () {\n      const transformer = new PartialTransformer({ direction: TransformDirection.FromDB });\n      const original = {};\n      const result = {};\n\n      transformer.shouldBeTransformed = () => true;\n      transformer.transformFromDB = (file, enc, cb) => cb(null, result);\n\n      expect((cb) => transformer._transform(original, 'utf8', cb), 'to call the callback').then(\n        (args) => {\n          expect(args[0], 'to be falsy');\n          expect(args[1], 'to be', result);\n        }\n      );\n    });\n  });\n\n  /** @test {PartialTransformer#applyToStream} */\n  describe.skip('#applyToStream', function () {\n    context('when #applyToFilteredStream is not overridden', function () {\n      it('should invoke #transformFromDB / #transformFromFilesystem', function () {\n        const transformer = new PartialTransformer();\n        transformer.shouldBeTransformed = () => true;\n        spy(transformer, 'withDirection');\n\n        transformer.applyToStream(createStream(), TransformDirection.FromDB);\n\n        expect(transformer.withDirection, 'was called once');\n      });\n    });\n\n    context('when #applyToFilteredStream is overridden', function () {\n      it('should invoke #applyToFilteredStream', function () {\n        const transformer = new PartialTransformer();\n        transformer.shouldBeTransformed = () => true;\n        transformer.applyToStream = () => true;\n\n        spy(transformer, 'withDirection');\n        spy(transformer, 'applyToFilteredStream');\n\n        expect(transformer.applyToStream(createStream(), TransformDirection.FromDB), 'to be true');\n        expect(transformer.withDirection, 'was not called');\n      });\n    });\n  });\n\n  /** @test {PartialTransformer#applyToFilteredStream} */\n  describe.skip('#applyToFilteredStream', function () {\n    it('should return false by default', function () {\n      expect(PartialTransformer.prototype.applyToFilteredStream(), 'to be false');\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/transform/PartialTransformer.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1206,
    "kind": "test",
    "name": "describe489",
    "testId": 489,
    "memberof": "test/src/lib/transform/PartialTransformer.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/transform/PartialTransformer.spec.js~describe489",
    "access": null,
    "description": "PartialTransformer",
    "lineNumber": 8,
    "testTargets": [
      "PartialTransformer"
    ]
  },
  {
    "__docId__": 1207,
    "kind": "test",
    "name": "describe490",
    "testId": 490,
    "memberof": "test/src/lib/transform/PartialTransformer.spec.js~describe489",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/PartialTransformer.spec.js~describe489.describe490",
    "access": null,
    "description": "#shouldBeTransformed",
    "lineNumber": 10,
    "testTargets": [
      "PartialTransformer#shouldBeTransformed"
    ]
  },
  {
    "__docId__": 1208,
    "kind": "test",
    "name": "it491",
    "testId": 491,
    "memberof": "test/src/lib/transform/PartialTransformer.spec.js~describe489.describe490",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/PartialTransformer.spec.js~describe489.describe490.it491",
    "access": null,
    "description": "should throw if not overridden",
    "lineNumber": 11
  },
  {
    "__docId__": 1209,
    "kind": "test",
    "name": "it492",
    "testId": 492,
    "memberof": "test/src/lib/transform/PartialTransformer.spec.js~describe489",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/PartialTransformer.spec.js~describe489.it492",
    "access": null,
    "description": "should pass original file if shouldBeTransformed returns false",
    "lineNumber": 22
  },
  {
    "__docId__": 1210,
    "kind": "test",
    "name": "it493",
    "testId": 493,
    "memberof": "test/src/lib/transform/PartialTransformer.spec.js~describe489",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/PartialTransformer.spec.js~describe489.it493",
    "access": null,
    "description": "should call super if shouldBeTransformed returns true",
    "lineNumber": 35
  },
  {
    "__docId__": 1211,
    "kind": "test",
    "name": "context494",
    "testId": 494,
    "memberof": "test/src/lib/transform/PartialTransformer.spec.js~describe489",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/PartialTransformer.spec.js~describe489.context494",
    "access": null,
    "description": "when #applyToFilteredStream is not overridden",
    "lineNumber": 54
  },
  {
    "__docId__": 1212,
    "kind": "test",
    "name": "it495",
    "testId": 495,
    "memberof": "test/src/lib/transform/PartialTransformer.spec.js~describe489.context494",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/PartialTransformer.spec.js~describe489.context494.it495",
    "access": null,
    "description": "should invoke #transformFromDB / #transformFromFilesystem",
    "lineNumber": 55
  },
  {
    "__docId__": 1213,
    "kind": "test",
    "name": "context496",
    "testId": 496,
    "memberof": "test/src/lib/transform/PartialTransformer.spec.js~describe489",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/PartialTransformer.spec.js~describe489.context496",
    "access": null,
    "description": "when #applyToFilteredStream is overridden",
    "lineNumber": 66
  },
  {
    "__docId__": 1214,
    "kind": "test",
    "name": "it497",
    "testId": 497,
    "memberof": "test/src/lib/transform/PartialTransformer.spec.js~describe489.context496",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/PartialTransformer.spec.js~describe489.context496.it497",
    "access": null,
    "description": "should invoke #applyToFilteredStream",
    "lineNumber": 67
  },
  {
    "__docId__": 1215,
    "kind": "test",
    "name": "it498",
    "testId": 498,
    "memberof": "test/src/lib/transform/PartialTransformer.spec.js~describe489",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/PartialTransformer.spec.js~describe489.it498",
    "access": null,
    "description": "should return false by default",
    "lineNumber": 83
  },
  {
    "__docId__": 1216,
    "kind": "testFile",
    "name": "test/src/lib/transform/SplittingTransformer.spec.js",
    "content": "import expect from 'unexpected';\nimport { spy } from 'sinon';\nimport proxyquire from 'proxyquire';\nimport File from 'vinyl';\nimport { TransformDirection } from '../../../../src/lib/transform/Transformer';\nimport AtviseFile from '../../../../src/lib/server/AtviseFile';\nimport SplittingTransformer, {\n  CombineFilesCache,\n} from '../../../../src/lib/transform/SplittingTransformer';\n\nclass StubSplittingTransformer extends proxyquire(\n  '../../../../src/lib/transform/SplittingTransformer',\n  {\n    '../server/AtviseFile': {\n      _esModule: true,\n      default: class StubAtviseFile extends AtviseFile {\n        static read(options) {\n          return Promise.resolve(options);\n        }\n      },\n    },\n  }\n).default {\n  constructor(combineError) {\n    super();\n\n    this.combineError = combineError;\n  }\n\n  createCombinedFile(files, last, callback) {\n    if (this.combineError) {\n      callback(this.combineError);\n    } else {\n      callback(null, last);\n    }\n  }\n}\n\n/** @test {CombineFilesCache} */\ndescribe.skip('CombineFilesCache', function () {\n  /** @test {CombineFilesCache#missingExtensions} */\n  describe('#missingExtensions', function () {\n    it('should return extensions if required files are missing', function () {\n      const cache = new CombineFilesCache();\n      cache._files.fakeDir = { '.ext': {} };\n      cache._required.fakeDir = ['.ext', '.ext2'];\n\n      expect(cache.missingExtensions('fakeDir'), 'to equal', ['.ext2']);\n    });\n\n    it('should return empty array if all required files are cached', function () {\n      const cache = new CombineFilesCache();\n      cache._files.fakeDir = { '.ext': {} };\n      cache._required.fakeDir = ['.ext'];\n\n      expect(cache.missingExtensions('fakeDir'), 'to equal', []);\n    });\n  });\n\n  /** @test {CombineFilesCache#gotAllFiles}\n  describe('#gotAllFiles', function() {\n    it('should forward readdir errors', function() {\n      const cache = new CombineFilesCache();\n\n      return expect(cb => cache.gotAllFiles(new File({ path: 'that/does/not.exist' }), cb),\n        'to call the callback with error', /ENOENT/);\n    });\n\n    it.skip('should store required files if missing', function() {\n      const cache = new StubCombineFilesCache();\n\n      return expect(cb => cache.gotAllFiles({ dirname: 'dirname' }, cb),\n        'to call the callback')\n        .then(args => {\n          expect(args[0], 'to be falsy');\n          expect(args[1], 'to be undefined');\n          expect(cache._required.dirname, 'to equal', ['.ext1', '.ext2']);\n        });\n    });\n\n    const fillCache = new StubCombineFilesCache();\n    const file1 = { dirname: 'dirname', extname: '.ext1' };\n    const file2 = { dirname: 'dirname', extname: '.ext2' };\n\n    it.skip('should cache passed file', function() {\n      return expect(cb => fillCache.gotAllFiles(file1, cb),\n        'to call the callback')\n        .then(args => {\n          expect(args[0], 'to be falsy');\n          expect(args[1], 'to be undefined');\n          expect(fillCache._required.dirname, 'to equal', ['.ext1', '.ext2']);\n          expect(fillCache._files.dirname['.ext1'], 'to equal', file1);\n        });\n    });\n\n    it.skip('should pass all cached files if all required are present', function() {\n      return expect(cb => fillCache.gotAllFiles(file2, cb),\n        'to call the callback')\n        .then(args => {\n          expect(args[0], 'to be falsy');\n          expect(args[1], 'to equal', {\n            '.ext1': file1,\n            '.ext2': file2,\n          });\n\n          // Expect cache is cleaned\n          expect(fillCache._files.dirname, 'to be undefined');\n        });\n    });\n  }); */\n});\n\n/** @test {SplittingTransformer} */\ndescribe('SplittingTransformer', function () {\n  /** @test {SplittingTransformer#transformFromFilesystem} */\n  describe('#transformFromFilesystem', function () {\n    it.skip('should forward cache errors', function () {\n      const transformer = new SplittingTransformer({\n        direction: TransformDirection.FromFilesystem,\n      });\n      transformer._combineFilesCache.gotAllFiles = (file, cb) => cb(new Error('Cache error'));\n\n      expect(\n        (cb) =>\n          transformer.transformFromFilesystem(\n            new File({ path: 'path/name.display/name.js' }),\n            'utf8',\n            cb\n          ),\n        'to call the callback with error',\n        'Cache error'\n      );\n    });\n\n    it.skip('should cache display files', function () {\n      const transformer = new SplittingTransformer({\n        direction: TransformDirection.FromFilesystem,\n      });\n      transformer._combineFilesCache.gotAllFiles = (files, cb) => cb(null, false);\n\n      return expect(\n        (cb) =>\n          transformer.transformFromFilesystem(\n            new File({ path: 'path/name.display/name.js' }),\n            'utf8',\n            cb\n          ),\n        'to call the callback'\n      ).then((args) => {\n        expect(args[0], 'to be falsy');\n      });\n    });\n\n    it.skip('should call #createCombinedFile if all required files are cached', function () {\n      const transformer = new SplittingTransformer({\n        direction: TransformDirection.FromFilesystem,\n      });\n      const stubDisplay = {};\n      transformer._combineFilesCache.gotAllFiles = (files, cb) => cb(null, [{}]);\n      transformer.createCombinedFile = (files, last, cb) => cb(null, stubDisplay);\n\n      return expect(\n        (cb) =>\n          transformer.transformFromFilesystem(\n            new File({ path: 'path/name.display/name.js' }),\n            'utf8',\n            cb\n          ),\n        'to call the callback'\n      ).then((args) => {\n        expect(args[0], 'to be falsy');\n        expect(args[1], 'to be', stubDisplay);\n      });\n    });\n  });\n\n  /** @test {SplittingTransformer.splitFile} */\n  describe.skip('.splitFile', function () {\n    const original = new File({\n      path: 'path/name.type.ext',\n    });\n\n    it('should return a file', function () {\n      expect(SplittingTransformer.splitFile(original, '.another'), 'to be a', File);\n    });\n\n    it('should apply the new extension', function () {\n      expect(SplittingTransformer.splitFile(original, '.another').extname, 'to equal', '.another');\n    });\n  });\n\n  /** @test {SplittingTransformer.combineFiles} */\n  describe.skip('.combineFiles', function () {\n    const originals = [\n      new File({ path: 'path/name.type/name.ext1' }),\n      new File({ path: 'path/name.type/name.ext2' }),\n    ];\n\n    it('should return a file', function () {\n      expect(SplittingTransformer.combineFiles(originals, '.another'), 'to be a', File);\n    });\n\n    it('should apply the new extension', function () {\n      expect(SplittingTransformer.combineFiles(originals, '.other').extname, 'to equal', '.other');\n    });\n  });\n\n  /** @test {SplittingTransformer#_flush} */\n  describe.skip('#_flush', function () {\n    it('should just callback if no files are missing', function () {\n      const transformer = new SplittingTransformer();\n      const callback = spy();\n\n      transformer._flush(callback);\n\n      expect(callback.calledOnce, 'to be', true);\n    });\n\n    it('should push additional files if some are missing', function (done) {\n      const transformer = new StubSplittingTransformer();\n      const file = {\n        cwd: '/fake/cwd',\n        base: '/base',\n      };\n\n      transformer._combineFilesCache._files['base/not/existent/dir'] = {\n        '.ext': file,\n      };\n      transformer._combineFilesCache._required['base/not/existent/dir'] = ['.ext', '.ext1'];\n      spy(transformer, 'push');\n\n      transformer._flush((err) => {\n        expect(err, 'to be falsy');\n        expect(transformer.push.calledOnce, 'to be true');\n        expect(transformer.push.lastCall.args[0], 'to be', file);\n\n        done();\n      });\n    });\n\n    it('should forward read errors', function (done) {\n      const transformer = new StubSplittingTransformer(new Error('Test error'));\n      const file = {\n        cwd: '/fake/cwd',\n        base: '/base',\n      };\n\n      transformer._combineFilesCache._files['base/not/existent/dir'] = {\n        '.ext': file,\n      };\n      transformer._combineFilesCache._required['base/not/existent/dir'] = ['.ext', '.ext1'];\n      spy(transformer, 'push');\n\n      transformer._flush((err) => {\n        expect(err, 'to have message', 'Test error');\n\n        done();\n      });\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/transform/SplittingTransformer.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1217,
    "kind": "test",
    "name": "describe499",
    "testId": 499,
    "memberof": "test/src/lib/transform/SplittingTransformer.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/transform/SplittingTransformer.spec.js~describe499",
    "access": null,
    "description": "#missingExtensions",
    "lineNumber": 42,
    "testTargets": [
      "CombineFilesCache#missingExtensions"
    ]
  },
  {
    "__docId__": 1218,
    "kind": "test",
    "name": "it500",
    "testId": 500,
    "memberof": "test/src/lib/transform/SplittingTransformer.spec.js~describe499",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/SplittingTransformer.spec.js~describe499.it500",
    "access": null,
    "description": "should return extensions if required files are missing",
    "lineNumber": 43
  },
  {
    "__docId__": 1219,
    "kind": "test",
    "name": "it501",
    "testId": 501,
    "memberof": "test/src/lib/transform/SplittingTransformer.spec.js~describe499",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/SplittingTransformer.spec.js~describe499.it501",
    "access": null,
    "description": "should return empty array if all required files are cached",
    "lineNumber": 51
  },
  {
    "__docId__": 1220,
    "kind": "test",
    "name": "describe502",
    "testId": 502,
    "memberof": "test/src/lib/transform/SplittingTransformer.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/transform/SplittingTransformer.spec.js~describe502",
    "access": null,
    "description": "SplittingTransformer",
    "lineNumber": 114,
    "testTargets": [
      "SplittingTransformer"
    ]
  },
  {
    "__docId__": 1221,
    "kind": "test",
    "name": "describe503",
    "testId": 503,
    "memberof": "test/src/lib/transform/SplittingTransformer.spec.js~describe502",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/SplittingTransformer.spec.js~describe502.describe503",
    "access": null,
    "description": "#transformFromFilesystem",
    "lineNumber": 116,
    "testTargets": [
      "SplittingTransformer#transformFromFilesystem"
    ]
  },
  {
    "__docId__": 1222,
    "kind": "test",
    "name": "it504",
    "testId": 504,
    "memberof": "test/src/lib/transform/SplittingTransformer.spec.js~describe502",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/SplittingTransformer.spec.js~describe502.it504",
    "access": null,
    "description": "should return a file",
    "lineNumber": 183
  },
  {
    "__docId__": 1223,
    "kind": "test",
    "name": "it505",
    "testId": 505,
    "memberof": "test/src/lib/transform/SplittingTransformer.spec.js~describe502",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/SplittingTransformer.spec.js~describe502.it505",
    "access": null,
    "description": "should apply the new extension",
    "lineNumber": 187
  },
  {
    "__docId__": 1224,
    "kind": "test",
    "name": "it506",
    "testId": 506,
    "memberof": "test/src/lib/transform/SplittingTransformer.spec.js~describe502",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/SplittingTransformer.spec.js~describe502.it506",
    "access": null,
    "description": "should return a file",
    "lineNumber": 199
  },
  {
    "__docId__": 1225,
    "kind": "test",
    "name": "it507",
    "testId": 507,
    "memberof": "test/src/lib/transform/SplittingTransformer.spec.js~describe502",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/SplittingTransformer.spec.js~describe502.it507",
    "access": null,
    "description": "should apply the new extension",
    "lineNumber": 203
  },
  {
    "__docId__": 1226,
    "kind": "test",
    "name": "it508",
    "testId": 508,
    "memberof": "test/src/lib/transform/SplittingTransformer.spec.js~describe502",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/SplittingTransformer.spec.js~describe502.it508",
    "access": null,
    "description": "should just callback if no files are missing",
    "lineNumber": 210
  },
  {
    "__docId__": 1227,
    "kind": "test",
    "name": "it509",
    "testId": 509,
    "memberof": "test/src/lib/transform/SplittingTransformer.spec.js~describe502",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/SplittingTransformer.spec.js~describe502.it509",
    "access": null,
    "description": "should push additional files if some are missing",
    "lineNumber": 219
  },
  {
    "__docId__": 1228,
    "kind": "test",
    "name": "it510",
    "testId": 510,
    "memberof": "test/src/lib/transform/SplittingTransformer.spec.js~describe502",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/SplittingTransformer.spec.js~describe502.it510",
    "access": null,
    "description": "should forward read errors",
    "lineNumber": 241
  },
  {
    "__docId__": 1229,
    "kind": "testFile",
    "name": "test/src/lib/transform/Transformer.spec.js",
    "content": "import { Stream } from 'stream';\nimport { inspect } from 'util';\nimport { stub } from 'sinon';\nimport { obj as createStream } from 'through2';\nimport expect from '../../../expect';\nimport Transformer, { TransformDirection } from '../../../../src/lib/transform/Transformer';\nimport AtviseFile from '../../../../src/lib/server/AtviseFile';\n\n/** @test {Transformer} */\ndescribe('Transformer', function () {\n  /** @test {Transformer#constructor} */\n  describe('#constructor', function () {\n    it('should throw with invalid direction', function () {\n      expect(() => new Transformer({ direction: 'asdf' }), 'to throw', 'Invalid direction');\n    });\n\n    it('should store direction', function () {\n      expect(\n        new Transformer({ direction: TransformDirection.FromDB }).direction,\n        'to equal',\n        TransformDirection.FromDB\n      );\n    });\n  });\n\n  /** @test {Transformer#withDirection} */\n  describe('#withDirection', function () {\n    let transformer;\n\n    beforeEach(() => (transformer = new Transformer()));\n\n    it('should throw without direction', function () {\n      expect(() => transformer.withDirection(), 'to throw', 'Invalid direction');\n    });\n\n    it('should throw with invalid direction', function () {\n      expect(() => transformer.withDirection('asdf'), 'to throw', 'Invalid direction');\n    });\n\n    it('should return self with direction set', function () {\n      const directed = transformer.withDirection(TransformDirection.FromDB);\n\n      expect(directed, 'to be a', Transformer);\n      expect(directed.direction, 'to equal', TransformDirection.FromDB);\n    });\n  });\n\n  /** @test {Transformer#_transform} */\n  describe.skip('#_transform', function () {\n    let transformer;\n\n    beforeEach(() => {\n      transformer = new Transformer();\n      stub(transformer, 'transformFromDB').callsFake((c, e, cb) => cb(null));\n      stub(transformer, 'transformFromFilesystem').callsFake((c, e, cb) => cb(null));\n    });\n\n    it('should fail without direction', function () {\n      return expect(\n        (cb) => transformer._transform({}, 'utf8', cb),\n        'to call the callback with error',\n        'Transformer has no direction'\n      );\n    });\n\n    it('should call transformFromDB with direction FromDB', function () {\n      transformer.withDirection(TransformDirection.FromDB)._transform({}, 'utf8', () => {});\n\n      return expect(transformer.transformFromDB, 'was called');\n    });\n\n    it('should call transformFromFilesystem with direction FromFilesystem', function () {\n      transformer.withDirection(TransformDirection.FromFilesystem)._transform({}, 'utf8', () => {});\n\n      return expect(transformer.transformFromFilesystem, 'was called');\n    });\n\n    it('should skip reference config files', function () {\n      const file = new AtviseFile({ path: './some/path/.index.htm.json' });\n      const stream = transformer.withDirection(TransformDirection.FromFilesystem);\n      return expect([file], 'when piped through', stream, 'to yield chunks satisfying', [\n        expect.it('to be', file),\n      ]).then(() => {\n        expect(transformer.transformFromDB, 'was not called');\n        expect(transformer.transformFromFilesystem, 'was not called');\n      });\n    });\n  });\n\n  /** @test {Transformer#transformFromDB} */\n  describe('#transformFromDB', function () {\n    const transformer = new Transformer();\n\n    it('should fail if not overridden', function () {\n      return expect(transformer.transformFromDB({}), 'to be rejected with', /must be overridden/);\n    });\n  });\n\n  /** @test {Transformer#transformFromFilesystem} */\n  describe('#transformFromFilesytem', function () {\n    const transformer = new Transformer();\n\n    it('should fail if not overridden', function () {\n      return expect(\n        transformer.transformFromFilesystem({}),\n        'to be rejected with',\n        /must be overridden/\n      );\n    });\n  });\n\n  /** @test {Transformer.applyTransformers} */\n  describe.skip('.applyTransformers', function () {\n    it('should throw on invalid direction', function () {\n      expect(\n        () => Transformer.applyTransformers(createStream(), [], 'asdf'),\n        'to throw error',\n        'Direction is invalid'\n      );\n    });\n\n    it('should return directed transformer if only one is passed', function () {\n      const firstTransformer = new Transformer();\n      const result = Transformer.applyTransformers(\n        createStream(),\n        [firstTransformer],\n        TransformDirection.FromDB\n      );\n\n      expect(result, 'to be', firstTransformer);\n      expect(firstTransformer.direction, 'to equal', TransformDirection.FromDB);\n    });\n\n    it('should return last transformer piped to previous', function () {\n      const firstTransformer = new Transformer();\n      const lastTransformer = new Transformer();\n      const result = Transformer.applyTransformers(\n        createStream(),\n        [firstTransformer, lastTransformer],\n        TransformDirection.FromDB\n      );\n\n      expect(result, 'to be', lastTransformer);\n      expect(firstTransformer.direction, 'to equal', TransformDirection.FromDB);\n      expect(lastTransformer.direction, 'to equal', TransformDirection.FromDB);\n    });\n\n    it('should reverse transformers if called with \"FromFilesystem\"', function () {\n      const firstTransformer = new Transformer();\n      const lastTransformer = new Transformer();\n      const result = Transformer.applyTransformers(\n        createStream(),\n        [firstTransformer, lastTransformer],\n        TransformDirection.FromFilesystem\n      );\n\n      expect(result, 'to be', firstTransformer);\n      expect(firstTransformer.direction, 'to equal', TransformDirection.FromFilesystem);\n      expect(lastTransformer.direction, 'to equal', TransformDirection.FromFilesystem);\n    });\n\n    it('should work with empty array as argument', function () {\n      expect(\n        Transformer.applyTransformers(createStream(), [], TransformDirection.FromDB),\n        'to be a',\n        Stream\n      );\n    });\n  });\n\n  /** @test {Transformer#inspect} @deprecated */\n  describe.skip('#inspect', function () {\n    it('should return constructor name if depth is less than zero ', function () {\n      expect(inspect(new Transformer({ opt: 'val' }), { depth: -1 }), 'to contain', 'Transformer');\n    });\n\n    it('should return options if depth is positive', function () {\n      expect(\n        inspect(new Transformer({ opt: 'val', opt2: 2 }), { depth: 1 }),\n        'to contain',\n        'Transformer',\n        \"opt: 'val'\",\n        'opt2: 2'\n      );\n    });\n\n    it('should return options if depth is null', function () {\n      expect(\n        inspect(new Transformer({ opt: 'val', opt2: 2 }), { depth: null }),\n        'to contain',\n        'Transformer',\n        \"opt: 'val'\",\n        'opt2: 2'\n      );\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/transform/Transformer.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1230,
    "kind": "test",
    "name": "describe511",
    "testId": 511,
    "memberof": "test/src/lib/transform/Transformer.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511",
    "access": null,
    "description": "Transformer",
    "lineNumber": 10,
    "testTargets": [
      "Transformer"
    ]
  },
  {
    "__docId__": 1231,
    "kind": "test",
    "name": "describe512",
    "testId": 512,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.describe512",
    "access": null,
    "description": "#constructor",
    "lineNumber": 12,
    "testTargets": [
      "Transformer#constructor"
    ]
  },
  {
    "__docId__": 1232,
    "kind": "test",
    "name": "it513",
    "testId": 513,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511.describe512",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.describe512.it513",
    "access": null,
    "description": "should throw with invalid direction",
    "lineNumber": 13
  },
  {
    "__docId__": 1233,
    "kind": "test",
    "name": "it514",
    "testId": 514,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511.describe512",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.describe512.it514",
    "access": null,
    "description": "should store direction",
    "lineNumber": 17
  },
  {
    "__docId__": 1234,
    "kind": "test",
    "name": "describe515",
    "testId": 515,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.describe515",
    "access": null,
    "description": "#withDirection",
    "lineNumber": 27,
    "testTargets": [
      "Transformer#withDirection"
    ]
  },
  {
    "__docId__": 1235,
    "kind": "test",
    "name": "it516",
    "testId": 516,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511.describe515",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.describe515.it516",
    "access": null,
    "description": "should throw without direction",
    "lineNumber": 32
  },
  {
    "__docId__": 1236,
    "kind": "test",
    "name": "it517",
    "testId": 517,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511.describe515",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.describe515.it517",
    "access": null,
    "description": "should throw with invalid direction",
    "lineNumber": 36
  },
  {
    "__docId__": 1237,
    "kind": "test",
    "name": "it518",
    "testId": 518,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511.describe515",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.describe515.it518",
    "access": null,
    "description": "should return self with direction set",
    "lineNumber": 40
  },
  {
    "__docId__": 1238,
    "kind": "test",
    "name": "it519",
    "testId": 519,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.it519",
    "access": null,
    "description": "should fail without direction",
    "lineNumber": 58
  },
  {
    "__docId__": 1239,
    "kind": "test",
    "name": "it520",
    "testId": 520,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.it520",
    "access": null,
    "description": "should call transformFromDB with direction FromDB",
    "lineNumber": 66
  },
  {
    "__docId__": 1240,
    "kind": "test",
    "name": "it521",
    "testId": 521,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.it521",
    "access": null,
    "description": "should call transformFromFilesystem with direction FromFilesystem",
    "lineNumber": 72
  },
  {
    "__docId__": 1241,
    "kind": "test",
    "name": "it522",
    "testId": 522,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.it522",
    "access": null,
    "description": "should skip reference config files",
    "lineNumber": 78
  },
  {
    "__docId__": 1242,
    "kind": "test",
    "name": "describe523",
    "testId": 523,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.describe523",
    "access": null,
    "description": "#transformFromDB",
    "lineNumber": 91,
    "testTargets": [
      "Transformer#transformFromDB"
    ]
  },
  {
    "__docId__": 1243,
    "kind": "test",
    "name": "it524",
    "testId": 524,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511.describe523",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.describe523.it524",
    "access": null,
    "description": "should fail if not overridden",
    "lineNumber": 94
  },
  {
    "__docId__": 1244,
    "kind": "test",
    "name": "describe525",
    "testId": 525,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.describe525",
    "access": null,
    "description": "#transformFromFilesytem",
    "lineNumber": 100,
    "testTargets": [
      "Transformer#transformFromFilesystem"
    ]
  },
  {
    "__docId__": 1245,
    "kind": "test",
    "name": "it526",
    "testId": 526,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511.describe525",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.describe525.it526",
    "access": null,
    "description": "should fail if not overridden",
    "lineNumber": 103
  },
  {
    "__docId__": 1246,
    "kind": "test",
    "name": "it527",
    "testId": 527,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.it527",
    "access": null,
    "description": "should throw on invalid direction",
    "lineNumber": 114
  },
  {
    "__docId__": 1247,
    "kind": "test",
    "name": "it528",
    "testId": 528,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.it528",
    "access": null,
    "description": "should return directed transformer if only one is passed",
    "lineNumber": 122
  },
  {
    "__docId__": 1248,
    "kind": "test",
    "name": "it529",
    "testId": 529,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.it529",
    "access": null,
    "description": "should return last transformer piped to previous",
    "lineNumber": 134
  },
  {
    "__docId__": 1249,
    "kind": "test",
    "name": "it530",
    "testId": 530,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.it530",
    "access": null,
    "description": "should reverse transformers if called with \"FromFilesystem\"",
    "lineNumber": 148
  },
  {
    "__docId__": 1250,
    "kind": "test",
    "name": "it531",
    "testId": 531,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.it531",
    "access": null,
    "description": "should work with empty array as argument",
    "lineNumber": 162
  },
  {
    "__docId__": 1251,
    "kind": "test",
    "name": "it532",
    "testId": 532,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.it532",
    "access": null,
    "description": "should return constructor name if depth is less than zero ",
    "lineNumber": 173
  },
  {
    "__docId__": 1252,
    "kind": "test",
    "name": "it533",
    "testId": 533,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.it533",
    "access": null,
    "description": "should return options if depth is positive",
    "lineNumber": 177
  },
  {
    "__docId__": 1253,
    "kind": "test",
    "name": "it534",
    "testId": 534,
    "memberof": "test/src/lib/transform/Transformer.spec.js~describe511",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/Transformer.spec.js~describe511.it534",
    "access": null,
    "description": "should return options if depth is null",
    "lineNumber": 187
  },
  {
    "__docId__": 1254,
    "kind": "testFile",
    "name": "test/src/lib/transform/XMLTransformer.spec.js",
    "content": "import { EOL } from 'os';\nimport expect from 'unexpected';\nimport { parse as xml2js } from 'modify-xml';\nimport Transformer, { TransformDirection } from '../../../../src/lib/transform/Transformer';\nimport XMLTransformer from '../../../../src/lib/transform/XMLTransformer';\n\nfunction nativeEOLs(string) {\n  return string.replace(/\\n/g, EOL);\n}\n\n/** @test {XMLTransformer} */\ndescribe('XMLTransformer', function () {\n  /** @test {XMLTransformer#constructor} */\n  describe('#constructor', function () {\n    it('should return a SplittingTransformer', function () {\n      expect(new XMLTransformer(), 'to be a', Transformer);\n    });\n\n    it('should create a _fromDBBuilder', function () {\n      const transformer = new XMLTransformer();\n\n      expect(transformer._fromDBBuilder, 'to be defined');\n      expect(transformer._fromDBBuilder, 'to be a', 'function');\n    });\n\n    it('should create a _fromFilesystemBuilder', function () {\n      const transformer = new XMLTransformer();\n\n      expect(transformer._fromDBBuilder, 'to be defined');\n      expect(transformer._fromDBBuilder, 'to be a', 'function');\n    });\n  });\n\n  /** @test {XMLTransformer#builder} */\n  describe('#builder', function () {\n    it('should return the #_fromDBBuilder if direction is FromDB', function () {\n      const transformer = new XMLTransformer({ direction: TransformDirection.FromDB });\n\n      expect(transformer.builder, 'to be defined');\n      expect(transformer.builder, 'to be', transformer._fromDBBuilder);\n    });\n\n    it('should return the #_fromDBBuilder if direction is FromFilesystem', function () {\n      const transformer = new XMLTransformer({ direction: TransformDirection.FromFilesystem });\n\n      expect(transformer.builder, 'to be defined');\n      expect(transformer.builder, 'to be', transformer._fromFilesystemBuilder);\n    });\n\n    it('should enforce tag order', function () {\n      const transformer = new XMLTransformer({ direction: TransformDirection.FromDB });\n      const dom = xml2js(\n        `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg>\n  <rect x=\"12\" y=\"13\"/>\n  <defs>\n    <some>defs</some>\n  </defs>\n  <metadata>\n    <some>meta</some>\n  </metadata>\n  <title>Test</title>\n</svg>`,\n        { compact: false }\n      );\n      expect(\n        transformer.builder(dom),\n        'to equal',\n        nativeEOLs(`<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<svg>\n  <title>Test</title>\n  <defs>\n    <some>defs</some>\n  </defs>\n  <metadata>\n    <some>meta</some>\n  </metadata>\n  <rect x=\"12\" y=\"13\"/>\n</svg>`)\n      );\n    });\n  });\n\n  /** @test {XMLTransformer#decodeContents} */\n  describe.skip('#decodeContents', function () {\n    it('should forward errors', function (done) {\n      expect(\n        (cb) => new XMLTransformer().decodeContents({ contents: 'no valid xml' }, cb),\n        'to call the callback with error',\n        /Text data outside of root node./\n      ).then(() => done());\n    });\n\n    it('should return object for valid xml', function (done) {\n      expect(\n        (cb) => new XMLTransformer().decodeContents({ contents: '<tag>value</tag>' }, cb),\n        'to call the callback'\n      ).then((args) => {\n        expect(args[0], 'to be falsy');\n        expect(args[1], 'to equal', {\n          elements: [\n            {\n              type: 'element',\n              name: 'tag',\n              elements: [\n                {\n                  type: 'text',\n                  text: 'value',\n                },\n              ],\n            },\n          ],\n        });\n        done();\n      });\n    });\n  });\n\n  const baseXmlObject = xml2js(\n    `<root>\n  <sub>test</sub>\n</root>`,\n    { compact: false }\n  );\n\n  const cdataXmlObject = xml2js(`<svg>\n  <script><![CDATA[test();]]></script>\n</svg>`);\n\n  function testBuilder(direction, object, expectedResult, callback) {\n    const transformer = new XMLTransformer({ direction });\n\n    expect((cb) => transformer.encodeContents(object, cb), 'to call the callback').then((args) => {\n      expect(args[0], 'to be falsy');\n      expect(args[1], 'to contain', expectedResult);\n      callback();\n    });\n  }\n\n  /** @test {XMLTransformer#encodeContents} */\n  describe.skip('#encodeContents', function () {\n    it('should forward errors', function () {\n      expect(\n        (cb) => new XMLTransformer().encodeContents(null, cb),\n        'to call the callback with error',\n        /Cannot read property/\n      );\n    });\n\n    context('when direction is FromDB', function () {\n      it('should indent with double space', function (done) {\n        testBuilder(\n          TransformDirection.FromDB,\n          baseXmlObject,\n          nativeEOLs(`<root>\n  <sub>test</sub>\n</root>`),\n          done\n        );\n      });\n    });\n\n    context('when direction is FromFilesytem', function () {\n      it('should indent with single space', function (done) {\n        testBuilder(\n          TransformDirection.FromFilesystem,\n          baseXmlObject,\n          '<root>\\r\\n <sub>test</sub>\\r\\n</root>',\n          done\n        );\n      });\n    });\n\n    it('should support CDATA', function () {\n      return expect(\n        (cb) =>\n          new XMLTransformer({ direction: TransformDirection.FromDB }).encodeContents(\n            cdataXmlObject,\n            cb\n          ),\n        'to call the callback'\n      ).then((args) =>\n        expect(\n          args[1],\n          'to end with',\n          nativeEOLs(`<svg>\n  <script><![CDATA[test();]]></script>\n</svg>`)\n        )\n      );\n    });\n\n    it(\"should escape '&' in attribute values\", function (done) {\n      const xml = nativeEOLs(`<root>\n  <node attribute=\"escape &amp; this\"/>\n</root>`);\n      const xmlObject = xml2js(xml);\n\n      testBuilder(TransformDirection.FromDB, xmlObject, xml, done);\n    });\n\n    it(\"should escape '<' in attribute values\", function (done) {\n      const xml = nativeEOLs(`<root>\n  <node attribute=\"escape &lt; this\"/>\n</root>`);\n      const xmlObject = xml2js(xml);\n\n      testBuilder(TransformDirection.FromDB, xmlObject, xml, done);\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/lib/transform/XMLTransformer.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1255,
    "kind": "test",
    "name": "describe535",
    "testId": 535,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535",
    "access": null,
    "description": "XMLTransformer",
    "lineNumber": 12,
    "testTargets": [
      "XMLTransformer"
    ]
  },
  {
    "__docId__": 1256,
    "kind": "test",
    "name": "describe536",
    "testId": 536,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.describe536",
    "access": null,
    "description": "#constructor",
    "lineNumber": 14,
    "testTargets": [
      "XMLTransformer#constructor"
    ]
  },
  {
    "__docId__": 1257,
    "kind": "test",
    "name": "it537",
    "testId": 537,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535.describe536",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.describe536.it537",
    "access": null,
    "description": "should return a SplittingTransformer",
    "lineNumber": 15
  },
  {
    "__docId__": 1258,
    "kind": "test",
    "name": "it538",
    "testId": 538,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535.describe536",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.describe536.it538",
    "access": null,
    "description": "should create a _fromDBBuilder",
    "lineNumber": 19
  },
  {
    "__docId__": 1259,
    "kind": "test",
    "name": "it539",
    "testId": 539,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535.describe536",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.describe536.it539",
    "access": null,
    "description": "should create a _fromFilesystemBuilder",
    "lineNumber": 26
  },
  {
    "__docId__": 1260,
    "kind": "test",
    "name": "describe540",
    "testId": 540,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.describe540",
    "access": null,
    "description": "#builder",
    "lineNumber": 35,
    "testTargets": [
      "XMLTransformer#builder"
    ]
  },
  {
    "__docId__": 1261,
    "kind": "test",
    "name": "it541",
    "testId": 541,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535.describe540",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.describe540.it541",
    "access": null,
    "description": "should return the #_fromDBBuilder if direction is FromDB",
    "lineNumber": 36
  },
  {
    "__docId__": 1262,
    "kind": "test",
    "name": "it542",
    "testId": 542,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535.describe540",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.describe540.it542",
    "access": null,
    "description": "should return the #_fromDBBuilder if direction is FromFilesystem",
    "lineNumber": 43
  },
  {
    "__docId__": 1263,
    "kind": "test",
    "name": "it543",
    "testId": 543,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535.describe540",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.describe540.it543",
    "access": null,
    "description": "should enforce tag order",
    "lineNumber": 50
  },
  {
    "__docId__": 1264,
    "kind": "test",
    "name": "it544",
    "testId": 544,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.it544",
    "access": null,
    "description": "should forward errors",
    "lineNumber": 86
  },
  {
    "__docId__": 1265,
    "kind": "test",
    "name": "it545",
    "testId": 545,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.it545",
    "access": null,
    "description": "should return object for valid xml",
    "lineNumber": 94
  },
  {
    "__docId__": 1266,
    "kind": "test",
    "name": "it546",
    "testId": 546,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.it546",
    "access": null,
    "description": "should forward errors",
    "lineNumber": 142
  },
  {
    "__docId__": 1267,
    "kind": "test",
    "name": "context547",
    "testId": 547,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.context547",
    "access": null,
    "description": "when direction is FromDB",
    "lineNumber": 150
  },
  {
    "__docId__": 1268,
    "kind": "test",
    "name": "it548",
    "testId": 548,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535.context547",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.context547.it548",
    "access": null,
    "description": "should indent with double space",
    "lineNumber": 151
  },
  {
    "__docId__": 1269,
    "kind": "test",
    "name": "context549",
    "testId": 549,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.context549",
    "access": null,
    "description": "when direction is FromFilesytem",
    "lineNumber": 163
  },
  {
    "__docId__": 1270,
    "kind": "test",
    "name": "it550",
    "testId": 550,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535.context549",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.context549.it550",
    "access": null,
    "description": "should indent with single space",
    "lineNumber": 164
  },
  {
    "__docId__": 1271,
    "kind": "test",
    "name": "it551",
    "testId": 551,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.it551",
    "access": null,
    "description": "should support CDATA",
    "lineNumber": 174
  },
  {
    "__docId__": 1272,
    "kind": "test",
    "name": "it552",
    "testId": 552,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.it552",
    "access": null,
    "description": "should escape '&' in attribute values",
    "lineNumber": 193
  },
  {
    "__docId__": 1273,
    "kind": "test",
    "name": "it553",
    "testId": 553,
    "memberof": "test/src/lib/transform/XMLTransformer.spec.js~describe535",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/lib/transform/XMLTransformer.spec.js~describe535.it553",
    "access": null,
    "description": "should escape '<' in attribute values",
    "lineNumber": 202
  },
  {
    "__docId__": 1274,
    "kind": "testFile",
    "name": "test/src/maintenance.spec.js",
    "content": "import Session from '../../src/lib/server/Session';\n\nprocess.on('unhandledRejection', (e) => {\n  process.emit('error', e);\n});\n\nbeforeEach(function () {\n  return Session.closeOpen().then((results) => {\n    if (results.length > 0) {\n      // eslint-disable-next-line no-console\n      console.log('Maintenance: Closed', results.length, 'open session');\n    }\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/maintenance.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1275,
    "kind": "testFile",
    "name": "test/src/tasks/import.spec.js",
    "content": "import { basename } from 'path';\nimport { read_service as ReadService } from 'node-opcua';\nimport scriptFiles from '@atscm/server-scripts';\nimport expect from '../../expect';\nimport importTask from '../../../src/tasks/import';\nimport Session from '../../../src/lib/server/Session';\n\n/** @test {importTask} */\ndescribe('importTask', function () {\n  it.skip('should import all scripts', async function () {\n    const startTime = Date.now();\n\n    await expect(importTask(), 'to yield objects satisfying', []);\n\n    const base = 'ns=1;s=SYSTEM.LIBRARY.ATVISE.SERVERSCRIPTS.atscm';\n\n    const session = await Session.create();\n    const scriptNames = scriptFiles.map((s) => basename(s, '.xml'));\n\n    const results = await expect(\n      (cb) =>\n        session.read(\n          scriptNames.map((script) => ({\n            nodeId: `${base}.${script}`,\n            attributeId: ReadService.AttributeIds.ServerTimestamp,\n          })),\n          cb\n        ),\n      'to call the callback without error'\n    ).then((all) => all[1]);\n\n    return expect(\n      results.map((r) => r.serverTimestamp),\n      'to have items satisfying',\n      (item) => {\n        expect(item, 'to be a', Date);\n        expect(item.valueOf(), 'to be greater than or equal to', startTime);\n      }\n    );\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/tasks/import.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1276,
    "kind": "test",
    "name": "describe554",
    "testId": 554,
    "memberof": "test/src/tasks/import.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/tasks/import.spec.js~describe554",
    "access": null,
    "description": "importTask",
    "lineNumber": 9,
    "testTargets": [
      "importTask"
    ]
  },
  {
    "__docId__": 1277,
    "kind": "testFile",
    "name": "test/src/tasks/pull.spec.js",
    "content": "import expect from 'unexpected';\nimport proxyquire from 'proxyquire';\nimport { ctor as throughStreamClass } from 'through2';\nimport { NodeClass } from 'node-opcua';\nimport NodeId from '../../../src/lib/model/opcua/NodeId';\n\nconst pull = proxyquire('../../../src/tasks/pull', {\n  '../lib/server/NodeStream': {\n    _esModule: true,\n    default: class StubStream extends throughStreamClass({ objectMode: true }) {\n      constructor() {\n        super();\n\n        this.push({\n          nodeId: new NodeId('AGENT.DISPLAYS.Main'),\n          typeDefinition: new NodeId('VariableTypes.ATVISE.Display'),\n          nodeClass: NodeClass.Variable,\n        });\n\n        this.end();\n      }\n    },\n  },\n  '../lib/server/NodeBrowser': {\n    _esModule: true,\n    default: class NBrowser {\n      async browse() {\n        return true;\n      }\n    },\n  },\n}).default;\n\n/** @test {pull} */\ndescribe('pull', function () {\n  it('should return a promise', function () {\n    const task = pull();\n\n    expect(task, 'to be a', Promise);\n\n    return task;\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/tasks/pull.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1278,
    "kind": "test",
    "name": "describe555",
    "testId": 555,
    "memberof": "test/src/tasks/pull.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/tasks/pull.spec.js~describe555",
    "access": null,
    "description": "pull",
    "lineNumber": 35,
    "testTargets": [
      "pull"
    ]
  },
  {
    "__docId__": 1279,
    "kind": "test",
    "name": "it556",
    "testId": 556,
    "memberof": "test/src/tasks/pull.spec.js~describe555",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/tasks/pull.spec.js~describe555.it556",
    "access": null,
    "description": "should return a promise",
    "lineNumber": 36
  },
  {
    "__docId__": 1280,
    "kind": "testFile",
    "name": "test/src/tasks/push.spec.js",
    "content": "import proxyquire from 'proxyquire';\nimport expect from '../../expect';\n\nconst push = proxyquire('../../../src/tasks/push', {\n  '../api': {\n    _esModule: true,\n    async readNode() {\n      throw new Error('Test');\n    },\n  },\n}).default;\n\n/** @test {push} */\ndescribe('push', function () {\n  it('should return a promise', function () {\n    const promise = push();\n    expect(promise, 'to be a', Promise);\n\n    return promise.catch((err) => {\n      if (err.message === 'Test') {\n        return;\n      }\n\n      throw err;\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/tasks/push.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1281,
    "kind": "test",
    "name": "describe557",
    "testId": 557,
    "memberof": "test/src/tasks/push.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/tasks/push.spec.js~describe557",
    "access": null,
    "description": "push",
    "lineNumber": 14,
    "testTargets": [
      "push"
    ]
  },
  {
    "__docId__": 1282,
    "kind": "test",
    "name": "it558",
    "testId": 558,
    "memberof": "test/src/tasks/push.spec.js~describe557",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/tasks/push.spec.js~describe557.it558",
    "access": null,
    "description": "should return a promise",
    "lineNumber": 15
  },
  {
    "__docId__": 1283,
    "kind": "testFile",
    "name": "test/src/tasks/watch.spec.js",
    "content": "import Emitter from 'events';\nimport proxyquire from 'proxyquire';\nimport { obj as createThroughStream } from 'through2';\nimport { spy, stub } from 'sinon';\nimport expect from '../../expect';\nimport watch, { WatchTask } from '../../../src/tasks/watch';\nimport NodeId from '../../../src/lib/model/opcua/NodeId';\n\nclass TestEmitter extends Emitter {\n  constructor(name, payload = true, delay = 1) {\n    super();\n\n    setTimeout(() => this.emit(name, payload), delay);\n  }\n}\n\nclass NoopStream {\n  constructor(otherStream) {\n    return otherStream.pipe(createThroughStream()).on('data', () => {});\n  }\n}\n\nconst stubGulp = {\n  src(path, options) {\n    const stream = createThroughStream();\n    stream.write(Object.assign({}, options, { path, nodeId: 'source node id' }));\n    stream.end();\n\n    return stream;\n  },\n};\n\nconst stubModule = proxyquire('../../../src/tasks/watch', {\n  sane: () => new TestEmitter('ready', 1),\n  'browser-sync': {\n    create() {\n      return {\n        init() {\n          this.emitter.emit('service:running', true);\n        },\n        emitter: new TestEmitter(),\n        // eslint-disable-next-line @typescript-eslint/no-empty-function\n        reload() {},\n      };\n    },\n  },\n  gulp: stubGulp,\n  '../util/fs': {\n    validateDirectoryExists: () => Promise.resolve(true),\n  },\n  '../lib/server/Watcher': {\n    default: class extends TestEmitter {\n      constructor() {\n        super('ready', 1);\n      }\n    },\n  },\n  '../lib/gulp/PullStream': { default: NoopStream },\n  '../lib/gulp/PushStream': { default: NoopStream },\n});\n\nconst StubWatchTask = stubModule.WatchTask;\nconst stubWatch = stubModule.default;\n\n/** @test {WatchTask} */\ndescribe('WatchTask', function () {\n  /** @test {WatchTask#constructor} */\n  describe('#constructor', function () {\n    it('should create a new browser-sync instance', function () {\n      expect(new WatchTask().browserSyncInstance, 'to be defined');\n    });\n  });\n\n  /** @test {WatchTask#_waitForWatcher} */\n  describe('#_waitForWatcher', function () {\n    it('should be rejected on error', function () {\n      const task = new WatchTask();\n      const fakeWatcher = new TestEmitter('error', new Error('Test error'));\n\n      return expect(task._waitForWatcher(fakeWatcher), 'to be rejected with', 'Test error');\n    });\n\n    it('should be fulfilled on ready', function () {\n      const task = new WatchTask();\n      const fakeWatcher = new TestEmitter('ready');\n\n      return expect(task._waitForWatcher(fakeWatcher), 'to be fulfilled');\n    });\n  });\n\n  /** @test {WatchTask#startFileWatcher} */\n  describe('#startFileWatcher', function () {\n    it('should fail if directory does not exist', function () {\n      class FailingTask extends WatchTask {\n        get directoryToWatch() {\n          return './does-not-exist';\n        }\n      }\n\n      const task = new FailingTask();\n\n      return expect(task.startFileWatcher(), 'to be rejected with', /does not exist/);\n    });\n\n    it('should fail if fs#stat fails', function () {\n      class FailingTask extends WatchTask {\n        get directoryToWatch() {\n          return 13;\n        }\n      }\n\n      const task = new FailingTask();\n\n      return expect(\n        task.startFileWatcher(),\n        'to be rejected with',\n        /\"?Path\"?.* must be (a|of type) string/i\n      );\n    });\n\n    it('should call #_waitForWatcher', function () {\n      const task = new StubWatchTask();\n      spy(task, '_waitForWatcher');\n\n      return expect(task.startFileWatcher(), 'to be fulfilled').then(() =>\n        expect(task._waitForWatcher, 'was called once')\n      );\n    });\n  });\n\n  /** @test {WatchTask#startServerWatcher} */\n  describe('#startServerWatcher', function () {\n    it('should call #_waitForWatcher', function () {\n      const task = new StubWatchTask();\n      spy(task, '_waitForWatcher');\n\n      return expect(task.startServerWatcher(), 'to be fulfilled').then(() =>\n        expect(task._waitForWatcher, 'was called once')\n      );\n    });\n  });\n\n  /** @test {WatchTask#initBrowserSync} */\n  describe('#initBrowserSync', function () {\n    it('should call BrowserSync#init', function () {\n      const task = new WatchTask();\n      stub(task.browserSyncInstance, 'init').returns(true);\n\n      task.initBrowserSync();\n      expect(task.browserSyncInstance.init, 'was called once');\n    });\n  });\n\n  /** @test {WatchTask#handleFileChange} */\n  describe('#handleFileChange', function () {\n    it.skip('should not do anything when lately pulled files change', function () {\n      const task = new StubWatchTask();\n\n      return expect(\n        task.handleFileChange('./path.file', './src', { mtime: new Date(-10000) }),\n        'to be fulfilled with',\n        false\n      );\n    });\n\n    it('should not do anything while pulling', function () {\n      const task = new StubWatchTask();\n      task._handlingChange = true;\n\n      return expect(\n        task.handleFileChange('./path.file', './src', { mtime: new Date(Date.now()) }),\n        'to be fulfilled with',\n        false\n      );\n    });\n\n    it.skip('should push changed files', function () {\n      const task = new StubWatchTask();\n\n      return expect(\n        task.handleFileChange('./path.file', './src', { mtime: new Date(Date.now()) }),\n        'to be fulfilled with',\n        true\n      );\n    });\n\n    it.skip('should reload browser', function () {\n      const task = new StubWatchTask();\n      spy(task.browserSyncInstance, 'reload');\n\n      return expect(\n        task.handleFileChange('./path.file', './src', { mtime: new Date(Date.now()) }),\n        'to be fulfilled with',\n        true\n      ).then(() => expect(task.browserSyncInstance.reload, 'was called once'));\n    });\n  });\n\n  /** @test {WatchTask#handleServerChange} */\n  describe('#handleServerChange', function () {\n    it('should do nothing while pushing', function () {\n      const task = new StubWatchTask();\n      task._handlingChange = true;\n\n      return expect(\n        task.handleServerChange({\n          nodeId: new NodeId('AGENT.OBJECTS.Test'),\n        }),\n        'to be fulfilled with',\n        false\n      );\n    });\n\n    it.skip('should do nothing when handling node that was just pushed', function () {\n      const task = new StubWatchTask();\n      task._lastPushed = 'ns=13;s=Test';\n\n      return expect(\n        task.handleServerChange({ nodeId: task._lastPushed }),\n        'to be fulfilled with',\n        false\n      );\n    });\n\n    it.skip('should pull changed nodes', function () {\n      const task = new StubWatchTask();\n\n      return expect(\n        task.handleServerChange({ nodeId: 'ns=13;s=Test', mtime: new Date() }),\n        'to be fulfilled with',\n        true\n      );\n    });\n  });\n\n  /** @test {WatchTask#run} */\n  describe('#run', function () {\n    it('should fail if file watcher errors', function () {\n      const task = new StubWatchTask();\n      task.startFileWatcher = () => Promise.reject(new Error('Test'));\n\n      return expect(task.run(), 'to be rejected with', 'Test');\n    });\n\n    it('should fail if server watcher errors', function () {\n      const task = new StubWatchTask();\n      task.startServerWatcher = () => Promise.reject(new Error('Test'));\n\n      return expect(task.run(), 'to be rejected with', 'Test');\n    });\n\n    it('should init browser sync', function () {\n      const task = new StubWatchTask();\n      stub(task.browserSyncInstance, 'init').callsFake(() => {\n        task.browserSyncInstance.emitter.emit('service:running', true);\n      });\n\n      return expect(task.run(), 'to be fulfilled').then(() =>\n        expect(task.browserSyncInstance.init, 'was called once')\n      );\n    });\n  });\n});\n\n/** @test {watch} */\ndescribe('watch', function () {\n  it('should export a function', function () {\n    expect(watch, 'to be a', 'function');\n  });\n\n  it('should resolve once watchers are ready', function () {\n    return expect(stubWatch(), 'to be fulfilled');\n  });\n\n  it('should export a description', function () {\n    expect(watch.description, 'to be defined');\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/tasks/watch.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1284,
    "kind": "test",
    "name": "describe559",
    "testId": 559,
    "memberof": "test/src/tasks/watch.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559",
    "access": null,
    "description": "WatchTask",
    "lineNumber": 66,
    "testTargets": [
      "WatchTask"
    ]
  },
  {
    "__docId__": 1285,
    "kind": "test",
    "name": "describe560",
    "testId": 560,
    "memberof": "test/src/tasks/watch.spec.js~describe559",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe560",
    "access": null,
    "description": "#constructor",
    "lineNumber": 68,
    "testTargets": [
      "WatchTask#constructor"
    ]
  },
  {
    "__docId__": 1286,
    "kind": "test",
    "name": "it561",
    "testId": 561,
    "memberof": "test/src/tasks/watch.spec.js~describe559.describe560",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe560.it561",
    "access": null,
    "description": "should create a new browser-sync instance",
    "lineNumber": 69
  },
  {
    "__docId__": 1287,
    "kind": "test",
    "name": "describe562",
    "testId": 562,
    "memberof": "test/src/tasks/watch.spec.js~describe559",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe562",
    "access": null,
    "description": "#_waitForWatcher",
    "lineNumber": 75,
    "testTargets": [
      "WatchTask#_waitForWatcher"
    ]
  },
  {
    "__docId__": 1288,
    "kind": "test",
    "name": "it563",
    "testId": 563,
    "memberof": "test/src/tasks/watch.spec.js~describe559.describe562",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe562.it563",
    "access": null,
    "description": "should be rejected on error",
    "lineNumber": 76
  },
  {
    "__docId__": 1289,
    "kind": "test",
    "name": "it564",
    "testId": 564,
    "memberof": "test/src/tasks/watch.spec.js~describe559.describe562",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe562.it564",
    "access": null,
    "description": "should be fulfilled on ready",
    "lineNumber": 83
  },
  {
    "__docId__": 1290,
    "kind": "test",
    "name": "describe565",
    "testId": 565,
    "memberof": "test/src/tasks/watch.spec.js~describe559",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe565",
    "access": null,
    "description": "#startFileWatcher",
    "lineNumber": 92,
    "testTargets": [
      "WatchTask#startFileWatcher"
    ]
  },
  {
    "__docId__": 1291,
    "kind": "test",
    "name": "it566",
    "testId": 566,
    "memberof": "test/src/tasks/watch.spec.js~describe559.describe565",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe565.it566",
    "access": null,
    "description": "should fail if directory does not exist",
    "lineNumber": 93
  },
  {
    "__docId__": 1292,
    "kind": "test",
    "name": "it567",
    "testId": 567,
    "memberof": "test/src/tasks/watch.spec.js~describe559.describe565",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe565.it567",
    "access": null,
    "description": "should fail if fs#stat fails",
    "lineNumber": 105
  },
  {
    "__docId__": 1293,
    "kind": "test",
    "name": "it568",
    "testId": 568,
    "memberof": "test/src/tasks/watch.spec.js~describe559.describe565",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe565.it568",
    "access": null,
    "description": "should call #_waitForWatcher",
    "lineNumber": 121
  },
  {
    "__docId__": 1294,
    "kind": "test",
    "name": "describe569",
    "testId": 569,
    "memberof": "test/src/tasks/watch.spec.js~describe559",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe569",
    "access": null,
    "description": "#startServerWatcher",
    "lineNumber": 132,
    "testTargets": [
      "WatchTask#startServerWatcher"
    ]
  },
  {
    "__docId__": 1295,
    "kind": "test",
    "name": "it570",
    "testId": 570,
    "memberof": "test/src/tasks/watch.spec.js~describe559.describe569",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe569.it570",
    "access": null,
    "description": "should call #_waitForWatcher",
    "lineNumber": 133
  },
  {
    "__docId__": 1296,
    "kind": "test",
    "name": "describe571",
    "testId": 571,
    "memberof": "test/src/tasks/watch.spec.js~describe559",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe571",
    "access": null,
    "description": "#initBrowserSync",
    "lineNumber": 144,
    "testTargets": [
      "WatchTask#initBrowserSync"
    ]
  },
  {
    "__docId__": 1297,
    "kind": "test",
    "name": "it572",
    "testId": 572,
    "memberof": "test/src/tasks/watch.spec.js~describe559.describe571",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe571.it572",
    "access": null,
    "description": "should call BrowserSync#init",
    "lineNumber": 145
  },
  {
    "__docId__": 1298,
    "kind": "test",
    "name": "describe573",
    "testId": 573,
    "memberof": "test/src/tasks/watch.spec.js~describe559",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe573",
    "access": null,
    "description": "#handleFileChange",
    "lineNumber": 155,
    "testTargets": [
      "WatchTask#handleFileChange"
    ]
  },
  {
    "__docId__": 1299,
    "kind": "test",
    "name": "it574",
    "testId": 574,
    "memberof": "test/src/tasks/watch.spec.js~describe559.describe573",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe573.it574",
    "access": null,
    "description": "should not do anything while pulling",
    "lineNumber": 166
  },
  {
    "__docId__": 1300,
    "kind": "test",
    "name": "describe575",
    "testId": 575,
    "memberof": "test/src/tasks/watch.spec.js~describe559",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe575",
    "access": null,
    "description": "#handleServerChange",
    "lineNumber": 200,
    "testTargets": [
      "WatchTask#handleServerChange"
    ]
  },
  {
    "__docId__": 1301,
    "kind": "test",
    "name": "it576",
    "testId": 576,
    "memberof": "test/src/tasks/watch.spec.js~describe559.describe575",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe575.it576",
    "access": null,
    "description": "should do nothing while pushing",
    "lineNumber": 201
  },
  {
    "__docId__": 1302,
    "kind": "test",
    "name": "describe577",
    "testId": 577,
    "memberof": "test/src/tasks/watch.spec.js~describe559",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe577",
    "access": null,
    "description": "#run",
    "lineNumber": 237,
    "testTargets": [
      "WatchTask#run"
    ]
  },
  {
    "__docId__": 1303,
    "kind": "test",
    "name": "it578",
    "testId": 578,
    "memberof": "test/src/tasks/watch.spec.js~describe559.describe577",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe577.it578",
    "access": null,
    "description": "should fail if file watcher errors",
    "lineNumber": 238
  },
  {
    "__docId__": 1304,
    "kind": "test",
    "name": "it579",
    "testId": 579,
    "memberof": "test/src/tasks/watch.spec.js~describe559.describe577",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe577.it579",
    "access": null,
    "description": "should fail if server watcher errors",
    "lineNumber": 245
  },
  {
    "__docId__": 1305,
    "kind": "test",
    "name": "it580",
    "testId": 580,
    "memberof": "test/src/tasks/watch.spec.js~describe559.describe577",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe559.describe577.it580",
    "access": null,
    "description": "should init browser sync",
    "lineNumber": 252
  },
  {
    "__docId__": 1306,
    "kind": "test",
    "name": "describe581",
    "testId": 581,
    "memberof": "test/src/tasks/watch.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe581",
    "access": null,
    "description": "watch",
    "lineNumber": 266,
    "testTargets": [
      "watch"
    ]
  },
  {
    "__docId__": 1307,
    "kind": "test",
    "name": "it582",
    "testId": 582,
    "memberof": "test/src/tasks/watch.spec.js~describe581",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe581.it582",
    "access": null,
    "description": "should export a function",
    "lineNumber": 267
  },
  {
    "__docId__": 1308,
    "kind": "test",
    "name": "it583",
    "testId": 583,
    "memberof": "test/src/tasks/watch.spec.js~describe581",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe581.it583",
    "access": null,
    "description": "should resolve once watchers are ready",
    "lineNumber": 271
  },
  {
    "__docId__": 1309,
    "kind": "test",
    "name": "it584",
    "testId": 584,
    "memberof": "test/src/tasks/watch.spec.js~describe581",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/tasks/watch.spec.js~describe581.it584",
    "access": null,
    "description": "should export a description",
    "lineNumber": 275
  },
  {
    "__docId__": 1310,
    "kind": "testFile",
    "name": "test/src/transform/DisplayTransformer.spec.js",
    "content": "import { Buffer } from 'buffer';\nimport File from 'vinyl';\nimport { stub } from 'sinon';\nimport expect from '../../expect';\nimport AtviseFile from '../../../src/lib/server/AtviseFile';\nimport { TransformDirection } from '../../../src/lib/transform/Transformer';\nimport DisplayTransformer from '../../../src/transform/DisplayTransformer';\n\n/** @test {DisplayTransformer} */\ndescribe.skip('DisplayTransformer', function () {\n  const nonDisplayFile = { isDisplay: false };\n\n  /** @test {DisplayTransformer#shouldBeTransformed} */\n  describe('#shouldBeTransformed', function () {\n    it('should return false for non-display files', function () {\n      expect(DisplayTransformer.prototype.shouldBeTransformed(nonDisplayFile), 'to equal', false);\n    });\n  });\n\n  /** @test {DisplayTransformer#transformFromDB} */\n  describe('#transformFromDB', function () {\n    function writeXMLToDisplayTransformer(xmlString) {\n      const transformer = new DisplayTransformer({ direction: TransformDirection.FromDB });\n      const file = new AtviseFile({\n        path: 'AGENT/DISPLAYS/Main.display.xml',\n        contents: Buffer.from(`<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n${xmlString}`),\n      });\n\n      const data = [];\n      transformer.on('data', (d) => data.push(d));\n\n      const promise = new Promise((resolve, reject) => {\n        transformer.once('error', (err) => reject(err));\n        transformer.once('end', () => resolve(data));\n      });\n\n      transformer.write(file);\n      transformer.end();\n\n      return promise;\n    }\n\n    it('should forward parse errors', function () {\n      return expect(\n        writeXMLToDisplayTransformer('invalid xml'),\n        'to be rejected with',\n        /Text data outside of root node/\n      );\n    });\n\n    it('should error with invalid xml', function () {\n      return expect(writeXMLToDisplayTransformer(''), 'to be rejected with', /No `svg` tag/);\n    });\n\n    function expectFileContents(xmlString, filter) {\n      return expect(writeXMLToDisplayTransformer(xmlString), 'to be fulfilled').then(\n        (resultingFiles) => {\n          const _files = resultingFiles.filter(filter);\n          try {\n            expect(_files, 'to have length', 1);\n          } catch (e) {\n            throw new Error('Error in expectFileContents: filter returned multiple files');\n          }\n\n          const file = _files[0];\n\n          return expect(file.contents, 'when decoded as', 'utf-8');\n        }\n      );\n    }\n\n    function expectConfig(xmlString) {\n      return expectFileContents(xmlString, (file) => file.extname === '.json').then((string) => {\n        let obj;\n        expect(() => (obj = JSON.parse(string)), 'not to throw');\n        return obj;\n      });\n    }\n\n    it('should store empty config for empty display', function () {\n      return expectConfig('<svg></svg>').then((config) => {\n        expect(config, 'to equal', {});\n      });\n    });\n\n    it('should store dependencies in config when referenced as \"src\"', function () {\n      return expectConfig(`<svg>\n  <script src=\"path/to/dependency.js\"></script>\n</svg>`).then((config) => {\n        expect(config.dependencies, 'to be defined');\n        expect(config.dependencies, 'to have length', 1);\n        expect(config.dependencies[0], 'to equal', 'path/to/dependency.js');\n      });\n    });\n\n    it('should store dependencies in config when referenced as \"xlink:href\"', function () {\n      return expectConfig(`<svg>\n  <script xlink:href=\"path/to/dependency.js\"></script>\n</svg>`).then((config) => {\n        expect(config.dependencies, 'to be defined');\n        expect(config.dependencies, 'to have length', 1);\n        expect(config.dependencies[0], 'to equal', 'path/to/dependency.js');\n      });\n    });\n\n    it('should store multiple dependencies in config', function () {\n      return expectConfig(`<svg>\n  <script src=\"path/to/dependency1.js\"></script>\n  <script src=\"path/to/dependency2.js\"></script>\n</svg>`).then((config) => {\n        expect(config.dependencies, 'to be defined');\n        expect(config.dependencies, 'to have length', 2);\n        expect(config.dependencies[0], 'to equal', 'path/to/dependency1.js');\n        expect(config.dependencies[1], 'to equal', 'path/to/dependency2.js');\n      });\n    });\n\n    context('when display contains inline script', function () {\n      const script = 'console.log(\"called\");';\n\n      it('should be stored when given with attributes', function () {\n        return expectFileContents(\n          `<svg>\n  <script type=\"text/javascript\">${script}</script>\n</svg>`,\n          (file) => file.extname === '.js'\n        ).then((string) => {\n          expect(string, 'to equal', script);\n        });\n      });\n\n      it('should be stored when given without attributes', function () {\n        return expectFileContents(\n          `<svg>\n  <script>${script}</script>\n</svg>`,\n          (file) => file.extname === '.js'\n        ).then((string) => {\n          expect(string, 'to equal', script);\n        });\n      });\n\n      it('should store empty inline scripts in separate file', function () {\n        return expectFileContents(\n          `<svg>\n  <script type=\"text/javascript\"></script>\n</svg>`,\n          (file) => file.extname === '.js'\n        ).then((string) => {\n          expect(string, 'to equal', '');\n        });\n      });\n    });\n\n    context('when display contains metadata tag', function () {\n      it('should work without actual metadata', function () {\n        return expectConfig(`<svg>\n  <metadata></metadata>\n</svg>`).then((config) => {\n          expect(config, 'to be defined');\n        });\n      });\n\n      it('should work without parameters', function () {\n        return expectConfig(`<svg>\n  <metadata>\n    <atv:gridconfig height=\"20\" width=\"20\" enabled=\"false\" gridstyle=\"lines\"/>\n  </metadata>\n</svg>`).then((config) => {\n          expect(config, 'to be defined');\n        });\n      });\n\n      it('should store parameters', function () {\n        return expectConfig(`<svg>\n  <metadata>\n    <atv:parameter behavior=\"mandatory\" desc=\"base\" valuetype=\"address\" name=\"base\"/>\n    <atv:parameter behavior=\"optional\" desc=\"state label\" substitute=\"$LABEL$\" valuetype=\"trstring\"\n      defaultvalue=\"T{Switched on}\" name=\"labelOn\"/>\n  </metadata>\n</svg>`).then((config) => {\n          expect(config.parameters, 'to be defined');\n          expect(config.parameters, 'to be a', Array);\n          expect(config.parameters, 'to have length', 2);\n          expect(config.parameters[0], 'to equal', {\n            name: 'base',\n            behavior: 'mandatory',\n            desc: 'base',\n            valuetype: 'address',\n          });\n          expect(config.parameters[1], 'to equal', {\n            name: 'labelOn',\n            behavior: 'optional',\n            desc: 'state label',\n            valuetype: 'trstring',\n            defaultvalue: 'T{Switched on}',\n            substitute: '$LABEL$',\n          });\n        });\n      });\n    });\n\n    context('when encoding fails', function () {\n      beforeEach(() =>\n        stub(DisplayTransformer.prototype, 'encodeContents').callsFake((obj, cb) =>\n          cb(new Error('Encode error'))\n        )\n      );\n      afterEach(() => DisplayTransformer.prototype.encodeContents.restore());\n\n      it('should forward encode error', function () {\n        return expect(\n          writeXMLToDisplayTransformer('<svg></svg>'),\n          'to be rejected with',\n          /Encode error/\n        );\n      });\n    });\n  });\n\n  /** @test {DisplayTransformer#createCombinedFile} */\n  describe('#createCombinedFile', function () {\n    function createDisplayWithFileContents(contents) {\n      let lastKey;\n      const files = Object.keys(contents).reduce((prev, ext) => {\n        const result = prev;\n\n        result[ext] = new File({\n          path: `path/to/test.display/test${ext}`,\n          contents: Buffer.from(contents[ext]),\n        });\n\n        lastKey = ext;\n        return result;\n      }, {});\n\n      const transformer = new DisplayTransformer({ direction: TransformDirection.FromFilesystem });\n\n      return (cb) => transformer.createCombinedFile(files, files[lastKey], cb);\n    }\n\n    it('should fail with invalid config file', function () {\n      return expect(\n        createDisplayWithFileContents({\n          '.json': '',\n        }),\n        'to call the callback with error',\n        /Error parsing JSON/\n      );\n    });\n\n    it('should fail without SVG file', function () {\n      return expect(\n        createDisplayWithFileContents({\n          '.json': '{}',\n        }),\n        'to call the callback with error',\n        /No display SVG in/\n      );\n    });\n\n    it('should fail with invalid SVG', function () {\n      return expect(\n        createDisplayWithFileContents({\n          '.svg': 'invalid XML',\n        }),\n        'to call the callback with error',\n        /Text data outside of root node/\n      );\n    });\n\n    it('should fail without `svg` tag', function () {\n      return expect(\n        createDisplayWithFileContents({\n          '.svg': '<root></root>',\n        }),\n        'to call the callback with error',\n        /Error parsing display SVG: No `svg` tag/\n      );\n    });\n\n    function expectDisplayWithFileContentToHaveXML(contents, xmlString) {\n      return expect(createDisplayWithFileContents(contents), 'to call the callback').then(\n        (args) => {\n          expect(args[0], 'to be falsy');\n          expect(args[1], 'to be a', File);\n          expect(args[1].contents, 'to be a', Buffer);\n\n          return expect(\n            args[1].contents.toString(),\n            'to equal',\n            `<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n${xmlString}`.replace(/\\r?\\n|\\r/g, '\\r\\n')\n          );\n        }\n      );\n    }\n\n    it('should work with empty svg tag', function () {\n      return expectDisplayWithFileContentToHaveXML(\n        {\n          '.svg': '<svg></svg>',\n        },\n        '<svg/>'\n      );\n    });\n\n    it('should inline script', function () {\n      return expectDisplayWithFileContentToHaveXML(\n        {\n          '.svg': '<svg><rect></rect></svg>',\n          '.js': 'code()',\n        },\n        `<svg>\n <rect/>\n <script type=\"text/ecmascript\"><![CDATA[code()]]></script>\n</svg>`\n      );\n    });\n\n    it('should link dependencies', function () {\n      return expectDisplayWithFileContentToHaveXML(\n        {\n          '.svg': '<svg><rect></rect></svg>',\n          '.json': '{ \"dependencies\": [\"path/to/dep.js\"] }',\n        },\n        `<svg>\n <rect/>\n <script xlink:href=\"path/to/dep.js\"/>\n</svg>`\n      );\n    });\n\n    it('should work without empty parameters config', function () {\n      return expectDisplayWithFileContentToHaveXML(\n        {\n          '.svg': '<svg><rect></rect></svg>',\n          '.json': '{ \"parameters\": [] }',\n        },\n        `<svg>\n <rect/>\n</svg>`\n      );\n    });\n\n    it('should reuse existant metadata section', function () {\n      return expectDisplayWithFileContentToHaveXML(\n        {\n          '.svg': `<svg>\n  <metadata>\n    <atv:gridconfig height=\"20\" width=\"20\" enabled=\"false\" gridstyle=\"lines\"/>\n  </metadata>\n</svg>`,\n          '.json': '{ \"parameters\": [{ \"name\": \"test\" }] }',\n        },\n        `<svg>\n <metadata>\n  <atv:parameter name=\"test\"/>\n  <atv:gridconfig height=\"20\" width=\"20\" enabled=\"false\" gridstyle=\"lines\"/>\n </metadata>\n</svg>`\n      );\n    });\n\n    it('should create metadata section if omitted', function () {\n      return expectDisplayWithFileContentToHaveXML(\n        {\n          '.svg': '<svg></svg>',\n          '.json': '{ \"parameters\": [{ \"name\": \"test\" }] }',\n        },\n        `<svg>\n <metadata>\n  <atv:parameter name=\"test\"/>\n </metadata>\n</svg>`\n      );\n    });\n\n    it('should keep parameters specified in SVG', function () {\n      return expectDisplayWithFileContentToHaveXML(\n        {\n          '.svg': `<svg>\n  <metadata>\n    <atv:parameter name=\"existant\"/>\n  </metadata>\n</svg>`,\n          '.json': '{ \"parameters\": [{ \"name\": \"test\" }] }',\n        },\n        `<svg>\n <metadata>\n  <atv:parameter name=\"test\"/>\n  <atv:parameter name=\"existant\"/>\n </metadata>\n</svg>`\n      );\n    });\n\n    it('should insert parameters before other atv tags', function () {\n      return expectDisplayWithFileContentToHaveXML(\n        {\n          '.svg': `<svg>\n  <metadata>\n    <atv:parameter name=\"existant\"/>\n    <atv:gridconfig height=\"20\" width=\"20\" enabled=\"false\" gridstyle=\"lines\"/>\n  </metadata>\n</svg>`,\n          '.json': '{ \"parameters\": [{ \"name\": \"test\" }] }',\n        },\n        `<svg>\n <metadata>\n  <atv:parameter name=\"test\"/>\n  <atv:parameter name=\"existant\"/>\n  <atv:gridconfig height=\"20\" width=\"20\" enabled=\"false\" gridstyle=\"lines\"/>\n </metadata>\n</svg>`\n      );\n    });\n\n    it('should insert parameters in the correct order', function () {\n      return expectDisplayWithFileContentToHaveXML(\n        {\n          '.svg': '<svg></svg>',\n          '.json': '{ \"parameters\": [{ \"name\": \"test\" }, { \"name\": \"another\" }] }',\n        },\n        `<svg>\n <metadata>\n  <atv:parameter name=\"test\"/>\n  <atv:parameter name=\"another\"/>\n </metadata>\n</svg>`\n      );\n    });\n\n    context('when encoding fails', function () {\n      beforeEach(() =>\n        stub(DisplayTransformer.prototype, 'encodeContents').callsFake((obj, cb) =>\n          cb(new Error('Encode error'))\n        )\n      );\n      afterEach(() => DisplayTransformer.prototype.encodeContents.restore());\n\n      it('should forward encode error', function () {\n        return expect(\n          createDisplayWithFileContents({\n            '.svg': '<svg><rect></rect></svg>',\n          }),\n          'to call the callback with error',\n          'Encode error'\n        );\n      });\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/transform/DisplayTransformer.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1311,
    "kind": "test",
    "name": "describe585",
    "testId": 585,
    "memberof": "test/src/transform/DisplayTransformer.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe585",
    "access": null,
    "description": "#shouldBeTransformed",
    "lineNumber": 14,
    "testTargets": [
      "DisplayTransformer#shouldBeTransformed"
    ]
  },
  {
    "__docId__": 1312,
    "kind": "test",
    "name": "it586",
    "testId": 586,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe585",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe585.it586",
    "access": null,
    "description": "should return false for non-display files",
    "lineNumber": 15
  },
  {
    "__docId__": 1313,
    "kind": "test",
    "name": "describe587",
    "testId": 587,
    "memberof": "test/src/transform/DisplayTransformer.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe587",
    "access": null,
    "description": "#transformFromDB",
    "lineNumber": 21,
    "testTargets": [
      "DisplayTransformer#transformFromDB"
    ]
  },
  {
    "__docId__": 1314,
    "kind": "test",
    "name": "it588",
    "testId": 588,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe587",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe587.it588",
    "access": null,
    "description": "should forward parse errors",
    "lineNumber": 44
  },
  {
    "__docId__": 1315,
    "kind": "test",
    "name": "it589",
    "testId": 589,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe587",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe587.it589",
    "access": null,
    "description": "should error with invalid xml",
    "lineNumber": 52
  },
  {
    "__docId__": 1316,
    "kind": "test",
    "name": "it590",
    "testId": 590,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe587",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe587.it590",
    "access": null,
    "description": "should store empty config for empty display",
    "lineNumber": 81
  },
  {
    "__docId__": 1317,
    "kind": "test",
    "name": "it591",
    "testId": 591,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe587",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe587.it591",
    "access": null,
    "description": "should store dependencies in config when referenced as \"src\"",
    "lineNumber": 87
  },
  {
    "__docId__": 1318,
    "kind": "test",
    "name": "it592",
    "testId": 592,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe587",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe587.it592",
    "access": null,
    "description": "should store dependencies in config when referenced as \"xlink:href\"",
    "lineNumber": 97
  },
  {
    "__docId__": 1319,
    "kind": "test",
    "name": "it593",
    "testId": 593,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe587",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe587.it593",
    "access": null,
    "description": "should store multiple dependencies in config",
    "lineNumber": 107
  },
  {
    "__docId__": 1320,
    "kind": "test",
    "name": "context594",
    "testId": 594,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe587",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe587.context594",
    "access": null,
    "description": "when display contains inline script",
    "lineNumber": 119
  },
  {
    "__docId__": 1321,
    "kind": "test",
    "name": "it595",
    "testId": 595,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe587.context594",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe587.context594.it595",
    "access": null,
    "description": "should be stored when given with attributes",
    "lineNumber": 122
  },
  {
    "__docId__": 1322,
    "kind": "test",
    "name": "it596",
    "testId": 596,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe587.context594",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe587.context594.it596",
    "access": null,
    "description": "should be stored when given without attributes",
    "lineNumber": 133
  },
  {
    "__docId__": 1323,
    "kind": "test",
    "name": "it597",
    "testId": 597,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe587.context594",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe587.context594.it597",
    "access": null,
    "description": "should store empty inline scripts in separate file",
    "lineNumber": 144
  },
  {
    "__docId__": 1324,
    "kind": "test",
    "name": "context598",
    "testId": 598,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe587",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe587.context598",
    "access": null,
    "description": "when display contains metadata tag",
    "lineNumber": 156
  },
  {
    "__docId__": 1325,
    "kind": "test",
    "name": "it599",
    "testId": 599,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe587.context598",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe587.context598.it599",
    "access": null,
    "description": "should work without actual metadata",
    "lineNumber": 157
  },
  {
    "__docId__": 1326,
    "kind": "test",
    "name": "it600",
    "testId": 600,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe587.context598",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe587.context598.it600",
    "access": null,
    "description": "should work without parameters",
    "lineNumber": 165
  },
  {
    "__docId__": 1327,
    "kind": "test",
    "name": "it601",
    "testId": 601,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe587.context598",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe587.context598.it601",
    "access": null,
    "description": "should store parameters",
    "lineNumber": 175
  },
  {
    "__docId__": 1328,
    "kind": "test",
    "name": "context602",
    "testId": 602,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe587",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe587.context602",
    "access": null,
    "description": "when encoding fails",
    "lineNumber": 204
  },
  {
    "__docId__": 1329,
    "kind": "test",
    "name": "it603",
    "testId": 603,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe587.context602",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe587.context602.it603",
    "access": null,
    "description": "should forward encode error",
    "lineNumber": 212
  },
  {
    "__docId__": 1330,
    "kind": "test",
    "name": "describe604",
    "testId": 604,
    "memberof": "test/src/transform/DisplayTransformer.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe604",
    "access": null,
    "description": "#createCombinedFile",
    "lineNumber": 223,
    "testTargets": [
      "DisplayTransformer#createCombinedFile"
    ]
  },
  {
    "__docId__": 1331,
    "kind": "test",
    "name": "it605",
    "testId": 605,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe604",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe604.it605",
    "access": null,
    "description": "should fail with invalid config file",
    "lineNumber": 243
  },
  {
    "__docId__": 1332,
    "kind": "test",
    "name": "it606",
    "testId": 606,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe604",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe604.it606",
    "access": null,
    "description": "should fail without SVG file",
    "lineNumber": 253
  },
  {
    "__docId__": 1333,
    "kind": "test",
    "name": "it607",
    "testId": 607,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe604",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe604.it607",
    "access": null,
    "description": "should fail with invalid SVG",
    "lineNumber": 263
  },
  {
    "__docId__": 1334,
    "kind": "test",
    "name": "it608",
    "testId": 608,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe604",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe604.it608",
    "access": null,
    "description": "should fail without `svg` tag",
    "lineNumber": 273
  },
  {
    "__docId__": 1335,
    "kind": "test",
    "name": "it609",
    "testId": 609,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe604",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe604.it609",
    "access": null,
    "description": "should work with empty svg tag",
    "lineNumber": 300
  },
  {
    "__docId__": 1336,
    "kind": "test",
    "name": "it610",
    "testId": 610,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe604",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe604.it610",
    "access": null,
    "description": "should inline script",
    "lineNumber": 309
  },
  {
    "__docId__": 1337,
    "kind": "test",
    "name": "it611",
    "testId": 611,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe604",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe604.it611",
    "access": null,
    "description": "should link dependencies",
    "lineNumber": 322
  },
  {
    "__docId__": 1338,
    "kind": "test",
    "name": "it612",
    "testId": 612,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe604",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe604.it612",
    "access": null,
    "description": "should work without empty parameters config",
    "lineNumber": 335
  },
  {
    "__docId__": 1339,
    "kind": "test",
    "name": "it613",
    "testId": 613,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe604",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe604.it613",
    "access": null,
    "description": "should reuse existant metadata section",
    "lineNumber": 347
  },
  {
    "__docId__": 1340,
    "kind": "test",
    "name": "it614",
    "testId": 614,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe604",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe604.it614",
    "access": null,
    "description": "should create metadata section if omitted",
    "lineNumber": 366
  },
  {
    "__docId__": 1341,
    "kind": "test",
    "name": "it615",
    "testId": 615,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe604",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe604.it615",
    "access": null,
    "description": "should keep parameters specified in SVG",
    "lineNumber": 380
  },
  {
    "__docId__": 1342,
    "kind": "test",
    "name": "it616",
    "testId": 616,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe604",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe604.it616",
    "access": null,
    "description": "should insert parameters before other atv tags",
    "lineNumber": 399
  },
  {
    "__docId__": 1343,
    "kind": "test",
    "name": "it617",
    "testId": 617,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe604",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe604.it617",
    "access": null,
    "description": "should insert parameters in the correct order",
    "lineNumber": 420
  },
  {
    "__docId__": 1344,
    "kind": "test",
    "name": "context618",
    "testId": 618,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe604",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe604.context618",
    "access": null,
    "description": "when encoding fails",
    "lineNumber": 435
  },
  {
    "__docId__": 1345,
    "kind": "test",
    "name": "it619",
    "testId": 619,
    "memberof": "test/src/transform/DisplayTransformer.spec.js~describe604.context618",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/DisplayTransformer.spec.js~describe604.context618.it619",
    "access": null,
    "description": "should forward encode error",
    "lineNumber": 443
  },
  {
    "__docId__": 1346,
    "kind": "testFile",
    "name": "test/src/transform/Mapping.spec.js",
    "content": "import { join } from 'path';\nimport { Buffer } from 'buffer';\nimport { stub, spy } from 'sinon';\nimport { DataType, VariantArrayType, NodeClass } from 'node-opcua';\nimport File from 'vinyl';\nimport Logger from 'gulplog';\nimport expect from '../../expect';\nimport { TransformDirection } from '../../../src/lib/transform/Transformer';\nimport NodeId from '../../../src/lib/model/opcua/NodeId';\nimport AtviseFile from '../../../src/lib/server/AtviseFile';\nimport MappingTransformer from '../../../src/transform/Mapping';\nimport { scalar, array, matrix } from '../../fixtures/dataTypes';\n\n/** @test {MappingTransformer} */\ndescribe.skip('MappingTransformer', function () {\n  before(() => Logger.on('error', () => true));\n\n  /** @test {MappingTransformer#transformFromDB} */\n  describe('#transformFromDB', function () {\n    context('when AtviseFile.fromReadResult returns error', function () {\n      let warnListener;\n      let debugListener;\n\n      beforeEach(() => {\n        stub(AtviseFile, 'fromReadResult').callsFake(() => {\n          throw new Error('Test');\n        });\n        Logger.on('warn', (warnListener = spy()));\n        Logger.on('debug', (debugListener = spy()));\n      });\n\n      afterEach(() => {\n        AtviseFile.fromReadResult.restore();\n        Logger.removeListener('warn', warnListener);\n        Logger.removeListener('debug', debugListener);\n      });\n\n      it('should not forward errors', function () {\n        const stream = new MappingTransformer({ direction: TransformDirection.FromDB });\n\n        return expect(\n          (cb) =>\n            stream.transformFromDB(\n              {\n                nodeId: new NodeId('AGENT.DISPLAYS.Main'),\n              },\n              'utf8',\n              cb\n            ),\n          'to call the callback'\n        ).then((args) => expect(args, 'to have length', 1));\n      });\n\n      it('should log warning', function () {\n        const stream = new MappingTransformer({ direction: TransformDirection.FromDB });\n\n        return expect(\n          (cb) =>\n            stream.transformFromDB(\n              {\n                nodeId: new NodeId('AGENT.DISPLAYS.Main'),\n              },\n              'utf8',\n              cb\n            ),\n          'to call the callback'\n        )\n          .then((args) => expect(args, 'to have length', 1))\n          .then(() => expect(warnListener, 'was called once'))\n          .then(() => expect(debugListener, 'was called once'));\n      });\n    });\n\n    context('when AtviseFile.fromReadResult returns \"no value\" error', function () {\n      let warnListener;\n      let debugListener;\n\n      beforeEach(() => {\n        stub(AtviseFile, 'fromReadResult').callsFake(() => {\n          throw new Error('no value');\n        });\n        Logger.on('warn', (warnListener = spy()));\n        Logger.on('debug', (debugListener = spy()));\n      });\n\n      afterEach(() => {\n        AtviseFile.fromReadResult.restore();\n        Logger.removeListener('warn', warnListener);\n        Logger.removeListener('debug', debugListener);\n      });\n\n      it('should only debug log', function () {\n        const stream = new MappingTransformer({ direction: TransformDirection.FromDB });\n\n        return expect(\n          (cb) =>\n            stream.transformFromDB(\n              {\n                nodeId: new NodeId('AGENT.DISPLAYS.Main'),\n              },\n              'utf8',\n              cb\n            ),\n          'to call the callback'\n        )\n          .then((args) => expect(args, 'to have length', 1))\n          .then(() => expect(debugListener, 'was called twice'))\n          .then(() => expect(warnListener, 'was not called'));\n      });\n    });\n\n    it('should return an AtviseFile for the given ReadResult', function () {\n      const stream = new MappingTransformer({ direction: TransformDirection.FromDB });\n\n      return expect(\n        [\n          {\n            nodeId: new NodeId('AGENT.DISPLAYS.Main'),\n            nodeClass: NodeClass.Variable,\n            value: {\n              value: '<xml></xml>',\n              $dataType: DataType.XmlElement,\n              $arrayType: VariantArrayType.Scalar,\n            },\n            references: {\n              HasTypeDefinition: [new NodeId('VariableTypes.ATVISE.Display')],\n            },\n          },\n        ],\n        'when piped through',\n        stream,\n        'to yield chunks satisfying',\n        [expect.it('to be an', AtviseFile)]\n      );\n    });\n\n    context('when file has non-standard type-definition', function () {\n      it('should push a reference config file', function () {\n        const stream = new MappingTransformer({ direction: TransformDirection.FromDB });\n\n        return expect(\n          [\n            {\n              nodeId: new NodeId('AGENT.OBJECTS.CustomVar'),\n              nodeClass: NodeClass.Variable,\n              value: {\n                value: '<xml></xml>',\n                $dataType: DataType.XmlElement,\n                $arrayType: VariantArrayType.Scalar,\n              },\n              references: {\n                HasTypeDefinition: [new NodeId('VariableTypes.PROJECT.CustomType')],\n              },\n            },\n          ],\n          'when piped through',\n          stream,\n          'to yield chunks satisfying',\n          [\n            {\n              basename: '.CustomVar.var.xml.json',\n              contents: Buffer.from(\n                JSON.stringify(\n                  {\n                    references: {\n                      HasTypeDefinition: ['ns=1;s=VariableTypes.PROJECT.CustomType'],\n                    },\n                  },\n                  null,\n                  '  '\n                )\n              ),\n            },\n            {\n              typeDefinition: new NodeId('VariableTypes.PROJECT.CustomType'),\n            },\n          ]\n        );\n      });\n\n      it('should sort references', function () {\n        const stream = new MappingTransformer({ direction: TransformDirection.FromDB });\n\n        return expect(\n          [\n            {\n              nodeId: new NodeId('ObjectTypes.PROJECT.CustomType'),\n              nodeClass: NodeClass.ObjectType,\n              references: {\n                toParent: 'HasSubtype',\n                HasTypeDefinition: [new NodeId('VariableTypes.PROJECT.CustomType')],\n                HasModellingRule: ['ns=0;i=78'],\n              },\n            },\n          ],\n          'when piped through',\n          stream,\n          'to yield chunks satisfying',\n          [\n            (file) => {\n              expect(\n                file.contents.toString(),\n                'to equal',\n                `{\n  \"references\": {\n    \"HasModellingRule\": [\n      \"ns=0;i=78\"\n    ],\n    \"HasTypeDefinition\": [\n      \"ns=1;s=VariableTypes.PROJECT.CustomType\"\n    ],\n    \"toParent\": \"HasSubtype\"\n  }\n}`\n              );\n            },\n          ]\n        );\n      });\n    });\n  });\n\n  /** @test {MappingTransformer#transformFromFilesystem} */\n  describe('#transformFromFilesystem', function () {\n    it('should write AtviseFiles for read Files', function () {\n      const stream = new MappingTransformer({ direction: TransformDirection.FromFilesystem });\n\n      return expect(\n        [new File({ path: 'Test.ext' })],\n        'when piped through',\n        stream,\n        'to yield chunks satisfying',\n        [expect.it('to be an', AtviseFile)]\n      );\n    });\n\n    it('should keep base', function () {\n      const stream = new MappingTransformer({ direction: TransformDirection.FromFilesystem });\n\n      return expect(\n        (cb) =>\n          stream.transformFromFilesystem(\n            new File({ path: 'folder/Test.ext', base: 'folder' }),\n            'utf8',\n            cb\n          ),\n        'to call the callback'\n      ).then((args) => {\n        expect(args[0], 'to be falsy');\n\n        const result = args[1];\n        expect(result.base, 'to equal', 'folder');\n        expect(result.relative, 'to equal', 'Test.ext');\n      });\n    });\n\n    it('should skip directories', function () {\n      const stream = new MappingTransformer({ direction: TransformDirection.FromFilesystem });\n\n      return expect(\n        (cb) => stream.transformFromFilesystem({ isDirectory: () => true }, 'utf8', cb),\n        'to call the callback'\n      ).then((args) => {\n        expect(args, 'to have length', 1);\n        expect(args[0], 'to be falsy');\n      });\n    });\n\n    it('should skip non-atscm dot files', function () {\n      const stream = new MappingTransformer({ direction: TransformDirection.FromFilesystem });\n\n      return expect(\n        (cb) =>\n          stream.transformFromFilesystem(\n            { isDirectory: () => false, stem: '.eslintrc' },\n            'utf8',\n            cb\n          ),\n        'to call the callback'\n      ).then((args) => {\n        expect(args, 'to have length', 1);\n        expect(args[0], 'to be falsy');\n      });\n    });\n\n    context('when file has non-standard type-definition', function () {\n      context('with reference config file', function () {\n        it('should read reference config file', function () {\n          const stream = new MappingTransformer({ direction: TransformDirection.FromFilesystem });\n\n          return expect(\n            [\n              new AtviseFile({\n                path: 'AGENT/OBJECTS/.CustomVar.var.ext.json',\n                contents: Buffer.from(\n                  JSON.stringify({\n                    references: { HasTypeDefinition: ['ns=1;s=VariableTypes.PROJECT.CustomType'] },\n                  })\n                ),\n              }),\n              new AtviseFile({ path: 'AGENT/OBJECTS/CustomVar.var.ext' }),\n            ],\n            'when piped through',\n            stream,\n            'to yield chunks satisfying',\n            [\n              {\n                typeDefinition: new NodeId('VariableTypes.PROJECT.CustomType'),\n              },\n            ]\n          );\n        });\n      });\n\n      context('when reference config file is missing', function () {\n        it('should forward error', function () {\n          const stream = new MappingTransformer({ direction: TransformDirection.FromFilesystem });\n\n          const promise = expect(stream, 'to error with', /missing reference file/i);\n\n          stream.write(new AtviseFile({ path: 'AGENT/OBJECTS/CustomVar.var.ext' }));\n          stream.end();\n\n          return promise;\n        });\n      });\n\n      context('when .rc file cannot be parsed', function () {\n        it('should forward error', function () {\n          const stream = new MappingTransformer({ direction: TransformDirection.FromFilesystem });\n\n          const promise = expect(stream, 'to error with', /Unexpected token/);\n\n          stream.write(\n            new AtviseFile({\n              contents: Buffer.from('{ \"invalid\" }'),\n              path: 'AGENT/OBJECTS/.CustomVar.var.ext.json',\n            })\n          );\n          stream.write(new AtviseFile({ path: 'AGENT/OBJECTS/CustomVar.var.ext' }));\n          stream.end();\n\n          return promise;\n        });\n      });\n    });\n  });\n\n  describe('should be able to map all types', function () {\n    async function testFromDBMapping({ sample }) {\n      const stream = new MappingTransformer({ direction: TransformDirection.FromDB });\n\n      const [err, [result]] = await expect(\n        [\n          Object.assign({}, sample, {\n            nodeId: new NodeId(`AGENT.OBJECTS.allTypes.${sample.dataType}${sample.arrayType}`),\n            value: {\n              value: sample.value,\n              $dataType: sample.dataType,\n              $arrayType: sample.arrayType,\n            },\n            references: {\n              toParent: 'HasComponent',\n              HasTypeDefinition: [new NodeId('ns=0;i=62')],\n            },\n          }),\n        ],\n        'when piped through',\n        stream,\n        'to yield chunks satisfying',\n        [(chunk) => expect(chunk, 'to be an', AtviseFile) && chunk]\n      );\n\n      expect(err, 'to be falsy');\n      expect(result.value, 'to equal', sample.value);\n\n      return result;\n    }\n\n    scalar.forEach((sample, i) => {\n      context(`when mapping ${sample.dataType}s`, function () {\n        it('should map scalar values', async function () {\n          return testFromDBMapping({ sample });\n        });\n        it('should map array values', async function () {\n          return testFromDBMapping({ sample: array[i] });\n        });\n        it('should map matrix values', async function () {\n          return testFromDBMapping({ sample: matrix[i] });\n        });\n      });\n    });\n  });\n\n  context('when a resource property is mapped', function () {\n    it('should wrap nodes in `.inner` folder', function () {\n      const stream = new MappingTransformer({ direction: TransformDirection.FromDB });\n\n      return expect(\n        [\n          {\n            nodeId: new NodeId('SYSTEM.LIBRARY.RESOURCES/index.html.Translate'),\n            parent: new NodeId('SYSTEM.LIBRARY.RESOURCES/index.html'),\n            nodeClass: NodeClass.Variable,\n            value: {\n              value: true,\n              $dataType: DataType.Boolean,\n              $arrayType: VariantArrayType.Scalar,\n            },\n            references: {\n              HasTypeDefinition: [new NodeId(NodeId.NodeIdType.NUMERIC, 68, 0)],\n            },\n          },\n        ],\n        'when piped through',\n        stream,\n        'to yield chunks satisfying',\n        [\n          {\n            dirname: join('SYSTEM/LIBRARY/RESOURCES/index.html.inner'),\n            basename: 'Translate.prop.bool',\n            contents: Buffer.from('true'),\n          },\n        ]\n      );\n    });\n\n    it('should unwrap properties `.inner` folder', function () {\n      const stream = new MappingTransformer({ direction: TransformDirection.FromFilesystem });\n\n      return expect(\n        [\n          new AtviseFile({\n            path: join('SYSTEM/LIBRARY/RESOURCES/test.htm.inner/Translate.prop.bool'),\n            contents: Buffer.from('true'),\n          }),\n        ],\n        'when piped through',\n        stream,\n        'to yield chunks satisfying',\n        [\n          {\n            path: join('SYSTEM/LIBRARY/RESOURCES/test.htm/Translate.prop.bool'),\n            value: true,\n          },\n        ]\n      );\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/transform/Mapping.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1347,
    "kind": "test",
    "name": "describe620",
    "testId": 620,
    "memberof": "test/src/transform/Mapping.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe620",
    "access": null,
    "description": "#transformFromDB",
    "lineNumber": 19,
    "testTargets": [
      "MappingTransformer#transformFromDB"
    ]
  },
  {
    "__docId__": 1348,
    "kind": "test",
    "name": "context621",
    "testId": 621,
    "memberof": "test/src/transform/Mapping.spec.js~describe620",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe620.context621",
    "access": null,
    "description": "when AtviseFile.fromReadResult returns error",
    "lineNumber": 20
  },
  {
    "__docId__": 1349,
    "kind": "test",
    "name": "it622",
    "testId": 622,
    "memberof": "test/src/transform/Mapping.spec.js~describe620.context621",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe620.context621.it622",
    "access": null,
    "description": "should not forward errors",
    "lineNumber": 38
  },
  {
    "__docId__": 1350,
    "kind": "test",
    "name": "it623",
    "testId": 623,
    "memberof": "test/src/transform/Mapping.spec.js~describe620.context621",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe620.context621.it623",
    "access": null,
    "description": "should log warning",
    "lineNumber": 54
  },
  {
    "__docId__": 1351,
    "kind": "test",
    "name": "context624",
    "testId": 624,
    "memberof": "test/src/transform/Mapping.spec.js~describe620",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe620.context624",
    "access": null,
    "description": "when AtviseFile.fromReadResult returns \"no value\" error",
    "lineNumber": 74
  },
  {
    "__docId__": 1352,
    "kind": "test",
    "name": "it625",
    "testId": 625,
    "memberof": "test/src/transform/Mapping.spec.js~describe620.context624",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe620.context624.it625",
    "access": null,
    "description": "should only debug log",
    "lineNumber": 92
  },
  {
    "__docId__": 1353,
    "kind": "test",
    "name": "it626",
    "testId": 626,
    "memberof": "test/src/transform/Mapping.spec.js~describe620",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe620.it626",
    "access": null,
    "description": "should return an AtviseFile for the given ReadResult",
    "lineNumber": 112
  },
  {
    "__docId__": 1354,
    "kind": "test",
    "name": "context627",
    "testId": 627,
    "memberof": "test/src/transform/Mapping.spec.js~describe620",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe620.context627",
    "access": null,
    "description": "when file has non-standard type-definition",
    "lineNumber": 137
  },
  {
    "__docId__": 1355,
    "kind": "test",
    "name": "it628",
    "testId": 628,
    "memberof": "test/src/transform/Mapping.spec.js~describe620.context627",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe620.context627.it628",
    "access": null,
    "description": "should push a reference config file",
    "lineNumber": 138
  },
  {
    "__docId__": 1356,
    "kind": "test",
    "name": "it629",
    "testId": 629,
    "memberof": "test/src/transform/Mapping.spec.js~describe620.context627",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe620.context627.it629",
    "access": null,
    "description": "should sort references",
    "lineNumber": 181
  },
  {
    "__docId__": 1357,
    "kind": "test",
    "name": "describe630",
    "testId": 630,
    "memberof": "test/src/transform/Mapping.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe630",
    "access": null,
    "description": "#transformFromFilesystem",
    "lineNumber": 224,
    "testTargets": [
      "MappingTransformer#transformFromFilesystem"
    ]
  },
  {
    "__docId__": 1358,
    "kind": "test",
    "name": "it631",
    "testId": 631,
    "memberof": "test/src/transform/Mapping.spec.js~describe630",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe630.it631",
    "access": null,
    "description": "should write AtviseFiles for read Files",
    "lineNumber": 225
  },
  {
    "__docId__": 1359,
    "kind": "test",
    "name": "it632",
    "testId": 632,
    "memberof": "test/src/transform/Mapping.spec.js~describe630",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe630.it632",
    "access": null,
    "description": "should keep base",
    "lineNumber": 237
  },
  {
    "__docId__": 1360,
    "kind": "test",
    "name": "it633",
    "testId": 633,
    "memberof": "test/src/transform/Mapping.spec.js~describe630",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe630.it633",
    "access": null,
    "description": "should skip directories",
    "lineNumber": 257
  },
  {
    "__docId__": 1361,
    "kind": "test",
    "name": "it634",
    "testId": 634,
    "memberof": "test/src/transform/Mapping.spec.js~describe630",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe630.it634",
    "access": null,
    "description": "should skip non-atscm dot files",
    "lineNumber": 269
  },
  {
    "__docId__": 1362,
    "kind": "test",
    "name": "context635",
    "testId": 635,
    "memberof": "test/src/transform/Mapping.spec.js~describe630",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe630.context635",
    "access": null,
    "description": "when file has non-standard type-definition",
    "lineNumber": 286
  },
  {
    "__docId__": 1363,
    "kind": "test",
    "name": "context636",
    "testId": 636,
    "memberof": "test/src/transform/Mapping.spec.js~describe630.context635",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe630.context635.context636",
    "access": null,
    "description": "with reference config file",
    "lineNumber": 287
  },
  {
    "__docId__": 1364,
    "kind": "test",
    "name": "it637",
    "testId": 637,
    "memberof": "test/src/transform/Mapping.spec.js~describe630.context635.context636",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe630.context635.context636.it637",
    "access": null,
    "description": "should read reference config file",
    "lineNumber": 288
  },
  {
    "__docId__": 1365,
    "kind": "test",
    "name": "context638",
    "testId": 638,
    "memberof": "test/src/transform/Mapping.spec.js~describe630.context635",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe630.context635.context638",
    "access": null,
    "description": "when reference config file is missing",
    "lineNumber": 315
  },
  {
    "__docId__": 1366,
    "kind": "test",
    "name": "it639",
    "testId": 639,
    "memberof": "test/src/transform/Mapping.spec.js~describe630.context635.context638",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe630.context635.context638.it639",
    "access": null,
    "description": "should forward error",
    "lineNumber": 316
  },
  {
    "__docId__": 1367,
    "kind": "test",
    "name": "context640",
    "testId": 640,
    "memberof": "test/src/transform/Mapping.spec.js~describe630.context635",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe630.context635.context640",
    "access": null,
    "description": "when .rc file cannot be parsed",
    "lineNumber": 328
  },
  {
    "__docId__": 1368,
    "kind": "test",
    "name": "it641",
    "testId": 641,
    "memberof": "test/src/transform/Mapping.spec.js~describe630.context635.context640",
    "testDepth": 3,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe630.context635.context640.it641",
    "access": null,
    "description": "should forward error",
    "lineNumber": 329
  },
  {
    "__docId__": 1369,
    "kind": "test",
    "name": "describe642",
    "testId": 642,
    "memberof": "test/src/transform/Mapping.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe642",
    "access": null,
    "description": "should be able to map all types",
    "lineNumber": 349
  },
  {
    "__docId__": 1370,
    "kind": "test",
    "name": "context643",
    "testId": 643,
    "memberof": "test/src/transform/Mapping.spec.js~describe642",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe642.context643",
    "access": null,
    "lineNumber": 381
  },
  {
    "__docId__": 1371,
    "kind": "test",
    "name": "it644",
    "testId": 644,
    "memberof": "test/src/transform/Mapping.spec.js~describe642.context643",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe642.context643.it644",
    "access": null,
    "description": "should map scalar values",
    "lineNumber": 382
  },
  {
    "__docId__": 1372,
    "kind": "test",
    "name": "it645",
    "testId": 645,
    "memberof": "test/src/transform/Mapping.spec.js~describe642.context643",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe642.context643.it645",
    "access": null,
    "description": "should map array values",
    "lineNumber": 385
  },
  {
    "__docId__": 1373,
    "kind": "test",
    "name": "it646",
    "testId": 646,
    "memberof": "test/src/transform/Mapping.spec.js~describe642.context643",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~describe642.context643.it646",
    "access": null,
    "description": "should map matrix values",
    "lineNumber": 388
  },
  {
    "__docId__": 1374,
    "kind": "test",
    "name": "context647",
    "testId": 647,
    "memberof": "test/src/transform/Mapping.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~context647",
    "access": null,
    "description": "when a resource property is mapped",
    "lineNumber": 395
  },
  {
    "__docId__": 1375,
    "kind": "test",
    "name": "it648",
    "testId": 648,
    "memberof": "test/src/transform/Mapping.spec.js~context647",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~context647.it648",
    "access": null,
    "description": "should wrap nodes in `.inner` folder",
    "lineNumber": 396
  },
  {
    "__docId__": 1376,
    "kind": "test",
    "name": "it649",
    "testId": 649,
    "memberof": "test/src/transform/Mapping.spec.js~context647",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Mapping.spec.js~context647.it649",
    "access": null,
    "description": "should unwrap properties `.inner` folder",
    "lineNumber": 428
  },
  {
    "__docId__": 1377,
    "kind": "testFile",
    "name": "test/src/transform/Newlines.spec.js",
    "content": "import { EOL } from 'os';\nimport expect from '../../expect';\nimport NewlinesTransformer from '../../../src/transform/Newlines';\nimport File from '../../../src/lib/server/AtviseFile';\n\ndescribe.skip('NewlinesTransformer', function () {\n  /** @test {MappingTransformer#constructor} */\n  describe('#constructor', function () {\n    context('trailingNewlines option', function () {\n      it('should default to false', function () {\n        const transformer = new NewlinesTransformer();\n        expect(transformer._addTrailingNewlines, 'to be', false);\n\n        const transformer2 = new NewlinesTransformer({});\n        expect(transformer2._addTrailingNewlines, 'to be', false);\n      });\n    });\n  });\n\n  /** @test {NewlinesTransformer#shouldBeTransformed} */\n  describe('#shouldBeTransformed', function () {\n    it('should return true for reference files', function () {\n      expect(\n        NewlinesTransformer.prototype.shouldBeTransformed,\n        'called with',\n        [\n          new File({\n            path: './src/test/.Object.json',\n            contents: Buffer.from('{}'),\n          }),\n        ],\n        'to be',\n        true\n      );\n    });\n\n    it('should return true for source files', function () {\n      expect(\n        NewlinesTransformer.prototype.shouldBeTransformed,\n        'called with',\n        [\n          new File({\n            path: './src/test/Test.script/Test.js',\n            contents: Buffer.from(''),\n          }),\n        ],\n        'to be',\n        true\n      );\n    });\n\n    it('should return false for binary files', function () {\n      expect(\n        NewlinesTransformer.prototype.shouldBeTransformed,\n        'called with',\n        [\n          new File({\n            path: './src/test/Test.jpg',\n            contents: Buffer.from(''),\n          }),\n        ],\n        'to be',\n        false\n      );\n    });\n  });\n\n  /** @test {NewlinesTransformer#transformFromDB} */\n  describe('#transformFromDB', function () {\n    it('should replace non-native newlines', function () {\n      const transformer = new NewlinesTransformer({ trailingNewlines: false });\n      const lines = ['first line', 'second'];\n\n      return expect(\n        (cb) =>\n          transformer.transformFromDB(\n            new File({\n              path: './src/test/Test.script/Test.js',\n              contents: Buffer.from(lines.join('\\r\\n')),\n            }),\n            'utf8',\n            cb\n          ),\n        'to call the callback without error'\n      ).then(([file]) =>\n        expect(file.contents, 'when decoded as', 'utf8', 'to equal', lines.join(EOL))\n      );\n    });\n\n    it('should add trailing newlines if set', function () {\n      const transformer = new NewlinesTransformer({ trailingNewlines: true });\n      const lines = ['first line', 'second'];\n\n      return expect(\n        (cb) =>\n          transformer.transformFromDB(\n            new File({\n              path: './src/test/Test.script/Test.js',\n              contents: Buffer.from(lines.join('\\r\\n')),\n            }),\n            'utf8',\n            cb\n          ),\n        'to call the callback without error'\n      ).then(([file]) =>\n        expect(file.contents, 'when decoded as', 'utf8', 'to equal', lines.concat('').join(EOL))\n      );\n    });\n  });\n\n  /** @test {NewlinesTransformer#transformFromFilesystem} */\n  describe('#transformFromFilesystem', function () {\n    it('should replace native newlines', function () {\n      const transformer = new NewlinesTransformer({ trailingNewlines: false });\n      const lines = ['first line', 'second'];\n\n      return expect(\n        (cb) =>\n          transformer.transformFromFilesystem(\n            new File({\n              path: './src/test/Test.script/Test.js',\n              contents: Buffer.from(lines.join(EOL)),\n            }),\n            'utf8',\n            cb\n          ),\n        'to call the callback without error'\n      ).then(([file]) =>\n        expect(file.contents, 'when decoded as', 'utf8', 'to equal', lines.join('\\r\\n'))\n      );\n    });\n\n    it('should remove trailing newlines if set', function () {\n      const transformer = new NewlinesTransformer({ trailingNewlines: true });\n      const lines = ['first line', 'second'];\n\n      return expect(\n        (cb) =>\n          transformer.transformFromFilesystem(\n            new File({\n              path: './src/test/Test.script/Test.js',\n              contents: Buffer.from(lines.concat('').join(EOL)),\n            }),\n            'utf8',\n            cb\n          ),\n        'to call the callback without error'\n      ).then(([file]) =>\n        expect(file.contents, 'when decoded as', 'utf8', 'to equal', lines.join('\\r\\n'))\n      );\n    });\n\n    it('should remove only one trailing newline if set', function () {\n      const transformer = new NewlinesTransformer({ trailingNewlines: true });\n      const lines = ['first line', 'second'];\n\n      return expect(\n        (cb) =>\n          transformer.transformFromFilesystem(\n            new File({\n              path: './src/test/Test.script/Test.js',\n              contents: Buffer.from(lines.concat('').concat('').join(EOL)),\n            }),\n            'utf8',\n            cb\n          ),\n        'to call the callback without error'\n      ).then(([file]) =>\n        expect(file.contents, 'when decoded as', 'utf8', 'to equal', lines.concat('').join('\\r\\n'))\n      );\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/transform/Newlines.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1378,
    "kind": "test",
    "name": "describe650",
    "testId": 650,
    "memberof": "test/src/transform/Newlines.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/transform/Newlines.spec.js~describe650",
    "access": null,
    "description": "#constructor",
    "lineNumber": 8,
    "testTargets": [
      "MappingTransformer#constructor"
    ]
  },
  {
    "__docId__": 1379,
    "kind": "test",
    "name": "context651",
    "testId": 651,
    "memberof": "test/src/transform/Newlines.spec.js~describe650",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Newlines.spec.js~describe650.context651",
    "access": null,
    "description": "trailingNewlines option",
    "lineNumber": 9
  },
  {
    "__docId__": 1380,
    "kind": "test",
    "name": "it652",
    "testId": 652,
    "memberof": "test/src/transform/Newlines.spec.js~describe650.context651",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/Newlines.spec.js~describe650.context651.it652",
    "access": null,
    "description": "should default to false",
    "lineNumber": 10
  },
  {
    "__docId__": 1381,
    "kind": "test",
    "name": "describe653",
    "testId": 653,
    "memberof": "test/src/transform/Newlines.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/transform/Newlines.spec.js~describe653",
    "access": null,
    "description": "#shouldBeTransformed",
    "lineNumber": 21,
    "testTargets": [
      "NewlinesTransformer#shouldBeTransformed"
    ]
  },
  {
    "__docId__": 1382,
    "kind": "test",
    "name": "it654",
    "testId": 654,
    "memberof": "test/src/transform/Newlines.spec.js~describe653",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Newlines.spec.js~describe653.it654",
    "access": null,
    "description": "should return true for reference files",
    "lineNumber": 22
  },
  {
    "__docId__": 1383,
    "kind": "test",
    "name": "it655",
    "testId": 655,
    "memberof": "test/src/transform/Newlines.spec.js~describe653",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Newlines.spec.js~describe653.it655",
    "access": null,
    "description": "should return true for source files",
    "lineNumber": 37
  },
  {
    "__docId__": 1384,
    "kind": "test",
    "name": "it656",
    "testId": 656,
    "memberof": "test/src/transform/Newlines.spec.js~describe653",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Newlines.spec.js~describe653.it656",
    "access": null,
    "description": "should return false for binary files",
    "lineNumber": 52
  },
  {
    "__docId__": 1385,
    "kind": "test",
    "name": "describe657",
    "testId": 657,
    "memberof": "test/src/transform/Newlines.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/transform/Newlines.spec.js~describe657",
    "access": null,
    "description": "#transformFromDB",
    "lineNumber": 69,
    "testTargets": [
      "NewlinesTransformer#transformFromDB"
    ]
  },
  {
    "__docId__": 1386,
    "kind": "test",
    "name": "it658",
    "testId": 658,
    "memberof": "test/src/transform/Newlines.spec.js~describe657",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Newlines.spec.js~describe657.it658",
    "access": null,
    "description": "should replace non-native newlines",
    "lineNumber": 70
  },
  {
    "__docId__": 1387,
    "kind": "test",
    "name": "it659",
    "testId": 659,
    "memberof": "test/src/transform/Newlines.spec.js~describe657",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Newlines.spec.js~describe657.it659",
    "access": null,
    "description": "should add trailing newlines if set",
    "lineNumber": 90
  },
  {
    "__docId__": 1388,
    "kind": "test",
    "name": "describe660",
    "testId": 660,
    "memberof": "test/src/transform/Newlines.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/transform/Newlines.spec.js~describe660",
    "access": null,
    "description": "#transformFromFilesystem",
    "lineNumber": 112,
    "testTargets": [
      "NewlinesTransformer#transformFromFilesystem"
    ]
  },
  {
    "__docId__": 1389,
    "kind": "test",
    "name": "it661",
    "testId": 661,
    "memberof": "test/src/transform/Newlines.spec.js~describe660",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Newlines.spec.js~describe660.it661",
    "access": null,
    "description": "should replace native newlines",
    "lineNumber": 113
  },
  {
    "__docId__": 1390,
    "kind": "test",
    "name": "it662",
    "testId": 662,
    "memberof": "test/src/transform/Newlines.spec.js~describe660",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Newlines.spec.js~describe660.it662",
    "access": null,
    "description": "should remove trailing newlines if set",
    "lineNumber": 133
  },
  {
    "__docId__": 1391,
    "kind": "test",
    "name": "it663",
    "testId": 663,
    "memberof": "test/src/transform/Newlines.spec.js~describe660",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/Newlines.spec.js~describe660.it663",
    "access": null,
    "description": "should remove only one trailing newline if set",
    "lineNumber": 153
  },
  {
    "__docId__": 1392,
    "kind": "testFile",
    "name": "test/src/transform/ScriptTransformer.spec.js",
    "content": "import Logger from 'gulplog';\nimport { spy } from 'sinon';\nimport expect from '../../expect';\nimport TransformerHelper from '../../helpers/Transformer';\nimport ScriptTransformer from '../../../src/transform/ScriptTransformer';\n\nconst transformerHelper = new TransformerHelper(ScriptTransformer);\n\n/** @test {ScriptTransformer} */\ndescribe.skip('ScriptTransformer', function () {\n  const ScriptPath = 'SYSTEM/LIBRARY/PROJECT/SERVERSCRIPTS/Test.script';\n  const QDPath = 'SYSTEM/LIBRARY/PROJECT/SERVERSCRIPTS/Test.qd';\n\n  /** @test {ScriptTransformer#shouldBeTransformed} */\n  describe('#shouldBeTransformed', function () {\n    it('should return true for ScriptCode type nodes', function () {\n      expect(ScriptTransformer.prototype.shouldBeTransformed({ isScript: true }), 'to be true');\n    });\n\n    it('should return true for QuickDynamic type nodes', function () {\n      expect(\n        ScriptTransformer.prototype.shouldBeTransformed({ isQuickDynamic: true }),\n        'to be true'\n      );\n    });\n  });\n\n  /** @test {ScriptTransformer#transformFromDB} */\n  describe('#transformFromDB', function () {\n    it('should forward parse errors', function () {\n      return expect(\n        transformerHelper.writeXMLToTransformer(ScriptPath, 'invalid xml'),\n        'to be rejected with',\n        /Text data outside of root node/\n      );\n    });\n\n    it('should warn with invalid xml', function () {\n      const onWarn = spy();\n      Logger.on('warn', onWarn);\n\n      return expect(\n        transformerHelper.writeXMLToTransformer(ScriptPath, '<root></root>'),\n        'to be fulfilled'\n      ).then(() => {\n        expect(onWarn, 'was called once');\n        expect(onWarn, 'to have a call satisfying', { args: [/Empty document/] });\n      });\n    });\n\n    it('should write empty config file for empty Script', function () {\n      return transformerHelper\n        .writeXMLToTransformer(ScriptPath, '<script></script>')\n        .then((files) => transformerHelper.expectFileContents(files))\n        .then((contents) => {\n          expect(contents[0], 'to equal', '{}');\n        });\n    });\n\n    it('should write empty .js file for empty Script', function () {\n      return transformerHelper\n        .writeXMLToTransformer(ScriptPath, '<script></script>')\n        .then((files) => transformerHelper.expectFileContents(files))\n        .then((contents) => {\n          expect(contents[1], 'to equal', '');\n        });\n    });\n\n    it('should only store metadata elements', function () {\n      return transformerHelper\n        .writeXMLToTransformer(\n          ScriptPath,\n          `<script>\n  <metadata>shouldn't be handled</metadata>\n</script>`\n        )\n        .then((files) => transformerHelper.expectFileContents(files))\n        .then((contents) => expect(JSON.parse(contents[0]), 'to equal', {}));\n    });\n\n    it('should store custom metadata elements', function () {\n      const onWarn = spy();\n      Logger.on('debug', onWarn);\n\n      return transformerHelper\n        .writeXMLToTransformer(\n          ScriptPath,\n          `<script>\n  <metadata>\n    <longrunning>1</longrunning>\n    <custom>test</custom>\n  </metadata>\n</script>`\n        )\n        .then((files) => transformerHelper.expectFileContents(files))\n        .then((contents) =>\n          expect(JSON.parse(contents[0]), 'to equal', {\n            metadata: {\n              longrunning: '1',\n              custom: 'test',\n            },\n          })\n        )\n        .then(() => {\n          expect(onWarn, 'was called once'); // should not be called for 'longrunning'\n          expect(onWarn, 'to have a call satisfying', { args: [/generic metadata/i] });\n        });\n    });\n\n    it('should store array of custom metadata elements if needed', function () {\n      return transformerHelper\n        .writeXMLToTransformer(\n          ScriptPath,\n          `<script>\n  <metadata>\n    <custom>test</custom>\n    <custom>test2</custom>\n  </metadata>\n</script>`\n        )\n        .then((files) => transformerHelper.expectFileContents(files))\n        .then((contents) =>\n          expect(JSON.parse(contents[0]), 'to equal', {\n            metadata: { custom: ['test', 'test2'] },\n          })\n        );\n    });\n\n    it('should store icon metadata', function () {\n      return transformerHelper\n        .writeXMLToTransformer(\n          ScriptPath,\n          `<script>\n  <metadata>\n    <icon type=\"image/png\">asdf</icon>\n  </metadata>\n</script>`\n        )\n        .then((files) => transformerHelper.expectFileContents(files))\n        .then((contents) =>\n          expect(JSON.parse(contents[0]), 'to equal', {\n            icon: {\n              type: 'image/png',\n              content: 'asdf',\n            },\n          })\n        );\n    });\n\n    it('should store empty icon metadata', function () {\n      return transformerHelper\n        .writeXMLToTransformer(\n          ScriptPath,\n          `<script>\n  <metadata>\n    <icon></icon>\n  </metadata>\n</script>`\n        )\n        .then((files) => transformerHelper.expectFileContents(files))\n        .then((contents) =>\n          expect(JSON.parse(contents[0]), 'to equal', {\n            icon: {\n              content: '',\n            },\n          })\n        );\n    });\n\n    it('should store visible metadata', function () {\n      return transformerHelper\n        .writeXMLToTransformer(\n          ScriptPath,\n          `<script>\n  <metadata>\n    <visible>1</visible>\n  </metadata>\n</script>`\n        )\n        .then((files) => transformerHelper.expectFileContents(files))\n        .then((contents) =>\n          expect(JSON.parse(contents[0]), 'to equal', {\n            visible: true,\n          })\n        );\n    });\n\n    it('should properly interpret visible metadata', function () {\n      return transformerHelper\n        .writeXMLToTransformer(\n          ScriptPath,\n          `<script>\n  <metadata>\n    <visible>0</visible>\n  </metadata>\n</script>`\n        )\n        .then((files) => transformerHelper.expectFileContents(files))\n        .then((contents) =>\n          expect(JSON.parse(contents[0]), 'to equal', {\n            visible: false,\n          })\n        );\n    });\n\n    it('should store title metadata', function () {\n      return transformerHelper\n        .writeXMLToTransformer(\n          ScriptPath,\n          `<script>\n  <metadata>\n    <title>script title</title>\n  </metadata>\n</script>`\n        )\n        .then((files) => transformerHelper.expectFileContents(files))\n        .then((contents) =>\n          expect(JSON.parse(contents[0]), 'to equal', {\n            title: 'script title',\n          })\n        );\n    });\n\n    it('should store description metadata', function () {\n      return transformerHelper\n        .writeXMLToTransformer(\n          ScriptPath,\n          `<script>\n  <metadata>\n    <description>script description</description>\n  </metadata>\n</script>`\n        )\n        .then((files) => transformerHelper.expectFileContents(files))\n        .then((contents) =>\n          expect(JSON.parse(contents[0]), 'to equal', {\n            description: 'script description',\n          })\n        );\n    });\n\n    it('should store parameters', function () {\n      return transformerHelper\n        .writeXMLToTransformer(\n          ScriptPath,\n          `<script>\n  <parameter name=\"paramname\"/>\n</script>`\n        )\n        .then((files) => transformerHelper.expectFileContents(files))\n        .then((contents) =>\n          expect(JSON.parse(contents[0]), 'to equal', {\n            parameters: [{ name: 'paramname' }],\n          })\n        );\n    });\n\n    it('should store relative parameter without target', function () {\n      return transformerHelper\n        .writeXMLToTransformer(\n          ScriptPath,\n          `<script>\n  <parameter name=\"double_prop\" type=\"node.value\" trigger=\"true\" relative=\"true\">\n    <RelativePath>\n      <Elements/>\n    </RelativePath>\n  </parameter>\n</script>`\n        )\n        .then((files) => transformerHelper.expectFileContents(files))\n        .then(([json]) => JSON.parse(json))\n        .then((config) => {\n          expect(config.parameters[0].relative, 'to be', 'true');\n          expect(config.parameters[0].target, 'to equal', {});\n        });\n    });\n\n    it('should store relative parameter with target', function () {\n      return transformerHelper\n        .writeXMLToTransformer(\n          ScriptPath,\n          `<script>\n  <parameter name=\"double_prop\" type=\"node.value\" trigger=\"true\" relative=\"true\">\n    <RelativePath>\n      <Elements>\n        <RelativePathElement>\n          <TargetName>\n            <NamespaceIndex>1</NamespaceIndex>\n            <Name>double</Name>\n          </TargetName>\n        </RelativePathElement>\n      </Elements>\n    </RelativePath>\n  </parameter>\n</script>`\n        )\n        .then((files) => transformerHelper.expectFileContents(files))\n        .then(([json]) => JSON.parse(json))\n        .then((config) => {\n          expect(config.parameters[0].relative, 'to be', 'true');\n          expect(config.parameters[0].target, 'to equal', {\n            namespaceIndex: 1,\n            name: 'double',\n          });\n        });\n    });\n\n    it('should store relative parameter target with invalid namespace', function () {\n      return transformerHelper\n        .writeXMLToTransformer(\n          ScriptPath,\n          `<script>\n  <parameter name=\"double_prop\" type=\"node.value\" trigger=\"true\" relative=\"true\">\n    <RelativePath>\n      <Elements>\n        <RelativePathElement>\n          <TargetName>\n            <NamespaceIndex>X</NamespaceIndex>\n            <Name>double</Name>\n          </TargetName>\n        </RelativePathElement>\n      </Elements>\n    </RelativePath>\n  </parameter>\n</script>`\n        )\n        .then((files) => transformerHelper.expectFileContents(files))\n        .then(([json]) => JSON.parse(json))\n        .then((config) => {\n          expect(config.parameters[0].relative, 'to be', 'true');\n          expect(config.parameters[0].target, 'to equal', {\n            namespaceIndex: 1,\n            name: 'double',\n          });\n        });\n    });\n\n    it('should store code', function () {\n      const code = 'console.log(\"called\");';\n      return transformerHelper\n        .writeXMLToTransformer(\n          ScriptPath,\n          `<script>\n  <code>${code}</code>\n</script>`\n        )\n        .then((files) => transformerHelper.expectFileContents(files))\n        .then((contents) => expect(contents[1], 'to equal', code));\n    });\n  });\n\n  /** @test {ScriptTransformer#createCombinedFile} */\n  describe('#createCombinedFile', function () {\n    it('should forward config parse errors', function () {\n      return expect(\n        transformerHelper.createCombinedFileWithContents(`${ScriptPath}/Test`, {\n          '.json': '\"description\": \"script description\" }',\n        }),\n        'to call the callback with error',\n        /Error parsing JSON in /\n      );\n    });\n\n    context('when called on a quick dynamic', function () {\n      it('should store empty metadata', function () {\n        return expect(\n          transformerHelper.createCombinedFileWithContents(`${QDPath}/Test`, {\n            '.json': '{ }',\n          }),\n          'to call the callback'\n        )\n          .then((args) => transformerHelper.expectFileContents([args[1]]))\n          .then((contents) => expect(contents[0], 'to contain', '<metadata/>'));\n      });\n\n      it('should insert icon metadata', function () {\n        return expect(\n          transformerHelper.createCombinedFileWithContents(`${QDPath}/Test`, {\n            '.json': '{ \"icon\": { \"type\": \"image/png\", \"content\": \"asdf\" } }',\n          }),\n          'to call the callback'\n        )\n          .then((args) => transformerHelper.expectFileContents([args[1]]))\n          .then((contents) =>\n            expect(contents[0], 'to contain', '<icon type=\"image/png\">asdf</icon>')\n          );\n      });\n\n      it('should insert visible metadata', function () {\n        return Promise.all([\n          expect(\n            transformerHelper.createCombinedFileWithContents(`${QDPath}/Test`, {\n              '.json': '{ \"visible\": false }',\n            }),\n            'to call the callback'\n          )\n            .then((args) => transformerHelper.expectFileContents([args[1]]))\n            .then((contents) => expect(contents[0], 'to contain', '<visible>0</visible>')),\n          expect(\n            transformerHelper.createCombinedFileWithContents(`${QDPath}/Test`, {\n              '.json': '{ \"visible\": true }',\n            }),\n            'to call the callback'\n          )\n            .then((args) => transformerHelper.expectFileContents([args[1]]))\n            .then((contents) => expect(contents[0], 'to contain', '<visible>1</visible>')),\n        ]);\n      });\n\n      it('should insert title metadata', function () {\n        return expect(\n          transformerHelper.createCombinedFileWithContents(`${QDPath}/Test`, {\n            '.json': '{ \"title\": \"qd title\" }',\n          }),\n          'to call the callback'\n        )\n          .then((args) => transformerHelper.expectFileContents([args[1]]))\n          .then((contents) => expect(contents[0], 'to contain', '<title>qd title</title>'));\n      });\n\n      it('should insert description metadata', function () {\n        return expect(\n          transformerHelper.createCombinedFileWithContents(`${QDPath}/Test`, {\n            '.json': '{ \"description\": \"qd desc\" }',\n          }),\n          'to call the callback'\n        )\n          .then((args) => transformerHelper.expectFileContents([args[1]]))\n          .then((contents) =>\n            expect(contents[0], 'to contain', '<description>qd desc</description>')\n          );\n      });\n    });\n\n    context('when called on a script', function () {\n      it('should ignore quickdynamic metadata', function () {\n        return expect(\n          transformerHelper.createCombinedFileWithContents(`${ScriptPath}/Test`, {\n            '.json': '{ \"icon\": { \"type\": \"image/png\", \"content\": \"asdf\" } }',\n          }),\n          'to call the callback'\n        )\n          .then((args) => transformerHelper.expectFileContents([args[1]]))\n          .then((contents) => expect(contents[0], 'not to contain', '<icon', '<metadata'));\n      });\n    });\n\n    it('should insert parameters', function () {\n      return expect(\n        transformerHelper.createCombinedFileWithContents(`${QDPath}/Test`, {\n          '.json': '{ \"parameters\": [{ \"name\": \"paramname\" }] }',\n        }),\n        'to call the callback'\n      )\n        .then((args) => transformerHelper.expectFileContents([args[1]]))\n        .then((contents) => expect(contents[0], 'to contain', '<parameter name=\"paramname\"/>'));\n    });\n\n    it('should insert relative parameter without target', function () {\n      return expect(\n        transformerHelper.createCombinedFileWithContents(`${QDPath}/Test`, {\n          '.json': '{ \"parameters\": [{ \"name\": \"paramname\", \"relative\": \"true\", \"target\": {} }] }',\n        }),\n        'to call the callback'\n      )\n        .then((args) => transformerHelper.expectFileContents([args[1]]))\n        .then((contents) =>\n          expect(\n            contents[0],\n            'to contain',\n            `<parameter name=\"paramname\" relative=\"true\">\n  <RelativePath>\n   <Elements/>`\n              .split('\\n')\n              .join('\\r\\n')\n          )\n        );\n    });\n\n    it('should insert relative parameter with target', function () {\n      return expect(\n        transformerHelper.createCombinedFileWithContents(`${QDPath}/Test`, {\n          '.json': JSON.stringify({\n            parameters: [\n              {\n                name: 'paramname',\n                relative: 'true',\n                target: {\n                  namespaceIndex: 2,\n                  name: 'Test',\n                },\n              },\n            ],\n          }),\n        }),\n        'to call the callback'\n      )\n        .then((args) => transformerHelper.expectFileContents([args[1]]))\n        .then((contents) =>\n          expect(\n            contents[0],\n            'to contain',\n            `<parameter name=\"paramname\" relative=\"true\">\n  <RelativePath>\n   <Elements>\n    <RelativePathElement>\n     <TargetName>\n      <NamespaceIndex>2</NamespaceIndex>\n      <Name>Test</Name>\n     </TargetName>\n    </RelativePathElement>\n   </Elements>`\n              .split('\\n')\n              .join('\\r\\n')\n          )\n        );\n    });\n\n    it('should insert custom metadata', function () {\n      return expect(\n        transformerHelper.createCombinedFileWithContents(`${QDPath}/Test`, {\n          '.json': '{ \"metadata\": { \"custom\": \"test\" } }',\n        }),\n        'to call the callback'\n      )\n        .then((args) => transformerHelper.expectFileContents([args[1]]))\n        .then((contents) => expect(contents[0], 'to contain', '<custom>test</custom>'));\n    });\n\n    it('should insert custom metadata array', function () {\n      return expect(\n        transformerHelper.createCombinedFileWithContents(`${QDPath}/Test`, {\n          '.json': '{ \"metadata\": { \"custom\": [\"test\", \"test2\"] } }',\n        }),\n        'to call the callback'\n      )\n        .then((args) => transformerHelper.expectFileContents([args[1]]))\n        .then((contents) =>\n          expect(contents[0], 'to contain', '<custom>test</custom>', '<custom>test2</custom>')\n        );\n    });\n\n    it('should insert script code', function () {\n      const code = 'console.log(\"called\");';\n      return expect(\n        transformerHelper.createCombinedFileWithContents(`${QDPath}/Test`, {\n          '.js': code,\n        }),\n        'to call the callback'\n      )\n        .then((args) => transformerHelper.expectFileContents([args[1]]))\n        .then((contents) => expect(contents[0], 'to contain', `<code><![CDATA[${code}]]></code>`));\n    });\n\n    context('when encoding fails', function () {\n      it('should forward encode errors', function () {\n        class FailingScriptTransformer extends ScriptTransformer {\n          encodeContents(object, callback) {\n            callback(new Error('Encode error'));\n          }\n        }\n\n        const helper = new TransformerHelper(FailingScriptTransformer);\n\n        return expect(\n          helper.createCombinedFileWithContents(`${QDPath}/Test`, {\n            '.json': '{ \"parameters\": [{ \"name\": \"paramname\" }] }',\n          }),\n          'to call the callback with error',\n          'Encode error'\n        );\n      });\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/transform/ScriptTransformer.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1393,
    "kind": "test",
    "name": "describe664",
    "testId": 664,
    "memberof": "test/src/transform/ScriptTransformer.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe664",
    "access": null,
    "description": "#shouldBeTransformed",
    "lineNumber": 15,
    "testTargets": [
      "ScriptTransformer#shouldBeTransformed"
    ]
  },
  {
    "__docId__": 1394,
    "kind": "test",
    "name": "it665",
    "testId": 665,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe664",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe664.it665",
    "access": null,
    "description": "should return true for ScriptCode type nodes",
    "lineNumber": 16
  },
  {
    "__docId__": 1395,
    "kind": "test",
    "name": "it666",
    "testId": 666,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe664",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe664.it666",
    "access": null,
    "description": "should return true for QuickDynamic type nodes",
    "lineNumber": 20
  },
  {
    "__docId__": 1396,
    "kind": "test",
    "name": "describe667",
    "testId": 667,
    "memberof": "test/src/transform/ScriptTransformer.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "access": null,
    "description": "#transformFromDB",
    "lineNumber": 29,
    "testTargets": [
      "ScriptTransformer#transformFromDB"
    ]
  },
  {
    "__docId__": 1397,
    "kind": "test",
    "name": "it668",
    "testId": 668,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it668",
    "access": null,
    "description": "should forward parse errors",
    "lineNumber": 30
  },
  {
    "__docId__": 1398,
    "kind": "test",
    "name": "it669",
    "testId": 669,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it669",
    "access": null,
    "description": "should warn with invalid xml",
    "lineNumber": 38
  },
  {
    "__docId__": 1399,
    "kind": "test",
    "name": "it670",
    "testId": 670,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it670",
    "access": null,
    "description": "should write empty config file for empty Script",
    "lineNumber": 51
  },
  {
    "__docId__": 1400,
    "kind": "test",
    "name": "it671",
    "testId": 671,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it671",
    "access": null,
    "description": "should write empty .js file for empty Script",
    "lineNumber": 60
  },
  {
    "__docId__": 1401,
    "kind": "test",
    "name": "it672",
    "testId": 672,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it672",
    "access": null,
    "description": "should only store metadata elements",
    "lineNumber": 69
  },
  {
    "__docId__": 1402,
    "kind": "test",
    "name": "it673",
    "testId": 673,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it673",
    "access": null,
    "description": "should store custom metadata elements",
    "lineNumber": 81
  },
  {
    "__docId__": 1403,
    "kind": "test",
    "name": "it674",
    "testId": 674,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it674",
    "access": null,
    "description": "should store array of custom metadata elements if needed",
    "lineNumber": 110
  },
  {
    "__docId__": 1404,
    "kind": "test",
    "name": "it675",
    "testId": 675,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it675",
    "access": null,
    "description": "should store icon metadata",
    "lineNumber": 129
  },
  {
    "__docId__": 1405,
    "kind": "test",
    "name": "it676",
    "testId": 676,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it676",
    "access": null,
    "description": "should store empty icon metadata",
    "lineNumber": 150
  },
  {
    "__docId__": 1406,
    "kind": "test",
    "name": "it677",
    "testId": 677,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it677",
    "access": null,
    "description": "should store visible metadata",
    "lineNumber": 170
  },
  {
    "__docId__": 1407,
    "kind": "test",
    "name": "it678",
    "testId": 678,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it678",
    "access": null,
    "description": "should properly interpret visible metadata",
    "lineNumber": 188
  },
  {
    "__docId__": 1408,
    "kind": "test",
    "name": "it679",
    "testId": 679,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it679",
    "access": null,
    "description": "should store title metadata",
    "lineNumber": 206
  },
  {
    "__docId__": 1409,
    "kind": "test",
    "name": "it680",
    "testId": 680,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it680",
    "access": null,
    "description": "should store description metadata",
    "lineNumber": 224
  },
  {
    "__docId__": 1410,
    "kind": "test",
    "name": "it681",
    "testId": 681,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it681",
    "access": null,
    "description": "should store parameters",
    "lineNumber": 242
  },
  {
    "__docId__": 1411,
    "kind": "test",
    "name": "it682",
    "testId": 682,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it682",
    "access": null,
    "description": "should store relative parameter without target",
    "lineNumber": 258
  },
  {
    "__docId__": 1412,
    "kind": "test",
    "name": "it683",
    "testId": 683,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it683",
    "access": null,
    "description": "should store relative parameter with target",
    "lineNumber": 278
  },
  {
    "__docId__": 1413,
    "kind": "test",
    "name": "it684",
    "testId": 684,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it684",
    "access": null,
    "description": "should store relative parameter target with invalid namespace",
    "lineNumber": 308
  },
  {
    "__docId__": 1414,
    "kind": "test",
    "name": "it685",
    "testId": 685,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe667",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe667.it685",
    "access": null,
    "description": "should store code",
    "lineNumber": 338
  },
  {
    "__docId__": 1415,
    "kind": "test",
    "name": "describe686",
    "testId": 686,
    "memberof": "test/src/transform/ScriptTransformer.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686",
    "access": null,
    "description": "#createCombinedFile",
    "lineNumber": 353,
    "testTargets": [
      "ScriptTransformer#createCombinedFile"
    ]
  },
  {
    "__docId__": 1416,
    "kind": "test",
    "name": "it687",
    "testId": 687,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe686",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686.it687",
    "access": null,
    "description": "should forward config parse errors",
    "lineNumber": 354
  },
  {
    "__docId__": 1417,
    "kind": "test",
    "name": "context688",
    "testId": 688,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe686",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686.context688",
    "access": null,
    "description": "when called on a quick dynamic",
    "lineNumber": 364
  },
  {
    "__docId__": 1418,
    "kind": "test",
    "name": "it689",
    "testId": 689,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe686.context688",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686.context688.it689",
    "access": null,
    "description": "should store empty metadata",
    "lineNumber": 365
  },
  {
    "__docId__": 1419,
    "kind": "test",
    "name": "it690",
    "testId": 690,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe686.context688",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686.context688.it690",
    "access": null,
    "description": "should insert icon metadata",
    "lineNumber": 376
  },
  {
    "__docId__": 1420,
    "kind": "test",
    "name": "it691",
    "testId": 691,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe686.context688",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686.context688.it691",
    "access": null,
    "description": "should insert visible metadata",
    "lineNumber": 389
  },
  {
    "__docId__": 1421,
    "kind": "test",
    "name": "it692",
    "testId": 692,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe686.context688",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686.context688.it692",
    "access": null,
    "description": "should insert title metadata",
    "lineNumber": 410
  },
  {
    "__docId__": 1422,
    "kind": "test",
    "name": "it693",
    "testId": 693,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe686.context688",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686.context688.it693",
    "access": null,
    "description": "should insert description metadata",
    "lineNumber": 421
  },
  {
    "__docId__": 1423,
    "kind": "test",
    "name": "context694",
    "testId": 694,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe686",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686.context694",
    "access": null,
    "description": "when called on a script",
    "lineNumber": 435
  },
  {
    "__docId__": 1424,
    "kind": "test",
    "name": "it695",
    "testId": 695,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe686.context694",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686.context694.it695",
    "access": null,
    "description": "should ignore quickdynamic metadata",
    "lineNumber": 436
  },
  {
    "__docId__": 1425,
    "kind": "test",
    "name": "it696",
    "testId": 696,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe686",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686.it696",
    "access": null,
    "description": "should insert parameters",
    "lineNumber": 448
  },
  {
    "__docId__": 1426,
    "kind": "test",
    "name": "it697",
    "testId": 697,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe686",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686.it697",
    "access": null,
    "description": "should insert relative parameter without target",
    "lineNumber": 459
  },
  {
    "__docId__": 1427,
    "kind": "test",
    "name": "it698",
    "testId": 698,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe686",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686.it698",
    "access": null,
    "description": "should insert relative parameter with target",
    "lineNumber": 480
  },
  {
    "__docId__": 1428,
    "kind": "test",
    "name": "it699",
    "testId": 699,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe686",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686.it699",
    "access": null,
    "description": "should insert custom metadata",
    "lineNumber": 519
  },
  {
    "__docId__": 1429,
    "kind": "test",
    "name": "it700",
    "testId": 700,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe686",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686.it700",
    "access": null,
    "description": "should insert custom metadata array",
    "lineNumber": 530
  },
  {
    "__docId__": 1430,
    "kind": "test",
    "name": "it701",
    "testId": 701,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe686",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686.it701",
    "access": null,
    "description": "should insert script code",
    "lineNumber": 543
  },
  {
    "__docId__": 1431,
    "kind": "test",
    "name": "context702",
    "testId": 702,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe686",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686.context702",
    "access": null,
    "description": "when encoding fails",
    "lineNumber": 555
  },
  {
    "__docId__": 1432,
    "kind": "test",
    "name": "it703",
    "testId": 703,
    "memberof": "test/src/transform/ScriptTransformer.spec.js~describe686.context702",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/transform/ScriptTransformer.spec.js~describe686.context702.it703",
    "access": null,
    "description": "should forward encode errors",
    "lineNumber": 556
  },
  {
    "__docId__": 1433,
    "kind": "testFile",
    "name": "test/src/util/cleanup.spec.js",
    "content": "import expect from 'unexpected';\nimport { stub, spy } from 'sinon';\nimport proxyquire from 'proxyquire';\nimport Logger from 'gulplog';\n\nfunction createCleanup(numberOfOpenSessions, closeOpenShouldFail) {\n  return proxyquire('../../../src/util/cleanup', {\n    '../lib/server/Session': {\n      __esModule: true,\n      default: class Session {\n        static get open() {\n          return new Array(numberOfOpenSessions);\n        }\n\n        static closeOpen() {\n          return closeOpenShouldFail\n            ? Promise.reject('Session.closeOpen error')\n            : Promise.resolve();\n        }\n      },\n    },\n  }).default;\n}\n\n/** @test {cleanup} */\ndescribe('cleanup', function () {\n  before(() => stub(process, 'kill'));\n  after(() => process.kill.restore());\n  afterEach(() => process.kill.resetHistory());\n\n  it('should call uninstall', function () {\n    const uninstall = spy();\n    createCleanup(0, false)(null, null, uninstall);\n\n    expect(uninstall.calledOnce, 'to be', true);\n  });\n\n  context('when receiving SIGINT', function () {\n    it('should log \"Ctrl-C\"', function () {\n      const onWarn = spy();\n      Logger.on('warn', onWarn);\n\n      createCleanup(0, false)(null, 'SIGINT', () => {});\n      expect(onWarn.calledOnce, 'to be', true);\n      expect(onWarn.lastCall.args[0], 'to match', /Ctrl-C/);\n    });\n  });\n\n  context('with open sessions', function () {\n    it('should return false', function () {\n      expect(\n        createCleanup(3, false)(null, null, () => {}),\n        'to be',\n        false\n      );\n    });\n\n    it('should call process.kill', function (done) {\n      createCleanup(3, false)(null, null, () => {});\n      setTimeout(() => {\n        expect(process.kill.calledOnce, 'to be', true);\n        done();\n      }, 10);\n    });\n\n    it('should forward Session.closeOpen errors', function (done) {\n      createCleanup(3, true)(null, null, () => {});\n      setTimeout(() => {\n        expect(process.kill.calledOnce, 'to be', true);\n        done();\n      }, 10);\n    });\n  });\n\n  context('without open sessions', function () {\n    it('should return true', function () {\n      expect(\n        createCleanup(0, false)(null, null, () => {}),\n        'to be',\n        true\n      );\n    });\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/util/cleanup.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1434,
    "kind": "test",
    "name": "describe704",
    "testId": 704,
    "memberof": "test/src/util/cleanup.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/util/cleanup.spec.js~describe704",
    "access": null,
    "description": "cleanup",
    "lineNumber": 26,
    "testTargets": [
      "cleanup"
    ]
  },
  {
    "__docId__": 1435,
    "kind": "test",
    "name": "it705",
    "testId": 705,
    "memberof": "test/src/util/cleanup.spec.js~describe704",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/util/cleanup.spec.js~describe704.it705",
    "access": null,
    "description": "should call uninstall",
    "lineNumber": 31
  },
  {
    "__docId__": 1436,
    "kind": "test",
    "name": "context706",
    "testId": 706,
    "memberof": "test/src/util/cleanup.spec.js~describe704",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/util/cleanup.spec.js~describe704.context706",
    "access": null,
    "description": "when receiving SIGINT",
    "lineNumber": 38
  },
  {
    "__docId__": 1437,
    "kind": "test",
    "name": "it707",
    "testId": 707,
    "memberof": "test/src/util/cleanup.spec.js~describe704.context706",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/util/cleanup.spec.js~describe704.context706.it707",
    "access": null,
    "description": "should log \"Ctrl-C\"",
    "lineNumber": 39
  },
  {
    "__docId__": 1438,
    "kind": "test",
    "name": "context708",
    "testId": 708,
    "memberof": "test/src/util/cleanup.spec.js~describe704",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/util/cleanup.spec.js~describe704.context708",
    "access": null,
    "description": "with open sessions",
    "lineNumber": 49
  },
  {
    "__docId__": 1439,
    "kind": "test",
    "name": "it709",
    "testId": 709,
    "memberof": "test/src/util/cleanup.spec.js~describe704.context708",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/util/cleanup.spec.js~describe704.context708.it709",
    "access": null,
    "description": "should return false",
    "lineNumber": 50
  },
  {
    "__docId__": 1440,
    "kind": "test",
    "name": "it710",
    "testId": 710,
    "memberof": "test/src/util/cleanup.spec.js~describe704.context708",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/util/cleanup.spec.js~describe704.context708.it710",
    "access": null,
    "description": "should call process.kill",
    "lineNumber": 58
  },
  {
    "__docId__": 1441,
    "kind": "test",
    "name": "it711",
    "testId": 711,
    "memberof": "test/src/util/cleanup.spec.js~describe704.context708",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/util/cleanup.spec.js~describe704.context708.it711",
    "access": null,
    "description": "should forward Session.closeOpen errors",
    "lineNumber": 66
  },
  {
    "__docId__": 1442,
    "kind": "test",
    "name": "context712",
    "testId": 712,
    "memberof": "test/src/util/cleanup.spec.js~describe704",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/util/cleanup.spec.js~describe704.context712",
    "access": null,
    "description": "without open sessions",
    "lineNumber": 75
  },
  {
    "__docId__": 1443,
    "kind": "test",
    "name": "it713",
    "testId": 713,
    "memberof": "test/src/util/cleanup.spec.js~describe704.context712",
    "testDepth": 2,
    "static": true,
    "longname": "test/src/util/cleanup.spec.js~describe704.context712.it713",
    "access": null,
    "description": "should return true",
    "lineNumber": 76
  },
  {
    "__docId__": 1444,
    "kind": "testFile",
    "name": "test/src/util/fs.spec.js",
    "content": "import expect from 'unexpected';\nimport { getStat, validateDirectoryExists } from '../../../src/util/fs';\n\n/** @test {getStat} */\ndescribe('getStat', function () {\n  it('should be fulfilled with valid path', function () {\n    return expect(getStat('./package.json'), 'to be fulfilled');\n  });\n\n  it('should be rejected with invalid path', function () {\n    return expect(getStat('./does-not-exist'), 'to be rejected');\n  });\n});\n\n/** @test {validateDirectoryExists} */\ndescribe('validateDirectoryExists', function () {\n  it('should be rejected with invalid path', function () {\n    return expect(validateDirectoryExists('./does-not-exist'), 'to be rejected');\n  });\n\n  it('shoud be rejected with non-directory path', function () {\n    return expect(validateDirectoryExists('./package.json'), 'to be rejected');\n  });\n\n  it('should be fulfilled with directory path ', function () {\n    return expect(validateDirectoryExists('./test'), 'to be fulfilled');\n  });\n});\n",
    "static": true,
    "longname": "/home/circleci/project/packages/atscm/test/src/util/fs.spec.js",
    "access": null,
    "description": null,
    "lineNumber": 1
  },
  {
    "__docId__": 1445,
    "kind": "test",
    "name": "describe714",
    "testId": 714,
    "memberof": "test/src/util/fs.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/util/fs.spec.js~describe714",
    "access": null,
    "description": "getStat",
    "lineNumber": 5,
    "testTargets": [
      "getStat"
    ]
  },
  {
    "__docId__": 1446,
    "kind": "test",
    "name": "it715",
    "testId": 715,
    "memberof": "test/src/util/fs.spec.js~describe714",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/util/fs.spec.js~describe714.it715",
    "access": null,
    "description": "should be fulfilled with valid path",
    "lineNumber": 6
  },
  {
    "__docId__": 1447,
    "kind": "test",
    "name": "it716",
    "testId": 716,
    "memberof": "test/src/util/fs.spec.js~describe714",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/util/fs.spec.js~describe714.it716",
    "access": null,
    "description": "should be rejected with invalid path",
    "lineNumber": 10
  },
  {
    "__docId__": 1448,
    "kind": "test",
    "name": "describe717",
    "testId": 717,
    "memberof": "test/src/util/fs.spec.js",
    "testDepth": 0,
    "static": true,
    "longname": "test/src/util/fs.spec.js~describe717",
    "access": null,
    "description": "validateDirectoryExists",
    "lineNumber": 16,
    "testTargets": [
      "validateDirectoryExists"
    ]
  },
  {
    "__docId__": 1449,
    "kind": "test",
    "name": "it718",
    "testId": 718,
    "memberof": "test/src/util/fs.spec.js~describe717",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/util/fs.spec.js~describe717.it718",
    "access": null,
    "description": "should be rejected with invalid path",
    "lineNumber": 17
  },
  {
    "__docId__": 1450,
    "kind": "test",
    "name": "it719",
    "testId": 719,
    "memberof": "test/src/util/fs.spec.js~describe717",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/util/fs.spec.js~describe717.it719",
    "access": null,
    "description": "shoud be rejected with non-directory path",
    "lineNumber": 21
  },
  {
    "__docId__": 1451,
    "kind": "test",
    "name": "it720",
    "testId": 720,
    "memberof": "test/src/util/fs.spec.js~describe717",
    "testDepth": 1,
    "static": true,
    "longname": "test/src/util/fs.spec.js~describe717.it720",
    "access": null,
    "description": "should be fulfilled with directory path ",
    "lineNumber": 25
  }
]