@jupiterone/cli 8.3.1 → 8.4.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__mocks__/ora.ts +1 -1
- package/dist/src/commands/j1Export.js +4 -4
- package/dist/src/commands/j1Export.js.map +1 -1
- package/dist/src/commands/j1Import.js +4 -4
- package/dist/src/commands/j1Import.js.map +1 -1
- package/dist/src/export/bulkDownloadToJson.js +6 -6
- package/dist/src/export/bulkDownloadToJson.js.map +1 -1
- package/dist/src/export/exportAssets.js +3 -3
- package/dist/src/export/exportAssets.js.map +1 -1
- package/dist/src/export/exportAssetsToJson.js +3 -3
- package/dist/src/export/exportAssetsToJson.js.map +1 -1
- package/dist/src/export/exportJsonAssetsToCsv.js +5 -5
- package/dist/src/export/exportJsonAssetsToCsv.js.map +1 -1
- package/dist/src/export/groupJsonAssetsByType.d.ts +1 -1
- package/dist/src/export/groupJsonAssetsByType.js +5 -6
- package/dist/src/export/groupJsonAssetsByType.js.map +1 -1
- package/dist/src/export/util.js.map +1 -1
- package/dist/src/export/writeAssetsToCsv.d.ts +1 -1
- package/dist/src/export/writeAssetsToCsv.js +6 -6
- package/dist/src/export/writeAssetsToCsv.js.map +1 -1
- package/dist/src/fileSystem.d.ts +1 -1
- package/dist/src/fileSystem.js +2 -2
- package/dist/src/fileSystem.js.map +1 -1
- package/dist/src/import/importAssets.js +1 -1
- package/dist/src/import/importAssets.js.map +1 -1
- package/dist/src/import/importAssetsFromCsv.js +9 -9
- package/dist/src/import/importAssetsFromCsv.js.map +1 -1
- package/dist/src/index.js +1 -3
- package/dist/src/index.js.map +1 -1
- package/dist/src/pause.js +3 -1
- package/dist/src/pause.js.map +1 -1
- package/dist/tsconfig.dist.tsbuildinfo +1 -7051
- package/jest.config.js +1 -1
- package/package.json +4 -4
- package/src/__tests__/cli-import.test.ts +6 -9
- package/src/__tests__/utils/fetchAssetsContents.ts +3 -3
- package/src/__tests__/utils/index.ts +1 -1
- package/src/export/__tests__/exportAssetsToJson.test.ts +56 -41
- package/src/export/__tests__/exportJsonAssetsToCsv.test.ts +117 -71
- package/src/export/__tests__/groupJsonAssetsByType.test.ts +6 -4
- package/src/export/__tests__/utils/createEntity.ts +13 -5
- package/src/export/__tests__/utils/createRelationship.ts +1 -1
- package/src/export/__tests__/utils/parseCsvToJson.ts +2 -2
- package/src/export/__tests__/utils/parseToCsv.ts +2 -3
- package/src/export/__tests__/writeAssetsToCsv.test.ts +6 -8
- package/src/export/exportAssets.ts +6 -2
- package/src/export/groupJsonAssetsByType.ts +12 -9
- package/src/export/util.ts +2 -2
- package/src/export/writeAssetsToCsv.ts +21 -12
- package/src/fileSystem.ts +6 -3
- package/src/index.ts +1 -3
- package/src/pause.ts +3 -1
- package/tsconfig.dist.json +1 -3
- package/tsconfig.json +2 -4
package/jest.config.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jupiterone/cli",
|
|
3
|
-
"version": "8.
|
|
3
|
+
"version": "8.4.2",
|
|
4
4
|
"description": "The JupiterOne cli",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
@@ -24,8 +24,8 @@
|
|
|
24
24
|
"test": "jest"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@jupiterone/integration-sdk-core": "^8.
|
|
28
|
-
"@jupiterone/integration-sdk-runtime": "^8.
|
|
27
|
+
"@jupiterone/integration-sdk-core": "^8.4.2",
|
|
28
|
+
"@jupiterone/integration-sdk-runtime": "^8.4.2",
|
|
29
29
|
"@lifeomic/attempt": "^3.0.0",
|
|
30
30
|
"commander": "^5.0.0",
|
|
31
31
|
"globby": "^11.0.1",
|
|
@@ -43,5 +43,5 @@
|
|
|
43
43
|
"csvtojson": "^2.0.10",
|
|
44
44
|
"memfs": "^3.2.0"
|
|
45
45
|
},
|
|
46
|
-
"gitHead": "
|
|
46
|
+
"gitHead": "1504c547765bd8636a8adcaf19098bc1b9f802e1"
|
|
47
47
|
}
|
|
@@ -61,15 +61,12 @@ beforeEach(async () => {
|
|
|
61
61
|
mockedCreateApiClient.mockReturnValue(axios);
|
|
62
62
|
vol.reset();
|
|
63
63
|
vol.fromJSON({
|
|
64
|
-
[`${TEST_STORAGE_LOCATION}/csv/entities/entity_type_1/${uuid()}.csv`]:
|
|
65
|
-
type1Entities,
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
[`${TEST_STORAGE_LOCATION}/csv/relationships/relationship_type_1/${uuid()}.csv`]: await parseToCsv(
|
|
71
|
-
type1Relationships,
|
|
72
|
-
),
|
|
64
|
+
[`${TEST_STORAGE_LOCATION}/csv/entities/entity_type_1/${uuid()}.csv`]:
|
|
65
|
+
await parseToCsv(type1Entities),
|
|
66
|
+
[`${TEST_STORAGE_LOCATION}/csv/entities/entity_type_2/${uuid()}.csv`]:
|
|
67
|
+
await parseToCsv(type2Entities),
|
|
68
|
+
[`${TEST_STORAGE_LOCATION}/csv/relationships/relationship_type_1/${uuid()}.csv`]:
|
|
69
|
+
await parseToCsv(type1Relationships),
|
|
73
70
|
});
|
|
74
71
|
mockedGlobby.mockImplementation((path) => {
|
|
75
72
|
let paths: string[] = [];
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { Volume } from
|
|
1
|
+
import { Volume } from 'memfs/lib/volume';
|
|
2
2
|
|
|
3
3
|
export function fetchAssetsContents(vol: Volume) {
|
|
4
4
|
const files = vol.toJSON();
|
|
5
5
|
return Object.keys(files)
|
|
6
|
-
.filter(filename => filename.endsWith('.csv'))
|
|
7
|
-
.map(filename => files[filename]) as string[];
|
|
6
|
+
.filter((filename) => filename.endsWith('.csv'))
|
|
7
|
+
.map((filename) => files[filename]) as string[];
|
|
8
8
|
}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
export * from './constants';
|
|
2
|
-
export * from './fetchAssetsContents';
|
|
2
|
+
export * from './fetchAssetsContents';
|
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import { mocked } from
|
|
1
|
+
import { mocked } from 'ts-jest/utils';
|
|
2
2
|
import ora from 'ora';
|
|
3
3
|
|
|
4
|
-
import {
|
|
5
|
-
|
|
4
|
+
import {
|
|
5
|
+
exportAssetsToJson,
|
|
6
|
+
ExportAssetsToJsonParams,
|
|
7
|
+
} from '../exportAssetsToJson';
|
|
8
|
+
import { DEFAULT_EXPORT_DIRECTORY } from '../../commands';
|
|
6
9
|
import { bulkDownloadToJson } from '../bulkDownloadToJson';
|
|
7
10
|
import * as log from '../../log';
|
|
8
|
-
import { TEST_API_KEY } from
|
|
11
|
+
import { TEST_API_KEY } from '../../__tests__/utils';
|
|
9
12
|
|
|
10
13
|
jest.mock('../bulkDownloadToJson');
|
|
11
14
|
jest.mock('../../log');
|
|
@@ -19,69 +22,81 @@ const options: ExportAssetsToJsonParams = {
|
|
|
19
22
|
includeDeleted: true,
|
|
20
23
|
includeEntities: true,
|
|
21
24
|
includeRelationships: true,
|
|
22
|
-
apiKey: TEST_API_KEY
|
|
23
|
-
}
|
|
25
|
+
apiKey: TEST_API_KEY,
|
|
26
|
+
};
|
|
24
27
|
|
|
25
28
|
test('should download both entities and relationships when specified to include them', async () => {
|
|
26
29
|
await exportAssetsToJson(options);
|
|
27
30
|
|
|
28
31
|
expect(bulkDownloadToJson).toHaveBeenCalledTimes(2);
|
|
29
|
-
expect(bulkDownloadToJson).toHaveBeenCalledWith(
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
32
|
+
expect(bulkDownloadToJson).toHaveBeenCalledWith(
|
|
33
|
+
expect.objectContaining({
|
|
34
|
+
storageDirectory: options.storageDirectory,
|
|
35
|
+
apiKey: options.apiKey,
|
|
36
|
+
includeDeleted: options.includeDeleted,
|
|
37
|
+
assetType: 'entities',
|
|
38
|
+
progress: expect.anything(),
|
|
39
|
+
}),
|
|
40
|
+
);
|
|
41
|
+
expect(bulkDownloadToJson).toHaveBeenCalledWith(
|
|
42
|
+
expect.objectContaining({
|
|
43
|
+
storageDirectory: options.storageDirectory,
|
|
44
|
+
apiKey: options.apiKey,
|
|
45
|
+
includeDeleted: options.includeDeleted,
|
|
46
|
+
assetType: 'relationships',
|
|
47
|
+
progress: expect.anything(),
|
|
48
|
+
}),
|
|
49
|
+
);
|
|
50
|
+
expect(mockedSpinner.succeed).toHaveBeenCalledWith(
|
|
51
|
+
expect.stringMatching(
|
|
52
|
+
/Export Successful, Downloaded \d+ entities and \d+ relationships!/g,
|
|
53
|
+
),
|
|
54
|
+
);
|
|
46
55
|
});
|
|
47
56
|
|
|
48
57
|
test('should exclude entities when includeEntities is false', async () => {
|
|
49
58
|
await exportAssetsToJson({
|
|
50
59
|
...options,
|
|
51
|
-
includeEntities: false
|
|
60
|
+
includeEntities: false,
|
|
52
61
|
});
|
|
53
62
|
|
|
54
63
|
expect(bulkDownloadToJson).toHaveBeenCalledTimes(1);
|
|
55
|
-
expect(bulkDownloadToJson).toHaveBeenCalledWith(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
64
|
+
expect(bulkDownloadToJson).toHaveBeenCalledWith(
|
|
65
|
+
expect.objectContaining({
|
|
66
|
+
storageDirectory: options.storageDirectory,
|
|
67
|
+
apiKey: options.apiKey,
|
|
68
|
+
includeDeleted: options.includeDeleted,
|
|
69
|
+
assetType: 'relationships',
|
|
70
|
+
progress: expect.anything(),
|
|
71
|
+
}),
|
|
72
|
+
);
|
|
62
73
|
});
|
|
63
74
|
|
|
64
75
|
test('should exclude relationships when includeRelationships is false', async () => {
|
|
65
76
|
await exportAssetsToJson({
|
|
66
77
|
...options,
|
|
67
|
-
includeRelationships: false
|
|
78
|
+
includeRelationships: false,
|
|
68
79
|
});
|
|
69
80
|
|
|
70
81
|
expect(bulkDownloadToJson).toHaveBeenCalledTimes(1);
|
|
71
|
-
expect(bulkDownloadToJson).toHaveBeenCalledWith(
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
82
|
+
expect(bulkDownloadToJson).toHaveBeenCalledWith(
|
|
83
|
+
expect.objectContaining({
|
|
84
|
+
storageDirectory: options.storageDirectory,
|
|
85
|
+
apiKey: options.apiKey,
|
|
86
|
+
includeDeleted: options.includeDeleted,
|
|
87
|
+
assetType: 'entities',
|
|
88
|
+
progress: expect.anything(),
|
|
89
|
+
}),
|
|
90
|
+
);
|
|
78
91
|
});
|
|
79
92
|
|
|
80
93
|
test('should log error when there is an issue bulk downloading', async () => {
|
|
81
94
|
const error = new Error();
|
|
82
95
|
mockedBulkDownload.mockRejectedValue(error);
|
|
83
96
|
|
|
84
|
-
await expect(exportAssetsToJson(options)).rejects.toThrow(error)
|
|
97
|
+
await expect(exportAssetsToJson(options)).rejects.toThrow(error);
|
|
85
98
|
expect(log.error).toHaveBeenCalledWith('Failed to export assets to JSON');
|
|
86
|
-
expect(mockedSpinner.fail).toHaveBeenCalledWith(
|
|
99
|
+
expect(mockedSpinner.fail).toHaveBeenCalledWith(
|
|
100
|
+
'Failed to export assets to JSON',
|
|
101
|
+
);
|
|
87
102
|
});
|
|
@@ -13,30 +13,40 @@ import { TEST_API_KEY } from '../../__tests__/utils';
|
|
|
13
13
|
|
|
14
14
|
jest.mock('fs');
|
|
15
15
|
jest.mock('../../log');
|
|
16
|
-
jest.mock('ora')
|
|
16
|
+
jest.mock('ora');
|
|
17
17
|
|
|
18
18
|
const mockedSpinner = ora().start();
|
|
19
19
|
const TEST_DIRECTORY = DEFAULT_EXPORT_DIRECTORY;
|
|
20
20
|
const TEST_FILES = {
|
|
21
|
-
[`${TEST_DIRECTORY}/json/entities/entity_type_1/${uuid()}.json`]:
|
|
22
|
-
[createEntity({ id: '1', type: '1' })]
|
|
23
|
-
)
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
[`${TEST_DIRECTORY}/json/entities/entity_type_2/${uuid()}.json`]:
|
|
28
|
-
[
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
)
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
21
|
+
[`${TEST_DIRECTORY}/json/entities/entity_type_1/${uuid()}.json`]:
|
|
22
|
+
JSON.stringify([createEntity({ id: '1', type: '1' })]),
|
|
23
|
+
[`${TEST_DIRECTORY}/json/entities/entity_type_1/${uuid()}.json`]:
|
|
24
|
+
JSON.stringify([createEntity({ id: '2', type: '1' })]),
|
|
25
|
+
[`${TEST_DIRECTORY}/json/entities/entity_type_2/${uuid()}.json`]:
|
|
26
|
+
JSON.stringify([createEntity({ id: '3', type: '2' })]),
|
|
27
|
+
[`${TEST_DIRECTORY}/json/entities/entity_type_2/${uuid()}.json`]:
|
|
28
|
+
JSON.stringify([
|
|
29
|
+
createEntity({ id: '4', type: '2' }),
|
|
30
|
+
createEntity({ id: '5', type: '2' }),
|
|
31
|
+
]),
|
|
32
|
+
[`${TEST_DIRECTORY}/json/relationships/relationship_type_1/${uuid()}.json`]:
|
|
33
|
+
JSON.stringify([
|
|
34
|
+
createRelationship({
|
|
35
|
+
from: createEntity({ id: '1', type: '1' }),
|
|
36
|
+
to: createEntity({ id: '3', type: '2' }),
|
|
37
|
+
}),
|
|
38
|
+
createRelationship({
|
|
39
|
+
from: createEntity({ id: '2', type: '1' }),
|
|
40
|
+
to: createEntity({ id: '3', type: '2' }),
|
|
41
|
+
}),
|
|
42
|
+
]),
|
|
43
|
+
[`${TEST_DIRECTORY}/json/relationships/relationship_type_2/${uuid()}.json`]:
|
|
44
|
+
JSON.stringify([
|
|
45
|
+
createRelationship({
|
|
46
|
+
from: createEntity({ id: '4', type: '2' }),
|
|
47
|
+
to: createEntity({ id: '2', type: '1' }),
|
|
48
|
+
}),
|
|
49
|
+
]),
|
|
40
50
|
};
|
|
41
51
|
|
|
42
52
|
beforeEach(() => {
|
|
@@ -48,7 +58,7 @@ test('should not export anything if there are no json assets', async () => {
|
|
|
48
58
|
includeEntities: true,
|
|
49
59
|
includeRelationships: true,
|
|
50
60
|
storageDirectory: TEST_DIRECTORY,
|
|
51
|
-
apiKey: TEST_API_KEY
|
|
61
|
+
apiKey: TEST_API_KEY,
|
|
52
62
|
});
|
|
53
63
|
|
|
54
64
|
expect(vol.toJSON()).toEqual({});
|
|
@@ -61,25 +71,40 @@ test('should export both entities and relationships when specified', async () =>
|
|
|
61
71
|
includeEntities: true,
|
|
62
72
|
includeRelationships: true,
|
|
63
73
|
storageDirectory: TEST_DIRECTORY,
|
|
64
|
-
apiKey: TEST_API_KEY
|
|
74
|
+
apiKey: TEST_API_KEY,
|
|
65
75
|
});
|
|
66
|
-
const assets = await Promise.all(
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
76
|
+
const assets = await Promise.all(
|
|
77
|
+
fetchAssetsContents(vol).map(convertCsvToJson),
|
|
78
|
+
);
|
|
79
|
+
|
|
80
|
+
expect(assets).toEqual(
|
|
81
|
+
expect.arrayContaining([
|
|
82
|
+
[createEntity({ id: '1', type: '1' })],
|
|
83
|
+
[createEntity({ id: '2', type: '1' })],
|
|
84
|
+
[createEntity({ id: '3', type: '2' })],
|
|
85
|
+
[
|
|
86
|
+
createEntity({ id: '4', type: '2' }),
|
|
87
|
+
createEntity({ id: '5', type: '2' }),
|
|
88
|
+
],
|
|
89
|
+
[
|
|
90
|
+
createRelationship({
|
|
91
|
+
from: createEntity({ id: '1', type: '1' }),
|
|
92
|
+
to: createEntity({ id: '3', type: '2' }),
|
|
93
|
+
}),
|
|
94
|
+
createRelationship({
|
|
95
|
+
from: createEntity({ id: '2', type: '1' }),
|
|
96
|
+
to: createEntity({ id: '3', type: '2' }),
|
|
97
|
+
}),
|
|
98
|
+
],
|
|
99
|
+
[
|
|
100
|
+
createRelationship({
|
|
101
|
+
from: createEntity({ id: '4', type: '2' }),
|
|
102
|
+
to: createEntity({ id: '2', type: '1' }),
|
|
103
|
+
}),
|
|
104
|
+
],
|
|
105
|
+
]),
|
|
106
|
+
);
|
|
107
|
+
expect(assets).toHaveLength(6);
|
|
83
108
|
});
|
|
84
109
|
|
|
85
110
|
test('should export only entities when includeRelationships is false', async () => {
|
|
@@ -89,21 +114,25 @@ test('should export only entities when includeRelationships is false', async ()
|
|
|
89
114
|
includeEntities: true,
|
|
90
115
|
includeRelationships: false,
|
|
91
116
|
storageDirectory: TEST_DIRECTORY,
|
|
92
|
-
apiKey: TEST_API_KEY
|
|
117
|
+
apiKey: TEST_API_KEY,
|
|
93
118
|
});
|
|
94
119
|
|
|
95
|
-
const assets = await Promise.all(
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
120
|
+
const assets = await Promise.all(
|
|
121
|
+
fetchAssetsContents(vol).map(convertCsvToJson),
|
|
122
|
+
);
|
|
123
|
+
|
|
124
|
+
expect(assets).toEqual(
|
|
125
|
+
expect.arrayContaining([
|
|
126
|
+
[createEntity({ id: '1', type: '1' })],
|
|
127
|
+
[createEntity({ id: '2', type: '1' })],
|
|
128
|
+
[createEntity({ id: '3', type: '2' })],
|
|
129
|
+
[
|
|
130
|
+
createEntity({ id: '4', type: '2' }),
|
|
131
|
+
createEntity({ id: '5', type: '2' }),
|
|
132
|
+
],
|
|
133
|
+
]),
|
|
134
|
+
);
|
|
135
|
+
expect(assets).toHaveLength(4);
|
|
107
136
|
});
|
|
108
137
|
|
|
109
138
|
test('should export only relationships when includeEntities is false', async () => {
|
|
@@ -113,39 +142,56 @@ test('should export only relationships when includeEntities is false', async ()
|
|
|
113
142
|
includeEntities: false,
|
|
114
143
|
includeRelationships: true,
|
|
115
144
|
storageDirectory: TEST_DIRECTORY,
|
|
116
|
-
apiKey: TEST_API_KEY
|
|
145
|
+
apiKey: TEST_API_KEY,
|
|
117
146
|
});
|
|
118
147
|
|
|
119
|
-
const assets = await Promise.all(
|
|
148
|
+
const assets = await Promise.all(
|
|
149
|
+
fetchAssetsContents(vol).map(convertCsvToJson),
|
|
150
|
+
);
|
|
120
151
|
|
|
121
|
-
expect(assets)
|
|
122
|
-
|
|
152
|
+
expect(assets).toEqual(
|
|
153
|
+
expect.arrayContaining([
|
|
154
|
+
[
|
|
155
|
+
createRelationship({
|
|
156
|
+
from: createEntity({ id: '1', type: '1' }),
|
|
157
|
+
to: createEntity({ id: '3', type: '2' }),
|
|
158
|
+
}),
|
|
159
|
+
createRelationship({
|
|
160
|
+
from: createEntity({ id: '2', type: '1' }),
|
|
161
|
+
to: createEntity({ id: '3', type: '2' }),
|
|
162
|
+
}),
|
|
163
|
+
],
|
|
123
164
|
[
|
|
124
|
-
createRelationship({
|
|
125
|
-
|
|
165
|
+
createRelationship({
|
|
166
|
+
from: createEntity({ id: '4', type: '2' }),
|
|
167
|
+
to: createEntity({ id: '2', type: '1' }),
|
|
168
|
+
}),
|
|
126
169
|
],
|
|
127
|
-
|
|
128
|
-
|
|
170
|
+
]),
|
|
171
|
+
);
|
|
129
172
|
|
|
130
173
|
expect(assets).toHaveLength(2);
|
|
131
|
-
|
|
132
174
|
});
|
|
133
175
|
|
|
134
176
|
test('should log error when export fails', async () => {
|
|
135
177
|
vol.fromJSON({
|
|
136
|
-
[`${TEST_DIRECTORY}/json/entities/entity_type_1/${uuid()}.json`]: '{;}'
|
|
137
|
-
})
|
|
178
|
+
[`${TEST_DIRECTORY}/json/entities/entity_type_1/${uuid()}.json`]: '{;}',
|
|
179
|
+
});
|
|
138
180
|
|
|
139
|
-
await expect(
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
181
|
+
await expect(
|
|
182
|
+
exportJsonAssetsToCsv({
|
|
183
|
+
includeEntities: true,
|
|
184
|
+
includeRelationships: true,
|
|
185
|
+
storageDirectory: TEST_DIRECTORY,
|
|
186
|
+
apiKey: TEST_API_KEY,
|
|
187
|
+
}),
|
|
188
|
+
).rejects.toThrow(/Unexpected token/g);
|
|
145
189
|
expect(log.error).toHaveBeenCalledWith('Failed to export JSON assets to CSV');
|
|
146
|
-
expect(mockedSpinner.fail).toHaveBeenCalledWith(
|
|
190
|
+
expect(mockedSpinner.fail).toHaveBeenCalledWith(
|
|
191
|
+
'Failed to export JSON assets to CSV',
|
|
192
|
+
);
|
|
147
193
|
});
|
|
148
194
|
|
|
149
195
|
function convertCsvToJson(content: string) {
|
|
150
196
|
return csvToJson({ checkType: true }).fromString(content);
|
|
151
|
-
}
|
|
197
|
+
}
|
|
@@ -13,9 +13,9 @@ beforeEach(() => {
|
|
|
13
13
|
});
|
|
14
14
|
|
|
15
15
|
test('should return nothing if there are no files found', async () => {
|
|
16
|
-
await expect(
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
await expect(
|
|
17
|
+
groupJsonAssetsByType({ assetDirectory: TEST_DIRECTORY }),
|
|
18
|
+
).resolves.toEqual({});
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
test('should group assets by type', async () => {
|
|
@@ -34,7 +34,9 @@ test('should group assets by type', async () => {
|
|
|
34
34
|
[`${TEST_DIRECTORY}/json/entities/entity_type_2/${uuid()}.json`]: '{}',
|
|
35
35
|
});
|
|
36
36
|
|
|
37
|
-
const batchedAssetFiles = await groupJsonAssetsByType({
|
|
37
|
+
const batchedAssetFiles = await groupJsonAssetsByType({
|
|
38
|
+
assetDirectory: TEST_DIRECTORY,
|
|
39
|
+
});
|
|
38
40
|
|
|
39
41
|
expect(batchedAssetFiles.entity_type_1).toHaveLength(5);
|
|
40
42
|
expect(batchedAssetFiles.entity_type_2).toHaveLength(6);
|
|
@@ -1,6 +1,14 @@
|
|
|
1
|
-
import { Entity } from
|
|
1
|
+
import { Entity } from '@jupiterone/integration-sdk-core';
|
|
2
2
|
|
|
3
|
-
export function createEntity({
|
|
3
|
+
export function createEntity({
|
|
4
|
+
type,
|
|
5
|
+
id,
|
|
6
|
+
optionalProps,
|
|
7
|
+
}: {
|
|
8
|
+
type: string;
|
|
9
|
+
id: string;
|
|
10
|
+
optionalProps?: object;
|
|
11
|
+
}) {
|
|
4
12
|
return {
|
|
5
13
|
id: `entity-${id}`,
|
|
6
14
|
name: `Entity ${id}`,
|
|
@@ -9,6 +17,6 @@ export function createEntity({ type, id, optionalProps }: { type: string, id: st
|
|
|
9
17
|
_class: 'Entity',
|
|
10
18
|
_type: `entity_type_${type}`,
|
|
11
19
|
_key: `entity-${id}`,
|
|
12
|
-
...optionalProps
|
|
13
|
-
} as Entity
|
|
14
|
-
}
|
|
20
|
+
...optionalProps,
|
|
21
|
+
} as Entity;
|
|
22
|
+
}
|
|
@@ -11,18 +11,16 @@ jest.mock('fs');
|
|
|
11
11
|
|
|
12
12
|
test('should write assets to csv files by given types', async () => {
|
|
13
13
|
vol.fromJSON({
|
|
14
|
-
[`${TEST_STORAGE_LOCATION}/json/entities/entity_type_1/${uuid()}.json`]:
|
|
15
|
-
[
|
|
14
|
+
[`${TEST_STORAGE_LOCATION}/json/entities/entity_type_1/${uuid()}.json`]:
|
|
15
|
+
JSON.stringify([
|
|
16
16
|
createEntity({ id: '1', type: '1' }),
|
|
17
17
|
createEntity({ id: '2', type: '1' }),
|
|
18
|
-
],
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
[
|
|
18
|
+
]),
|
|
19
|
+
[`${TEST_STORAGE_LOCATION}/json/entities/entity_type_2/${uuid()}.json`]:
|
|
20
|
+
JSON.stringify([
|
|
22
21
|
createEntity({ id: '3', type: '2' }),
|
|
23
22
|
createEntity({ id: '4', type: '2' }),
|
|
24
|
-
],
|
|
25
|
-
),
|
|
23
|
+
]),
|
|
26
24
|
});
|
|
27
25
|
|
|
28
26
|
await writeAssetsToCsv({
|
|
@@ -4,10 +4,14 @@ import { deleteDirectory } from '../fileSystem';
|
|
|
4
4
|
import { exportAssetsToJson } from './exportAssetsToJson';
|
|
5
5
|
import { exportJsonAssetsToCsv } from './exportJsonAssetsToCsv';
|
|
6
6
|
|
|
7
|
-
export type ExportAssetsParams = Omit<ExportOptions, 'dataDir'> & {
|
|
7
|
+
export type ExportAssetsParams = Omit<ExportOptions, 'dataDir'> & {
|
|
8
|
+
storageDirectory: string;
|
|
9
|
+
};
|
|
8
10
|
|
|
9
11
|
export default async function exportAssets(options: ExportAssetsParams) {
|
|
10
|
-
log.info(
|
|
12
|
+
log.info(
|
|
13
|
+
`Starting account export to the [${options.storageDirectory}] directory`,
|
|
14
|
+
);
|
|
11
15
|
log.info(`Exporting Entities: ${options.includeEntities}`);
|
|
12
16
|
log.info(`Exporting Relationships: ${options.includeRelationships}`);
|
|
13
17
|
log.info(`Include Deleted Assets: ${options.includeDeleted}`);
|
|
@@ -4,19 +4,22 @@ import path from 'path';
|
|
|
4
4
|
import _ from 'lodash';
|
|
5
5
|
|
|
6
6
|
interface BatchAssetParams {
|
|
7
|
-
assetDirectory: string
|
|
7
|
+
assetDirectory: string;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
export async function groupJsonAssetsByType({
|
|
10
|
+
export async function groupJsonAssetsByType({
|
|
11
|
+
assetDirectory,
|
|
12
|
+
}: BatchAssetParams) {
|
|
11
13
|
const assetJsonFiles = await globby([
|
|
12
|
-
upath.toUnix(`${assetDirectory}/**/*.json`)
|
|
14
|
+
upath.toUnix(`${assetDirectory}/**/*.json`),
|
|
13
15
|
]);
|
|
14
16
|
|
|
15
|
-
const assetJsonFilesByType = _.groupBy(assetJsonFiles, p =>
|
|
17
|
+
const assetJsonFilesByType = _.groupBy(assetJsonFiles, (p) =>
|
|
18
|
+
path.basename(path.dirname(p)),
|
|
19
|
+
);
|
|
16
20
|
|
|
17
|
-
return Object.keys(assetJsonFilesByType)
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
}, {} as { [key: string]: string[] })
|
|
21
|
+
return Object.keys(assetJsonFilesByType).reduce((acc, key) => {
|
|
22
|
+
acc[key] = assetJsonFilesByType[key];
|
|
23
|
+
return acc;
|
|
24
|
+
}, {} as { [key: string]: string[] });
|
|
22
25
|
}
|
package/src/export/util.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export function sanitizeContent(content: string) {
|
|
2
|
-
return content.replace(/\\n/g, '\\\\n').replace(/\\r/g, '\\\\r')
|
|
3
|
-
}
|
|
2
|
+
return content.replace(/\\n/g, '\\\\n').replace(/\\r/g, '\\\\r');
|
|
3
|
+
}
|