Socket
Socket
Sign inDemoInstall

scrubbr

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

scrubbr - npm Package Compare versions

Comparing version 0.1.1 to 1.0.0

2

dist/Scrubbr.d.ts

@@ -94,3 +94,3 @@ import { JSONSchema7 } from 'json-schema';

*/
serialize<Type = any>(schemaType: string, data: unknown, context?: ContextObject, options?: ScrubbrOptions): Promise<Type>;
serialize<Type = any>(schemaType: string, data: unknown, context?: ContextObject, options?: ScrubbrOptions): Type;
/**

@@ -97,0 +97,0 @@ * Traverse into a node of data on an object to serialize.

@@ -32,38 +32,2 @@ "use strict";

};
var __awaiter = (this && this.__awaiter) || function (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());
});
};
var __generator = (this && this.__generator) || function (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 };
}
};
Object.defineProperty(exports, "__esModule", { value: true });

@@ -244,29 +208,19 @@ var fs = __importStar(require("fs"));

if (options === void 0) { options = {}; }
return __awaiter(this, void 0, void 0, function () {
var schema, state, clonedData, serialized;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
schema = this.getSchemaFor(schemaType);
if (!schema) {
throw this.error("Could not find the type: " + schemaType);
}
this.logger.info("Serializing data with TS type: '" + schemaType + "'");
// Merge contexts
context = __assign(__assign({}, this.globalContext), context);
this.logger.debug("Using context: '" + JSON.stringify(context, null, ' ') + "'");
// Create state
options = __assign(__assign({}, this.options), options);
state = new ScrubbrState_1.ScrubbrState(data, schema, options, context);
// Serialize
state.rootSchemaType = schemaType;
state.schemaType = schemaType;
clonedData = JSON.parse(JSON.stringify(data));
return [4 /*yield*/, this.walkData(clonedData, state)];
case 1:
serialized = (_a.sent());
return [2 /*return*/, serialized];
}
});
});
var schema = this.getSchemaFor(schemaType);
if (!schema) {
throw this.error("Could not find the type: " + schemaType);
}
this.logger.info("Serializing data with TS type: '" + schemaType + "'");
// Merge contexts
context = __assign(__assign({}, this.globalContext), context);
this.logger.debug("Using context: '" + JSON.stringify(context, null, ' ') + "'");
// Create state
options = __assign(__assign({}, this.options), options);
var state = new ScrubbrState_1.ScrubbrState(data, schema, options, context);
// Serialize
state.rootSchemaType = schemaType;
state.schemaType = schemaType;
var clonedData = JSON.parse(JSON.stringify(data));
var serialized = this.walkData(clonedData, state);
return serialized;
};

@@ -279,23 +233,13 @@ /**

Scrubbr.prototype.walkData = function (node, state) {
return __awaiter(this, void 0, void 0, function () {
var serializedNode;
return __generator(this, function (_a) {
switch (_a.label) {
case 0: return [4 /*yield*/, this.serializeNode(node, state)];
case 1:
serializedNode = _a.sent();
if (!(serializedNode === null)) return [3 /*break*/, 2];
return [2 /*return*/, serializedNode];
case 2:
if (!Array.isArray(serializedNode)) return [3 /*break*/, 4];
return [4 /*yield*/, this.walkArrayNode(serializedNode, state)];
case 3: return [2 /*return*/, _a.sent()];
case 4:
if (!(typeof serializedNode === 'object')) return [3 /*break*/, 6];
return [4 /*yield*/, this.walkObjectNode(serializedNode, state)];
case 5: return [2 /*return*/, _a.sent()];
case 6: return [2 /*return*/, serializedNode];
}
});
});
var serializedNode = this.serializeNode(node, state);
if (serializedNode === null) {
return serializedNode;
}
else if (Array.isArray(serializedNode)) {
return this.walkArrayNode(serializedNode, state);
}
else if (typeof serializedNode === 'object') {
return this.walkObjectNode(serializedNode, state);
}
return serializedNode;
};

@@ -308,38 +252,20 @@ /**

Scrubbr.prototype.walkObjectNode = function (node, state) {
return __awaiter(this, void 0, void 0, function () {
var nodeProps, schemaProps, filteredNode, pathPrefix, i, _a, name_1, value, propSchema, propPath, propState, _b, _c;
return __generator(this, function (_d) {
switch (_d.label) {
case 0:
nodeProps = Object.entries(node);
schemaProps = state.schemaDef.properties || {};
filteredNode = {};
pathPrefix = state.path ? state.path + "." : '';
i = 0;
_d.label = 1;
case 1:
if (!(i < nodeProps.length)) return [3 /*break*/, 4];
_a = nodeProps[i], name_1 = _a[0], value = _a[1];
propSchema = schemaProps[name_1];
propPath = "" + pathPrefix + name_1;
state.logger.debug("[PATH] " + propPath);
propState = state.createNodeState(value, name_1, propPath, propSchema);
// Property not defined in the schema, do not serialize property
if (!propSchema) {
state.logger.debug("Property '" + name_1 + "' not defined in " + state.schemaType + ".");
return [3 /*break*/, 3];
}
_b = filteredNode;
_c = name_1;
return [4 /*yield*/, this.walkData(value, propState)];
case 2:
_b[_c] = _d.sent();
_d.label = 3;
case 3:
i++;
return [3 /*break*/, 1];
case 4: return [2 /*return*/, filteredNode];
}
});
});
var nodeProps = Object.entries(node);
var schemaProps = state.schemaDef.properties || {};
var filteredNode = {};
var pathPrefix = state.path ? state.path + "." : '';
for (var i = 0; i < nodeProps.length; i++) {
var _a = nodeProps[i], name_1 = _a[0], value = _a[1];
var propSchema = schemaProps[name_1];
var propPath = "" + pathPrefix + name_1;
state.logger.debug("[PATH] " + propPath);
var propState = state.createNodeState(value, name_1, propPath, propSchema);
// Property not defined in the schema, do not serialize property
if (!propSchema) {
state.logger.debug("Property '" + name_1 + "' not defined in " + state.schemaType + ".");
continue;
}
filteredNode[name_1] = this.walkData(value, propState);
}
return filteredNode;
};

@@ -352,42 +278,24 @@ /**

Scrubbr.prototype.walkArrayNode = function (node, state) {
return __awaiter(this, void 0, void 0, function () {
var schema, listSchema, tupleSchema, isTuple, filteredNode, i, value, itemSchema, itemPath, itemState, _a, _b;
return __generator(this, function (_c) {
switch (_c.label) {
case 0:
schema = state.schemaDef;
listSchema = schema.items;
tupleSchema = [];
isTuple = Array.isArray(schema.items);
if (isTuple) {
tupleSchema = schema.items;
}
filteredNode = [];
i = 0;
_c.label = 1;
case 1:
if (!(i < node.length)) return [3 /*break*/, 4];
value = node[i];
itemSchema = isTuple ? tupleSchema[i] : listSchema;
itemPath = state.path + "[" + i + "]";
state.logger.debug("[PATH] " + itemPath);
itemState = state.createListState(value, i, itemPath, itemSchema);
// Skip items past the tuple length
if (isTuple && i >= tupleSchema.length) {
state.logger.debug("Index " + i + " not defined in tuple");
return [3 /*break*/, 4];
}
_a = filteredNode;
_b = i;
return [4 /*yield*/, this.walkData(value, itemState)];
case 2:
_a[_b] = _c.sent();
_c.label = 3;
case 3:
i++;
return [3 /*break*/, 1];
case 4: return [2 /*return*/, filteredNode];
}
});
});
var schema = state.schemaDef;
var listSchema = schema.items;
var tupleSchema = [];
var isTuple = Array.isArray(schema.items);
if (isTuple) {
tupleSchema = schema.items;
}
var filteredNode = [];
for (var i = 0; i < node.length; i++) {
var value = node[i];
var itemSchema = isTuple ? tupleSchema[i] : listSchema;
var itemPath = state.path + "[" + i + "]";
state.logger.debug("[PATH] " + itemPath);
var itemState = state.createListState(value, i, itemPath, itemSchema);
// Skip items past the tuple length
if (isTuple && i >= tupleSchema.length) {
state.logger.debug("Index " + i + " not defined in tuple");
break;
}
filteredNode[i] = this.walkData(value, itemState);
}
return filteredNode;
};

@@ -400,36 +308,26 @@ /**

Scrubbr.prototype.serializeNode = function (data, state) {
return __awaiter(this, void 0, void 0, function () {
var originalDef, schemaType, circularRef, schemaDef;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
originalDef = state.schemaDef;
schemaType = this.getTypeName(state.schemaDef, state);
if (schemaType) {
circularRef = this.isCircularReference(schemaType, state);
if (circularRef) {
return [2 /*return*/, data];
}
state = this.setStateSchemaDefinition(schemaType, state);
}
return [4 /*yield*/, this.runGenericSerializers(data, state)];
case 1:
// Run serializers
data = _a.sent();
return [4 /*yield*/, this.runTypeSerializers(data, state)];
case 2:
data = _a.sent();
schemaDef = state.schemaDef;
if (schemaDef &&
schemaType &&
originalDef !== schemaDef &&
!schemaDef.properties &&
(schemaDef.allOf || schemaDef.anyOf || schemaDef.oneOf)) {
state.logger.debug("'" + state.schemaType + "' appears to be an union type.");
return [2 /*return*/, this.serializeNode(data, state)];
}
return [2 /*return*/, data];
}
});
});
var originalDef = state.schemaDef;
// Get typescript type for the schema definition
var schemaType = this.getTypeName(state.schemaDef, state);
if (schemaType) {
var circularRef = this.isCircularReference(schemaType, state);
if (circularRef) {
return data;
}
state = this.setStateSchemaDefinition(schemaType, state);
}
// Run serializers
data = this.runGenericSerializers(data, state);
data = this.runTypeSerializers(data, state);
// If the type definition is an alias to a union, walk one level deeper
var schemaDef = state.schemaDef;
if (schemaDef &&
schemaType &&
originalDef !== schemaDef &&
!schemaDef.properties &&
(schemaDef.allOf || schemaDef.anyOf || schemaDef.oneOf)) {
state.logger.debug("'" + state.schemaType + "' appears to be an union type.");
return this.serializeNode(data, state);
}
return data;
};

