Skip to content

Commit

Permalink
feat: support nested objects in 'fromJSON()'
Browse files Browse the repository at this point in the history
  • Loading branch information
FlorianLoch committed May 13, 2020
1 parent fa106d0 commit f8c329c
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 1 deletion.
29 changes: 29 additions & 0 deletions src/__tests__/volume.test.ts
Expand Up @@ -222,6 +222,35 @@ describe('volume', () => {
expect(vol.toJSON()).toEqual(json);
});

it('Accept a nested dict as input because its nicer to read', () => {
const vol1 = new Volume();
const vol2 = new Volume();

const jsonFlat = {
'/dir/file': '...',
'/dir/dir/dir2/hello.sh': 'world',
'/hello.js': 'console.log(123)',
'/dir/dir/test.txt': 'Windows',
};
const jsonNested = {
'/dir/': {
file: '...',
dir: {
dir2: {
'hello.sh': 'world',
},
'test.txt': 'Windows',
},
},
'/hello.js': 'console.log(123)',
};

vol1.fromJSON(jsonFlat);
vol2.fromJSON(jsonNested);

expect(vol1.toJSON()).toEqual(vol2.toJSON());
});

it('Invalid JSON throws error', () => {
try {
const vol = new Volume();
Expand Down
25 changes: 24 additions & 1 deletion src/volume.ts
Expand Up @@ -509,6 +509,10 @@ function validateGid(gid: number) {
// ---------------------------------------- Volume

export type DirectoryJSON = Record<string, string | null>;
// tslint:disable-next-line:interface-over-type-literal
export type NestedDirectoryJSON = {
[key: string]: string | NestedDirectoryJSON | null;
};

/**
* `Volume` represents a file system.
Expand Down Expand Up @@ -864,7 +868,7 @@ export class Volume {
}

// fromJSON(json: {[filename: string]: string}, cwd: string = '/') {
fromJSON(json: DirectoryJSON, cwd: string = process.cwd()) {
fromJSON(json: NestedDirectoryJSON, cwd: string = process.cwd()) {
for (let filename in json) {
const data = json[filename];

Expand All @@ -878,6 +882,25 @@ export class Volume {
this.writeFileSync(filename, data);
} else {
this.mkdirpBase(filename, MODE.DIR);

if (data !== null && typeof data === 'object') {
const child: NestedDirectoryJSON = {};

for (const childFilename in data) {
let combinedFilename;

// the path interpreted as directory could end with the separator symbol...
if (filename.endsWith(sep)) {
combinedFilename = filename + childFilename;
} else {
combinedFilename = filename + sep + childFilename;
}

child[combinedFilename] = data[childFilename];
}

this.fromJSON(child, '');
}
}
}
}
Expand Down

0 comments on commit f8c329c

Please sign in to comment.