Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

factorial-form

Package Overview
Dependencies
Maintainers
3
Versions
28
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

factorial-form - npm Package Compare versions

Comparing version 1.0.1 to 1.0.2

__tests__/Field.spec.ts

14

.eslintrc.js
module.exports = {
parser: 'babel-eslint',
plugins: [ 'flowtype' ],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],

@@ -16,8 +16,10 @@ env: {

sourceType: 'module',
ecmaFeatures: {
experimentalObjectRestSpread: true
}
},
extends: [
'plugin:flowtype/recommended',
'standard'
]
rules: {
'object-curly-spacing': ['warn', 'always']
}
};
# Changelog
## `1.0.0`
- Upgrade mobx dependency
- Removed decorators
- Switched to typescript
## `0.2.0`

@@ -4,0 +10,0 @@

'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.numberParser = exports.Field = exports.Form = undefined;
Object.defineProperty(exports, '__esModule', { value: true });
var _Form = require('./Form');
var mobx = require('mobx');
var omitBy = require('lodash/omitBy');
var mapValues = require('lodash/mapValues');
var get = require('lodash/get');
var isNull = require('lodash/isNull');
var isObject = require('lodash/isObject');
var forEach = require('lodash/forEach');
var some = require('lodash/some');
var isFinite = require('lodash/isFinite');
var moment = require('moment');
var last = require('lodash/last');
var flat = require('flat');
var _Form2 = _interopRequireDefault(_Form);
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
var _Field = require('./Field');
var omitBy__default = /*#__PURE__*/_interopDefaultLegacy(omitBy);
var mapValues__default = /*#__PURE__*/_interopDefaultLegacy(mapValues);
var get__default = /*#__PURE__*/_interopDefaultLegacy(get);
var isNull__default = /*#__PURE__*/_interopDefaultLegacy(isNull);
var isObject__default = /*#__PURE__*/_interopDefaultLegacy(isObject);
var forEach__default = /*#__PURE__*/_interopDefaultLegacy(forEach);
var some__default = /*#__PURE__*/_interopDefaultLegacy(some);
var isFinite__default = /*#__PURE__*/_interopDefaultLegacy(isFinite);
var moment__default = /*#__PURE__*/_interopDefaultLegacy(moment);
var last__default = /*#__PURE__*/_interopDefaultLegacy(last);
var flat__default = /*#__PURE__*/_interopDefaultLegacy(flat);
var _Field2 = _interopRequireDefault(_Field);
/*! *****************************************************************************
Copyright (c) Microsoft Corporation.
var _numberParser = require('./numberParser');
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted.
var _numberParser2 = _interopRequireDefault(_numberParser);
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
***************************************************************************** */
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function __awaiter(thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
}
exports.Form = _Form2.default;
exports.Field = _Field2.default;
exports.numberParser = _numberParser2.default;
function __generator(thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
}
/**
* Support any input that may contains decimals
* and other stuff. Check the test cases to understand
* which cases we handle.
*
* Improve this if you find how.
*/
function numberParser(str) {
var cleanString = str.replace(/[^\d,.-]/g, '');
var sign = cleanString.charAt(0) === '-' ? '-' : '+';
var parts = cleanString.split(/[.,]/);
var decimals = parts.length > 1 && last__default['default'](parts).length < 3
? parts.pop()
: null;
var number = parts.join('').replace(/[.,]\d*$/, '').replace(/\D/g, '');
return Number(sign + number + (decimals ? '.' + decimals : ''));
}
var DATE_FORMAT = 'L';
var Field = /** @class */ (function () {
function Field(value, type) {
this.type = type;
this.mapAndSet(value);
this.originalValue = this.value;
this.errors = null;
mobx.makeObservable(this, {
value: mobx.observable,
errors: mobx.observable,
originalValue: mobx.observable,
isDirty: mobx.computed,
mapAndSet: mobx.action,
set: mobx.action,
clean: mobx.action,
setErrors: mobx.action
});
}
/**
* Converts the incoming value
* before being persisted in the field
*/
Field.prototype._mapIn = function (value) {
if (value == null)
return '';
switch (this.type) {
case 'timestamp':
if (typeof value !== 'number')
throw new Error('Fields expects a number');
return moment__default['default'].unix(value).format(DATE_FORMAT);
case 'date':
if (typeof value !== 'string')
throw new Error('Fields expects an string');
return moment__default['default'](value, 'YYYY-MM-DD', true).format(DATE_FORMAT);
case 'number':
if (typeof value !== 'number')
throw new Error('Fields expects a number');
return value.toString();
case 'cents':
if (typeof value !== 'number')
throw new Error('Fields expects a number');
return (value / 100).toString();
case 'boolean':
case 'string':
case 'file':
case 'any':
return value;
default:
throw new Error("unknown field type: " + this.type);
}
};
/**
* Converts back the value from the field
*/
Field.prototype._mapOut = function () {
var value = typeof this.value === 'string'
? this.value.trim()
: this.value;
switch (this.type) {
case 'timestamp':
return moment__default['default'].utc(String(value), DATE_FORMAT).unix() || null;
case 'date':
var date = moment__default['default'](String(value), DATE_FORMAT, true);
return date.isValid() ? date.format('YYYY-MM-DD') : null;
case 'number':
var number = numberParser(typeof value === 'number' ? value.toString() : String(value));
return number != null && isFinite__default['default'](number) ? Math.round(number) : null;
case 'cents':
var cents = numberParser(typeof value === 'number' ? value.toString() : String(value));
return cents != null && isFinite__default['default'](cents) ? Math.round(cents * 100) : null;
case 'boolean':
return value;
case 'string':
case 'file':
case 'any':
return value || null;
default:
throw new Error("unknown field type: " + this.type);
}
};
Object.defineProperty(Field.prototype, "isDirty", {
get: function () {
return this.originalValue !== this.value;
},
enumerable: false,
configurable: true
});
Field.prototype.mapAndSet = function (value) {
this.value = this._mapIn(value);
};
Field.prototype.set = function (value) {
this.value = value;
};
Field.prototype.clean = function () {
this.originalValue = this.value;
};
Field.prototype.setErrors = function (errors) {
this.errors = errors;
};
return Field;
}());
var buildFields = function (values, schema) {
return omitBy__default['default'](mapValues__default['default'](flat__default['default'](schema), function (value, attribute) {
return isObject__default['default'](value)
? null
: new Field(get__default['default'](values, attribute), value);
}), isNull__default['default']);
};
var Form = /** @class */ (function () {
function Form(values, schema) {
this.fields = buildFields(values, schema);
mobx.makeObservable(this, {
cleanAll: mobx.action,
resetErrors: mobx.action,
setErrors: mobx.action,
resetValues: mobx.action,
setValues: mobx.action,
handleErrors: mobx.action,
isComplete: mobx.computed,
values: mobx.computed,
isDirty: mobx.computed
});
}
Form.prototype.data = function () {
return flat__default['default'].unflatten(mapValues__default['default'](this.fields, function (field) { return field._mapOut(); }));
};
Form.prototype.has = function (attribute) {
return Boolean(this.fields[attribute]);
};
Form.prototype.get = function (attribute) {
var field = this.fields[attribute];
if (!field)
throw new Error("Field \"" + attribute + "\" not found");
return field;
};
/**
* Cleans all the forms by reseting their original
* values
*/
Form.prototype.cleanAll = function () {
forEach__default['default'](this.fields, function (field) {
return field.clean();
});
};
/**
* Resets all the error fields
*/
Form.prototype.resetErrors = function () {
forEach__default['default'](this.fields, function (field) {
field.setErrors(null);
});
};
/**
* Sets the errors with a given
* hash of attribute -> error
*/
Form.prototype.setErrors = function (errors) {
var _this = this;
this.resetErrors();
var flatErrors = flat__default['default'](errors, { safe: true });
forEach__default['default'](flatErrors, function (error, attribute) {
if (_this.has(attribute)) {
_this.get(attribute).setErrors(error);
}
});
};
Object.defineProperty(Form.prototype, "isComplete", {
/**
* Checks if all fields have a value.
*/
get: function () {
return !some__default['default'](this.fields, function (field) {
switch (field.type) {
case 'number':
case 'cents':
case 'boolean':
return field.value === '' || isNull__default['default'](field.value);
default:
return !field.value;
}
});
},
enumerable: false,
configurable: true
});
Object.defineProperty(Form.prototype, "values", {
/**
* Return the values from the form as they are
*/
get: function () {
return mapValues__default['default'](this.fields, function (field) { return field.value; });
},
enumerable: false,
configurable: true
});
Object.defineProperty(Form.prototype, "isDirty", {
/**
* Return whether the form is dirty
*/
get: function () {
return some__default['default'](this.fields, function (field) { return field.isDirty; });
},
enumerable: false,
configurable: true
});
/**
* Reset values
*/
Form.prototype.resetValues = function () {
forEach__default['default'](this.fields, function (field) { return field.set(''); });
};
/**
* Sets the fields values with a given
* hash of attribute -> value
*/
Form.prototype.setValues = function (values) {
var _this = this;
forEach__default['default'](values, function (value, attribute) {
if (!_this.has(attribute))
return;
var field = _this.get(attribute);
field.setErrors(null);
field.mapAndSet(value);
});
};
/**
* Creates a new model on the given collection
*/
Form.prototype.create = function (collection, options) {
var _this = this;
if (options === void 0) { options = { optimistic: true }; }
return this.handleErrors(function () { return collection.create(_this.data(), options); });
};
/**
* Saves the model with the given fields
*/
Form.prototype.save = function (model, options) {
var _this = this;
if (options === void 0) { options = { optimistic: true, patch: true }; }
return this.handleErrors(function () { return __awaiter(_this, void 0, void 0, function () { return __generator(this, function (_a) {
return [2 /*return*/, model.save(this.data(), options)];
}); }); });
};
Form.prototype.handleErrors = function (fn) {
return __awaiter(this, void 0, void 0, function () {
var values, _a, error_1, payload_1;
var _this = this;
return __generator(this, function (_b) {
switch (_b.label) {
case 0:
_b.trys.push([0, 2, , 3]);
_a = mobx.toJS;
return [4 /*yield*/, fn()];
case 1:
values = _a.apply(void 0, [_b.sent()]);
return [3 /*break*/, 3];
case 2:
error_1 = _b.sent();
payload_1 = error_1.payload;
mobx.action('handleErrors-error', function () {
_this.setErrors(mobx.toJS(payload_1 || error_1));
_this.cleanAll();
})();
throw error_1;
case 3:
mobx.action('handleErrors-done', function () {
_this.setValues(values);
_this.resetErrors();
_this.cleanAll();
})();
return [2 /*return*/, values];
}
});
});
};
return Form;
}());
exports.Field = Field;
exports.Form = Form;
exports.numberParser = numberParser;
{
"name": "factorial-form",
"version": "1.0.1",
"version": "1.0.2",
"description": "Factorial form library",
"repository": {
"type": "git",
"url": "git@github.com:factorial/factorial-form.git"
"url": "git@github.com:factorialco/factorial-form.git"
},
"license": "MIT",
"jest": {
"collectCoverage": true,
"testRegex": "/__tests__/.*\\.spec\\.js$",
"collectCoverageFrom": [
"src/**/*.js"
]
"roots": [ "." ],
"transform": { ".+\\.tsx?$": "ts-jest" },
"testRegex": "/__tests__/.*\\.spec\\.ts$"
},
"standard": {
"parser": "babel-eslint",
"globals": [
"it",
"describe",
"beforeEach",
"expect",
"Class",
"jest"
]
},
"dependencies": {
"lodash": "^4.17.4",
"moment": "2.21.0",
"flat": "2.0.1"
"flat": "5.0.2",
"lodash": "^4.17.21",
"moment": "2.29.1",
"mobx": "^6.3.2",
"rollup-plugin-dts": "^3.0.2"
},
"peerDependencies": {
"mobx": "^5.9.4"
"mobx": "^6.3.2"
},
"devDependencies": {
"babel-cli": "^6.24.1",
"babel-core": "^6.25.0",
"babel-eslint": "^7.2.3",
"babel-jest": "^20.0.3",
"babel-plugin-transform-async-to-generator": "^6.24.1",
"babel-plugin-transform-decorators-legacy": "^1.3.4",
"babel-plugin-transform-flow-strip-types": "^6.22.0",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-polyfill": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-stage-1": "^6.24.1",
"babel-register": "^6.24.1",
"eslint": "^3.19.0",
"eslint-config-standard": "^10.2.1",
"eslint-plugin-flowtype": "2.34.0",
"eslint-plugin-import": "^2.3.0",
"eslint-plugin-node": "^5.0.0",
"eslint-plugin-promise": "^3.5.0",
"eslint-plugin-standard": "^3.0.1",
"flow-bin": "^0.47.0",
"flow-copy-source": "^1.1.0",
"husky": "^0.13.4",
"jest": "^20.0.4",
"lint-staged": "^3.6.0",
"mobx": "^5.9.4",
"prettier-standard": "^5.0.0",
"rimraf": "^2.6.1"
"@types/jest": "26.0.23",
"@types/lodash": "4.14.170",
"@typescript-eslint/eslint-plugin": "4.26.1",
"@typescript-eslint/parser": "4.26.1",
"eslint": "7.28.0",
"husky": "4.3.0",
"jest": "27.0.4",
"lint-staged": "11.0.0",
"rimraf": "3.0.2",
"rollup": "2.51.2",
"rollup-plugin-node-resolve": "5.2.0",
"rollup-plugin-typescript2": "^0.30.0",
"ts-jest": "27.0.3",
"tslib": "2.3.0",
"typescript": "4.3.2"
},
"main": "lib",
"types": "./lib/index.d.ts",
"scripts": {
"build": "yarn build:clean && rollup --config",
"build:clean": "rimraf lib",
"build:lib": "babel -d lib src --ignore '**/__tests__/**'",
"build:flow": "flow-copy-source -v -i '**/__tests__/**' src lib",
"build": "npm run build:clean && npm run build:lib && npm run build:flow",
"prepublish": "npm run build",
"jest": "BABEL_ENV=test NODE_PATH=src jest --no-cache",
"lint": "eslint src __tests__",
"flow": "flow",
"test": "npm run flow && npm run lint && npm run jest",
"format": "prettier-standard --print-width 60 \"{src,__tests__}/**/*.js\"",
"prepush": "npm test",
"prepublish": "yarn build",
"jest": "NODE_PATH=src jest --no-cache",
"lint": "eslint --ext .ts --cache src/ __tests__/",
"test": "yarn lint && yarn jest",
"prepush": "yarn test",
"watch": "rollup --config -w",
"lint-staged": {
"linters": {
"{src|__tests__}/**/*.js": [
"prettier-standard",
"{src|__tests__}/**/*.ts": [
"git add"

@@ -83,0 +57,0 @@ ]

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc