@caleuche/cli 0.1.3 → 0.2.0
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/CHANGELOG.md +12 -0
- package/README.md +102 -103
- package/dist/batch.js +98 -0
- package/dist/common.js +62 -0
- package/dist/compile.js +19 -0
- package/dist/index.js +7 -39
- package/dist/interfaces.js +1 -0
- package/dist/utils.js +13 -1
- package/package.json +6 -6
- package/src/batch.ts +112 -0
- package/src/common.ts +67 -0
- package/src/compile.ts +24 -0
- package/src/index.ts +21 -67
- package/src/interfaces.ts +22 -0
- package/src/utils.ts +71 -50
- package/test/bach.test.ts +285 -0
- package/test/common.test.ts +69 -0
- package/test/compile.test.ts +255 -0
- package/test/utils.test.ts +267 -0
- package/tsconfig.json +12 -11
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach, vi } from "vitest";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
vi.mock("fs");
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
const mockFs = vi.mocked(fs);
|
|
7
|
+
|
|
8
|
+
vi.mock("@caleuche/core");
|
|
9
|
+
import { compileSample, Sample } from "@caleuche/core";
|
|
10
|
+
const mockCompileSample = vi.mocked(compileSample);
|
|
11
|
+
|
|
12
|
+
vi.mock("../src/utils");
|
|
13
|
+
import {
|
|
14
|
+
parse,
|
|
15
|
+
resolveSampleFile,
|
|
16
|
+
createOutputDirectory,
|
|
17
|
+
resolveTemplate,
|
|
18
|
+
isObject,
|
|
19
|
+
} from "../src/utils";
|
|
20
|
+
const mockParse = vi.mocked(parse);
|
|
21
|
+
const mockResolveSampleFile = vi.mocked(resolveSampleFile);
|
|
22
|
+
const mockCreateOutputDirectory = vi.mocked(createOutputDirectory);
|
|
23
|
+
const mockResolveTemplate = vi.mocked(resolveTemplate);
|
|
24
|
+
const mockIsObject = vi.mocked(isObject);
|
|
25
|
+
|
|
26
|
+
import { compile } from "../src/compile";
|
|
27
|
+
|
|
28
|
+
describe("compile", () => {
|
|
29
|
+
let mockExit: any;
|
|
30
|
+
let mockConsoleError: any;
|
|
31
|
+
|
|
32
|
+
beforeEach(() => {
|
|
33
|
+
vi.clearAllMocks();
|
|
34
|
+
mockExit = vi.spyOn(process, "exit").mockImplementation(() => {
|
|
35
|
+
throw new Error("process.exit");
|
|
36
|
+
});
|
|
37
|
+
mockConsoleError = vi.spyOn(console, "error").mockImplementation(() => {});
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
afterEach(() => {
|
|
41
|
+
vi.restoreAllMocks();
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
describe("error handling", () => {
|
|
45
|
+
it("should exit when data file cannot be parsed", () => {
|
|
46
|
+
const mockSample: Sample = {
|
|
47
|
+
template: "test template",
|
|
48
|
+
type: "javascript",
|
|
49
|
+
dependencies: [],
|
|
50
|
+
input: [],
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
|
|
54
|
+
mockFs.existsSync.mockReturnValue(true);
|
|
55
|
+
mockParse.mockReturnValueOnce(mockSample);
|
|
56
|
+
mockResolveTemplate.mockReturnValue("resolved template");
|
|
57
|
+
mockParse.mockReturnValueOnce(null);
|
|
58
|
+
|
|
59
|
+
expect(() => {
|
|
60
|
+
compile("sample", "data.json", "output", {});
|
|
61
|
+
}).toThrow("process.exit");
|
|
62
|
+
|
|
63
|
+
expect(mockConsoleError).toHaveBeenCalledWith(
|
|
64
|
+
"Failed to parse input data file: data.json",
|
|
65
|
+
);
|
|
66
|
+
expect(mockExit).toHaveBeenCalledWith(1);
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
it("should exit when data is not an object", () => {
|
|
70
|
+
const mockSample: Sample = {
|
|
71
|
+
template: "test template",
|
|
72
|
+
type: "javascript",
|
|
73
|
+
dependencies: [],
|
|
74
|
+
input: [],
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
|
|
78
|
+
mockFs.existsSync.mockReturnValue(true);
|
|
79
|
+
mockParse.mockReturnValueOnce(mockSample);
|
|
80
|
+
mockResolveTemplate.mockReturnValue("resolved template");
|
|
81
|
+
mockParse.mockReturnValueOnce("not an object");
|
|
82
|
+
mockIsObject.mockReturnValue(false);
|
|
83
|
+
|
|
84
|
+
expect(() => {
|
|
85
|
+
compile("sample", "data.json", "output", {});
|
|
86
|
+
}).toThrow("process.exit");
|
|
87
|
+
|
|
88
|
+
expect(mockConsoleError).toHaveBeenCalledWith(
|
|
89
|
+
"Failed to parse input data file: data.json",
|
|
90
|
+
);
|
|
91
|
+
expect(mockExit).toHaveBeenCalledWith(1);
|
|
92
|
+
});
|
|
93
|
+
|
|
94
|
+
it("should exit when compilation fails", () => {
|
|
95
|
+
const mockSample: Sample = {
|
|
96
|
+
template: "test template",
|
|
97
|
+
type: "javascript",
|
|
98
|
+
dependencies: [],
|
|
99
|
+
input: [],
|
|
100
|
+
};
|
|
101
|
+
const mockData = { name: "test" };
|
|
102
|
+
|
|
103
|
+
mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
|
|
104
|
+
mockFs.existsSync.mockReturnValue(true);
|
|
105
|
+
mockParse.mockReturnValueOnce(mockSample);
|
|
106
|
+
mockResolveTemplate.mockReturnValue("resolved template");
|
|
107
|
+
mockParse.mockReturnValueOnce(mockData);
|
|
108
|
+
mockIsObject.mockReturnValue(true);
|
|
109
|
+
mockCompileSample.mockImplementation(() => {
|
|
110
|
+
throw new Error("Compilation error");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
expect(() => {
|
|
114
|
+
compile("sample", "data.json", "output", {});
|
|
115
|
+
}).toThrow("process.exit");
|
|
116
|
+
|
|
117
|
+
expect(mockConsoleError).toHaveBeenCalledWith(
|
|
118
|
+
"Error during compilation: Compilation error",
|
|
119
|
+
);
|
|
120
|
+
expect(mockExit).toHaveBeenCalledWith(1);
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it("should handle unknown compilation errors", () => {
|
|
124
|
+
const mockSample: Sample = {
|
|
125
|
+
template: "test template",
|
|
126
|
+
type: "javascript",
|
|
127
|
+
dependencies: [],
|
|
128
|
+
input: [],
|
|
129
|
+
};
|
|
130
|
+
const mockData = { name: "test" };
|
|
131
|
+
|
|
132
|
+
mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
|
|
133
|
+
mockFs.existsSync.mockReturnValue(true);
|
|
134
|
+
mockParse.mockReturnValueOnce(mockSample);
|
|
135
|
+
mockResolveTemplate.mockReturnValue("resolved template");
|
|
136
|
+
mockParse.mockReturnValueOnce(mockData);
|
|
137
|
+
mockIsObject.mockReturnValue(true);
|
|
138
|
+
mockCompileSample.mockImplementation(() => {
|
|
139
|
+
throw "Unknown error";
|
|
140
|
+
});
|
|
141
|
+
|
|
142
|
+
expect(() => {
|
|
143
|
+
compile("sample", "data.json", "output", {});
|
|
144
|
+
}).toThrow("process.exit");
|
|
145
|
+
|
|
146
|
+
expect(mockConsoleError).toHaveBeenCalledWith(
|
|
147
|
+
"An unknown error occurred during compilation.",
|
|
148
|
+
);
|
|
149
|
+
expect(mockExit).toHaveBeenCalledWith(1);
|
|
150
|
+
});
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
describe("successful compilation", () => {
|
|
154
|
+
it("should compile successfully and write output files", () => {
|
|
155
|
+
const mockSample: Sample = {
|
|
156
|
+
template: "test template",
|
|
157
|
+
type: "javascript",
|
|
158
|
+
dependencies: [],
|
|
159
|
+
input: [],
|
|
160
|
+
};
|
|
161
|
+
const mockData = { name: "test" };
|
|
162
|
+
const mockOutput = {
|
|
163
|
+
items: [
|
|
164
|
+
{ fileName: "sample.js", content: "console.log('test');" },
|
|
165
|
+
{ fileName: "package.json", content: '{"name": "test"}' },
|
|
166
|
+
],
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
|
|
170
|
+
mockFs.existsSync.mockReturnValue(true);
|
|
171
|
+
mockParse.mockReturnValueOnce(mockSample);
|
|
172
|
+
mockResolveTemplate.mockReturnValue("resolved template");
|
|
173
|
+
mockParse.mockReturnValueOnce(mockData);
|
|
174
|
+
mockIsObject.mockReturnValue(true);
|
|
175
|
+
mockCompileSample.mockReturnValue(mockOutput);
|
|
176
|
+
mockCreateOutputDirectory.mockImplementation(() => {});
|
|
177
|
+
mockFs.writeFileSync.mockImplementation(() => {});
|
|
178
|
+
|
|
179
|
+
// This should not throw
|
|
180
|
+
compile("sample", "data.json", "output", { project: true });
|
|
181
|
+
|
|
182
|
+
expect(mockCreateOutputDirectory).toHaveBeenCalledWith("output");
|
|
183
|
+
expect(mockFs.writeFileSync).toHaveBeenCalledWith(
|
|
184
|
+
path.join("output", "sample.js"),
|
|
185
|
+
"console.log('test');",
|
|
186
|
+
);
|
|
187
|
+
expect(mockFs.writeFileSync).toHaveBeenCalledWith(
|
|
188
|
+
path.join("output", "package.json"),
|
|
189
|
+
'{"name": "test"}',
|
|
190
|
+
);
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
it("should pass correct options to compileSample", () => {
|
|
194
|
+
const mockSample: Sample = {
|
|
195
|
+
template: "test template",
|
|
196
|
+
type: "javascript",
|
|
197
|
+
dependencies: [],
|
|
198
|
+
input: [],
|
|
199
|
+
};
|
|
200
|
+
const mockData = { name: "test" };
|
|
201
|
+
const mockOutput = {
|
|
202
|
+
items: [{ fileName: "sample.js", content: "console.log('test');" }],
|
|
203
|
+
};
|
|
204
|
+
|
|
205
|
+
mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
|
|
206
|
+
mockFs.existsSync.mockReturnValue(true);
|
|
207
|
+
mockParse.mockReturnValueOnce(mockSample);
|
|
208
|
+
mockResolveTemplate.mockReturnValue("resolved template");
|
|
209
|
+
mockParse.mockReturnValueOnce(mockData);
|
|
210
|
+
mockIsObject.mockReturnValue(true);
|
|
211
|
+
mockCompileSample.mockReturnValue(mockOutput);
|
|
212
|
+
mockCreateOutputDirectory.mockImplementation(() => {});
|
|
213
|
+
mockFs.writeFileSync.mockImplementation(() => {});
|
|
214
|
+
|
|
215
|
+
compile("sample", "data.json", "output", { project: true });
|
|
216
|
+
|
|
217
|
+
expect(mockCompileSample).toHaveBeenCalledWith(
|
|
218
|
+
{ ...mockSample, template: "resolved template" },
|
|
219
|
+
mockData,
|
|
220
|
+
{ project: true },
|
|
221
|
+
);
|
|
222
|
+
});
|
|
223
|
+
|
|
224
|
+
it("should default project option to false", () => {
|
|
225
|
+
const mockSample: Sample = {
|
|
226
|
+
template: "test template",
|
|
227
|
+
type: "javascript",
|
|
228
|
+
dependencies: [],
|
|
229
|
+
input: [],
|
|
230
|
+
};
|
|
231
|
+
const mockData = { name: "test" };
|
|
232
|
+
const mockOutput = {
|
|
233
|
+
items: [{ fileName: "sample.js", content: "console.log('test');" }],
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
|
|
237
|
+
mockFs.existsSync.mockReturnValue(true);
|
|
238
|
+
mockParse.mockReturnValueOnce(mockSample);
|
|
239
|
+
mockResolveTemplate.mockReturnValue("resolved template");
|
|
240
|
+
mockParse.mockReturnValueOnce(mockData);
|
|
241
|
+
mockIsObject.mockReturnValue(true);
|
|
242
|
+
mockCompileSample.mockReturnValue(mockOutput);
|
|
243
|
+
mockCreateOutputDirectory.mockImplementation(() => {});
|
|
244
|
+
mockFs.writeFileSync.mockImplementation(() => {});
|
|
245
|
+
|
|
246
|
+
compile("sample", "data.json", "output", {});
|
|
247
|
+
|
|
248
|
+
expect(mockCompileSample).toHaveBeenCalledWith(
|
|
249
|
+
{ ...mockSample, template: "resolved template" },
|
|
250
|
+
mockData,
|
|
251
|
+
{ project: false },
|
|
252
|
+
);
|
|
253
|
+
});
|
|
254
|
+
});
|
|
255
|
+
});
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
import { describe, it, expect, beforeEach, afterEach } from "vitest";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { tmpdir } from "os";
|
|
5
|
+
import {
|
|
6
|
+
parse,
|
|
7
|
+
resolveSampleFile,
|
|
8
|
+
isDirectory,
|
|
9
|
+
createOutputDirectory,
|
|
10
|
+
resolveTemplate,
|
|
11
|
+
isObject,
|
|
12
|
+
} from "../src/utils";
|
|
13
|
+
import { Sample } from "@caleuche/core";
|
|
14
|
+
|
|
15
|
+
function multiline(strings: TemplateStringsArray, ...values: any[]) {
|
|
16
|
+
let result = strings[0];
|
|
17
|
+
for (let i = 0; i < values.length; i++) {
|
|
18
|
+
result += values[i] + strings[i + 1];
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const lines = result.split("\n");
|
|
22
|
+
|
|
23
|
+
if (lines[0].trim() === "") lines.shift();
|
|
24
|
+
if (lines[lines.length - 1].trim() === "") lines.pop();
|
|
25
|
+
|
|
26
|
+
const nonEmptyLines = lines.filter((line) => line.trim() !== "");
|
|
27
|
+
if (nonEmptyLines.length === 0) return "";
|
|
28
|
+
|
|
29
|
+
const minIndent = Math.min(
|
|
30
|
+
...nonEmptyLines.map((line) => line.match(/^ */)?.[0].length || 0),
|
|
31
|
+
);
|
|
32
|
+
|
|
33
|
+
return lines.map((line) => line.slice(minIndent)).join("\n");
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
describe("utils", () => {
|
|
37
|
+
let tempDir: string;
|
|
38
|
+
|
|
39
|
+
beforeEach(() => {
|
|
40
|
+
tempDir = fs.mkdtempSync(path.join(tmpdir(), "caleuche-cli-test-"));
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
afterEach(() => {
|
|
44
|
+
if (fs.existsSync(tempDir)) {
|
|
45
|
+
fs.rmSync(tempDir, { recursive: true, force: true });
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
describe("parse", () => {
|
|
50
|
+
it("should parse valid JSON file", () => {
|
|
51
|
+
const jsonFile = path.join(tempDir, "test.json");
|
|
52
|
+
const testData = { name: "test", value: 42 };
|
|
53
|
+
fs.writeFileSync(jsonFile, JSON.stringify(testData));
|
|
54
|
+
|
|
55
|
+
const result = parse(jsonFile);
|
|
56
|
+
expect(result).toEqual(testData);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
it("should parse valid YAML file", () => {
|
|
60
|
+
const yamlFile = path.join(tempDir, "test.yaml");
|
|
61
|
+
const yamlContent = multiline`
|
|
62
|
+
name: test
|
|
63
|
+
value: 42`;
|
|
64
|
+
fs.writeFileSync(yamlFile, yamlContent);
|
|
65
|
+
|
|
66
|
+
const result = parse(yamlFile);
|
|
67
|
+
expect(result).toEqual({ name: "test", value: 42 });
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it("should parse valid YML file", () => {
|
|
71
|
+
const ymlFile = path.join(tempDir, "test.yml");
|
|
72
|
+
const ymlContent = multiline`
|
|
73
|
+
name: test
|
|
74
|
+
value: 42`;
|
|
75
|
+
fs.writeFileSync(ymlFile, ymlContent);
|
|
76
|
+
|
|
77
|
+
const result = parse(ymlFile);
|
|
78
|
+
expect(result).toEqual({ name: "test", value: 42 });
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
it("should return null for invalid JSON", () => {
|
|
82
|
+
const invalidJsonFile = path.join(tempDir, "invalid.json");
|
|
83
|
+
fs.writeFileSync(invalidJsonFile, "{ invalid json }");
|
|
84
|
+
|
|
85
|
+
const result = parse(invalidJsonFile);
|
|
86
|
+
expect(result).toBeNull();
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
it("should return null for invalid YAML", () => {
|
|
90
|
+
const invalidYamlFile = path.join(tempDir, "invalid.yaml");
|
|
91
|
+
fs.writeFileSync(
|
|
92
|
+
invalidYamlFile,
|
|
93
|
+
multiline`
|
|
94
|
+
invalid: yaml: structure:
|
|
95
|
+
broken
|
|
96
|
+
`,
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const result = parse(invalidYamlFile);
|
|
100
|
+
expect(result).toBeNull();
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("should return null for non-existent file", () => {
|
|
104
|
+
const nonExistentFile = path.join(tempDir, "nonexistent.json");
|
|
105
|
+
const result = parse(nonExistentFile);
|
|
106
|
+
expect(result).toBeNull();
|
|
107
|
+
});
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
describe("resolveSampleFile", () => {
|
|
111
|
+
it("should return the file path if it's a file", () => {
|
|
112
|
+
const filePath = path.join(tempDir, "sample.yaml");
|
|
113
|
+
fs.writeFileSync(filePath, "test content");
|
|
114
|
+
|
|
115
|
+
const result = resolveSampleFile(filePath);
|
|
116
|
+
expect(result).toBe(filePath);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
it("should return sample.yaml path if input is a directory", () => {
|
|
120
|
+
const dirPath = path.join(tempDir, "sample-dir");
|
|
121
|
+
fs.mkdirSync(dirPath);
|
|
122
|
+
|
|
123
|
+
const result = resolveSampleFile(dirPath);
|
|
124
|
+
expect(result).toBe(path.join(dirPath, "sample.yaml"));
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
it("should return the path as-is if it doesn't exist", () => {
|
|
128
|
+
const nonExistentPath = path.join(tempDir, "nonexistent");
|
|
129
|
+
|
|
130
|
+
const result = resolveSampleFile(nonExistentPath);
|
|
131
|
+
expect(result).toBe(nonExistentPath);
|
|
132
|
+
});
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
describe("isDirectory", () => {
|
|
136
|
+
it("should return true for directories", () => {
|
|
137
|
+
const dirPath = path.join(tempDir, "testdir");
|
|
138
|
+
fs.mkdirSync(dirPath);
|
|
139
|
+
|
|
140
|
+
expect(isDirectory(dirPath)).toBe(true);
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
it("should return false for files", () => {
|
|
144
|
+
const filePath = path.join(tempDir, "testfile.txt");
|
|
145
|
+
fs.writeFileSync(filePath, "test content");
|
|
146
|
+
|
|
147
|
+
expect(isDirectory(filePath)).toBe(false);
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it("should return false for non-existent paths", () => {
|
|
151
|
+
const nonExistentPath = path.join(tempDir, "nonexistent");
|
|
152
|
+
expect(isDirectory(nonExistentPath)).toBe(false);
|
|
153
|
+
});
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
describe("createOutputDirectory", () => {
|
|
157
|
+
it("should create directory if it doesn't exist", () => {
|
|
158
|
+
const newDir = path.join(tempDir, "new-output");
|
|
159
|
+
expect(fs.existsSync(newDir)).toBe(false);
|
|
160
|
+
|
|
161
|
+
createOutputDirectory(newDir);
|
|
162
|
+
expect(fs.existsSync(newDir)).toBe(true);
|
|
163
|
+
expect(fs.lstatSync(newDir).isDirectory()).toBe(true);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
it("should create nested directories", () => {
|
|
167
|
+
const nestedDir = path.join(tempDir, "nested", "output", "dir");
|
|
168
|
+
expect(fs.existsSync(nestedDir)).toBe(false);
|
|
169
|
+
|
|
170
|
+
createOutputDirectory(nestedDir);
|
|
171
|
+
expect(fs.existsSync(nestedDir)).toBe(true);
|
|
172
|
+
expect(fs.lstatSync(nestedDir).isDirectory()).toBe(true);
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
it("should not throw if directory already exists", () => {
|
|
176
|
+
const existingDir = path.join(tempDir, "existing");
|
|
177
|
+
fs.mkdirSync(existingDir);
|
|
178
|
+
|
|
179
|
+
expect(() => createOutputDirectory(existingDir)).not.toThrow();
|
|
180
|
+
});
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
describe("resolveTemplate", () => {
|
|
184
|
+
it("should read template file from sample directory", () => {
|
|
185
|
+
const sampleDir = path.join(tempDir, "sample");
|
|
186
|
+
fs.mkdirSync(sampleDir);
|
|
187
|
+
|
|
188
|
+
const templateContent = "Hello, <%= name %>!";
|
|
189
|
+
const templateFile = path.join(sampleDir, "template.txt");
|
|
190
|
+
fs.writeFileSync(templateFile, templateContent);
|
|
191
|
+
|
|
192
|
+
const sample: Sample = {
|
|
193
|
+
template: "template.txt",
|
|
194
|
+
type: "javascript",
|
|
195
|
+
dependencies: [],
|
|
196
|
+
input: [],
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
const result = resolveTemplate(sampleDir, sample);
|
|
200
|
+
expect(result).toBe(templateContent);
|
|
201
|
+
});
|
|
202
|
+
|
|
203
|
+
it("should return template string if file doesn't exist", () => {
|
|
204
|
+
const sampleDir = path.join(tempDir, "sample");
|
|
205
|
+
fs.mkdirSync(sampleDir);
|
|
206
|
+
|
|
207
|
+
const sample: Sample = {
|
|
208
|
+
template: "inline template content",
|
|
209
|
+
type: "javascript",
|
|
210
|
+
dependencies: [],
|
|
211
|
+
input: [],
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
const result = resolveTemplate(sampleDir, sample);
|
|
215
|
+
expect(result).toBe("inline template content");
|
|
216
|
+
});
|
|
217
|
+
|
|
218
|
+
it("should handle template files with various extensions", () => {
|
|
219
|
+
const sampleDir = path.join(tempDir, "sample");
|
|
220
|
+
fs.mkdirSync(sampleDir);
|
|
221
|
+
|
|
222
|
+
const templateContent = "function test() { return 'hello'; }";
|
|
223
|
+
const templateFile = path.join(sampleDir, "template.js");
|
|
224
|
+
fs.writeFileSync(templateFile, templateContent);
|
|
225
|
+
|
|
226
|
+
const sample: Sample = {
|
|
227
|
+
template: "template.js",
|
|
228
|
+
type: "javascript",
|
|
229
|
+
dependencies: [],
|
|
230
|
+
input: [],
|
|
231
|
+
};
|
|
232
|
+
|
|
233
|
+
const result = resolveTemplate(sampleDir, sample);
|
|
234
|
+
expect(result).toBe(templateContent);
|
|
235
|
+
});
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
describe("isObject", () => {
|
|
239
|
+
it("should return true for plain objects", () => {
|
|
240
|
+
expect(isObject({})).toBe(true);
|
|
241
|
+
expect(isObject({ a: 1, b: 2 })).toBe(true);
|
|
242
|
+
expect(isObject({ nested: { object: true } })).toBe(true);
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
it("should return false for arrays", () => {
|
|
246
|
+
expect(isObject([])).toBe(false);
|
|
247
|
+
expect(isObject([1, 2, 3])).toBe(false);
|
|
248
|
+
expect(isObject([{}])).toBe(false);
|
|
249
|
+
});
|
|
250
|
+
|
|
251
|
+
it("should return false for null", () => {
|
|
252
|
+
expect(isObject(null)).toBe(false);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it("should return false for primitives", () => {
|
|
256
|
+
expect(isObject("string")).toBe(false);
|
|
257
|
+
expect(isObject(42)).toBe(false);
|
|
258
|
+
expect(isObject(true)).toBe(false);
|
|
259
|
+
expect(isObject(undefined)).toBe(false);
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
it("should return false for functions", () => {
|
|
263
|
+
expect(isObject(() => {})).toBe(false);
|
|
264
|
+
expect(isObject(function () {})).toBe(false);
|
|
265
|
+
});
|
|
266
|
+
});
|
|
267
|
+
});
|
package/tsconfig.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "es2020",
|
|
4
|
-
"module": "commonjs",
|
|
5
|
-
"outDir": "dist",
|
|
6
|
-
"rootDir": "src",
|
|
7
|
-
"strict": true,
|
|
8
|
-
"esModuleInterop": true
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2020",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"outDir": "dist",
|
|
6
|
+
"rootDir": "src",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"resolveJsonModule": true
|
|
10
|
+
},
|
|
11
|
+
"include": ["src/**/*"]
|
|
12
|
+
}
|