@@ -532,44 +430,28 @@ /**

Scrubbr.prototype.runGenericSerializers = function (dataNode, state) {
return __awaiter(this, void 0, void 0, function () {
var serialized, i, serializerFn, result;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
if (!this.genericSerializers.length) {
return [2 /*return*/, dataNode];
}
state.logger.debug("Running " + this.genericSerializers.length + " generic serializers");
serialized = dataNode;
i = 0;
_a.label = 1;
case 1:
if (!(i < this.genericSerializers.length)) return [3 /*break*/, 4];
serializerFn = this.genericSerializers[i];
return [4 /*yield*/, serializerFn.call(null, serialized, state)];
case 2:
result = _a.sent();
if (typeof result === 'undefined') {
state.logger.warn("Generic serializer returned 'undefined' at object path: " + state.path);
}
if (result instanceof helpers_1.UseType) {
state.logger.debug("Overriding type: '" + result.typeName + "'");
if (result.typeName === state.schemaType) {
state.logger.warn("Trying to override type with the same type ('" + result.typeName + "') at object path: " + state.path);
}
if (typeof result.data !== 'undefined') {
serialized = result.data;
}
state = this.setStateSchemaDefinition(result.typeName, state);
}
else {
serialized = result;
}
_a.label = 3;
case 3:
i++;
return [3 /*break*/, 1];
case 4: return [2 /*return*/, serialized];
if (!this.genericSerializers.length) {
return dataNode;
}
state.logger.debug("Running " + this.genericSerializers.length + " generic serializers");
var serialized = dataNode;
for (var i = 0; i < this.genericSerializers.length; i++) {
var serializerFn = this.genericSerializers[i];
var result = serializerFn.call(null, serialized, state);
if (typeof result === 'undefined') {
state.logger.warn("Generic serializer returned 'undefined' at object path: " + state.path);
}
if (result instanceof helpers_1.UseType) {
state.logger.debug("Overriding type: '" + result.typeName + "'");
if (result.typeName === state.schemaType) {
state.logger.warn("Trying to override type with the same type ('" + result.typeName + "') at object path: " + state.path);
}
});
});
if (typeof result.data !== 'undefined') {
serialized = result.data;
}
state = this.setStateSchemaDefinition(result.typeName, state);
}
else {
serialized = result;
}
}
return serialized;
};

@@ -580,57 +462,46 @@ /**

Scrubbr.prototype.runTypeSerializers = function (dataNode, state) {
return __awaiter(this, void 0, void 0, function () {
var typeName, serializerFns, serialized, i, result, circularRef;
return __generator(this, function (_a) {
switch (_a.label) {
case 0:
typeName = state.schemaType;
if (!typeName) {
return [2 /*return*/, dataNode];
}
if (!this.getSchemaFor(typeName)) {
this.error("No type named '" + typeName + "'.", state);
return [2 /*return*/, dataNode];
}
serializerFns = this.typeSerializers.get(typeName) || [];
if (!serializerFns.length) {
return [2 /*return*/, dataNode];
}
state.logger.debug("Running " + serializerFns.length + " serializers for type '" + typeName + "'");
serialized = dataNode;
i = 0;
_a.label = 1;
case 1:
if (!(i < serializerFns.length)) return [3 /*break*/, 8];
return [4 /*yield*/, serializerFns[i].call(null, dataNode, state)];
case 2:
result = _a.sent();
if (typeof result === 'undefined') {
state.logger.warn("Serializer for type '" + typeName + "' returned 'undefined' at object path: " + state.path);
}
if (!(result instanceof helpers_1.UseType)) return [3 /*break*/, 6];
state.logger.debug("Overriding type: '" + typeName + "'");
// Serialized data
if (typeof result.data !== 'undefined') {
serialized = result.data;
}
if (!(result.typeName === state.schemaType)) return [3 /*break*/, 3];
state.logger.warn("Trying to override type with the same type ('" + result.typeName + "') at object path: " + state.path);
return [3 /*break*/, 5];
case 3:
circularRef = this.isCircularReference(result.typeName, state);
if (!!circularRef) return [3 /*break*/, 5];
var typeName = state.schemaType;
if (!typeName) {
return dataNode;
}
if (!this.getSchemaFor(typeName)) {
this.error("No type named '" + typeName + "'.", state);
return dataNode;
}
var serializerFns = this.typeSerializers.get(typeName) || [];
if (!serializerFns.length) {
return dataNode;
}
state.logger.debug("Running " + serializerFns.length + " serializers for type '" + typeName + "'");
var serialized = dataNode;
for (var i = 0; i < serializerFns.length; i++) {
var result = serializerFns[i].call(null, dataNode, state);
if (typeof result === 'undefined') {
state.logger.warn("Serializer for type '" + typeName + "' returned 'undefined' at object path: " + state.path);
}
// Change type
if (result instanceof helpers_1.UseType) {
state.logger.debug("Overriding type: '" + typeName + "'");
// Serialized data
if (typeof result.data !== 'undefined') {
serialized = result.data;
}
// No type change
if (result.typeName === state.schemaType) {
state.logger.warn("Trying to override type with the same type ('" + result.typeName + "') at object path: " + state.path);
}
else {
// Stop serializing this type and switch to the new type, if it's not a circular reference
var circularRef = this.isCircularReference(result.typeName, state);
if (!circularRef) {
state = this.setStateSchemaDefinition(result.typeName, state);
return [4 /*yield*/, this.runTypeSerializers(serialized, state)];
case 4: return [2 /*return*/, _a.sent()];
case 5: return [3 /*break*/, 7];
case 6:
serialized = result;
_a.label = 7;
case 7:
i++;
return [3 /*break*/, 1];
case 8: return [2 /*return*/, serialized];
return this.runTypeSerializers(serialized, state);
}
}
});
});
}
else {
serialized = result;
}
}
return serialized;
};

