Some rollup fixes - the handlebars-helper library needs dynamic requires removed from it, likely best to fork it and do this.

This commit is contained in:
Michael Drury 2021-01-30 02:54:52 +00:00
parent 34a6e88fe2
commit ff75f8e8a5
8 changed files with 192 additions and 137 deletions

View File

@ -174,7 +174,8 @@ export const getSchemaForDatasource = datasource => {
* utility function for the readableToRuntimeBinding and runtimeToReadableBinding.
*/
function bindingReplacement(bindableProperties, textWithBindings, convertTo) {
const convertFrom = convertTo === "runtimeBinding" ? "readableBinding" : "runtimeBinding"
const convertFrom =
convertTo === "runtimeBinding" ? "readableBinding" : "runtimeBinding"
if (typeof textWithBindings !== "string") {
return textWithBindings
}
@ -190,10 +191,7 @@ function bindingReplacement(bindableProperties, textWithBindings, convertTo) {
for (let from of convertFromProps) {
if (newBoundValue.includes(from)) {
const binding = bindableProperties.find(el => el[convertFrom] === from)
newBoundValue = newBoundValue.replace(
from,
binding[convertTo],
)
newBoundValue = newBoundValue.replace(from, binding[convertTo])
}
}
result = result.replace(boundValue, newBoundValue)
@ -205,12 +203,20 @@ function bindingReplacement(bindableProperties, textWithBindings, convertTo) {
* Converts a readable data binding into a runtime data binding
*/
export function readableToRuntimeBinding(bindableProperties, textWithBindings) {
return bindingReplacement(bindableProperties, textWithBindings, "runtimeBinding")
return bindingReplacement(
bindableProperties,
textWithBindings,
"runtimeBinding"
)
}
/**
* Converts a runtime data binding into a readable data binding
*/
export function runtimeToReadableBinding(bindableProperties, textWithBindings) {
return bindingReplacement(bindableProperties, textWithBindings, "readableBinding")
return bindingReplacement(
bindableProperties,
textWithBindings,
"readableBinding"
)
}

View File

@ -20,11 +20,12 @@
"lodash": "^4.17.20"
},
"devDependencies": {
"@rollup/plugin-commonjs": "^17.1.0",
"@rollup/plugin-json": "^4.1.0",
"@rollup/plugin-replace": "^2.3.4",
"doctrine": "^3.0.0",
"jest": "^26.6.3",
"rollup": "^2.36.2",
"rollup-plugin-commonjs": "^10.1.0",
"rollup-plugin-node-builtins": "^2.1.2",
"rollup-plugin-node-globals": "^1.4.0",
"rollup-plugin-node-resolve": "^5.2.0",

View File

@ -1,23 +1,36 @@
import commonjs from "rollup-plugin-commonjs"
import commonjs from "@rollup/plugin-commonjs"
import resolve from "rollup-plugin-node-resolve"
import builtins from "rollup-plugin-node-builtins"
import globals from "rollup-plugin-node-globals"
import json from "@rollup/plugin-json"
import replace from "@rollup/plugin-replace"
import { terser } from "rollup-plugin-terser"
const production = !process.env.ROLLUP_WATCH
export default {
input: "src/index.js",
input: "src/esIndex.js",
output: [
{
sourcemap: true,
format: "es",
format: "esm",
file: "./dist/bundle.js",
name: "templates",
exports: "named",
},
],
plugins: [
// this replacement is a crazy hack to fix an issue that
// rollup has with the handlebars-helper package
// if we don't do this then the browser will always error
// with the isNumber function being unavailable
replace({
include: [
"node_modules/handlebars-helpers/lib/**",
"node_modules/handlebar-utils/lib/**",
],
"utils.isNumber(": "!isNaN(",
"isNumber(": "!isNaN(",
}),
resolve({
mainFields: ["module", "main"],
preferBuiltins: true,

View File

@ -0,0 +1,12 @@
import templates from "./index"
/**
* This file is simply an entrypoint for rollup - makes a lot of cjs problems go away
*/
export const isValid = templates.isValid
export const makePropSafe = templates.makePropSafe
export const getManifest = templates.getManifest
export const processStringSync = templates.processStringSync
export const processObjectSync = templates.processObjectSync
export const processString = templates.processString
export const processObject = templates.processObject

View File

@ -20,117 +20,115 @@ function testObject(object) {
}
}
module.exports = {
/**
* Given an input object this will recurse through all props to try and update any handlebars statements within.
* @param {object|array} object The input structure which is to be recursed, it is important to note that
* if the structure contains any cycles then this will fail.
* @param {object} context The context that handlebars should fill data from.
* @returns {Promise<object|array>} The structure input, as fully updated as possible.
*/
processObject: async (object, context) => {
testObject(object)
for (let key of Object.keys(object)) {
if (object[key] != null) {
let val = object[key]
if (typeof val === "string") {
object[key] = await module.exports.processString(object[key], context)
} else if (typeof val === "object") {
object[key] = await module.exports.processObject(object[key], context)
}
}
}
return object
},
/**
* This will process a single handlebars containing string. If the string passed in has no valid handlebars statements
* then nothing will occur.
* @param {string} string The template string which is the filled from the context object.
* @param {object} context An object of information which will be used to enrich the string.
* @returns {Promise<string>} The enriched string, all templates should have been replaced if they can be.
*/
processString: async (string, context) => {
// TODO: carry out any async calls before carrying out async call
return module.exports.processStringSync(string, context)
},
/**
* Given an input object this will recurse through all props to try and update any handlebars statements within. This is
* a pure sync call and therefore does not have the full functionality of the async call.
* @param {object|array} object The input structure which is to be recursed, it is important to note that
* if the structure contains any cycles then this will fail.
* @param {object} context The context that handlebars should fill data from.
* @returns {object|array} The structure input, as fully updated as possible.
*/
processObjectSync: (object, context) => {
testObject(object)
for (let key of Object.keys(object)) {
/**
* Given an input object this will recurse through all props to try and update any handlebars statements within.
* @param {object|array} object The input structure which is to be recursed, it is important to note that
* if the structure contains any cycles then this will fail.
* @param {object} context The context that handlebars should fill data from.
* @returns {Promise<object|array>} The structure input, as fully updated as possible.
*/
module.exports.processObject = async (object, context) => {
testObject(object)
for (let key of Object.keys(object)) {
if (object[key] != null) {
let val = object[key]
if (typeof val === "string") {
object[key] = module.exports.processStringSync(object[key], context)
object[key] = await module.exports.processString(object[key], context)
} else if (typeof val === "object") {
object[key] = module.exports.processObjectSync(object[key], context)
object[key] = await module.exports.processObject(object[key], context)
}
}
return object
},
/**
* This will process a single handlebars containing string. If the string passed in has no valid handlebars statements
* then nothing will occur. This is a pure sync call and therefore does not have the full functionality of the async call.
* @param {string} string The template string which is the filled from the context object.
* @param {object} context An object of information which will be used to enrich the string.
* @returns {string} The enriched string, all templates should have been replaced if they can be.
*/
processStringSync: (string, context) => {
let clonedContext = removeNull(cloneDeep(context))
clonedContext = addConstants(clonedContext)
// remove any null/undefined properties
if (typeof string !== "string") {
throw "Cannot process non-string types."
}
string = processors.preprocess(string)
// this does not throw an error when template can't be fulfilled, have to try correct beforehand
const template = hbsInstance.compile(string)
return processors.postprocess(template(clonedContext))
},
/**
* Simple utility function which makes sure that a templating property has been wrapped in literal specifiers correctly.
* @param {string} property The property which is to be wrapped.
* @returns {string} The wrapped property ready to be added to a templating string.
*/
makePropSafe: property => {
return `[${property}]`.replace("[[", "[").replace("]]", "]")
},
/**
* Checks whether or not a template string contains totally valid syntax (simply tries running it)
* @param string The string to test for valid syntax - this may contain no templates and will be considered valid.
* @returns {boolean} Whether or not the input string is valid.
*/
isValid: string => {
const specialCases = ["isNumber", "expected a number"]
// don't really need a real context to check if its valid
const context = {}
try {
hbsInstance.compile(processors.preprocess(string, false))(context)
return true
} catch (err) {
const msg = err ? err.message : ""
const foundCase = specialCases.find(spCase => msg.includes(spCase))
// special case for maths functions - don't have inputs yet
return !!foundCase
}
},
/**
* We have generated a static manifest file from the helpers that this string templating package makes use of.
* This manifest provides information about each of the helpers and how it can be used.
* @returns The manifest JSON which has been generated from the helpers.
*/
getManifest: () => {
return manifest
},
}
return object
}
/**
* This will process a single handlebars containing string. If the string passed in has no valid handlebars statements
* then nothing will occur.
* @param {string} string The template string which is the filled from the context object.
* @param {object} context An object of information which will be used to enrich the string.
* @returns {Promise<string>} The enriched string, all templates should have been replaced if they can be.
*/
module.exports.processString = async (string, context) => {
// TODO: carry out any async calls before carrying out async call
return module.exports.processStringSync(string, context)
}
/**
* Given an input object this will recurse through all props to try and update any handlebars statements within. This is
* a pure sync call and therefore does not have the full functionality of the async call.
* @param {object|array} object The input structure which is to be recursed, it is important to note that
* if the structure contains any cycles then this will fail.
* @param {object} context The context that handlebars should fill data from.
* @returns {object|array} The structure input, as fully updated as possible.
*/
module.exports.processObjectSync = (object, context) => {
testObject(object)
for (let key of Object.keys(object)) {
let val = object[key]
if (typeof val === "string") {
object[key] = module.exports.processStringSync(object[key], context)
} else if (typeof val === "object") {
object[key] = module.exports.processObjectSync(object[key], context)
}
}
return object
}
/**
* This will process a single handlebars containing string. If the string passed in has no valid handlebars statements
* then nothing will occur. This is a pure sync call and therefore does not have the full functionality of the async call.
* @param {string} string The template string which is the filled from the context object.
* @param {object} context An object of information which will be used to enrich the string.
* @returns {string} The enriched string, all templates should have been replaced if they can be.
*/
module.exports.processStringSync = (string, context) => {
let clonedContext = removeNull(cloneDeep(context))
clonedContext = addConstants(clonedContext)
// remove any null/undefined properties
if (typeof string !== "string") {
throw "Cannot process non-string types."
}
string = processors.preprocess(string)
// this does not throw an error when template can't be fulfilled, have to try correct beforehand
const template = hbsInstance.compile(string)
return processors.postprocess(template(clonedContext))
}
/**
* Simple utility function which makes sure that a templating property has been wrapped in literal specifiers correctly.
* @param {string} property The property which is to be wrapped.
* @returns {string} The wrapped property ready to be added to a templating string.
*/
module.exports.makePropSafe = property => {
return `[${property}]`.replace("[[", "[").replace("]]", "]")
}
/**
* Checks whether or not a template string contains totally valid syntax (simply tries running it)
* @param string The string to test for valid syntax - this may contain no templates and will be considered valid.
* @returns {boolean} Whether or not the input string is valid.
*/
module.exports.isValid = string => {
const specialCases = ["isNumber", "expected a number"]
// don't really need a real context to check if its valid
const context = {}
try {
hbsInstance.compile(processors.preprocess(string, false))(context)
return true
} catch (err) {
const msg = err ? err.message : ""
const foundCase = specialCases.find(spCase => msg.includes(spCase))
// special case for maths functions - don't have inputs yet
return !!foundCase
}
}
/**
* We have generated a static manifest file from the helpers that this string templating package makes use of.
* This manifest provides information about each of the helpers and how it can be used.
* @returns The manifest JSON which has been generated from the helpers.
*/
module.exports.getManifest = () => {
return manifest
}

View File

@ -28,7 +28,7 @@ module.exports.removeNull = obj => {
module.exports.addConstants = obj => {
if (obj.now == null) {
obj.now = new Date().toISOString()
obj.now = new Date()
}
return obj
}

View File

@ -293,7 +293,12 @@ describe("Cover a few complex use cases", () => {
it("should make sure case is valid", () => {
const validity = isValid("{{ avg [c355ec2b422e54f988ae553c8acd811ea].[a] [c355ec2b422e54f988ae553c8acd811ea].[b] }}")
expect(validity).toBe(true)
})
it("should be able to solve an example from docs", async () => {
const output = await processString(`{{first ( split "a-b-c" "-") 2}}`, {})
expect(output).toBe(`a,b`)
})
})

View File

@ -465,6 +465,19 @@
"@types/yargs" "^15.0.0"
chalk "^4.0.0"
"@rollup/plugin-commonjs@^17.1.0":
version "17.1.0"
resolved "https://registry.yarnpkg.com/@rollup/plugin-commonjs/-/plugin-commonjs-17.1.0.tgz#757ec88737dffa8aa913eb392fade2e45aef2a2d"
integrity sha512-PoMdXCw0ZyvjpCMT5aV4nkL0QywxP29sODQsSGeDpr/oI49Qq9tRtAsb/LbYbDzFlOydVEqHmmZWFtXJEAX9ew==
dependencies:
"@rollup/pluginutils" "^3.1.0"
commondir "^1.0.1"
estree-walker "^2.0.1"
glob "^7.1.6"
is-reference "^1.2.1"
magic-string "^0.25.7"
resolve "^1.17.0"
"@rollup/plugin-json@^4.1.0":
version "4.1.0"
resolved "https://registry.yarnpkg.com/@rollup/plugin-json/-/plugin-json-4.1.0.tgz#54e09867ae6963c593844d8bd7a9c718294496f3"
@ -472,7 +485,15 @@
dependencies:
"@rollup/pluginutils" "^3.0.8"
"@rollup/pluginutils@^3.0.8":
"@rollup/plugin-replace@^2.3.4":
version "2.3.4"
resolved "https://registry.yarnpkg.com/@rollup/plugin-replace/-/plugin-replace-2.3.4.tgz#7dd84c17755d62b509577f2db37eb524d7ca88ca"
integrity sha512-waBhMzyAtjCL1GwZes2jaE9MjuQ/DQF2BatH3fRivUF3z0JBFrU0U6iBNC/4WR+2rLKhaAhPWDNPYp4mI6RqdQ==
dependencies:
"@rollup/pluginutils" "^3.1.0"
magic-string "^0.25.7"
"@rollup/pluginutils@^3.0.8", "@rollup/pluginutils@^3.1.0":
version "3.1.0"
resolved "https://registry.yarnpkg.com/@rollup/pluginutils/-/pluginutils-3.1.0.tgz#706b4524ee6dc8b103b3c995533e5ad680c02b9b"
integrity sha512-GksZ6pr6TpIjHm8h9lSQ8pi8BE9VeubNT0OMJ3B5uZJ8pz73NPiqOtCog/x2/QzM1ENChPKxMDhiQuRHsqc+lg==
@ -1394,6 +1415,11 @@ commander@^2.20.0:
resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33"
integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==
commondir@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b"
integrity sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs=
component-emitter@^1.2.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/component-emitter/-/component-emitter-1.3.0.tgz#16e4070fba8ae29b679f2215853ee181ab2eabc0"
@ -1793,6 +1819,11 @@ estree-walker@^1.0.1:
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-1.0.1.tgz#31bc5d612c96b704106b477e6dd5d8aa138cb700"
integrity sha512-1fMXF3YP4pZZVozF8j/ZLfvnR8NSIljt56UhbZ5PeeDmmGHpgpdwQt7ITlGvYaQukCvuBRMLEiKiYC+oeIg4cg==
estree-walker@^2.0.1:
version "2.0.2"
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
esutils@^2.0.2:
version "2.0.3"
resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64"
@ -2086,7 +2117,7 @@ getpass@^0.1.1:
dependencies:
assert-plus "^1.0.0"
glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4:
glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6:
version "7.1.6"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6"
integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==
@ -2565,7 +2596,7 @@ is-potential-custom-element-name@^1.0.0:
resolved "https://registry.yarnpkg.com/is-potential-custom-element-name/-/is-potential-custom-element-name-1.0.0.tgz#0c52e54bcca391bb2c494b21e8626d7336c6e397"
integrity sha1-DFLlS8yjkbssSUsh6GJtczbG45c=
is-reference@^1.1.2:
is-reference@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/is-reference/-/is-reference-1.2.1.tgz#8b2dac0b371f4bc994fdeaba9eb542d03002d0b7"
integrity sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==
@ -3383,7 +3414,7 @@ magic-string@^0.22.5:
dependencies:
vlq "^0.2.2"
magic-string@^0.25.2:
magic-string@^0.25.7:
version "0.25.7"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.25.7.tgz#3f497d6fd34c669c6798dcb821f2ef31f5445051"
integrity sha512-4CrMT5DOHTDk4HYDlzmwu4FVCcIYI8gauveasrdCu2IKIFOJ3f0v/8MDGJCDL9oD2ppz/Av1b0Nj345H9M+XIA==
@ -4086,7 +4117,7 @@ resolve-url@^0.2.1:
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
integrity sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo=
resolve@^1.10.0, resolve@^1.11.0, resolve@^1.11.1, resolve@^1.18.1:
resolve@^1.10.0, resolve@^1.11.1, resolve@^1.17.0, resolve@^1.18.1:
version "1.19.0"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.19.0.tgz#1af5bf630409734a067cae29318aac7fa29a267c"
integrity sha512-rArEXAgsBG4UgRGcynxWIWKFvh/XZCcS8UJdHhwy91zwAvCZIbcs+vAbflgBnNjYMs/i/i+/Ux6IZhML1yPvxg==
@ -4114,17 +4145,6 @@ ripemd160@^2.0.0, ripemd160@^2.0.1:
hash-base "^3.0.0"
inherits "^2.0.1"
rollup-plugin-commonjs@^10.1.0:
version "10.1.0"
resolved "https://registry.yarnpkg.com/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz#417af3b54503878e084d127adf4d1caf8beb86fb"
integrity sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==
dependencies:
estree-walker "^0.6.1"
is-reference "^1.1.2"
magic-string "^0.25.2"
resolve "^1.11.0"
rollup-pluginutils "^2.8.1"
rollup-plugin-node-builtins@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/rollup-plugin-node-builtins/-/rollup-plugin-node-builtins-2.1.2.tgz#24a1fed4a43257b6b64371d8abc6ce1ab14597e9"