
Security News
Socket Releases Free Certified Patches for Critical vm2 Sandbox Escape
A critical vm2 sandbox escape can allow untrusted JavaScript to break isolation and execute commands on the host Node.js process.
Copies properties from one object into another using a super-simple template.
Copies properties from one object into another using a super-simple template.
$ npm install simonize
Run npm install to install mocha (a dev dependency) and then run the tests.
$ npm install
$ npm test
The template defines both the shape of the output, the property datatypes, and default values.
const simonize = require('simonize');
const template = {
id: 'new',
name: '',
email: '',
admin: false
};
simonize(template);
Result:
{ id: 'new', name: '', email: '', admin: false }
The template provides the default values in the absence of an input object. The second parameter to simonize is an input object. In the following example, the input has some of the template fields and the values are numbers instead of a string for the id and a boolean for the admin flag. Calling simonize with this input converts the values into the correct datatypes and merges them with the default values.
const input = { id: 12345, admin: 1 };
simonize(template, input);
Result:
{ id: '12345', name: '', email: '', admin: true }
The template is a very simple schema providing both the datatype and the default value for each property. Templates can be arbitrarily complex including nested objects and array specifications. Nested objects are handled as expected. Arrays are slightly more involved and are discussed next.
Arrays are specified in the template using a one- or two-element array where the zero-index element is the template for the expected contents of each element in the input array. A second element can be optionally specified indicating a default array in case no array is present in the input. This is made clearer with the following examples:
In this example, only one of the elements in the template is overridden by the input.
const template = [{ name: 'default name', value: 'default value' }];
simonize(template, [{ name: 'my name' }]);
Result:
[{ name: 'my name', value: 'default value' }];
If, however, the input is undefined, then we get an empty array.
const template = [{ name: 'default name', value: 'default value' }];
simonize(template);
Result:
[];
The optional second array element specifies a default array. In the following example, the default array contains one undefined element so the template is copied to the output one time.
const template = [
{ name: 'default name', value: 'default value' },
[undefined]
];
simonize(template);
Result:
[{ name: 'default name', value: 'default value' }];
These concepts also apply to primitive values:
const template = [10, [undefined, 5]];
simonize(template, [1, null, 'x', 1 / 0, '4', undefined]);
simonize(template);
Results:
[1, 0, 10, 10, 4, 10][(10, 5)];
This example highlights number conversions, discussed below, as well as the use of the default array. Note that the second (template[1]) default array can have undefined values, which results in the template array default value (template[0]) to be used or it can specify actual values.
A null template value will force the output value to null and the input is ignored.
const template = { security: { token: null } };
simonize(template, { security: { token: 12345 } });
Result:
{
security: {
token: null;
}
}
An undefined template value will return the input as-is. Note that this bypasses the inherent cloning behavior of simonize. Use this feature with care or don't use it at all.
const template = { data: { any: undefined } };
simonize(template, { data: { any: 1 / 0 } });
Result:
{
data: {
any: Infinity;
}
}
A null input value forces a built-in default value to be returned and the default value from the template is ignored.
simonize(5, null); // returns 0
simonize('hello', null); // returns ''
simonize(true, null); // returns false
simonize({ a: 1, b: 2 }, null); // returns {}
simonize(['test'], null); // returns []
For template objects and arrays, input values that are not objects or arrays are also considered to be null.
simonize({ a: 1, b: 2 }, 'not an object'); // returns {}
simonize(['test'], 'not an array'); // returns []
An undefined input value results in the template default value being applied and returned. All of the following result in the same output.
const template = { person: { name: 'Bob' } };
simonize(template);
simonize(template, {});
simonize(template, { person: undefined });
Results:
{
person: {
name: 'Bob';
}
}
{
person: {
name: 'Bob';
}
}
{
person: {
name: 'Bob';
}
}
Object, array, string, number, and boolean values are converted according to the following rules:
undefined, replace the input with an empty object ({}).null or the input is not an object, return an empty object ({}).undefined, replace the input with either the value of the second template array element or an empty array if the second template element is not an arraynull or the input is not an array, return an empty array ([]).undefined, return the default value from the template.null, return the empty string ('').String(input).trim() and return the result.Number(input).isFinite(num).undefined, return the default value from the template.!! operator pair to the input.Any input properties that do not have a corresponding template property are not returned by simonize.
Since the template and input are recursively traversed until primitive properties are discovered, this utility performs a deep clone of both the template and the input.
I developed this while working on a React project using the Formik form utilities and the yup validation library. While great for validation, I was also using yup to cast back and forth between data and values from the form. There were many unpredictable aspects to using a fantastic validation libary to also do object casting. It was great at the former but less so at the latter. Therefore, I developed this little utility to help me out.
To be sure, there are many object mapping utilities available but most focus on mapping between different property names between the source and the target. I was looking for more of a filter-and-conversion utiltity that also respects the target datatypes. JSON schema (and associated libraries) could work but it seemed a bit too heavy-weight for my purposes.
The idea of using the template to specify the default values and then deriving the desired target property type from the default value type makes for a very compact mini-schema. I called it a template so that I wouldn't get confused between the yup terminology of schema, which I am still using.
Originally, I wanted to call it "copyprops" but that name was too similar to an existing package. The name "simonize" reminded me of the automotive cleaning process and, since objects are effectively cleaned and polished, the name seemed appropriate!
MIT License
Copyright (c) 2022 Frank Hellwig
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
FAQs
Copies properties from one object into another using a super-simple template.
The npm package simonize receives a total of 10 weekly downloads. As such, simonize popularity was classified as not popular.
We found that simonize demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Security News
A critical vm2 sandbox escape can allow untrusted JavaScript to break isolation and execute commands on the host Node.js process.

Research
Five malicious NuGet packages impersonate Chinese .NET libraries to deploy a stealer targeting browser credentials, crypto wallets, SSH keys, and local files.

Security News
pnpm 11 turns on a 1-day Minimum Release Age and blocks exotic subdeps by default, adding safeguards against fast-moving supply chain attacks.