@@ -637,0 +508,0 @@ /**

@@ -8,3 +8,3 @@ import { JSONSchema7 } from 'json-schema';

*/
export declare type TypeSerializer = (data: unknown, state: ScrubbrState) => unknown | Promise<unknown>;
export declare type TypeSerializer = (data: unknown, state: ScrubbrState) => unknown;
/**

@@ -14,3 +14,3 @@ * Serializer called for each node within the data object that is being serialized.

*/
export declare type GenericSerializer = (data: unknown, state: ScrubbrState) => unknown | Promise<unknown>;
export declare type GenericSerializer = (data: unknown, state: ScrubbrState) => unknown;
/**

@@ -17,0 +17,0 @@ * Options passed to the Scrubbr constructor

@@ -68,3 +68,3 @@ # Scrubbr

// Serialize the data based on the UserList type defined in schema.ts
return await scrubbr.serialize('UserList', data);
return scrubbr.serialize('UserList', data);
}

@@ -71,0 +71,0 @@ ```

@@ -9,3 +9,2 @@ # Custom Serializers

```typescript

@@ -18,3 +17,2 @@ scrubbr.addTypeSerializer('User', (data, state) => {

## Context

@@ -28,6 +26,6 @@

const context = {
userId: 5
}
userId: 5,
};
scrubbr.addTypeSerializer('User', serializeUser);
const serialized = await scrubbr.serialize('MemberList', data, context);
const serialized = scrubbr.serialize('MemberList', data, context);

@@ -49,3 +47,2 @@ // Only return the logged-in user

```typescript
function userLoggedIn(user) {

@@ -59,5 +56,4 @@ scrubbr.setGlobalContext({ loggedInUserId: user.id });

};
const serialized = await scrubbr.serialize('MemberList', data, context);
const serialized = scrubbr.serialize('MemberList', data, context);
}
```

@@ -79,3 +75,3 @@

password: string;
}
};

@@ -85,3 +81,3 @@ type PublicUser = {

name: string;
}
};
```

@@ -93,6 +89,6 @@

const context = {
userId: 5
}
userId: 5,
};
scrubbr.addTypeSerializer('User', serializeUser);
const serialized = await scrubbr.serialize('MemberList', data, context);
const serialized = scrubbr.serialize('MemberList', data, context);

@@ -122,8 +118,8 @@ // Convert User to PublicUser for everyone but the logged-in user

* `state.path` - The object path to where you are (i.e. `blog.posts[1].author.name`)
* `state.name` - The name of the property that is being serialized.
* `state.index` - If the node being serialized is an item in an array, this is the index in that array.
- `state.path` - The object path to where you are (i.e. `blog.posts[1].author.name`)
- `state.name` - The name of the property that is being serialized.
- `state.index` - If the node being serialized is an item in an array, this is the index in that array.
!!! note
In most cases Type Serializers provide a cleaner and more elegant way to serialize your data than Generic Serializers.
In most cases Type Serializers provide a cleaner and more elegant way to serialize your data than Generic Serializers.

@@ -136,3 +132,3 @@ Let's say we want to convert every `startTime` date value to the local timezone.

startTime: Date;
}
};
type Meeting = {

@@ -142,7 +138,7 @@ name: string;

recurring: string;
}
};
type AppointmentList = {
events: Event[];
meeting: Meeting[];
}
};
```

@@ -152,3 +148,3 @@

import moment from 'moment-timezone';
import Scrubbr, {ScrubbrState} from 'scrubbr';
import Scrubbr, { ScrubbrState } from 'scrubbr';

@@ -174,3 +170,3 @@ const scrubbr = new Scrubbr('./schema.ts');

scrubbr.addGenericSerializer(serializeStartTime);
const serialized = await scrubbr.serialize('AppointmentList', data, context);
const serialized = scrubbr.serialize('AppointmentList', data, context);
}

@@ -184,3 +180,3 @@

startTime: '2021-06-26T19:00:00.000Z',
}
},
],

@@ -192,7 +188,6 @@ meeting: [

recurring: 'daily',
}
]
}
},
],
};
}
```

@@ -211,7 +206,7 @@

startTime: StartTime;
}
};
type Meeting = {
name: string;
startTime: StartTime;
}
};
type AppointmentList = {

@@ -221,3 +216,3 @@ events: Event[];

recurring: string;
}
};
```

@@ -227,3 +222,3 @@

import moment from 'moment-timezone';
import Scrubbr, {ScrubbrState} from 'scrubbr';
import Scrubbr, { ScrubbrState } from 'scrubbr';

@@ -245,3 +240,3 @@ const scrubbr = new Scrubbr('./schema.ts');

scrubbr.addTypeSerializer('StartTime', serializeStartTime);
const serialized = await scrubbr.serialize('AppointmentList', data, context);
const serialized = scrubbr.serialize('AppointmentList', data, context);
}

@@ -255,3 +250,3 @@

startTime: '2021-06-26T19:00:00.000Z',
}
},
],

@@ -263,7 +258,6 @@ meeting: [

recurring: 'daily',
}
]
}
},
],
};
}
```

@@ -20,3 +20,3 @@ # Tips & Tricks

!!! warning
You cannot load just any JSON schema into scrubbr, it needs to follow the output conventions of [ts-json-schema-generator](https://www.npmjs.com/package/ts-json-schema-generator):
You cannot load just any JSON schema into scrubbr, it needs to follow the output conventions of [ts-json-schema-generator](https://www.npmjs.com/package/ts-json-schema-generator):

@@ -54,3 +54,2 @@ * All types are defined in the root `definitions` object.

```typescript
// Global config

@@ -67,3 +66,2 @@ const scrubbr = new Scrubbr('./schema.ts');

}
```

@@ -83,3 +81,3 @@

// Serialize
const output = await scrubbr.serialize('UserList', data);
const output = scrubbr.serialize('UserList', data);
const jsonSchema = scrubbr.getSchemaFor('UserList');

@@ -86,0 +84,0 @@

{
"name": "scrubbr",
"version": "0.1.1",
"version": "1.0.0",
"description": "Serialize and sanitize JSON data using TypeScript.",

@@ -5,0 +5,0 @@ "repository": "https://github.com/jgillick/scrubbr",

@@ -210,3 +210,3 @@ import * as fs from 'fs';

*/
async serialize<Type = any>(
serialize<Type = any>(
schemaType: string,

@@ -216,3 +216,3 @@ data: unknown,

options: ScrubbrOptions = {}
): Promise<Type> {
): Type {
const schema = this.getSchemaFor(schemaType);

@@ -249,3 +249,3 @@ if (!schema) {

const clonedData = JSON.parse(JSON.stringify(data));
const serialized = (await this.walkData(clonedData, state)) as Type;
const serialized = this.walkData(clonedData, state) as Type;
return serialized;

@@ -259,4 +259,4 @@ }

*/
private async walkData(node: unknown, state: ScrubbrState): Promise<unknown> {
const serializedNode = await this.serializeNode(node, state);
private walkData(node: unknown, state: ScrubbrState): unknown {
const serializedNode = this.serializeNode(node, state);

@@ -266,5 +266,5 @@ if (serializedNode === null) {

} else if (Array.isArray(serializedNode)) {
return await this.walkArrayNode(serializedNode, state);
return this.walkArrayNode(serializedNode, state);
} else if (typeof serializedNode === 'object') {
return await this.walkObjectNode(serializedNode as ObjectNode, state);
return this.walkObjectNode(serializedNode as ObjectNode, state);
}

@@ -279,6 +279,3 @@ return serializedNode;

*/
private async walkObjectNode(
node: ObjectNode,
state: ScrubbrState
): Promise<unknown> {
private walkObjectNode(node: ObjectNode, state: ScrubbrState): unknown {
const nodeProps = Object.entries(node);

@@ -310,3 +307,3 @@ const schemaProps = state.schemaDef.properties || {};

filteredNode[name] = await this.walkData(value, propState);
filteredNode[name] = this.walkData(value, propState);
}

@@ -321,6 +318,3 @@ return filteredNode;

*/
private async walkArrayNode(
node: unknown[],
state: ScrubbrState
): Promise<unknown> {
private walkArrayNode(node: unknown[], state: ScrubbrState): unknown {
const schema = state.schemaDef;

@@ -355,3 +349,3 @@ const listSchema = schema.items as JSONSchema7 | JSONSchema7[];

filteredNode[i] = await this.walkData(value, itemState);
filteredNode[i] = this.walkData(value, itemState);
}

@@ -367,6 +361,3 @@

*/
private async serializeNode(
data: unknown,
state: ScrubbrState
): Promise<unknown> {
private serializeNode(data: unknown, state: ScrubbrState): unknown {
const originalDef = state.schemaDef;

@@ -385,4 +376,4 @@

// Run serializers
data = await this.runGenericSerializers(data, state);
data = await this.runTypeSerializers(data, state);
data = this.runGenericSerializers(data, state);
data = this.runTypeSerializers(data, state);

@@ -518,6 +509,6 @@ // If the type definition is an alias to a union, walk one level deeper

*/
private async runGenericSerializers(
private runGenericSerializers(
dataNode: unknown,
state: ScrubbrState
): Promise<unknown> {
): unknown {
if (!this.genericSerializers.length) {

@@ -534,3 +525,3 @@ return dataNode;

const serializerFn = this.genericSerializers[i];
const result = await serializerFn.call(null, serialized, state);
const result = serializerFn.call(null, serialized, state);

@@ -566,6 +557,3 @@ if (typeof result === 'undefined') {

*/
private async runTypeSerializers(
dataNode: unknown,
state: ScrubbrState
): Promise<unknown> {
private runTypeSerializers(dataNode: unknown, state: ScrubbrState): unknown {
const typeName = state.schemaType;

@@ -592,3 +580,3 @@ if (!typeName) {

for (let i = 0; i < serializerFns.length; i++) {
const result = await serializerFns[i].call(null, dataNode, state);
const result = serializerFns[i].call(null, dataNode, state);

@@ -620,3 +608,3 @@ if (typeof result === 'undefined') {

state = this.setStateSchemaDefinition(result.typeName, state);
return await this.runTypeSerializers(serialized, state);
return this.runTypeSerializers(serialized, state);
}

@@ -623,0 +611,0 @@ }

@@ -9,6 +9,3 @@ import { JSONSchema7 } from 'json-schema';

*/
export type TypeSerializer = (
data: unknown,
state: ScrubbrState
) => unknown | Promise<unknown>;
export type TypeSerializer = (data: unknown, state: ScrubbrState) => unknown;

@@ -19,6 +16,3 @@ /**

*/
export type GenericSerializer = (
data: unknown,
state: ScrubbrState
) => unknown | Promise<unknown>;
export type GenericSerializer = (data: unknown, state: ScrubbrState) => unknown;

@@ -25,0 +19,0 @@ /**

@@ -27,5 +27,6 @@ import 'jest';

const data = { value: 'test' };
const scrub = scrubbr.serialize('CircularReferenceTest1', data);
return expect(scrub).rejects.toThrowError();
return expect(() =>
scrubbr.serialize('CircularReferenceTest1', data)
).toThrowError();
}, 500);
});

@@ -19,10 +19,10 @@ import 'jest';

test('pass context to serializers', async () => {
test('pass context to serializers', () => {
const testContext = { hello: 'world' };
await scrubbr.serialize('ContextTest', data, testContext);
scrubbr.serialize('ContextTest', data, testContext);
expect(receivedContext.hello).toBe('world');
});
test('no context passes empty object', async () => {
await scrubbr.serialize('ContextTest', data);
test('no context passes empty object', () => {
scrubbr.serialize('ContextTest', data);
expect(typeof receivedContext).toBe('object');

@@ -33,3 +33,3 @@ expect(Object.keys(receivedContext).length).toBe(0);

describe('global context', () => {
test('merge global context with passed context object', async () => {
test('merge global context with passed context object', () => {
const globalContext = { foo: 'bar' };

@@ -39,7 +39,7 @@ const passedContext = { hello: 'world' };

scrubbr.setGlobalContext(globalContext);
await scrubbr.serialize('ContextTest', data, passedContext);
scrubbr.serialize('ContextTest', data, passedContext);
expect(Object.keys(receivedContext)).toEqual(['foo', 'hello']);
});
test('passed context overrides global context', async () => {
test('passed context overrides global context', () => {
const globalContext = { foo: 'bar' };

@@ -49,3 +49,3 @@ const passedContext = { foo: 'boo' };

scrubbr.setGlobalContext(globalContext);
await scrubbr.serialize('ContextTest', data, passedContext);
scrubbr.serialize('ContextTest', data, passedContext);
expect(Object.keys(receivedContext)).toEqual(['foo']);

@@ -55,7 +55,7 @@ expect(receivedContext.foo).toEqual('boo');

test('global context still used if no context is passed', async () => {
test('global context still used if no context is passed', () => {
const globalContext = { foo: 'bar' };
scrubbr.setGlobalContext(globalContext);
await scrubbr.serialize('ContextTest', data);
scrubbr.serialize('ContextTest', data);
expect(receivedContext.foo).toEqual('bar');

@@ -62,0 +62,0 @@ });

@@ -7,3 +7,3 @@ import 'jest';

describe('do not serialize properties not in schema', () => {
test('root object', async () => {
test('root object', () => {
const data = {

@@ -14,3 +14,3 @@ value1: 1,

};
const serialized = await scrubbr.serialize('ExtraPropsTest', data);
const serialized = scrubbr.serialize('ExtraPropsTest', data);
expect(serialized).toEqual(

@@ -22,3 +22,3 @@ expect.objectContaining({ value1: 1, value2: 'foo' })

test('child object', async () => {
test('child object', () => {
const data = {

@@ -31,3 +31,3 @@ child: {

};
const serialized = await scrubbr.serialize('ExtraPropsChildTest', data);
const serialized = scrubbr.serialize('ExtraPropsChildTest', data);
expect(serialized.child).toEqual(

@@ -39,3 +39,3 @@ expect.objectContaining({ value1: 1, value2: 'foo' })

test('as array item', async () => {
test('as array item', () => {
const data = {

@@ -55,3 +55,3 @@ list: [

};
const serialized = await scrubbr.serialize('ExtraPropsArrayTest', data);
const serialized = scrubbr.serialize('ExtraPropsArrayTest', data);
expect(serialized.list[0]).toEqual(

@@ -58,0 +58,0 @@ expect.objectContaining({ value1: 1, value2: 'foo' })

@@ -22,3 +22,3 @@ import 'jest';

test('call serializer for every node of the object', async () => {
test('call serializer for every node of the object', () => {
const paths: string[] = [];

@@ -30,3 +30,3 @@ serializerFn.mockImplementation((data, state) => {

const serialized = await scrubbr.serialize('GenericSerializerTest', data);
const serialized = scrubbr.serialize('GenericSerializerTest', data);

@@ -47,3 +47,3 @@ expect(serializerFn).toBeCalled();

test('pass context to generic serializers', async () => {
test('pass context to generic serializers', () => {
const context = { foo: 'bar' };

@@ -67,6 +67,6 @@

await scrubbr.serialize('GenericSerializerTest', data, context);
scrubbr.serialize('GenericSerializerTest', data, context);
});
test('modify node', async () => {
test('modify node', () => {
serializerFn.mockImplementation((data, state) => {

@@ -79,7 +79,7 @@ if (state.path == 'child.node') {

const serialized = await scrubbr.serialize('GenericSerializerTest', data);
const serialized = scrubbr.serialize('GenericSerializerTest', data);
expect(serialized.child.node).toBe('Changed!');
});
test('remove part of the tree', async () => {
test('remove part of the tree', () => {
const paths: string[] = [];

@@ -94,7 +94,7 @@ serializerFn.mockImplementation((data, state) => {

await scrubbr.serialize('GenericSerializerTest', data);
scrubbr.serialize('GenericSerializerTest', data);
expect(paths).toEqual(['', 'child', 'child.node', 'children']);
});
test('override node type', async () => {
test('override node type', () => {
serializerFn.mockImplementation((data, state) => {

@@ -107,7 +107,7 @@ if (state.path == 'child') {

const serialized = await scrubbr.serialize('GenericSerializerTest', data);
const serialized = scrubbr.serialize('GenericSerializerTest', data);
expect(serialized.child.extra).toBe('bar');
});
test('override type and transform node', async () => {
test('override type and transform node', () => {
serializerFn.mockImplementation((data, state) => {

@@ -124,3 +124,3 @@ if (state.path == 'child') {

const serialized = await scrubbr.serialize('GenericSerializerTest', {
const serialized = scrubbr.serialize('GenericSerializerTest', {
child: {

@@ -127,0 +127,0 @@ node: 'foo',

@@ -9,3 +9,3 @@ import 'jest';

describe('<Record>', () => {
test('return all matching properties', async () => {
test('return all matching properties', () => {
const data = {

@@ -18,3 +18,3 @@ value: {

};
const serialized = await scrubbr.serialize('RecordTest', data);
const serialized = scrubbr.serialize('RecordTest', data);
expect(serialized.value).toBeDefined();

@@ -21,0 +21,0 @@ expect(serialized.value).toEqual(

@@ -7,7 +7,7 @@ import 'jest';

describe('Tuples', () => {
test('convert tuple to array', async () => {
test('convert tuple to array', () => {
const data = {
value: ['string', 123, false],
};
const serialized = await scrubbr.serialize('TupleTest', data);
const serialized = scrubbr.serialize('TupleTest', data);
expect(serialized.value.length).toBe(3);

@@ -17,7 +17,7 @@ expect(serialized.value).toEqual(['string', 123, false]);

test('enforce max length', async () => {
test('enforce max length', () => {
const data = {
value: ['string', 123, false, 'extra item'],
};
const serialized = await scrubbr.serialize('TupleTest', data);
const serialized = scrubbr.serialize('TupleTest', data);
expect(serialized.value.length).toEqual(3);

@@ -27,3 +27,3 @@ expect(serialized.value).toEqual(['string', 123, false]);

test('follow type references', async () => {
test('follow type references', () => {
const data = {

@@ -37,3 +37,3 @@ value: [

};
const serialized = await scrubbr.serialize('TypleTypeReference', data);
const serialized = scrubbr.serialize('TypleTypeReference', data);
expect(serialized.value.length).toEqual(1);

@@ -40,0 +40,0 @@ expect(serialized.value[0].name).toBe('foo');

@@ -11,3 +11,3 @@ import 'jest';

test('call serializer for each matching type', async () => {
test('call serializer for each matching type', () => {
const values: string[] = [];

@@ -25,3 +25,3 @@ const serializerFn = jest.fn((data, _state) => {

};
await scrubbr.serialize('TypeSerializerTest', data);
scrubbr.serialize('TypeSerializerTest', data);

@@ -32,3 +32,3 @@ expect(serializerFn).toHaveBeenCalledTimes(3);

test('override type', async () => {
test('override type', () => {
const typeBSerializerFn = jest.fn((data, _state) => data);

@@ -44,7 +44,7 @@

};
await scrubbr.serialize('TypeSerializerTest', data);
scrubbr.serialize('TypeSerializerTest', data);
expect(typeBSerializerFn).toHaveBeenCalledTimes(4);
});
test('override type and transform node', async () => {
test('override type and transform node', () => {
scrubbr.addTypeSerializer('TargetTypeA', () => {

@@ -60,7 +60,7 @@ const newData = {

};
const serialized = await scrubbr.serialize('TypeSerializerTest', data);
const serialized = scrubbr.serialize('TypeSerializerTest', data);
expect(serialized.node.value).toBe('boo');
});
test('union type', async () => {
test('union type', () => {
const typeASerializerFn = jest.fn((data, _state) => data);

@@ -75,3 +75,3 @@ const typeBSerializerFn = jest.fn((data, _state) => data);

};
await scrubbr.serialize('TypeSerializerUnionTest', data);
scrubbr.serialize('TypeSerializerUnionTest', data);
expect(typeASerializerFn).toHaveBeenCalledTimes(0);

@@ -81,3 +81,3 @@ expect(typeBSerializerFn).toHaveBeenCalledTimes(1);

test('add multiple types to a single serializer', async () => {
test('add multiple types to a single serializer', () => {
let receivedTypes = new Set<string>();

@@ -99,3 +99,3 @@

scrubbr.addTypeSerializer(['TargetTypeA', 'TargetTypeB'], serializerFn);
await scrubbr.serialize('TypeSerializerTest', data, {});
scrubbr.serialize('TypeSerializerTest', data, {});

@@ -102,0 +102,0 @@ expect(serializerFn).toHaveBeenCalledTimes(2);

@@ -23,4 +23,4 @@ import 'jest';

test('automatically choose between two types', async () => {
await scrubbr.serialize('UnionTypeTestSimple', {
test('automatically choose between two types', () => {
scrubbr.serialize('UnionTypeTestSimple', {
value: {

@@ -36,14 +36,14 @@ nodeA: 'foo',

test('choose between primitive types', async () => {
await scrubbr.serialize('UnionTypeTestPrimitive', { value: 'test' });
test('choose between primitive types', () => {
scrubbr.serialize('UnionTypeTestPrimitive', { value: 'test' });
expect(pathTypes.get('value')).toBe(null);
});
test('union between TypeScript type and primitive', async () => {
await scrubbr.serialize('UnionTypeTestMixed', { value: 'test' });
test('union between TypeScript type and primitive', () => {
scrubbr.serialize('UnionTypeTestMixed', { value: 'test' });
expect(pathTypes.get('value')).toBe('UnionTypeTestType1');
});
test('Aliased union type', async () => {
await scrubbr.serialize('UnionTypeTestAlias', {
test('Aliased union type', () => {
scrubbr.serialize('UnionTypeTestAlias', {
value: {

@@ -57,3 +57,3 @@ nodeA: 'foo',

test('Override type', async () => {
test('Override type', () => {
firstSerializerFn.mockImplementation((data, state) => {

@@ -66,3 +66,3 @@ if (state.path == 'value') {

const output = await scrubbr.serialize('UnionTypeTestSimple', {
const output = scrubbr.serialize('UnionTypeTestSimple', {
value: {

@@ -78,3 +78,3 @@ nodeA: 'foo',

// test('change type and override value', async () => {
// test('change type and override value', () => {
// firstSerializerFn.mockImplementation((data, state) => {

@@ -91,3 +91,3 @@ // if (state.path == 'value') {

// const output = await scrubbr.serialize('UnionTypeTestSimple', {
// const output = scrubbr.serialize('UnionTypeTestSimple', {
// value: {

@@ -94,0 +94,0 @@ // nodeA: 'foo',

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