@ldsg/cli 0.3.31 → 0.3.33
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/.rush/temp/package-deps_build.json +27 -27
- package/.rush/temp/shrinkwrap-deps.json +58 -3
- package/.tsbuildinfo +1 -1
- package/CHANGELOG.json +52 -0
- package/CHANGELOG.md +15 -1
- package/README.md +5 -2
- package/dist/__tests__/commands.test.js +104 -104
- package/dist/__tests__/formatter.test.js +66 -63
- package/dist/__tests__/formatter.test.js.map +1 -1
- package/dist/__tests__/json-file-mutator.test.js +48 -45
- package/dist/__tests__/json-file-mutator.test.js.map +1 -1
- package/dist/__tests__/source-resolver.test.js +39 -39
- package/dist/cli.js +89 -89
- package/dist/cli.js.map +1 -1
- package/dist/commands/resource/convert.d.ts +1 -1
- package/dist/commands/resource/convert.js +9 -7
- package/dist/commands/resource/convert.js.map +1 -1
- package/dist/commands/resource/create.d.ts +2 -2
- package/dist/commands/resource/create.js +5 -5
- package/dist/commands/resource/delete.d.ts +2 -2
- package/dist/commands/resource/delete.js.map +1 -1
- package/dist/commands/resource/diff.d.ts +2 -2
- package/dist/commands/resource/diff.js +8 -8
- package/dist/commands/resource/get.d.ts +1 -1
- package/dist/commands/resource/list.d.ts +2 -2
- package/dist/commands/resource/list.js +11 -11
- package/dist/commands/resource/list.js.map +1 -1
- package/dist/commands/resource/tree.d.ts +1 -1
- package/dist/commands/resource/update.d.ts +2 -2
- package/dist/commands/resource/update.js +1 -1
- package/dist/constants.js +2 -2
- package/dist/types/get-extend-app-data-params.d.ts +2 -2
- package/dist/types/resource-record.d.ts +2 -2
- package/dist/utils/formatter.d.ts +1 -1
- package/dist/utils/formatter.js +25 -25
- package/dist/utils/get-extend-app-data-params-using-npm-ldsg-module.d.ts +1 -1
- package/dist/utils/get-extend-app-data-params-using-npm-ldsg-module.js +12 -12
- package/dist/utils/get-extend-app-data-params-using-npm-ldsg-module.js.map +1 -1
- package/dist/utils/get-extend-app-data-params-using-workspace-ldsg-module/index.d.ts +1 -1
- package/dist/utils/get-extend-app-data-params-using-workspace-ldsg-module/index.js +20 -20
- package/dist/utils/get-extend-app-data-params-using-workspace-ldsg-module/index.js.map +1 -1
- package/dist/utils/json-file-mutator.d.ts +2 -2
- package/dist/utils/json-file-mutator.js +4 -4
- package/dist/utils/json-file-mutator.js.map +1 -1
- package/dist/utils/source-resolver.d.ts +1 -1
- package/dist/utils/source-resolver.js +15 -15
- package/dist/utils/source-resolver.js.map +1 -1
- package/jest.config.js +8 -8
- package/package.json +13 -10
- package/src/__tests__/commands.test.ts +116 -116
- package/src/__tests__/formatter.test.ts +68 -65
- package/src/__tests__/json-file-mutator.test.ts +57 -52
- package/src/__tests__/source-resolver.test.ts +43 -43
- package/src/cli.ts +132 -114
- package/src/commands/resource/convert.ts +13 -11
- package/src/commands/resource/create.ts +8 -8
- package/src/commands/resource/delete.ts +6 -4
- package/src/commands/resource/diff.ts +10 -10
- package/src/commands/resource/get.ts +2 -2
- package/src/commands/resource/list.ts +20 -18
- package/src/commands/resource/tree.ts +2 -2
- package/src/commands/resource/update.ts +4 -4
- package/src/constants.ts +2 -2
- package/src/types/get-extend-app-data-params.ts +5 -3
- package/src/types/resource-record.ts +2 -2
- package/src/utils/formatter.ts +27 -27
- package/src/utils/get-extend-app-data-params-using-npm-ldsg-module.ts +20 -16
- package/src/utils/get-extend-app-data-params-using-workspace-ldsg-module/index.ts +28 -26
- package/src/utils/json-file-mutator.ts +18 -12
- package/src/utils/source-resolver.ts +26 -21
|
@@ -4,130 +4,133 @@ import {
|
|
|
4
4
|
formatJson,
|
|
5
5
|
formatPrettyList,
|
|
6
6
|
formatPrettyTree,
|
|
7
|
-
formatPrettyDiff
|
|
8
|
-
} from
|
|
7
|
+
formatPrettyDiff,
|
|
8
|
+
} from "../utils/formatter";
|
|
9
9
|
|
|
10
|
-
describe(
|
|
11
|
-
describe(
|
|
12
|
-
it(
|
|
13
|
-
const result = formatSuccess({ id:
|
|
14
|
-
expect(result).toEqual({ success: true, data: { id:
|
|
10
|
+
describe("formatter", () => {
|
|
11
|
+
describe("formatSuccess", () => {
|
|
12
|
+
it("should format success response", () => {
|
|
13
|
+
const result = formatSuccess({ id: "1" });
|
|
14
|
+
expect(result).toEqual({ success: true, data: { id: "1" } });
|
|
15
15
|
});
|
|
16
16
|
});
|
|
17
17
|
|
|
18
|
-
describe(
|
|
19
|
-
it(
|
|
20
|
-
const result = formatError(
|
|
21
|
-
expect(result).toEqual({
|
|
18
|
+
describe("formatError", () => {
|
|
19
|
+
it("should format error response", () => {
|
|
20
|
+
const result = formatError("NOT_FOUND", "Resource not found");
|
|
21
|
+
expect(result).toEqual({
|
|
22
|
+
success: false,
|
|
23
|
+
error: { code: "NOT_FOUND", message: "Resource not found" },
|
|
24
|
+
});
|
|
22
25
|
});
|
|
23
26
|
});
|
|
24
27
|
|
|
25
|
-
describe(
|
|
26
|
-
it(
|
|
27
|
-
const result = formatJson({ a: 1, b:
|
|
28
|
+
describe("formatJson", () => {
|
|
29
|
+
it("should format JSON with 2-space indent", () => {
|
|
30
|
+
const result = formatJson({ a: 1, b: "test" });
|
|
28
31
|
expect(result).toBe('{\n "a": 1,\n "b": "test"\n}');
|
|
29
32
|
});
|
|
30
33
|
});
|
|
31
34
|
|
|
32
|
-
describe(
|
|
33
|
-
it(
|
|
34
|
-
expect(formatPrettyList([])).toBe(
|
|
35
|
+
describe("formatPrettyList", () => {
|
|
36
|
+
it("should return message for empty list", () => {
|
|
37
|
+
expect(formatPrettyList([])).toBe("No resources found.");
|
|
35
38
|
});
|
|
36
39
|
|
|
37
|
-
it(
|
|
40
|
+
it("should format list with header and rows", () => {
|
|
38
41
|
const resources = [
|
|
39
|
-
{ id:
|
|
40
|
-
{ id:
|
|
42
|
+
{ id: "1", kind: "application", parentId: null, title: "App1" },
|
|
43
|
+
{ id: "2", kind: "form", parentId: "1", title: "Form1" },
|
|
41
44
|
];
|
|
42
45
|
const result = formatPrettyList(resources);
|
|
43
|
-
expect(result).toContain(
|
|
44
|
-
expect(result).toContain(
|
|
45
|
-
expect(result).toContain(
|
|
46
|
-
expect(result).toContain(
|
|
46
|
+
expect(result).toContain("ID");
|
|
47
|
+
expect(result).toContain("KIND");
|
|
48
|
+
expect(result).toContain("PARENT ID");
|
|
49
|
+
expect(result).toContain("Total: 2 resource(s)");
|
|
47
50
|
});
|
|
48
51
|
});
|
|
49
52
|
|
|
50
|
-
describe(
|
|
51
|
-
it(
|
|
53
|
+
describe("formatPrettyTree", () => {
|
|
54
|
+
it("should format a tree with root and children", () => {
|
|
52
55
|
const tree = {
|
|
53
|
-
resource: { id:
|
|
56
|
+
resource: { id: "1", kind: "application", parentId: null, settings: {} },
|
|
54
57
|
children: [
|
|
55
58
|
{
|
|
56
|
-
resource: { id:
|
|
57
|
-
children: []
|
|
58
|
-
}
|
|
59
|
-
]
|
|
59
|
+
resource: { id: "2", kind: "form", parentId: "1", settings: {} },
|
|
60
|
+
children: [],
|
|
61
|
+
},
|
|
62
|
+
],
|
|
60
63
|
};
|
|
61
64
|
|
|
62
65
|
const result = formatPrettyTree(tree, false);
|
|
63
|
-
expect(result).toContain(
|
|
64
|
-
expect(result).toContain(
|
|
65
|
-
expect(result).toContain(
|
|
66
|
+
expect(result).toContain("1");
|
|
67
|
+
expect(result).toContain("2");
|
|
68
|
+
expect(result).toContain("└──");
|
|
66
69
|
});
|
|
67
70
|
|
|
68
|
-
it(
|
|
71
|
+
it("should show kind prefix with showKind option", () => {
|
|
69
72
|
const tree = {
|
|
70
|
-
resource: { id:
|
|
71
|
-
children: []
|
|
73
|
+
resource: { id: "1", kind: "application", parentId: null, settings: {} },
|
|
74
|
+
children: [],
|
|
72
75
|
};
|
|
73
76
|
|
|
74
77
|
const result = formatPrettyTree(tree, true);
|
|
75
|
-
expect(result).toContain(
|
|
78
|
+
expect(result).toContain("[application]");
|
|
76
79
|
});
|
|
77
80
|
});
|
|
78
81
|
|
|
79
|
-
describe(
|
|
80
|
-
it(
|
|
82
|
+
describe("formatPrettyDiff", () => {
|
|
83
|
+
it("should show no differences message", () => {
|
|
81
84
|
const diff = {
|
|
82
|
-
id:
|
|
83
|
-
kind:
|
|
84
|
-
sourceA:
|
|
85
|
-
sourceB:
|
|
85
|
+
id: "1",
|
|
86
|
+
kind: "application",
|
|
87
|
+
sourceA: "a.json",
|
|
88
|
+
sourceB: "b.json",
|
|
86
89
|
changed: [],
|
|
87
90
|
added: [],
|
|
88
91
|
removed: [],
|
|
89
|
-
sideA: { id:
|
|
90
|
-
sideB: { id:
|
|
92
|
+
sideA: { id: "1", kind: "application", parentId: null, settings: {} },
|
|
93
|
+
sideB: { id: "1", kind: "application", parentId: null, settings: {} },
|
|
91
94
|
} as any;
|
|
92
95
|
|
|
93
96
|
const result = formatPrettyDiff(diff);
|
|
94
|
-
expect(result).toContain(
|
|
97
|
+
expect(result).toContain("No differences found.");
|
|
95
98
|
});
|
|
96
99
|
|
|
97
|
-
it(
|
|
100
|
+
it("should show changed fields", () => {
|
|
98
101
|
const diff = {
|
|
99
|
-
id:
|
|
100
|
-
kind:
|
|
101
|
-
sourceA:
|
|
102
|
-
sourceB:
|
|
103
|
-
changed: [{ path:
|
|
102
|
+
id: "1",
|
|
103
|
+
kind: "application",
|
|
104
|
+
sourceA: "a.json",
|
|
105
|
+
sourceB: "b.json",
|
|
106
|
+
changed: [{ path: "settings.title", from: "Old", to: "New" }],
|
|
104
107
|
added: [],
|
|
105
108
|
removed: [],
|
|
106
|
-
sideA: { id:
|
|
107
|
-
sideB: { id:
|
|
109
|
+
sideA: { id: "1", kind: "application", parentId: null, settings: {} },
|
|
110
|
+
sideB: { id: "1", kind: "application", parentId: null, settings: {} },
|
|
108
111
|
} as any;
|
|
109
112
|
|
|
110
113
|
const result = formatPrettyDiff(diff);
|
|
111
|
-
expect(result).toContain(
|
|
112
|
-
expect(result).toContain(
|
|
113
|
-
expect(result).toContain(
|
|
114
|
+
expect(result).toContain("settings.title");
|
|
115
|
+
expect(result).toContain("Old");
|
|
116
|
+
expect(result).toContain("New");
|
|
114
117
|
});
|
|
115
118
|
|
|
116
|
-
it(
|
|
119
|
+
it("should show side-only existence", () => {
|
|
117
120
|
const diffA: any = {
|
|
118
|
-
id:
|
|
119
|
-
kind:
|
|
120
|
-
sourceA:
|
|
121
|
-
sourceB:
|
|
121
|
+
id: "1",
|
|
122
|
+
kind: "application",
|
|
123
|
+
sourceA: "a.json",
|
|
124
|
+
sourceB: "b.json",
|
|
122
125
|
changed: [],
|
|
123
126
|
added: [],
|
|
124
127
|
removed: [],
|
|
125
128
|
sideA: null,
|
|
126
|
-
sideB: { id:
|
|
129
|
+
sideB: { id: "1", kind: "application", parentId: null, settings: {} },
|
|
127
130
|
};
|
|
128
131
|
|
|
129
132
|
const result = formatPrettyDiff(diffA);
|
|
130
|
-
expect(result).toContain(
|
|
133
|
+
expect(result).toContain("only exists in source B");
|
|
131
134
|
});
|
|
132
135
|
});
|
|
133
136
|
});
|
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
import fs from
|
|
2
|
-
import { appendRecord, updateRecord, removeRecord, generateId } from
|
|
3
|
-
import { SourceData } from
|
|
4
|
-
import { ResourceRecords } from
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import { appendRecord, updateRecord, removeRecord, generateId } from "../utils/json-file-mutator";
|
|
3
|
+
import { SourceData } from "../types/resource-record";
|
|
4
|
+
import { ResourceRecords } from "@ldsg/types";
|
|
5
5
|
|
|
6
|
-
jest.mock(
|
|
6
|
+
jest.mock("fs-extra");
|
|
7
7
|
|
|
8
8
|
const mockedFs = fs as jest.Mocked<typeof fs>;
|
|
9
9
|
|
|
10
|
-
describe(
|
|
10
|
+
describe("json-file-mutator", () => {
|
|
11
11
|
const arrayRecords: ResourceRecords = [
|
|
12
|
-
{ id:
|
|
13
|
-
{ id:
|
|
14
|
-
{ id:
|
|
15
|
-
{ id:
|
|
12
|
+
{ id: "1", kind: "application", parentId: null, settings: { title: "App1" } },
|
|
13
|
+
{ id: "2", kind: "form", parentId: "1", settings: { title: "Form1" } },
|
|
14
|
+
{ id: "3", kind: "table", parentId: "1", settings: { title: "Table1" } },
|
|
15
|
+
{ id: "4", kind: "field", parentId: "3", settings: { title: "Field1" } },
|
|
16
16
|
];
|
|
17
17
|
|
|
18
18
|
const arraySourceData: SourceData = {
|
|
19
19
|
resourceRecords: arrayRecords,
|
|
20
|
-
format:
|
|
21
|
-
filePath:
|
|
20
|
+
format: "array",
|
|
21
|
+
filePath: "/test/data.json",
|
|
22
22
|
};
|
|
23
23
|
|
|
24
24
|
const objectSourceData: SourceData = {
|
|
25
25
|
resourceRecords: arrayRecords,
|
|
26
|
-
format:
|
|
27
|
-
filePath:
|
|
26
|
+
format: "object",
|
|
27
|
+
filePath: "/test/data.json",
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
beforeEach(() => {
|
|
@@ -32,102 +32,107 @@ describe('json-file-mutator', () => {
|
|
|
32
32
|
mockedFs.readJson.mockResolvedValue([...arrayRecords]);
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
-
describe(
|
|
36
|
-
it(
|
|
35
|
+
describe("generateId", () => {
|
|
36
|
+
it("should generate a string id", () => {
|
|
37
37
|
const id = generateId();
|
|
38
|
-
expect(typeof id).toBe(
|
|
38
|
+
expect(typeof id).toBe("string");
|
|
39
39
|
expect(id.length).toBeGreaterThan(5);
|
|
40
40
|
});
|
|
41
41
|
|
|
42
|
-
it(
|
|
42
|
+
it("should generate unique ids", () => {
|
|
43
43
|
const ids = new Set(Array.from({ length: 10 }, () => generateId()));
|
|
44
44
|
expect(ids.size).toBe(10);
|
|
45
45
|
});
|
|
46
46
|
});
|
|
47
47
|
|
|
48
|
-
describe(
|
|
49
|
-
it(
|
|
48
|
+
describe("appendRecord", () => {
|
|
49
|
+
it("should append a new record to array format", async () => {
|
|
50
50
|
mockedFs.readJson.mockResolvedValue([...arrayRecords]);
|
|
51
51
|
|
|
52
|
-
const newRecord = { id:
|
|
52
|
+
const newRecord = { id: "5", kind: "form", parentId: "1", settings: { title: "Form2" } };
|
|
53
53
|
const result = await appendRecord(arraySourceData, newRecord);
|
|
54
54
|
|
|
55
|
-
expect(result.record.id).toBe(
|
|
55
|
+
expect(result.record.id).toBe("5");
|
|
56
56
|
expect(result.allRecords).toHaveLength(5);
|
|
57
57
|
expect(mockedFs.writeJson).toHaveBeenCalledWith(
|
|
58
|
-
|
|
59
|
-
expect.arrayContaining([expect.objectContaining({ id:
|
|
60
|
-
{ spaces: 2 }
|
|
58
|
+
"/test/data.json",
|
|
59
|
+
expect.arrayContaining([expect.objectContaining({ id: "5" })]),
|
|
60
|
+
{ spaces: 2 },
|
|
61
61
|
);
|
|
62
62
|
});
|
|
63
63
|
|
|
64
|
-
it(
|
|
64
|
+
it("should append to object format preserving structure", async () => {
|
|
65
65
|
mockedFs.readJson.mockResolvedValue({ resourceRecords: [...arrayRecords] });
|
|
66
66
|
|
|
67
|
-
const newRecord = { id:
|
|
67
|
+
const newRecord = { id: "5", kind: "form", parentId: "1", settings: {} };
|
|
68
68
|
await appendRecord(objectSourceData, newRecord);
|
|
69
69
|
|
|
70
70
|
expect(mockedFs.writeJson).toHaveBeenCalledWith(
|
|
71
|
-
|
|
71
|
+
"/test/data.json",
|
|
72
72
|
expect.objectContaining({
|
|
73
|
-
resourceRecords: expect.arrayContaining([expect.objectContaining({ id:
|
|
73
|
+
resourceRecords: expect.arrayContaining([expect.objectContaining({ id: "5" })]),
|
|
74
74
|
}),
|
|
75
|
-
{ spaces: 2 }
|
|
75
|
+
{ spaces: 2 },
|
|
76
76
|
);
|
|
77
77
|
});
|
|
78
78
|
|
|
79
|
-
it(
|
|
80
|
-
const dupRecord = { id:
|
|
81
|
-
await expect(appendRecord(arraySourceData, dupRecord)).rejects.toThrow(
|
|
79
|
+
it("should throw on duplicate id", async () => {
|
|
80
|
+
const dupRecord = { id: "1", kind: "application", parentId: null, settings: {} };
|
|
81
|
+
await expect(appendRecord(arraySourceData, dupRecord)).rejects.toThrow("already exists");
|
|
82
82
|
});
|
|
83
83
|
|
|
84
|
-
it(
|
|
85
|
-
const newRecord = { id:
|
|
84
|
+
it("should not write file in dry-run mode", async () => {
|
|
85
|
+
const newRecord = { id: "5", kind: "form", parentId: "1", settings: {} };
|
|
86
86
|
await appendRecord(arraySourceData, newRecord, true);
|
|
87
87
|
|
|
88
88
|
expect(mockedFs.writeJson).not.toHaveBeenCalled();
|
|
89
89
|
});
|
|
90
90
|
});
|
|
91
91
|
|
|
92
|
-
describe(
|
|
93
|
-
it(
|
|
92
|
+
describe("updateRecord", () => {
|
|
93
|
+
it("should update settings and merge", async () => {
|
|
94
94
|
mockedFs.readJson.mockResolvedValue([...arrayRecords]);
|
|
95
95
|
|
|
96
|
-
const result = await updateRecord(arraySourceData,
|
|
96
|
+
const result = await updateRecord(arraySourceData, "1", {
|
|
97
|
+
title: "Updated App",
|
|
98
|
+
newField: "value",
|
|
99
|
+
});
|
|
97
100
|
|
|
98
|
-
expect(result.record.settings).toEqual({ title:
|
|
101
|
+
expect(result.record.settings).toEqual({ title: "Updated App", newField: "value" });
|
|
99
102
|
expect(mockedFs.writeJson).toHaveBeenCalled();
|
|
100
103
|
});
|
|
101
104
|
|
|
102
|
-
it(
|
|
103
|
-
await expect(updateRecord(arraySourceData,
|
|
105
|
+
it("should throw on non-existent id", async () => {
|
|
106
|
+
await expect(updateRecord(arraySourceData, "nonexistent", { title: "x" })).rejects.toThrow(
|
|
107
|
+
"not found",
|
|
108
|
+
);
|
|
104
109
|
});
|
|
105
110
|
|
|
106
|
-
it(
|
|
107
|
-
await updateRecord(arraySourceData,
|
|
111
|
+
it("should not write file in dry-run mode", async () => {
|
|
112
|
+
await updateRecord(arraySourceData, "1", { title: "Dry Run" }, true);
|
|
108
113
|
|
|
109
114
|
expect(mockedFs.writeJson).not.toHaveBeenCalled();
|
|
110
115
|
});
|
|
111
116
|
});
|
|
112
117
|
|
|
113
|
-
describe(
|
|
114
|
-
it(
|
|
118
|
+
describe("removeRecord", () => {
|
|
119
|
+
it("should remove record and its children", async () => {
|
|
115
120
|
mockedFs.readJson.mockResolvedValue([...arrayRecords]);
|
|
116
121
|
|
|
117
|
-
const result = await removeRecord(arraySourceData,
|
|
122
|
+
const result = await removeRecord(arraySourceData, "3");
|
|
118
123
|
|
|
119
124
|
expect(result.removed).toHaveLength(2);
|
|
120
|
-
expect(result.removed.map((r) => r.id)).toEqual([
|
|
125
|
+
expect(result.removed.map((r) => r.id)).toEqual(["3", "4"]);
|
|
121
126
|
expect(result.allRecords).toHaveLength(2);
|
|
122
|
-
expect(result.allRecords.map((r) => r.id)).toEqual([
|
|
127
|
+
expect(result.allRecords.map((r) => r.id)).toEqual(["1", "2"]);
|
|
123
128
|
});
|
|
124
129
|
|
|
125
|
-
it(
|
|
126
|
-
await expect(removeRecord(arraySourceData,
|
|
130
|
+
it("should throw on non-existent id", async () => {
|
|
131
|
+
await expect(removeRecord(arraySourceData, "nonexistent")).rejects.toThrow("not found");
|
|
127
132
|
});
|
|
128
133
|
|
|
129
|
-
it(
|
|
130
|
-
const result = await removeRecord(arraySourceData,
|
|
134
|
+
it("should not write file in dry-run mode", async () => {
|
|
135
|
+
const result = await removeRecord(arraySourceData, "3", true);
|
|
131
136
|
|
|
132
137
|
expect(result.removed).toHaveLength(2);
|
|
133
138
|
expect(mockedFs.writeJson).not.toHaveBeenCalled();
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import fs from
|
|
2
|
-
import path from
|
|
3
|
-
import os from
|
|
4
|
-
import { resolveSource, isStdinSource, getSourceDescription } from
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import os from "os";
|
|
4
|
+
import { resolveSource, isStdinSource, getSourceDescription } from "../utils/source-resolver";
|
|
5
5
|
|
|
6
|
-
jest.mock(
|
|
6
|
+
jest.mock("fs-extra");
|
|
7
7
|
|
|
8
8
|
const mockedFs = fs as jest.Mocked<typeof fs> & {
|
|
9
9
|
pathExists: jest.Mock;
|
|
@@ -11,50 +11,50 @@ const mockedFs = fs as jest.Mocked<typeof fs> & {
|
|
|
11
11
|
stat: jest.Mock;
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
describe(
|
|
14
|
+
describe("source-resolver", () => {
|
|
15
15
|
const tmpDir = os.tmpdir();
|
|
16
|
-
const testFilePath = path.join(tmpDir,
|
|
17
|
-
const testDirPath = path.join(tmpDir,
|
|
18
|
-
const defaultFilePath = path.join(process.cwd(),
|
|
16
|
+
const testFilePath = path.join(tmpDir, "test-resources.json");
|
|
17
|
+
const testDirPath = path.join(tmpDir, "test-resource-dir");
|
|
18
|
+
const defaultFilePath = path.join(process.cwd(), "resource-records.json");
|
|
19
19
|
|
|
20
20
|
const arrayData = [
|
|
21
|
-
{ id:
|
|
22
|
-
{ id:
|
|
21
|
+
{ id: "1", kind: "application", parentId: null, settings: {} },
|
|
22
|
+
{ id: "2", kind: "form", parentId: "1", settings: {} },
|
|
23
23
|
];
|
|
24
24
|
|
|
25
25
|
const objectData = {
|
|
26
|
-
resourceRecords: [{ id:
|
|
26
|
+
resourceRecords: [{ id: "1", kind: "application", parentId: null, settings: {} }],
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
beforeEach(() => {
|
|
30
30
|
jest.resetAllMocks();
|
|
31
31
|
});
|
|
32
32
|
|
|
33
|
-
describe(
|
|
34
|
-
it(
|
|
33
|
+
describe("resolveSource", () => {
|
|
34
|
+
it("should read array format JSON file", async () => {
|
|
35
35
|
mockedFs.pathExists.mockResolvedValue(true);
|
|
36
36
|
mockedFs.readJson.mockResolvedValue(arrayData);
|
|
37
37
|
mockedFs.stat.mockResolvedValue({ isDirectory: () => false } as fs.Stats);
|
|
38
38
|
|
|
39
39
|
const result = await resolveSource(testFilePath);
|
|
40
40
|
expect(result.resourceRecords).toHaveLength(2);
|
|
41
|
-
expect(result.format).toBe(
|
|
41
|
+
expect(result.format).toBe("array");
|
|
42
42
|
expect(result.filePath).toBe(testFilePath);
|
|
43
43
|
});
|
|
44
44
|
|
|
45
|
-
it(
|
|
45
|
+
it("should read object format JSON file", async () => {
|
|
46
46
|
mockedFs.pathExists.mockResolvedValue(true);
|
|
47
47
|
mockedFs.readJson.mockResolvedValue(objectData);
|
|
48
48
|
mockedFs.stat.mockResolvedValue({ isDirectory: () => false } as fs.Stats);
|
|
49
49
|
|
|
50
50
|
const result = await resolveSource(testFilePath);
|
|
51
51
|
expect(result.resourceRecords).toHaveLength(1);
|
|
52
|
-
expect(result.format).toBe(
|
|
52
|
+
expect(result.format).toBe("object");
|
|
53
53
|
expect(result.filePath).toBe(testFilePath);
|
|
54
54
|
});
|
|
55
55
|
|
|
56
|
-
it(
|
|
57
|
-
const dirFile = path.join(testDirPath,
|
|
56
|
+
it("should read directory by appending default filename", async () => {
|
|
57
|
+
const dirFile = path.join(testDirPath, "resource-records.json");
|
|
58
58
|
mockedFs.pathExists.mockResolvedValue(true);
|
|
59
59
|
mockedFs.readJson.mockResolvedValue(arrayData);
|
|
60
60
|
mockedFs.stat.mockResolvedValue({ isDirectory: () => true } as fs.Stats);
|
|
@@ -64,62 +64,62 @@ describe('source-resolver', () => {
|
|
|
64
64
|
expect(result.resourceRecords).toHaveLength(2);
|
|
65
65
|
});
|
|
66
66
|
|
|
67
|
-
it(
|
|
67
|
+
it("should throw on missing default file", async () => {
|
|
68
68
|
mockedFs.pathExists.mockResolvedValue(false);
|
|
69
69
|
|
|
70
|
-
await expect(resolveSource(undefined)).rejects.toThrow(
|
|
70
|
+
await expect(resolveSource(undefined)).rejects.toThrow("Default source file not found");
|
|
71
71
|
});
|
|
72
72
|
|
|
73
|
-
it(
|
|
73
|
+
it("should throw on non-existent file", async () => {
|
|
74
74
|
mockedFs.pathExists.mockResolvedValue(false);
|
|
75
|
-
mockedFs.stat.mockRejectedValue(new Error(
|
|
76
|
-
mockedFs.readJson.mockRejectedValue(new Error(
|
|
75
|
+
mockedFs.stat.mockRejectedValue(new Error("ENOENT"));
|
|
76
|
+
mockedFs.readJson.mockRejectedValue(new Error("File not found"));
|
|
77
77
|
|
|
78
|
-
await expect(resolveSource(
|
|
78
|
+
await expect(resolveSource("/nonexistent/file.json")).rejects.toThrow("Source not found");
|
|
79
79
|
});
|
|
80
80
|
|
|
81
|
-
it(
|
|
81
|
+
it("should throw on invalid JSON format", async () => {
|
|
82
82
|
mockedFs.pathExists.mockResolvedValue(true);
|
|
83
|
-
mockedFs.readJson.mockResolvedValue(
|
|
83
|
+
mockedFs.readJson.mockResolvedValue("invalid");
|
|
84
84
|
mockedFs.stat.mockResolvedValue({ isDirectory: () => false } as fs.Stats);
|
|
85
85
|
|
|
86
|
-
await expect(resolveSource(testFilePath)).rejects.toThrow(
|
|
86
|
+
await expect(resolveSource(testFilePath)).rejects.toThrow("Invalid resource records format");
|
|
87
87
|
});
|
|
88
88
|
|
|
89
|
-
it(
|
|
89
|
+
it("should throw on valid object without resourceRecords field", async () => {
|
|
90
90
|
mockedFs.pathExists.mockResolvedValue(true);
|
|
91
|
-
mockedFs.readJson.mockResolvedValue({ foo:
|
|
91
|
+
mockedFs.readJson.mockResolvedValue({ foo: "bar" });
|
|
92
92
|
mockedFs.stat.mockResolvedValue({ isDirectory: () => false } as fs.Stats);
|
|
93
93
|
|
|
94
|
-
await expect(resolveSource(testFilePath)).rejects.toThrow(
|
|
94
|
+
await expect(resolveSource(testFilePath)).rejects.toThrow("Invalid resource records format");
|
|
95
95
|
});
|
|
96
96
|
});
|
|
97
97
|
|
|
98
|
-
describe(
|
|
99
|
-
it(
|
|
100
|
-
expect(isStdinSource(
|
|
98
|
+
describe("isStdinSource", () => {
|
|
99
|
+
it("should return true for -", () => {
|
|
100
|
+
expect(isStdinSource("-")).toBe(true);
|
|
101
101
|
});
|
|
102
102
|
|
|
103
|
-
it(
|
|
104
|
-
expect(isStdinSource(
|
|
103
|
+
it("should return false for file paths", () => {
|
|
104
|
+
expect(isStdinSource("./data.json")).toBe(false);
|
|
105
105
|
});
|
|
106
106
|
|
|
107
|
-
it(
|
|
107
|
+
it("should return false for undefined", () => {
|
|
108
108
|
expect(isStdinSource(undefined)).toBe(false);
|
|
109
109
|
});
|
|
110
110
|
});
|
|
111
111
|
|
|
112
|
-
describe(
|
|
113
|
-
it(
|
|
114
|
-
expect(getSourceDescription(undefined)).toBe(
|
|
112
|
+
describe("getSourceDescription", () => {
|
|
113
|
+
it("should return default path for undefined", () => {
|
|
114
|
+
expect(getSourceDescription(undefined)).toBe("./resource-records.json");
|
|
115
115
|
});
|
|
116
116
|
|
|
117
117
|
it('should return "stdin" for -', () => {
|
|
118
|
-
expect(getSourceDescription(
|
|
118
|
+
expect(getSourceDescription("-")).toBe("stdin");
|
|
119
119
|
});
|
|
120
120
|
|
|
121
|
-
it(
|
|
122
|
-
expect(getSourceDescription(
|
|
121
|
+
it("should return the path itself", () => {
|
|
122
|
+
expect(getSourceDescription("./data.json")).toBe("./data.json");
|
|
123
123
|
});
|
|
124
124
|
});
|
|
125
125
|
});
|