UNPKG

json-tots

Version:

Template of Templates, a.k.a Template Should Eat Itself

239 lines (237 loc) 11 kB
"use strict"; var _Object$keys = require("@babel/runtime-corejs3/core-js-stable/object/keys"); var _Object$getOwnPropertySymbols = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols"); var _filterInstanceProperty2 = require("@babel/runtime-corejs3/core-js-stable/instance/filter"); var _Object$getOwnPropertyDescriptor = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptor"); var _forEachInstanceProperty = require("@babel/runtime-corejs3/core-js-stable/instance/for-each"); var _Object$getOwnPropertyDescriptors = require("@babel/runtime-corejs3/core-js-stable/object/get-own-property-descriptors"); var _Object$defineProperties = require("@babel/runtime-corejs3/core-js-stable/object/define-properties"); var _Object$defineProperty = require("@babel/runtime-corejs3/core-js-stable/object/define-property"); var _interopRequireDefault = require("@babel/runtime-corejs3/helpers/interopRequireDefault"); var _map = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/map")); var _startsWith = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/starts-with")); var _concat = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/concat")); var _reduce = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/reduce")); var _filter = _interopRequireDefault(require("@babel/runtime-corejs3/core-js-stable/instance/filter")); var _defineProperty2 = _interopRequireDefault(require("@babel/runtime-corejs3/helpers/defineProperty")); function ownKeys(object, enumerableOnly) { var keys = _Object$keys(object); if (_Object$getOwnPropertySymbols) { var symbols = _Object$getOwnPropertySymbols(object); enumerableOnly && (symbols = _filterInstanceProperty2(symbols).call(symbols, function (sym) { return _Object$getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; } function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var _context5, _context6; var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? _forEachInstanceProperty(_context5 = ownKeys(Object(source), !0)).call(_context5, function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }) : _Object$getOwnPropertyDescriptors ? _Object$defineProperties(target, _Object$getOwnPropertyDescriptors(source)) : _forEachInstanceProperty(_context6 = ownKeys(Object(source))).call(_context6, function (key) { _Object$defineProperty(target, key, _Object$getOwnPropertyDescriptor(source, key)); }); } return target; } /* eslint-disable array-callback-return */ var traverse = require('traverse'); var jp = require('jsonpath'); var F = require('functional-pipelines'); var defaultConfig = { "throws": false, nullifyMissing: true, operators: { constraints: { '?': { drop: true }, '!': { nullable: true } } } }; var bins = require('./core/builtins'); var _require = require('./core/render'), renderStringNode = _require.renderStringNode, renderFunctionExpressionNode = _require.renderFunctionExpressionNode, renderArrayNode = _require.renderArrayNode, renderData = _require.data; var _require2 = require('./core/operators'), jpify = _require2.jpify; var _require3 = require('./core/policy/key/run-policy'), runPolicy = _require3.runPolicy; /** * Transforms JSON document using a JSON template * @param template Template JSON * @param sources A map of alternative document-sources, including `default` source * @param tags Reference to a map that gets populated with Tags * @param functions A map of user-defined function, if name-collision occurs with builtin functions, user-defined functions take precedence * @param args A map of extended arguments to @function expressions, args keys are either functionName (if used only once), functionKey (if globally unique) or functionPath which is unique but ugliest option to write * @param config Allows to override defaultConfig * @param builtins A map of builtin functions, defaults to ./core/builtins.js functions * @returns {function(*=): *} */ var transform = function transform(template) { var _ref = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, _ref$meta = _ref.meta, meta = _ref$meta === void 0 ? 0 : _ref$meta, _ref$sources = _ref.sources, sources = _ref$sources === void 0 ? { "default": {} } : _ref$sources, _ref$tags = _ref.tags, tags = _ref$tags === void 0 ? {} : _ref$tags, _ref$functions = _ref.functions, functions = _ref$functions === void 0 ? {} : _ref$functions, _ref$args = _ref.args, args = _ref$args === void 0 ? {} : _ref$args, _ref$config = _ref.config, config = _ref$config === void 0 ? defaultConfig : _ref$config; var _ref2 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, _ref2$builtins = _ref2.builtins, builtins = _ref2$builtins === void 0 ? bins : _ref2$builtins; return function (document) { var result; functions = _objectSpread(_objectSpread({}, bins), functions); var options = { meta: meta, sources: _objectSpread(_objectSpread({}, sources), {}, { origin: document }), tags: tags, functions: functions, args: args, config: config }; if (F.isString(template)) { var _renderStringNode = renderStringNode({ node: template, path: ['$'] }, options); result = _renderStringNode.rendered; } else { var _context; result = (0, _map["default"])(_context = traverse(template)).call(_context, function (node) { var self = this; var contextRef = self; var rendered; var asts; if (F.isFunction(node)) { rendered = node(document); } else if (F.isString(node)) { if ((0, _startsWith["default"])(node).call(node, '@')) { var _renderFunctionExpres = renderFunctionExpressionNode(contextRef, options, document); rendered = _renderFunctionExpres.rendered; } else { var _renderStringNode2 = renderStringNode(contextRef, options); rendered = _renderStringNode2.rendered; asts = _renderStringNode2.asts; } } else if (F.isArray(node)) { var _renderArrayNode = renderArrayNode(contextRef, options); rendered = _renderArrayNode.rendered; asts = _renderArrayNode.asts; } else { rendered = node; } if (self.isRoot) { return; } if (rendered === undefined) { if (jp.value(config, '$.operators.constraints["?"].drop')) { self.remove(true); } else { self.update(null); } } else if (rendered === null) { if (jp.value(config, '$.operators.constraints["!"].nullable')) { self.update(null); } else { var _context2; throw new Error((0, _concat["default"])(_context2 = "Missing required attribute: [".concat(jp.stringify(self.path), ": ")).call(_context2, asts ? asts[0].source : '', "]")); } } else if (F.isReduced(rendered)) { self.update(F.unreduced(rendered), true); // stopHere, don't traverse children } else { self.update(rendered); } }); } return result; }; }; var reRenderTags = function reRenderTags(template) { var _ref3 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, _ref3$meta = _ref3.meta, meta = _ref3$meta === void 0 ? 0 : _ref3$meta, _ref3$sources = _ref3.sources, sources = _ref3$sources === void 0 ? { "default": {} } : _ref3$sources, _ref3$tags = _ref3.tags, tags = _ref3$tags === void 0 ? {} : _ref3$tags, _ref3$functions = _ref3.functions, functions = _ref3$functions === void 0 ? {} : _ref3$functions, _ref3$args = _ref3.args, args = _ref3$args === void 0 ? {} : _ref3$args, _ref3$config = _ref3.config, config = _ref3$config === void 0 ? defaultConfig : _ref3$config; var _ref4 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, _ref4$builtins = _ref4.builtins, builtins = _ref4$builtins === void 0 ? bins : _ref4$builtins; return function (document) { var _context3; return (0, _reduce["default"])(F).call(F, function (template, _ref5) { var path = _ref5.path, tag = _ref5.tag, source = _ref5.source, templatePath = _ref5.templatePath, tagPath = _ref5.tagPath; var value = tags[tagPath]; var rendered = jp.value(template, path).replace(source, value); jp.value(template, path, rendered); return template; }, function () { return template; }, (0, _filter["default"])(_context3 = sources['@@next']).call(_context3, function (job) { return job['type'] === '@@tag'; })); }; }; var applyPolicies = function applyPolicies(template) { var _ref6 = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}, _ref6$meta = _ref6.meta, meta = _ref6$meta === void 0 ? 0 : _ref6$meta, _ref6$sources = _ref6.sources, sources = _ref6$sources === void 0 ? { "default": {} } : _ref6$sources, _ref6$tags = _ref6.tags, tags = _ref6$tags === void 0 ? {} : _ref6$tags, _ref6$functions = _ref6.functions, functions = _ref6$functions === void 0 ? {} : _ref6$functions, _ref6$args = _ref6.args, args = _ref6$args === void 0 ? {} : _ref6$args, _ref6$config = _ref6.config, config = _ref6$config === void 0 ? defaultConfig : _ref6$config; var _ref7 = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}, _ref7$builtins = _ref7.builtins, builtins = _ref7$builtins === void 0 ? bins : _ref7$builtins; return function (document) { var _context4; return (0, _reduce["default"])(F).call(F, function (acc, _ref8) { var path = _ref8.path, tag = _ref8.tag, source = _ref8.source, templatePath = _ref8.templatePath, tagPath = _ref8.tagPath; var policy = jp.value(sources, jpify(tag)); var _runPolicy = runPolicy(policy, acc, document)({ path: path, tag: tag, source: source, templatePath: templatePath, tagPath: tagPath }), rendered = _runPolicy.template, tPath = _runPolicy.templatePath; return rendered; }, function () { return template; }, (0, _filter["default"])(_context4 = sources['@@next']).call(_context4, function (job) { return job['type'] === '@@policy'; })); }; }; module.exports = { transform: transform, reRenderTags: reRenderTags, applyPolicies: applyPolicies, data: _objectSpread(_objectSpread({}, renderData), {}, { defaultConfig: defaultConfig }) };