Skip to content
This repository was archived by the owner on Jul 13, 2023. It is now read-only.

Commit 3d64afe

Browse files
authored
Merge pull request #18 from dotvirus/dev
Dev
2 parents a42ed76 + bec02db commit 3d64afe

File tree

8 files changed

+163
-612
lines changed

8 files changed

+163
-612
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
node_modules

README.md

Lines changed: 40 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,9 @@
22

33
# ptree
44

5-
Deep object walking, manipulation and validation
5+
Deep object walking & manipulation
66

7-
This package wraps regular Objects and Arrays, providing more functionality for accessing, manipulating and validating deep object/array integrity.
7+
This package wraps regular Objects and Arrays, providing more functionality for accessing & manipulating deep objects.
88

99
# Install
1010

@@ -39,6 +39,7 @@ const root = new ptree([1, 2, 3]);
3939
Get the value at given key.
4040
Key can be a dot-separated string, or an array containing single key segments as strings, numbers or functions.
4141
If a non-existing key is accessed (see example 3), undefined is returned.
42+
If no argument is passed, the root object is returned (same as getRoot()).
4243

4344
```javascript
4445
const root = new ptree({ a: 2, b: 3 });
@@ -172,125 +173,6 @@ console.log(root.map(v => v * v)); // -> { a: 25, b: { c: 49, d: 64, e: 81 } }
172173
console.log(root.map(v => v.toString())); // -> { a: '5', b: { c: '7', d: '8', e: '9' } }
173174
```
174175

175-
# validate
176-
177-
Checks the integrity of the root object.
178-
This is done by defining rules for each key you want to check.
179-
180-
```javascript
181-
const root = new ptree([1, 2, 3]);
182-
183-
// Check if keys are defined
184-
// this returns false, because the array is only length 3.
185-
console.log(
186-
root.validate([
187-
{
188-
key: "0"
189-
},
190-
{
191-
key: "1"
192-
},
193-
{
194-
key: "2"
195-
},
196-
{
197-
key: "3"
198-
}
199-
])
200-
); // -> false
201-
202-
// Like above, but this time index 3 is optional
203-
console.log(
204-
root.validate([
205-
{
206-
key: "0"
207-
},
208-
{
209-
key: "1"
210-
},
211-
{
212-
key: "2"
213-
},
214-
{
215-
key: "3",
216-
optional: true
217-
}
218-
])
219-
); // -> true
220-
221-
// Check for equality at given keys
222-
console.log(
223-
root.validate([
224-
{
225-
key: "0",
226-
rules: [v => v === 1]
227-
},
228-
{
229-
key: "1",
230-
rules: [v => v === 2]
231-
}
232-
])
233-
); // -> true
234-
235-
// Wildcard
236-
console.log(
237-
root.validate([
238-
{
239-
key: "*",
240-
rules: [v => typeof v === "number"]
241-
}
242-
])
243-
); // -> true
244-
245-
// Error message
246-
const root = new ptree({
247-
a: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
248-
});
249-
250-
console.log(
251-
root.validate([
252-
{
253-
key: "a",
254-
rules: [
255-
v => Array.isArray(v),
256-
v => (v.length > 5 ? "Array too long!" : true)
257-
]
258-
}
259-
])
260-
); // -> "Array too long!"
261-
262-
// Using (pre/post) transforms, you can alter the object before or after applying your rules; this alters the original object!
263-
// Trim all strings before checking rules
264-
const tree = new ptree({
265-
a: " string",
266-
b: [" not trimmed "]
267-
});
268-
269-
tree.validate([
270-
{
271-
key: "*",
272-
preTransform: [v => v.trim()],
273-
rules: [v => true]
274-
// postTransform: [
275-
// ]
276-
}
277-
]);
278-
279-
console.log(tree.root); // -> { a: 'string', b: [ 'not trimmed' ] }
280-
281-
// Access the original object in rules (or transforms)
282-
const root = new ptree({ a: 5, b: 5 });
283-
284-
console.log(
285-
root.validate([
286-
{
287-
key: "a",
288-
rules: [(v, obj) => v === obj.b]
289-
}
290-
])
291-
);
292-
```
293-
294176
# copy
295177

