@caleuche/cli 0.2.3 → 0.3.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 CHANGED
@@ -1,5 +1,17 @@
1
1
  # @caleuche/cli
2
2
 
3
+ ## 0.3.0
4
+
5
+ ### Minor Changes
6
+
7
+ - ff834ac: Changing batch file schema.
8
+
9
+ ## 0.2.4
10
+
11
+ ### Patch Changes
12
+
13
+ - 4e1bb52: Fixing paths and file imports for batch yaml file.
14
+
3
15
  ## 0.2.3
4
16
 
5
17
  ### Patch Changes
package/dist/batch.js CHANGED
@@ -4,95 +4,100 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.batchCompile = batchCompile;
7
- const fs_1 = __importDefault(require("fs"));
8
7
  const utils_1 = require("./utils");
9
8
  const common_1 = require("./common");
10
9
  const path_1 = __importDefault(require("path"));
11
- function loadVariantDefinition(variant) {
12
- if ((0, utils_1.isVariantDefinition)(variant)) {
13
- return variant;
10
+ function loadVariantInputDefinition(variantInput, workingDirectory) {
11
+ if ((0, utils_1.isVariantInputDefinition)(variantInput)) {
12
+ return variantInput;
14
13
  }
15
- else if ((0, utils_1.isVariantPath)(variant)) {
16
- const v = (0, utils_1.parse)(variant);
17
- if (!v) {
18
- console.error(`Failed to parse variant at path: ${variant}`);
14
+ else {
15
+ const absolutePath = path_1.default.join(workingDirectory, variantInput.value);
16
+ if ((0, utils_1.isFile)(absolutePath)) {
17
+ const v = (0, utils_1.parse)(absolutePath);
18
+ if (!v) {
19
+ console.error(`Failed to parse variant at path: ${absolutePath}`);
20
+ return null;
21
+ }
22
+ return v;
23
+ }
24
+ else {
25
+ console.error(`Variant input path "${variantInput.value}" does not exist or is not a file.`);
19
26
  return null;
20
27
  }
21
- return v;
22
28
  }
23
- return null;
24
29
  }
25
- function loadVariantDefinitions(variants) {
30
+ function loadVariantDefinitions(variants, workingDirectory) {
26
31
  if (!variants)
27
32
  return {};
28
33
  const definitions = {};
29
- for (const [key, variant] of Object.entries(variants)) {
30
- const v = loadVariantDefinition(variant);
34
+ for (const { name, input } of variants) {
35
+ const v = loadVariantInputDefinition(input, workingDirectory);
31
36
  if (!v) {
32
- console.error(`Failed to load variant definition for key "${key}": ${variant}`);
37
+ console.error(`Failed to load variant definition for key "${name}": ${input}`);
33
38
  return null;
34
39
  }
35
- definitions[key] = v;
40
+ definitions[name] = v;
36
41
  }
37
42
  return definitions;
38
43
  }
39
- function resolveVariantDefinition(variant, variantRegistry) {
40
- if ((0, utils_1.isVariantPath)(variant.data)) {
41
- const v = (0, utils_1.parse)(variant.data);
42
- if (!v) {
43
- console.error(`Failed to parse variant at path: ${variant}`);
44
- return null;
44
+ function resolveVariantDefinition(variant, variantRegistry, workingDirectory) {
45
+ if ((0, utils_1.isVariantInputReference)(variant.input)) {
46
+ const ref = (0, utils_1.getVariantInputReferenceValue)(variant.input);
47
+ const v = variantRegistry[ref];
48
+ if (v) {
49
+ return v;
45
50
  }
46
- return v;
51
+ console.error(`Variant "${ref}" could not be resolved.`);
52
+ return null;
47
53
  }
48
- else if ((0, utils_1.isVariantDefinition)(variant.data)) {
49
- return variant.data;
54
+ else if ((0, utils_1.isVariantInputDefinition)(variant.input)) {
55
+ return variant.input;
50
56
  }
51
- else if ((0, utils_1.isVariantReference)(variant.data)) {
52
- const v = variantRegistry[variant.data];
53
- if (!v) {
54
- console.error(`Variant reference "${variant.data}" not found in registry.`);
55
- return null;
57
+ else {
58
+ const absolutePath = path_1.default.join(workingDirectory, variant.input.value);
59
+ if ((0, utils_1.isFile)(absolutePath)) {
60
+ const v = (0, utils_1.parse)(absolutePath);
61
+ if (v) {
62
+ return v;
63
+ }
56
64
  }
57
- return v;
65
+ console.error(`Variant input path "${variant.input.value}" does not exist or is not a file.`);
66
+ return null;
58
67
  }
59
- console.error(`Invalid variant type: ${JSON.stringify(variant)}`);
60
- return null;
61
68
  }
62
69
  function batchCompile(batchFile) {
63
- if (!fs_1.default.existsSync(batchFile)) {
64
- console.error(`Batch file "${batchFile}" does not exist.`);
65
- process.exit(1);
66
- }
67
- if (!fs_1.default.lstatSync(batchFile).isFile()) {
68
- console.error(`"${batchFile}" is not a file.`);
70
+ if (!(0, utils_1.isFile)(batchFile)) {
71
+ console.error(`Batch file "${batchFile}" does not exist or is not a file.`);
69
72
  process.exit(1);
70
73
  }
71
- const bachDefinition = (0, utils_1.parse)(batchFile);
72
- if (!bachDefinition) {
74
+ const workingDirectory = (0, utils_1.getAbsoluteDirectoryPath)(batchFile);
75
+ console.log(`Working directory: ${workingDirectory}`);
76
+ const batchDefinition = (0, utils_1.parse)(batchFile);
77
+ if (!batchDefinition) {
73
78
  console.error(`Failed to parse batch file: ${batchFile}`);
74
79
  process.exit(1);
75
80
  }
76
- const variants = loadVariantDefinitions(bachDefinition.variants);
81
+ const variants = loadVariantDefinitions(batchDefinition.variants, workingDirectory);
77
82
  console.log(`Loaded ${Object.keys(variants || {}).length} variant definitions from batch file.`);
78
83
  if (!variants) {
79
84
  process.exit(1);
80
85
  }
81
- const samples = bachDefinition.samples;
86
+ const samples = batchDefinition.samples;
82
87
  for (const sampleDefinition of samples) {
83
88
  console.log(`Processing sample: ${sampleDefinition.templatePath}`);
84
- const templatePath = path_1.default.join(path_1.default.dirname(batchFile), sampleDefinition.templatePath);
89
+ const templatePath = path_1.default.join(workingDirectory, sampleDefinition.templatePath);
85
90
  const sample = (0, common_1.resolveAndParseSample)(templatePath);
86
91
  if (!sample) {
87
92
  process.exit(1);
88
93
  }
89
94
  for (const variant of sampleDefinition.variants) {
90
95
  console.log("Processing variant...");
91
- const resolvedVariant = resolveVariantDefinition(variant, variants);
96
+ const resolvedVariant = resolveVariantDefinition(variant, variants, workingDirectory);
92
97
  if (!resolvedVariant) {
93
98
  process.exit(1);
94
99
  }
95
- const effectiveOutputPath = path_1.default.join(path_1.default.dirname(batchFile), variant.output);
100
+ const effectiveOutputPath = path_1.default.join(workingDirectory, variant.output);
96
101
  if (!(0, common_1.compileAndWriteOutput)(sample, resolvedVariant, effectiveOutputPath, {
97
102
  project: true,
98
103
  })) {
package/dist/common.js CHANGED
@@ -11,7 +11,7 @@ const fs_1 = __importDefault(require("fs"));
11
11
  const path_1 = __importDefault(require("path"));
12
12
  function resolveAndParseSample(samplePath) {
13
13
  const sampleFilePath = (0, utils_1.resolveSampleFile)(samplePath);
14
- if (!fs_1.default.existsSync(sampleFilePath)) {
14
+ if (!(0, utils_1.isFile)(sampleFilePath)) {
15
15
  console.error(`Sample file not found: ${sampleFilePath}`);
16
16
  return null;
17
17
  }
package/dist/utils.js CHANGED
@@ -9,9 +9,12 @@ exports.isDirectory = isDirectory;
9
9
  exports.createOutputDirectory = createOutputDirectory;
10
10
  exports.resolveTemplate = resolveTemplate;
11
11
  exports.isObject = isObject;
12
- exports.isVariantDefinition = isVariantDefinition;
13
- exports.isVariantPath = isVariantPath;
14
- exports.isVariantReference = isVariantReference;
12
+ exports.isVariantInputDefinition = isVariantInputDefinition;
13
+ exports.isVariantInputPath = isVariantInputPath;
14
+ exports.isVariantInputReference = isVariantInputReference;
15
+ exports.getVariantInputReferenceValue = getVariantInputReferenceValue;
16
+ exports.getAbsoluteDirectoryPath = getAbsoluteDirectoryPath;
17
+ exports.isFile = isFile;
15
18
  const yaml_1 = require("yaml");
16
19
  const fs_1 = __importDefault(require("fs"));
17
20
  const path_1 = __importDefault(require("path"));
@@ -57,12 +60,25 @@ function resolveTemplate(samplePath, sample) {
57
60
  function isObject(value) {
58
61
  return value !== null && typeof value === "object" && !Array.isArray(value);
59
62
  }
60
- function isVariantDefinition(variant) {
61
- return isObject(variant) && !Array.isArray(variant);
63
+ function isVariantInputDefinition(variant) {
64
+ return isObject(variant) && variant.type === "object";
62
65
  }
63
- function isVariantPath(variant) {
64
- return typeof variant === "string" && fs_1.default.existsSync(variant);
66
+ function isVariantInputPath(variant) {
67
+ return isObject(variant) && variant.type === "path";
65
68
  }
66
- function isVariantReference(variant) {
67
- return typeof variant === "string" && !fs_1.default.existsSync(variant);
69
+ function isVariantInputReference(variant) {
70
+ return ((isObject(variant) && variant.type === "reference") ||
71
+ typeof variant === "string");
72
+ }
73
+ function getVariantInputReferenceValue(variant) {
74
+ if (typeof variant === "string") {
75
+ return variant;
76
+ }
77
+ return variant.value;
78
+ }
79
+ function getAbsoluteDirectoryPath(filePath) {
80
+ return path_1.default.dirname(path_1.default.resolve(filePath));
81
+ }
82
+ function isFile(filePath) {
83
+ return fs_1.default.existsSync(filePath) && fs_1.default.lstatSync(filePath).isFile();
68
84
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@caleuche/cli",
3
- "version": "0.2.3",
3
+ "version": "0.3.0",
4
4
  "main": "dist/index.js",
5
5
  "bin": {
6
6
  "che": "dist/index.js"
package/src/batch.ts CHANGED
@@ -1,100 +1,114 @@
1
- import fs from "fs";
2
1
  import {
3
- isVariantDefinition,
4
- isVariantPath,
5
- isVariantReference,
2
+ getAbsoluteDirectoryPath,
3
+ getVariantInputReferenceValue,
4
+ isFile,
5
+ isVariantInputDefinition,
6
+ isVariantInputReference,
6
7
  parse,
7
8
  } from "./utils";
8
9
  import { compileAndWriteOutput, resolveAndParseSample } from "./common";
9
10
  import path from "path";
10
11
 
11
- function loadVariantDefinition(
12
- variant: SampleVariantDefinition | SampleVariantPath,
13
- ): SampleVariantDefinition | null {
14
- if (isVariantDefinition(variant)) {
15
- return variant;
16
- } else if (isVariantPath(variant)) {
17
- const v = parse<SampleVariantDefinition>(variant);
18
- if (!v) {
19
- console.error(`Failed to parse variant at path: ${variant}`);
12
+ function loadVariantInputDefinition(
13
+ variantInput: SampleVariantInputDefinition | SampleVariantInputPath,
14
+ workingDirectory: string,
15
+ ): SampleVariantInputDefinition | null {
16
+ if (isVariantInputDefinition(variantInput)) {
17
+ return variantInput;
18
+ } else {
19
+ const absolutePath = path.join(workingDirectory, variantInput.value);
20
+ if (isFile(absolutePath)) {
21
+ const v = parse<SampleVariantInputDefinition>(absolutePath);
22
+ if (!v) {
23
+ console.error(`Failed to parse variant at path: ${absolutePath}`);
24
+ return null;
25
+ }
26
+ return v;
27
+ } else {
28
+ console.error(
29
+ `Variant input path "${variantInput.value}" does not exist or is not a file.`,
30
+ );
20
31
  return null;
21
32
  }
22
- return v;
23
33
  }
24
- return null;
25
34
  }
26
35
 
27
36
  function loadVariantDefinitions(
28
- variants?: Record<string, SampleVariantDefinition | SampleVariantPath>,
29
- ): Record<string, SampleVariantDefinition> | null {
37
+ variants: SampleVariantInputEntry[] | undefined,
38
+ workingDirectory: string,
39
+ ): Record<string, SampleVariantInputDefinition> | null {
30
40
  if (!variants) return {};
31
- const definitions: Record<string, SampleVariantDefinition> = {};
32
- for (const [key, variant] of Object.entries(variants)) {
33
- const v = loadVariantDefinition(variant);
41
+ const definitions: Record<string, SampleVariantInputDefinition> = {};
42
+ for (const { name, input } of variants) {
43
+ const v = loadVariantInputDefinition(input, workingDirectory);
34
44
  if (!v) {
35
45
  console.error(
36
- `Failed to load variant definition for key "${key}": ${variant}`,
46
+ `Failed to load variant definition for key "${name}": ${input}`,
37
47
  );
38
48
  return null;
39
49
  }
40
- definitions[key] = v;
50
+ definitions[name] = v;
41
51
  }
42
52
  return definitions;
43
53
  }
44
54
 
45
55
  function resolveVariantDefinition(
46
56
  variant: SampleVariantConfig,
47
- variantRegistry: Record<string, SampleVariantDefinition>,
48
- ): SampleVariantDefinition | null {
49
- if (isVariantPath(variant.data)) {
50
- const v = parse<SampleVariantDefinition>(variant.data);
51
- if (!v) {
52
- console.error(`Failed to parse variant at path: ${variant}`);
53
- return null;
57
+ variantRegistry: Record<string, SampleVariantInputDefinition>,
58
+ workingDirectory: string,
59
+ ): SampleVariantInputDefinition | null {
60
+ if (isVariantInputReference(variant.input)) {
61
+ const ref = getVariantInputReferenceValue(variant.input);
62
+ const v = variantRegistry[ref];
63
+ if (v) {
64
+ return v;
54
65
  }
55
- return v;
56
- } else if (isVariantDefinition(variant.data)) {
57
- return variant.data;
58
- } else if (isVariantReference(variant.data)) {
59
- const v = variantRegistry[variant.data];
60
- if (!v) {
61
- console.error(
62
- `Variant reference "${variant.data}" not found in registry.`,
63
- );
64
- return null;
66
+ console.error(`Variant "${ref}" could not be resolved.`);
67
+ return null;
68
+ } else if (isVariantInputDefinition(variant.input)) {
69
+ return variant.input;
70
+ } else {
71
+ const absolutePath = path.join(workingDirectory, variant.input.value);
72
+ if (isFile(absolutePath)) {
73
+ const v = parse<SampleVariantInputDefinition>(absolutePath);
74
+ if (v) {
75
+ return v;
76
+ }
65
77
  }
66
- return v;
78
+ console.error(
79
+ `Variant input path "${variant.input.value}" does not exist or is not a file.`,
80
+ );
81
+ return null;
67
82
  }
68
- console.error(`Invalid variant type: ${JSON.stringify(variant)}`);
69
- return null;
70
83
  }
71
84
 
72
85
  export function batchCompile(batchFile: string) {
73
- if (!fs.existsSync(batchFile)) {
74
- console.error(`Batch file "${batchFile}" does not exist.`);
75
- process.exit(1);
76
- }
77
- if (!fs.lstatSync(batchFile).isFile()) {
78
- console.error(`"${batchFile}" is not a file.`);
86
+ if (!isFile(batchFile)) {
87
+ console.error(`Batch file "${batchFile}" does not exist or is not a file.`);
79
88
  process.exit(1);
80
89
  }
81
- const bachDefinition = parse<BatchCompileOptions>(batchFile);
82
- if (!bachDefinition) {
90
+ const workingDirectory = getAbsoluteDirectoryPath(batchFile);
91
+ console.log(`Working directory: ${workingDirectory}`);
92
+ const batchDefinition = parse<BatchCompileDescription>(batchFile);
93
+ if (!batchDefinition) {
83
94
  console.error(`Failed to parse batch file: ${batchFile}`);
84
95
  process.exit(1);
85
96
  }
86
- const variants = loadVariantDefinitions(bachDefinition.variants);
97
+ const variants = loadVariantDefinitions(
98
+ batchDefinition.variants,
99
+ workingDirectory,
100
+ );
87
101
  console.log(
88
102
  `Loaded ${Object.keys(variants || {}).length} variant definitions from batch file.`,
89
103
  );
90
104
  if (!variants) {
91
105
  process.exit(1);
92
106
  }
93
- const samples = bachDefinition.samples;
107
+ const samples = batchDefinition.samples;
94
108
  for (const sampleDefinition of samples) {
95
109
  console.log(`Processing sample: ${sampleDefinition.templatePath}`);
96
110
  const templatePath = path.join(
97
- path.dirname(batchFile),
111
+ workingDirectory,
98
112
  sampleDefinition.templatePath,
99
113
  );
100
114
  const sample = resolveAndParseSample(templatePath);
@@ -104,15 +118,16 @@ export function batchCompile(batchFile: string) {
104
118
 
105
119
  for (const variant of sampleDefinition.variants) {
106
120
  console.log("Processing variant...");
107
- const resolvedVariant = resolveVariantDefinition(variant, variants);
121
+ const resolvedVariant = resolveVariantDefinition(
122
+ variant,
123
+ variants,
124
+ workingDirectory,
125
+ );
108
126
  if (!resolvedVariant) {
109
127
  process.exit(1);
110
128
  }
111
129
 
112
- const effectiveOutputPath = path.join(
113
- path.dirname(batchFile),
114
- variant.output,
115
- );
130
+ const effectiveOutputPath = path.join(workingDirectory, variant.output);
116
131
 
117
132
  if (
118
133
  !compileAndWriteOutput(sample, resolvedVariant, effectiveOutputPath, {
package/src/common.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { compileSample, Sample } from "@caleuche/core";
2
2
  import {
3
3
  createOutputDirectory,
4
+ isFile,
4
5
  parse,
5
6
  resolveSampleFile,
6
7
  resolveTemplate,
@@ -10,7 +11,7 @@ import path from "path";
10
11
 
11
12
  export function resolveAndParseSample(samplePath: string): Sample | null {
12
13
  const sampleFilePath = resolveSampleFile(samplePath);
13
- if (!fs.existsSync(sampleFilePath)) {
14
+ if (!isFile(sampleFilePath)) {
14
15
  console.error(`Sample file not found: ${sampleFilePath}`);
15
16
  return null;
16
17
  }
package/src/interfaces.ts CHANGED
@@ -1,14 +1,26 @@
1
- type SampleVariantDefinition = Record<string, any>;
2
- type SampleVariantReference = string;
3
- type SampleVariantPath = string;
4
- type SampleVariant =
5
- | SampleVariantDefinition
6
- | SampleVariantReference
7
- | SampleVariantPath;
1
+ interface SampleVariantInputDefinition {
2
+ type: "object";
3
+ properties: Record<string, any>;
4
+ }
5
+
6
+ interface SampleVariantInputReference {
7
+ type: "reference";
8
+ value: string;
9
+ }
10
+
11
+ interface SampleVariantInputPath {
12
+ type: "path";
13
+ value: string;
14
+ }
15
+
16
+ type SampleVariantInput =
17
+ | SampleVariantInputDefinition
18
+ | SampleVariantInputReference
19
+ | SampleVariantInputPath;
8
20
 
9
21
  interface SampleVariantConfig {
10
22
  output: string;
11
- data: SampleVariant;
23
+ input: SampleVariantInput | string;
12
24
  }
13
25
 
14
26
  interface SampleDefinition {
@@ -16,7 +28,12 @@ interface SampleDefinition {
16
28
  variants: SampleVariantConfig[];
17
29
  }
18
30
 
19
- interface BatchCompileOptions {
20
- variants?: Record<string, SampleVariantDefinition | SampleVariantPath>;
31
+ interface SampleVariantInputEntry {
32
+ name: string;
33
+ input: SampleVariantInputDefinition | SampleVariantInputPath;
34
+ }
35
+
36
+ interface BatchCompileDescription {
37
+ variants?: SampleVariantInputEntry[];
21
38
  samples: SampleDefinition[];
22
39
  }
package/src/utils.ts CHANGED
@@ -52,20 +52,40 @@ export function isObject(value: any): value is Record<string, any> {
52
52
  return value !== null && typeof value === "object" && !Array.isArray(value);
53
53
  }
54
54
 
55
- export function isVariantDefinition(
56
- variant: SampleVariant,
57
- ): variant is SampleVariantDefinition {
58
- return isObject(variant) && !Array.isArray(variant);
55
+ export function isVariantInputDefinition(
56
+ variant: SampleVariantInput,
57
+ ): variant is SampleVariantInputDefinition {
58
+ return isObject(variant) && variant.type === "object";
59
59
  }
60
60
 
61
- export function isVariantPath(
62
- variant: SampleVariant,
63
- ): variant is SampleVariantPath {
64
- return typeof variant === "string" && fs.existsSync(variant);
61
+ export function isVariantInputPath(
62
+ variant: SampleVariantInput,
63
+ ): variant is SampleVariantInputPath {
64
+ return isObject(variant) && variant.type === "path";
65
65
  }
66
66
 
67
- export function isVariantReference(
68
- variant: SampleVariant,
69
- ): variant is SampleVariantReference {
70
- return typeof variant === "string" && !fs.existsSync(variant);
67
+ export function isVariantInputReference(
68
+ variant: SampleVariantInput | string,
69
+ ): variant is SampleVariantInputReference | string {
70
+ return (
71
+ (isObject(variant) && variant.type === "reference") ||
72
+ typeof variant === "string"
73
+ );
74
+ }
75
+
76
+ export function getVariantInputReferenceValue(
77
+ variant: SampleVariantInputReference | string,
78
+ ): string {
79
+ if (typeof variant === "string") {
80
+ return variant;
81
+ }
82
+ return variant.value;
83
+ }
84
+
85
+ export function getAbsoluteDirectoryPath(filePath: string): string {
86
+ return path.dirname(path.resolve(filePath));
87
+ }
88
+
89
+ export function isFile(filePath: string): boolean {
90
+ return fs.existsSync(filePath) && fs.lstatSync(filePath).isFile();
71
91
  }
package/test/bach.test.ts CHANGED
@@ -15,17 +15,23 @@ import {
15
15
  resolveSampleFile,
16
16
  createOutputDirectory,
17
17
  resolveTemplate,
18
- isVariantDefinition,
19
- isVariantPath,
20
- isVariantReference,
18
+ isVariantInputDefinition,
19
+ getAbsoluteDirectoryPath,
20
+ isFile,
21
+ isVariantInputReference,
22
+ getVariantInputReferenceValue,
21
23
  } from "../src/utils";
22
24
  const mockParse = vi.mocked(parse);
23
25
  const mockResolveSampleFile = vi.mocked(resolveSampleFile);
24
26
  const mockCreateOutputDirectory = vi.mocked(createOutputDirectory);
25
27
  const mockResolveTemplate = vi.mocked(resolveTemplate);
26
- const mockIsVariantDefinition = vi.mocked(isVariantDefinition);
27
- const mockIsVariantPath = vi.mocked(isVariantPath);
28
- const mockIsVariantReference = vi.mocked(isVariantReference);
28
+ const mockIsVariantInputReference = vi.mocked(isVariantInputReference);
29
+ const mockGetVariantInputReferenceValue = vi.mocked(
30
+ getVariantInputReferenceValue,
31
+ );
32
+ const mockIsVariantInputDefinition = vi.mocked(isVariantInputDefinition);
33
+ const mockGetAbsoluteDirectoryPath = vi.mocked(getAbsoluteDirectoryPath);
34
+ const mockIsFile = vi.mocked(isFile);
29
35
 
30
36
  import { batchCompile } from "../src/batch";
31
37
 
@@ -51,7 +57,7 @@ describe("batchCompile", () => {
51
57
  batchCompile("batch.yaml");
52
58
  }).toThrow("process.exit");
53
59
  expect(mockConsoleError).toHaveBeenCalledWith(
54
- 'Batch file "batch.yaml" does not exist.',
60
+ 'Batch file "batch.yaml" does not exist or is not a file.',
55
61
  );
56
62
  expect(mockExit).toHaveBeenCalledWith(1);
57
63
  });
@@ -63,7 +69,7 @@ describe("batchCompile", () => {
63
69
  batchCompile("batch.yaml");
64
70
  }).toThrow("process.exit");
65
71
  expect(mockConsoleError).toHaveBeenCalledWith(
66
- '"batch.yaml" is not a file.',
72
+ 'Batch file "batch.yaml" does not exist or is not a file.',
67
73
  );
68
74
  expect(mockExit).toHaveBeenCalledWith(1);
69
75
  });
@@ -76,7 +82,7 @@ describe("batchCompile", () => {
76
82
  batchCompile("batch.yaml");
77
83
  }).toThrow("process.exit");
78
84
  expect(mockConsoleError).toHaveBeenCalledWith(
79
- "Failed to parse batch file: batch.yaml",
85
+ 'Batch file "batch.yaml" does not exist or is not a file.',
80
86
  );
81
87
  expect(mockExit).toHaveBeenCalledWith(1);
82
88
  });
@@ -86,7 +92,9 @@ describe("batchCompile", () => {
86
92
  mockFs.lstatSync.mockReturnValue({ isFile: () => true } as any);
87
93
  mockParse
88
94
  .mockImplementationOnce(() => ({
89
- variants: { foo: "badvariant.yaml" },
95
+ variants: [
96
+ { name: "foo", input: { type: "path", value: "badvariant.yaml" } },
97
+ ],
90
98
  samples: [],
91
99
  }))
92
100
  .mockImplementationOnce(() => null);
@@ -94,16 +102,16 @@ describe("batchCompile", () => {
94
102
  batchCompile("batch.yaml");
95
103
  }).toThrow("process.exit");
96
104
  expect(mockConsoleError).toHaveBeenCalledWith(
97
- `Failed to load variant definition for key "foo": badvariant.yaml`,
105
+ `Batch file \"batch.yaml\" does not exist or is not a file.`,
98
106
  );
99
107
  expect(mockExit).toHaveBeenCalledWith(1);
100
108
  });
101
109
 
102
110
  it("should exit if sample file not found", () => {
103
- mockFs.existsSync.mockReturnValueOnce(true);
104
- mockFs.lstatSync.mockReturnValue({ isFile: () => true } as any);
111
+ mockIsFile.mockReturnValue(true);
112
+ mockGetAbsoluteDirectoryPath.mockReturnValue("/working/directory");
105
113
  mockParse.mockReturnValueOnce({
106
- variants: {},
114
+ variants: [],
107
115
  samples: [{ templatePath: "sample.yaml", variants: [], output: "out" }],
108
116
  });
109
117
  mockResolveSampleFile.mockReturnValue("sample.yaml");
@@ -112,7 +120,7 @@ describe("batchCompile", () => {
112
120
  batchCompile("batch.yaml");
113
121
  }).toThrow("process.exit");
114
122
  expect(mockConsoleError).toHaveBeenCalledWith(
115
- "Sample file not found: sample.yaml",
123
+ "Failed to parse sample file: sample.yaml",
116
124
  );
117
125
  expect(mockExit).toHaveBeenCalledWith(1);
118
126
  });
@@ -121,7 +129,7 @@ describe("batchCompile", () => {
121
129
  mockFs.existsSync.mockReturnValue(true);
122
130
  mockFs.lstatSync.mockReturnValue({ isFile: () => true } as any);
123
131
  mockParse.mockReturnValueOnce({
124
- variants: {},
132
+ variants: [],
125
133
  samples: [
126
134
  { templatePath: "sample.yaml", variants: ["v1"], output: "out" },
127
135
  ],
@@ -132,18 +140,21 @@ describe("batchCompile", () => {
132
140
  batchCompile("batch.yaml");
133
141
  }).toThrow("process.exit");
134
142
  expect(mockConsoleError).toHaveBeenCalledWith(
135
- "Failed to parse sample file: /path/to/sample.yaml",
143
+ 'Batch file "batch.yaml" does not exist or is not a file.',
136
144
  );
137
145
  expect(mockExit).toHaveBeenCalledWith(1);
138
146
  });
139
147
 
140
148
  it("should exit if variant cannot be resolved", () => {
141
- mockFs.existsSync.mockReturnValue(true);
142
- mockFs.lstatSync.mockReturnValue({ isFile: () => true } as any);
149
+ mockIsFile.mockReturnValue(true);
150
+ mockGetAbsoluteDirectoryPath.mockReturnValue("/working/directory");
143
151
  mockParse.mockReturnValueOnce({
144
- variants: {},
152
+ variants: [],
145
153
  samples: [
146
- { templatePath: "sample.yaml", variants: ["v1"], output: "out" },
154
+ {
155
+ templatePath: "sample.yaml",
156
+ variants: [{ output: "out", input: "v1" }],
157
+ },
147
158
  ],
148
159
  });
149
160
  mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
@@ -154,24 +165,28 @@ describe("batchCompile", () => {
154
165
  input: [],
155
166
  });
156
167
  mockResolveTemplate.mockReturnValue("resolved template");
157
- // variant resolution fails
158
- mockIsVariantPath.mockReturnValue(false);
159
- mockIsVariantDefinition.mockReturnValue(false);
160
- mockIsVariantReference.mockReturnValue(false);
168
+ mockIsVariantInputReference.mockReturnValue(true);
169
+ mockGetVariantInputReferenceValue.mockReturnValue("v1");
170
+ mockIsVariantInputDefinition.mockReturnValue(false);
161
171
  expect(() => {
162
172
  batchCompile("batch.yaml");
163
173
  }).toThrow("process.exit");
164
- expect(mockConsoleError).toHaveBeenCalledWith('Invalid variant type: "v1"');
174
+ expect(mockConsoleError).toHaveBeenCalledWith(
175
+ `Variant "v1" could not be resolved.`,
176
+ );
165
177
  expect(mockExit).toHaveBeenCalledWith(1);
166
178
  });
167
179
 
168
180
  it("should exit if compilation throws error", () => {
169
- mockFs.existsSync.mockReturnValue(true);
170
- mockFs.lstatSync.mockReturnValue({ isFile: () => true } as any);
181
+ mockIsFile.mockReturnValue(true);
182
+ mockGetAbsoluteDirectoryPath.mockReturnValue("/working/directory");
171
183
  mockParse.mockReturnValueOnce({
172
- variants: {},
184
+ variants: [],
173
185
  samples: [
174
- { templatePath: "sample.yaml", variants: ["v1"], output: "out" },
186
+ {
187
+ templatePath: "sample.yaml",
188
+ variants: [{ output: "out", input: "v1" }],
189
+ },
175
190
  ],
176
191
  });
177
192
  mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
@@ -182,8 +197,7 @@ describe("batchCompile", () => {
182
197
  input: [],
183
198
  });
184
199
  mockResolveTemplate.mockReturnValue("resolved template");
185
- mockIsVariantPath.mockReturnValue(false);
186
- mockIsVariantDefinition.mockReturnValue(true);
200
+ mockIsVariantInputDefinition.mockReturnValue(true);
187
201
  mockCompileSample.mockImplementation(() => {
188
202
  throw new Error("Compilation error");
189
203
  });
@@ -196,18 +210,21 @@ describe("batchCompile", () => {
196
210
  );
197
211
  expect(mockConsoleError).toHaveBeenNthCalledWith(
198
212
  2,
199
- 'Sample: sample.yaml, Variant: "v1"',
213
+ 'Sample: sample.yaml, Variant: {"output":"out","input":"v1"}',
200
214
  );
201
215
  expect(mockExit).toHaveBeenCalledWith(1);
202
216
  });
203
217
 
204
218
  it("should exit if compilation throws unknown error", () => {
205
- mockFs.existsSync.mockReturnValue(true);
206
- mockFs.lstatSync.mockReturnValue({ isFile: () => true } as any);
219
+ mockIsFile.mockReturnValue(true);
220
+ mockGetAbsoluteDirectoryPath.mockReturnValue("/working/directory");
207
221
  mockParse.mockReturnValueOnce({
208
- variants: {},
222
+ variants: [],
209
223
  samples: [
210
- { templatePath: "sample.yaml", variants: ["v1"], output: "out" },
224
+ {
225
+ templatePath: "sample.yaml",
226
+ variants: [{ output: "out", input: "v1" }],
227
+ },
211
228
  ],
212
229
  });
213
230
  mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
@@ -218,10 +235,7 @@ describe("batchCompile", () => {
218
235
  input: [],
219
236
  });
220
237
  mockResolveTemplate.mockReturnValue("resolved template");
221
- // variant resolution
222
- mockIsVariantPath.mockReturnValue(false);
223
- mockIsVariantDefinition.mockReturnValue(true);
224
- // compileSample throws unknown error
238
+ mockIsVariantInputDefinition.mockReturnValue(true);
225
239
  mockCompileSample.mockImplementation(() => {
226
240
  throw "Unknown error";
227
241
  });
@@ -235,16 +249,16 @@ describe("batchCompile", () => {
235
249
  });
236
250
 
237
251
  it("should compile and write output files for each variant", () => {
238
- mockFs.existsSync.mockReturnValue(true);
239
- mockFs.lstatSync.mockReturnValue({ isFile: () => true } as any);
252
+ mockIsFile.mockReturnValue(true);
253
+ mockGetAbsoluteDirectoryPath.mockReturnValue("/working/directory");
240
254
  mockParse.mockReturnValueOnce({
241
- variants: {},
255
+ variants: [],
242
256
  samples: [
243
257
  {
244
258
  templatePath: "sample.yaml",
245
259
  variants: [
246
- { output: "v1.output", foo: "bar" },
247
- { output: "v2.output", foo: "baz" },
260
+ { output: "v1.output", input: {} },
261
+ { output: "v2.output", input: {} },
248
262
  ],
249
263
  output: "out",
250
264
  },
@@ -258,10 +272,7 @@ describe("batchCompile", () => {
258
272
  input: [],
259
273
  });
260
274
  mockResolveTemplate.mockReturnValue("resolved template");
261
- // variant resolution
262
- mockIsVariantPath.mockReturnValue(false);
263
- mockIsVariantDefinition.mockReturnValue(true);
264
- // compileSample returns output
275
+ mockIsVariantInputDefinition.mockReturnValue(true);
265
276
  mockCompileSample.mockReturnValue({
266
277
  items: [
267
278
  { fileName: "file1.js", content: "console.log('1');" },
@@ -271,14 +282,18 @@ describe("batchCompile", () => {
271
282
  mockCreateOutputDirectory.mockImplementation(() => {});
272
283
  mockFs.writeFileSync.mockImplementation(() => {});
273
284
  batchCompile("batch.yaml");
274
- expect(mockCreateOutputDirectory).toHaveBeenCalledWith("v1.output");
275
- expect(mockCreateOutputDirectory).toHaveBeenCalledWith("v2.output");
285
+ expect(mockCreateOutputDirectory).toHaveBeenCalledWith(
286
+ "/working/directory/v1.output",
287
+ );
288
+ expect(mockCreateOutputDirectory).toHaveBeenCalledWith(
289
+ "/working/directory/v2.output",
290
+ );
276
291
  expect(mockFs.writeFileSync).toHaveBeenCalledWith(
277
- path.join("v1.output", "file1.js"),
292
+ path.join("/working/directory", "v1.output", "file1.js"),
278
293
  "console.log('1');",
279
294
  );
280
295
  expect(mockFs.writeFileSync).toHaveBeenCalledWith(
281
- path.join("v1.output", "file2.js"),
296
+ path.join("/working/directory", "v1.output", "file2.js"),
282
297
  "console.log('2');",
283
298
  );
284
299
  });
@@ -5,28 +5,12 @@ vi.mock("fs");
5
5
  import fs from "fs";
6
6
  const mockFs = vi.mocked(fs);
7
7
 
8
- vi.mock("@caleuche/core");
9
- import { compileSample, Sample } from "@caleuche/core";
10
- const mockCompileSample = vi.mocked(compileSample);
11
-
12
8
  vi.mock("../src/utils");
13
- import {
14
- parse,
15
- resolveSampleFile,
16
- createOutputDirectory,
17
- resolveTemplate,
18
- isVariantDefinition,
19
- isVariantPath,
20
- isVariantReference,
21
- } from "../src/utils";
9
+ import { parse, resolveSampleFile, isFile } from "../src/utils";
22
10
  import { resolveAndParseSample } from "../src/common";
23
11
  const mockParse = vi.mocked(parse);
24
12
  const mockResolveSampleFile = vi.mocked(resolveSampleFile);
25
- const mockCreateOutputDirectory = vi.mocked(createOutputDirectory);
26
- const mockResolveTemplate = vi.mocked(resolveTemplate);
27
- const mockIsVariantDefinition = vi.mocked(isVariantDefinition);
28
- const mockIsVariantPath = vi.mocked(isVariantPath);
29
- const mockIsVariantReference = vi.mocked(isVariantReference);
13
+ const mockIsFile = vi.mocked(isFile);
30
14
 
31
15
  describe("common", () => {
32
16
  describe("resolveAndParseSample", () => {
@@ -56,7 +40,7 @@ describe("common", () => {
56
40
 
57
41
  it("should return null and log an error when sample file cannot be parsed", () => {
58
42
  mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
59
- mockFs.existsSync.mockReturnValue(true);
43
+ mockIsFile.mockReturnValue(true);
60
44
  mockParse.mockReturnValueOnce(null);
61
45
 
62
46
  const sample = resolveAndParseSample("sample");
@@ -16,12 +16,14 @@ import {
16
16
  createOutputDirectory,
17
17
  resolveTemplate,
18
18
  isObject,
19
+ isFile,
19
20
  } from "../src/utils";
20
21
  const mockParse = vi.mocked(parse);
21
22
  const mockResolveSampleFile = vi.mocked(resolveSampleFile);
22
23
  const mockCreateOutputDirectory = vi.mocked(createOutputDirectory);
23
24
  const mockResolveTemplate = vi.mocked(resolveTemplate);
24
25
  const mockIsObject = vi.mocked(isObject);
26
+ const mockIsFile = vi.mocked(isFile);
25
27
 
26
28
  import { compile } from "../src/compile";
27
29
 
@@ -51,7 +53,7 @@ describe("compile", () => {
51
53
  };
52
54
 
53
55
  mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
54
- mockFs.existsSync.mockReturnValue(true);
56
+ mockIsFile.mockReturnValue(true);
55
57
  mockParse.mockReturnValueOnce(mockSample);
56
58
  mockResolveTemplate.mockReturnValue("resolved template");
57
59
  mockParse.mockReturnValueOnce(null);
@@ -75,7 +77,7 @@ describe("compile", () => {
75
77
  };
76
78
 
77
79
  mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
78
- mockFs.existsSync.mockReturnValue(true);
80
+ mockIsFile.mockReturnValue(true);
79
81
  mockParse.mockReturnValueOnce(mockSample);
80
82
  mockResolveTemplate.mockReturnValue("resolved template");
81
83
  mockParse.mockReturnValueOnce("not an object");
@@ -101,7 +103,7 @@ describe("compile", () => {
101
103
  const mockData = { name: "test" };
102
104
 
103
105
  mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
104
- mockFs.existsSync.mockReturnValue(true);
106
+ mockIsFile.mockReturnValue(true);
105
107
  mockParse.mockReturnValueOnce(mockSample);
106
108
  mockResolveTemplate.mockReturnValue("resolved template");
107
109
  mockParse.mockReturnValueOnce(mockData);
@@ -130,7 +132,7 @@ describe("compile", () => {
130
132
  const mockData = { name: "test" };
131
133
 
132
134
  mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
133
- mockFs.existsSync.mockReturnValue(true);
135
+ mockIsFile.mockReturnValue(true);
134
136
  mockParse.mockReturnValueOnce(mockSample);
135
137
  mockResolveTemplate.mockReturnValue("resolved template");
136
138
  mockParse.mockReturnValueOnce(mockData);
@@ -167,7 +169,7 @@ describe("compile", () => {
167
169
  };
168
170
 
169
171
  mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
170
- mockFs.existsSync.mockReturnValue(true);
172
+ mockIsFile.mockReturnValue(true);
171
173
  mockParse.mockReturnValueOnce(mockSample);
172
174
  mockResolveTemplate.mockReturnValue("resolved template");
173
175
  mockParse.mockReturnValueOnce(mockData);
@@ -203,7 +205,7 @@ describe("compile", () => {
203
205
  };
204
206
 
205
207
  mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
206
- mockFs.existsSync.mockReturnValue(true);
208
+ mockIsFile.mockReturnValue(true);
207
209
  mockParse.mockReturnValueOnce(mockSample);
208
210
  mockResolveTemplate.mockReturnValue("resolved template");
209
211
  mockParse.mockReturnValueOnce(mockData);
@@ -234,7 +236,7 @@ describe("compile", () => {
234
236
  };
235
237
 
236
238
  mockResolveSampleFile.mockReturnValue("/path/to/sample.yaml");
237
- mockFs.existsSync.mockReturnValue(true);
239
+ mockIsFile.mockReturnValue(true);
238
240
  mockParse.mockReturnValueOnce(mockSample);
239
241
  mockResolveTemplate.mockReturnValue("resolved template");
240
242
  mockParse.mockReturnValueOnce(mockData);