296178
Deep-copies the root object/array.
@@ -328,3 +210,40 @@ new ptree({
328210
b: 3
329211
}).includes(5); // -> false
330212
```
213+
214+
# Remove
215+
216+
Removes a property from an object
217+
218+
```javascript
219+
const obj = {
220+
a: {
221+
b: 2,
222+
c: {
223+
d: 3,
224+
e: 5,
225+
f: [1, 2, 3]
226+
}
227+
}
228+
};
229+
230+
console.log(obj.a.b); // -> 2
231+
new ptree(obj).remove("a.b");
232+
console.log(obj.a.b); // -> undefined
233+
```
234+
235+
# Pick
236+
237+
Returns a new object only with the given keys
238+
239+
# every/all
240+
241+
Same as Array.prototype.every, but deep.
242+
243+
# some/any
244+
245+
Same as Array.prototype.some, but deep.
246+
247+
# Merge
248+
249+
Same as Object.assign(), but deep. Second argument controls if existing keys should be overwritten (default: true, like Object.assign()).

dist/index.d.ts

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,4 @@
11
export declare type Key = string | number | (() => string | number);
2-
export declare type DefaultFunction = (root: object) => any;
3-
export declare type TransformFunction = (val: any, root: object) => any;
4-
export declare type Rule = (val: any, root: object) => boolean | string;
5-
export declare type ValidationProp = {
6-
key: Key;
7-
optional?: boolean;
8-
default?: any | DefaultFunction;
9-
rules?: Rule | Rule[];
10-
preTransform?: TransformFunction | TransformFunction[];
11-
postTransform?: TransformFunction | TransformFunction[];
12-
};
132
interface KeyValueMap {
143
[key: string]: any;
154
}
@@ -19,6 +8,8 @@ export default class PTree {
198
constructor(root: object);
209
static from(root: object): PTree;
2110
get(key?: Key): any;
11+
wildcard(pattern: string): string[];
12+
innerNodes(prev?: string): string[];
2213
keys(prev?: string): string[];
2314
remove(key: Key): any;
2415
set(key: Key, value: any): void;
@@ -30,7 +21,6 @@ export default class PTree {
3021
equal(other: object): boolean;
3122
findKey(finder: (val: any, key: string, root: object) => boolean): string | undefined;
3223
map(mapper: (val: any, key: string, root: object) => any): any;
33-
validate(props: ValidationProp[]): boolean | string;
3424
copy(): any;
3525
each(func: (val: any, key: string, root: object) => void): void;
3626
forEach(func: (val: any, key: string, root: object) => void): void;

dist/index.js

Lines changed: 33 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
"use strict";
22
Object.defineProperty(exports, "__esModule", { value: true });
3+
const pm = require("picomatch");
34
function getSegments(path) {
45
let segments = [];
56
if (typeof path === "string") {
@@ -56,6 +57,38 @@ class PTree {
5657
}
5758
return obj;
5859
}
60+
wildcard(pattern) {
61+
const isMatch = pm(pattern.replace(/[.]/g, "/"));
62+
return this.keys().filter(key => isMatch(key.replace(/[.]/g, "/")));
63+
}
64+
innerNodes(prev) {
65+
let keys = [];
66+
if (!Array.isArray(this.root)) {
67+
let props = Object.keys(this.root);
68+
props.forEach(key => {
69+
const v = this.root[key];
70+
if (typeof v === "object" && v !== null) {
71+
keys.push(key);
72+
keys.push(...new PTree(v).innerNodes(key));
73+
}
74+
});
75+
}
76+
else if (Array.isArray(this.root)) {
77+
this.root.forEach((v, i) => {
78+
if (typeof v === "object" && v !== null) {
79+
keys.push(i.toString());
80+
keys.push(...new PTree(v).innerNodes(i.toString()));
81+
}
82+
});
83+
}
84+
else {
85+
throw `Tried to get keys of atomic value`;
86+
}
87+
if (prev !== undefined) {
88+
keys = keys.map(k => `${prev}.${k}`);
89+
}
90+
return keys;
91+
}
5992
keys(prev) {
6093
let keys = [];
6194
if (!Array.isArray(this.root)) {
@@ -196,71 +229,6 @@ class PTree {
196229
});
197230
return mapped;
198231
}
199-
validate(props) {
200-
for (const prop of props) {
201-
if (!prop.key) {
202-
throw "PTree: Invalid key in validation function";
203-
}
204-
if (prop.key === "*") {
205-
props.push(...this.keys().map(key => {
206-
return {
207-
key,
208-
optional: prop.optional,
209-
rules: prop.rules,
210-
preTransform: prop.preTransform,
211-
postTransform: prop.postTransform
212-
};
213-
}));
214-
continue;
215-
}
216-
let value = this.get(prop.key);
217-
if (value === undefined && !prop.optional) {
218-
return false;
219-
}
220-
if (value === undefined && prop.optional) {
221-
if (prop.default !== undefined) {
222-
if (typeof prop.default == "function")
223-
this.set(prop.key, prop.default(this.root));
224-
else
225-
this.set(prop.key, prop.default);
226-
}
227-
continue;
228-
}
229-
if (prop.preTransform) {
230-
if (Array.isArray(prop.preTransform))
231-
for (const transformer of prop.preTransform) {
232-
this.set(prop.key, transformer(value, this.root));
233-
}
234-
else
235-
this.set(prop.key, prop.preTransform(value, this.root));
236-
value = this.get(prop.key);
237-
}
238-
if (prop.rules) {
239-
if (Array.isArray(prop.rules)) {
240-
for (const rule of prop.rules) {
241-
const result = rule(value, this.root);
242-
if (result === true)
243-
continue;
244-
return result;
245-
}
246-
}
247-
else {
248-
const result = prop.rules(value, this.root);
249-
if (!result)
250-
return result;
251-
}
252-
}
253-
if (prop.postTransform) {
254-
if (Array.isArray(prop.postTransform))
255-
for (const transformer of prop.postTransform) {
256-
this.set(prop.key, transformer(value, this.root));
257-
}
258-
else
259-
this.set(prop.key, prop.postTransform(value, this.root));
260-
}
261-
}
262-
return true;
263-
}
264232
copy() {
265233
return JSON.parse(JSON.stringify(this.root));
266234
}

package-lock.json

Lines changed: 19 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
{
22
"name": "@dotvirus/ptree",
3-
"version": "1.5.2",
4-
"description": "Deep object walking, manipulation and validation",
3+
"version": "2.1.0",
4+
"description": "Deep object walking & manipulation",
55
"main": "dist/index.js",
66
"scripts": {
7+
"deploy": "tsc && npm run test && npm publish --access public",
78
"watch": "tsc --watch",
8-
"build": "tsc",
99
"test": "node test/"
1010
},
1111
"types": "dist/index.d.ts",
@@ -15,13 +15,21 @@
1515
"type": "git",
1616
"url": "https://github.com/dotvirus/ptree.ts.git"
1717
},
18+
"files": [
19+
"dist/"
20+
],
1821
"keywords": [
1922
"typescript",
20-
"object-validator",
2123
"object-manipulation",
2224
"tree-structure",
2325
"deep",
2426
"ptree",
2527
"leaf"
26-
]
28+
],
29+
"dependencies": {
30+
"picomatch": "^2.1.1"
31+
},
32+
"devDependencies": {
33+
"@types/node": "^12.12.18"
34+
}
2735
}

0 commit comments

Comments
 (0)