skir 0.0.6 → 0.0.8

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.
Files changed (55) hide show
  1. package/dist/command_line_parser.d.ts +2 -2
  2. package/dist/command_line_parser.d.ts.map +1 -1
  3. package/dist/command_line_parser.js +105 -36
  4. package/dist/command_line_parser.js.map +1 -1
  5. package/dist/command_line_parser.test.js +166 -39
  6. package/dist/command_line_parser.test.js.map +1 -1
  7. package/dist/compiler.js +51 -54
  8. package/dist/compiler.js.map +1 -1
  9. package/dist/config.d.ts +2 -2
  10. package/dist/config.d.ts.map +1 -1
  11. package/dist/config.js +3 -5
  12. package/dist/config.js.map +1 -1
  13. package/dist/config_parser.d.ts +6 -0
  14. package/dist/config_parser.d.ts.map +1 -1
  15. package/dist/config_parser.js +55 -31
  16. package/dist/config_parser.js.map +1 -1
  17. package/dist/config_parser.test.js +53 -20
  18. package/dist/config_parser.test.js.map +1 -1
  19. package/dist/error_renderer.d.ts +1 -0
  20. package/dist/error_renderer.d.ts.map +1 -1
  21. package/dist/error_renderer.js +6 -3
  22. package/dist/error_renderer.js.map +1 -1
  23. package/dist/exit_error.d.ts +8 -0
  24. package/dist/exit_error.d.ts.map +1 -0
  25. package/dist/exit_error.js +8 -0
  26. package/dist/exit_error.js.map +1 -0
  27. package/dist/io.d.ts +2 -0
  28. package/dist/io.d.ts.map +1 -1
  29. package/dist/io.js +22 -3
  30. package/dist/io.js.map +1 -1
  31. package/dist/module_collector.d.ts.map +1 -1
  32. package/dist/module_collector.js +12 -7
  33. package/dist/module_collector.js.map +1 -1
  34. package/dist/module_set.js +4 -4
  35. package/dist/parser.js +6 -6
  36. package/dist/project_initializer.d.ts.map +1 -1
  37. package/dist/project_initializer.js +97 -15
  38. package/dist/project_initializer.js.map +1 -1
  39. package/dist/snapshotter.d.ts +9 -2
  40. package/dist/snapshotter.d.ts.map +1 -1
  41. package/dist/snapshotter.js +35 -17
  42. package/dist/snapshotter.js.map +1 -1
  43. package/package.json +8 -6
  44. package/src/command_line_parser.ts +134 -42
  45. package/src/compiler.ts +65 -60
  46. package/src/config.ts +4 -6
  47. package/src/config_parser.ts +66 -32
  48. package/src/error_renderer.ts +11 -3
  49. package/src/exit_error.ts +6 -0
  50. package/src/io.ts +22 -3
  51. package/src/module_collector.ts +21 -7
  52. package/src/module_set.ts +4 -4
  53. package/src/parser.ts +6 -6
  54. package/src/project_initializer.ts +97 -15
  55. package/src/snapshotter.ts +49 -30
@@ -1,31 +1,113 @@
1
- import * as fs from "fs";
2
- import * as paths from "path";
1
+ import * as FileSystem from "fs";
2
+ import * as Paths from "path";
3
+ import { rewritePathForRendering } from "./io.js";
3
4
  export function initializeProject(rootDir) {
4
- const skirYmlPath = paths.join(rootDir, "skir.yml");
5
+ const skirYmlPath = Paths.join(rootDir, "skir.yml");
5
6
  // Check if skir.yml already exists
6
- if (fs.existsSync(skirYmlPath)) {
7
+ if (FileSystem.existsSync(skirYmlPath)) {
7
8
  console.log("A skir.yml file already exists in this directory. Skipping project initialization.");
8
9
  return;
9
10
  }
10
11
  // Create skir.yml file
11
- fs.writeFileSync(skirYmlPath, SKIR_YML_CONTENT, "utf-8");
12
+ FileSystem.writeFileSync(skirYmlPath, SKIR_YML_CONTENT, "utf-8");
12
13
  // Check if skir-src directory exists
13
- const skirSrcDir = paths.join(rootDir, "skir-src");
14
- if (!fs.existsSync(skirSrcDir)) {
14
+ const skirSrcDir = Paths.join(rootDir, "skir-src");
15
+ if (!FileSystem.existsSync(skirSrcDir)) {
15
16
  // Create skir-src directory
16
- fs.mkdirSync(skirSrcDir, { recursive: true });
17
+ FileSystem.mkdirSync(skirSrcDir, { recursive: true });
17
18
  // Create hello_world.skir file
18
- const helloWorldPath = paths.join(skirSrcDir, "hello_world.skir");
19
- fs.writeFileSync(helloWorldPath, HELLO_WORLD_SKIR_CONTENT, "utf-8");
19
+ const helloWorldPath = Paths.join(skirSrcDir, "hello_world.skir");
20
+ FileSystem.writeFileSync(helloWorldPath, HELLO_WORLD_SKIR_CONTENT, "utf-8");
20
21
  }
21
- console.log(`Done. Please edit: ${paths.resolve(skirYmlPath)}`);
22
+ console.log(`Done. Please edit: ${rewritePathForRendering(skirYmlPath)}`);
22
23
  }
23
- const SKIR_YML_CONTENT = `srcDir: skir-src
24
+ const SKIR_YML_CONTENT = `# Configuration file for Skir code generator
25
+ #
26
+ # Documentation: https://skir.build/
27
+ #
28
+ # Cheat sheet:
29
+ # npx skir gen Generate code from .skir files
30
+ # npx skir gen --watch Watch for changes and regenerate automatically
31
+ # npx skir format Format all .skir files
32
+ # npx skir snapshot Take a snapshot of the source directory, verify no
33
+ # breaking changes since last snapshot
24
34
 
35
+ # Directory containing .skir files
36
+ srcDir: skir-src
37
+
38
+ # Uncomment and configure the generators for your target language(s).
25
39
  generators:
26
- - mod: skir-python-gen
27
- skiroutDir: ./skirout
28
- config: {}
40
+ # # --------------------------------------------------------------------------
41
+ # # C++ code generator
42
+ # # Home: https://github.com/gepheum/skir-cc-gen
43
+ # # To install runtime dependencies, follow instructions in repository README
44
+ # # --------------------------------------------------------------------------
45
+ # - mod: skir-cc-gen
46
+ # outDir: ./skirout
47
+ # config:
48
+ # # Set to true if you use GoogleTest
49
+ # writeGoogleTestHeaders: false
50
+
51
+ # # --------------------------------------------------------------------------
52
+ # # Dart code generator
53
+ # # Home: https://github.com/gepheum/skir-dart-gen
54
+ # # To install runtime dependencies: dart pub add skir_client
55
+ # # --------------------------------------------------------------------------
56
+ # - mod: skir-dart-gen
57
+ # outDir: ./skirout
58
+ # config: {}
59
+
60
+ # # --------------------------------------------------------------------------
61
+ # # Java code generator
62
+ # # Home: https://github.com/gepheum/skir-java-gen
63
+ # # Add the following line to your build.gradle dependencies:
64
+ # # implementation("build.skir:skir-client:latest.release")
65
+ # # --------------------------------------------------------------------------
66
+ # - mod: skir-java-gen
67
+ # outDir: ./src/main/java/skirout
68
+ # config: {}
69
+ # # Alternatively:
70
+ # # outDir: ./src/main/java/skirout/my/project
71
+ # # config:
72
+ # # packagePrefix: "my.project."
73
+
74
+ # # --------------------------------------------------------------------------
75
+ # # Kotlin code generator
76
+ # # Home: https://github.com/gepheum/skir-kotlin-gen
77
+ # # Add the following line to your build.gradle dependencies:
78
+ # # implementation("build.skir:skir-client:latest.release")
79
+ # # --------------------------------------------------------------------------
80
+ # - mod: skir-kotlin-gen
81
+ # outDir: ./src/main/kotlin/skirout
82
+ # config: {}
83
+ # # Alternatively:
84
+ # # outDir: ./src/main/kotlin/skirout/my/project
85
+ # # config:
86
+ # # packagePrefix: "my.project."
87
+
88
+ # # --------------------------------------------------------------------------
89
+ # # Python code generator
90
+ # # Home: https://github.com/gepheum/skir-python-gen
91
+ # # To install runtime dependencies: pip install skir-client
92
+ # # --------------------------------------------------------------------------
93
+ # - mod: skir-python-gen
94
+ # outDir: ./skirout
95
+ # config: {}
96
+ # # Alternatively:
97
+ # # outDir: ./my/project/skirout
98
+ # # config:
99
+ # # packagePrefix: "my.project."
100
+
101
+ # # --------------------------------------------------------------------------
102
+ # # TypeScript/JavaScript code generator
103
+ # # Home: https://github.com/gepheum/skir-typescript-gen
104
+ # # To install runtime dependencies: npm i skir-client
105
+ # # --------------------------------------------------------------------------
106
+ # - mod: skir-typescript-gen
107
+ # outDir: ./src/skirout
108
+ # config:
109
+ # # Use ".js" for ES modules, "" for CommonJS
110
+ # importPathExtension: ".js"
29
111
  `;
30
112
  const HELLO_WORLD_SKIR_CONTENT = `/// A point in 2D space.
31
113
  struct Point {
@@ -1 +1 @@
1
- {"version":3,"file":"project_initializer.js","sourceRoot":"","sources":["../src/project_initializer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,KAAK,MAAM,MAAM,CAAC;AAE9B,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAEpD,mCAAmC;IACnC,IAAI,EAAE,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QAC/B,OAAO,CAAC,GAAG,CACT,oFAAoF,CACrF,CAAC;QACF,OAAO;IACT,CAAC;IAED,uBAAuB;IACvB,EAAE,CAAC,aAAa,CAAC,WAAW,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAC;IAEzD,qCAAqC;IACrC,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACnD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/B,4BAA4B;QAC5B,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE9C,+BAA+B;QAC/B,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;QAClE,EAAE,CAAC,aAAa,CAAC,cAAc,EAAE,wBAAwB,EAAE,OAAO,CAAC,CAAC;IACtE,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,sBAAsB,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;AAClE,CAAC;AAED,MAAM,gBAAgB,GAAG;;;;;;CAMxB,CAAC;AAEF,MAAM,wBAAwB,GAAG;;;;;;;CAOhC,CAAC"}
1
+ {"version":3,"file":"project_initializer.js","sourceRoot":"","sources":["../src/project_initializer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,IAAI,CAAC;AACjC,OAAO,KAAK,KAAK,MAAM,MAAM,CAAC;AAC9B,OAAO,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAC;AAElD,MAAM,UAAU,iBAAiB,CAAC,OAAe;IAC/C,MAAM,WAAW,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IAEpD,mCAAmC;IACnC,IAAI,UAAU,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QACvC,OAAO,CAAC,GAAG,CACT,oFAAoF,CACrF,CAAC;QACF,OAAO;IACT,CAAC;IAED,uBAAuB;IACvB,UAAU,CAAC,aAAa,CAAC,WAAW,EAAE,gBAAgB,EAAE,OAAO,CAAC,CAAC;IAEjE,qCAAqC;IACrC,MAAM,UAAU,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;IACnD,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;QACvC,4BAA4B;QAC5B,UAAU,CAAC,SAAS,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEtD,+BAA+B;QAC/B,MAAM,cAAc,GAAG,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,kBAAkB,CAAC,CAAC;QAClE,UAAU,CAAC,aAAa,CAAC,cAAc,EAAE,wBAAwB,EAAE,OAAO,CAAC,CAAC;IAC9E,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,sBAAsB,uBAAuB,CAAC,WAAW,CAAC,EAAE,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuFxB,CAAC;AAEF,MAAM,wBAAwB,GAAG;;;;;;;CAOhC,CAAC"}
@@ -1,9 +1,16 @@
1
+ import { ModuleSet } from "./module_set.js";
1
2
  export declare function takeSnapshot(args: {
2
3
  rootDir: string;
3
4
  srcDir: string;
4
- check: boolean;
5
- }): Promise<void>;
5
+ subcommand: "ci" | "dry-run" | undefined;
6
+ }): Promise<boolean>;
7
+ interface CorruptedError {
8
+ kind: "corrupted";
9
+ error: any;
10
+ }
11
+ export declare function snapshotFileContentToModuleSet(fileContent: string): ModuleSet | CorruptedError;
6
12
  export declare function viewSnapshot(args: {
7
13
  rootDir: string;
8
14
  }): Promise<void>;
15
+ export {};
9
16
  //# sourceMappingURL=snapshotter.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"snapshotter.d.ts","sourceRoot":"","sources":["../src/snapshotter.ts"],"names":[],"mappings":"AAaA,wBAAsB,YAAY,CAAC,IAAI,EAAE;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,OAAO,CAAC;CAChB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6ChB;AAoDD,wBAAsB,YAAY,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmC3E"}
1
+ {"version":3,"file":"snapshotter.d.ts","sourceRoot":"","sources":["../src/snapshotter.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,wBAAsB,YAAY,CAAC,IAAI,EAAE;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,IAAI,GAAG,SAAS,GAAG,SAAS,CAAC;CAC1C,GAAG,OAAO,CAAC,OAAO,CAAC,CAkDnB;AAED,UAAU,cAAc;IACtB,IAAI,EAAE,WAAW,CAAC;IAClB,KAAK,EAAE,GAAG,CAAC;CACZ;AAqBD,wBAAgB,8BAA8B,CAC5C,WAAW,EAAE,MAAM,GAClB,SAAS,GAAG,cAAc,CAmC5B;AAED,wBAAsB,YAAY,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAA;CAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAmC3E"}
@@ -2,22 +2,23 @@ import { readFile, writeFile } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import { checkBackwardCompatibility } from "./compatibility_checker.js";
4
4
  import { formatError, makeGreen, makeRed, renderBreakingChanges, renderErrors, } from "./error_renderer.js";
5
+ import { rewritePathForRendering } from "./io.js";
5
6
  import { collectModules } from "./module_collector.js";
6
7
  import { ModuleSet } from "./module_set.js";
7
8
  export async function takeSnapshot(args) {
8
9
  const newModuleSet = await collectModules(args.srcDir);
9
10
  if (newModuleSet.errors.length) {
10
11
  renderErrors(newModuleSet.errors);
11
- process.exit(1);
12
+ return false;
12
13
  }
13
14
  const snapshotPath = join(args.rootDir, "skir-snapshot.json");
14
- const oldModuleSet = await readLastSnapshot(join(args.rootDir, snapshotPath));
15
+ const oldModuleSet = await readLastSnapshot(snapshotPath);
15
16
  if (!(oldModuleSet instanceof ModuleSet)) {
16
- console.error(makeRed(`Corrupted snapshot file: ${snapshotPath}`));
17
+ console.error(makeRed(`Corrupted snapshot file: ${rewritePathForRendering(snapshotPath)}`));
17
18
  console.error(`Error: ${oldModuleSet.error.toString()}`);
18
19
  console.log("If the snapshot file cannot be restored to a valid state, delete it and run again. " +
19
20
  "Breaking changes from recent commits will not be detected, but a valid snapshot will be created for future comparisons.");
20
- process.exit(1);
21
+ return false;
21
22
  }
22
23
  const breakingChanges = checkBackwardCompatibility({
23
24
  before: oldModuleSet,
@@ -28,27 +29,49 @@ export async function takeSnapshot(args) {
28
29
  before: oldModuleSet,
29
30
  after: newModuleSet,
30
31
  });
31
- process.exit(1);
32
+ return false;
32
33
  }
33
34
  const now = new Date();
34
35
  const newSnapshot = makeSnapshot(newModuleSet, now);
35
36
  if (sameModules(newSnapshot, makeSnapshot(oldModuleSet, now))) {
36
37
  console.log("No changes detected since last snapshot.");
37
- return;
38
+ return true;
38
39
  }
39
- if (args.check) {
40
- console.error(makeRed(`Modules have changed since the last snapshot. ` +
41
- `Run the command without 'check' to take a new snapshot.`));
42
- process.exit(1);
40
+ if (args.subcommand === "ci") {
41
+ console.error(makeRed("Modules have changed since the last snapshot."));
42
+ console.log("Run 'npx skir snapshot' to take a new snapshot.");
43
+ return false;
44
+ }
45
+ else if (args.subcommand === "dry-run") {
46
+ console.log(makeGreen("Changes detected since last snapshot."));
47
+ console.log("No breaking changes found.");
48
+ return true;
43
49
  }
44
50
  await writeFile(snapshotPath, JSON.stringify(newSnapshot, null, 2), "utf-8");
45
51
  console.log("Snapshot taken. No breaking changes detected.");
52
+ return true;
46
53
  }
47
54
  async function readLastSnapshot(snapshotPath) {
55
+ let textContent;
56
+ try {
57
+ textContent = await readFile(snapshotPath, "utf-8");
58
+ }
59
+ catch (error) {
60
+ const isNotFoundError = error instanceof Error && "code" in error && error.code === "ENOENT";
61
+ if (isNotFoundError) {
62
+ return ModuleSet.fromMap(new Map());
63
+ }
64
+ else {
65
+ // Rethrow I/O error
66
+ throw error;
67
+ }
68
+ }
69
+ return snapshotFileContentToModuleSet(textContent);
70
+ }
71
+ export function snapshotFileContentToModuleSet(fileContent) {
48
72
  let snapshot;
49
73
  try {
50
- const textContent = await readFile(snapshotPath, "utf-8");
51
- snapshot = JSON.parse(textContent);
74
+ snapshot = JSON.parse(fileContent);
52
75
  }
53
76
  catch (error) {
54
77
  if (error instanceof SyntaxError) {
@@ -57,12 +80,7 @@ async function readLastSnapshot(snapshotPath) {
57
80
  error: error,
58
81
  };
59
82
  }
60
- const isNotFoundError = error instanceof Error && "code" in error && error.code === "ENOENT";
61
- if (isNotFoundError) {
62
- return ModuleSet.fromMap(new Map());
63
- }
64
83
  else {
65
- // Rethrow I/O error
66
84
  throw error;
67
85
  }
68
86
  }
@@ -1 +1 @@
1
- {"version":3,"file":"snapshotter.js","sourceRoot":"","sources":["../src/snapshotter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"snapshotter.js","sourceRoot":"","sources":["../src/snapshotter.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skir",
3
- "version": "0.0.6",
3
+ "version": "0.0.8",
4
4
  "description": "",
5
5
  "homepage": "https://github.com/gepheum/skir#readme",
6
6
  "bugs": {
@@ -54,17 +54,19 @@
54
54
  "zod": "^4.2.1"
55
55
  },
56
56
  "devDependencies": {
57
+ "@eslint/js": "^9.39.2",
57
58
  "@types/mocha": "^10.0.1",
58
59
  "@types/node": "^20.6.0",
59
- "@typescript-eslint/eslint-plugin": "^6.13.0",
60
- "@typescript-eslint/parser": "^6.13.0",
60
+ "@typescript-eslint/eslint-plugin": "^8.50.1",
61
+ "@typescript-eslint/parser": "^8.50.1",
61
62
  "buckwheat": "^1.1.2",
62
- "eslint": "^8.54.0",
63
- "mocha": "^10.8.2",
63
+ "eslint": "^9.39.2",
64
+ "mocha": "^11.7.5",
64
65
  "prettier": "^3.2.4",
65
66
  "prettier-plugin-organize-imports": "^4.2.0",
66
67
  "ts-node": "^10.9.2",
67
68
  "tsx": "^4.21.0",
68
- "typescript": "^5.2.2"
69
+ "typescript": "^5.2.2",
70
+ "typescript-eslint": "^8.50.1"
69
71
  }
70
72
  }
@@ -6,12 +6,12 @@ export type ParsedArgs =
6
6
  }
7
7
  | {
8
8
  kind: "format";
9
- subcommand?: "check";
9
+ subcommand?: "ci";
10
10
  root?: string;
11
11
  }
12
12
  | {
13
13
  kind: "snapshot";
14
- subcommand?: "check" | "view";
14
+ subcommand?: "ci" | "view" | "dry-run";
15
15
  root?: string;
16
16
  }
17
17
  | {
@@ -80,30 +80,36 @@ export function parseCommandLine(args: string[]): ParsedArgs {
80
80
  const COMMAND_BASE = "npx skir";
81
81
 
82
82
  const HELP_TEXT = `
83
- Usage: ${COMMAND_BASE} <command> [subcommand] [options]
83
+ Usage: ${COMMAND_BASE} <command> [options]
84
84
 
85
85
  Commands:
86
- gen [watch] Generate code from Skir source files to target languages
87
- watch: Automatically regenerate when .skir files change
88
- format [check] Format all .skir files in the specified directory
89
- check: Fail if code is not properly formatted
90
- snapshot [check|view] Manage .skir file snapshots for compatibility checking
91
- check: Fail if there are breaking changes since last snapshot
92
- view: Display the last snapshot
93
- init Initialize a new Skir project with a minimal skir.yml file
94
- help Display this help message
86
+ init Initialize a new Skir project in the current directory
87
+ gen Generate code from .skir files to target languages
88
+ format Format all .skir files in the source directory
89
+ snapshot Take a snapshot of the source directory, look for
90
+ breaking changes since the last snapshot
91
+ help Display this help message
95
92
 
96
93
  Options:
97
- --root, -r <path> Path to the directory containing the skir.yml configuration file
94
+ --root, -r <path> Path to the directory containing the skir.yml file
95
+ --watch, -w Automatically run code generation when .skir files change
96
+ (gen only)
97
+ --ci Fail if code is not properly formatted (format) or if code
98
+ has changed since the last snapshot (snapshot)
99
+ --dry-run Look for breaking changes since the last snapshot without
100
+ taking a new snapshot (snapshot only)
101
+ --view Display the last snapshot (snapshot only)
98
102
 
99
103
  Examples:
104
+ ${COMMAND_BASE} init
100
105
  ${COMMAND_BASE} gen
101
- ${COMMAND_BASE} gen watch
106
+ ${COMMAND_BASE} gen --watch
102
107
  ${COMMAND_BASE} format --root path/to/root/dir
103
- ${COMMAND_BASE} format check -r path/to/root/dir
108
+ ${COMMAND_BASE} format --ci -r path/to/root/dir
104
109
  ${COMMAND_BASE} snapshot
105
- ${COMMAND_BASE} snapshot check
106
- ${COMMAND_BASE} snapshot view --root path/to/root/dir
110
+ ${COMMAND_BASE} snapshot --ci
111
+ ${COMMAND_BASE} snapshot --dry-run
112
+ ${COMMAND_BASE} snapshot --view --root path/to/root/dir
107
113
  `;
108
114
 
109
115
  export class CommandLineParseError extends Error {
@@ -115,7 +121,10 @@ export class CommandLineParseError extends Error {
115
121
 
116
122
  type ParsedOptions = {
117
123
  root?: string;
118
- subcommand?: string;
124
+ watch?: boolean;
125
+ ci?: boolean;
126
+ dryRun?: boolean;
127
+ view?: boolean;
119
128
  unknown: string[];
120
129
  };
121
130
 
@@ -128,7 +137,21 @@ function parseOptions(args: string[]): ParsedOptions {
128
137
  const arg = args[i];
129
138
  if (!arg) continue;
130
139
 
131
- if (arg === "--root" || arg === "-r") {
140
+ // Check for --option=value syntax
141
+ if (arg.startsWith("--root=") || arg.startsWith("-r=")) {
142
+ const value = arg.substring(arg.indexOf("=") + 1);
143
+ if (!value) {
144
+ throw new CommandLineParseError(
145
+ `Option ${arg.split("=")[0]} requires a value`,
146
+ );
147
+ }
148
+ if (options.root !== undefined) {
149
+ throw new CommandLineParseError(
150
+ `Option ${arg.split("=")[0]} specified multiple times`,
151
+ );
152
+ }
153
+ options.root = value;
154
+ } else if (arg === "--root" || arg === "-r") {
132
155
  if (i + 1 >= args.length) {
133
156
  throw new CommandLineParseError(`Option ${arg} requires a value`);
134
157
  }
@@ -139,14 +162,37 @@ function parseOptions(args: string[]): ParsedOptions {
139
162
  }
140
163
  options.root = args[i + 1];
141
164
  i++; // Skip the next argument as it's the value
165
+ } else if (arg === "--watch" || arg === "-w") {
166
+ if (options.watch) {
167
+ throw new CommandLineParseError(
168
+ `Option ${arg} specified multiple times`,
169
+ );
170
+ }
171
+ options.watch = true;
172
+ } else if (arg === "--ci") {
173
+ if (options.ci) {
174
+ throw new CommandLineParseError(`Option --ci specified multiple times`);
175
+ }
176
+ options.ci = true;
177
+ } else if (arg === "--dry-run") {
178
+ if (options.dryRun) {
179
+ throw new CommandLineParseError(
180
+ `Option --dry-run specified multiple times`,
181
+ );
182
+ }
183
+ options.dryRun = true;
184
+ } else if (arg === "--view") {
185
+ if (options.view) {
186
+ throw new CommandLineParseError(
187
+ `Option --view specified multiple times`,
188
+ );
189
+ }
190
+ options.view = true;
142
191
  } else if (arg.startsWith("-")) {
143
192
  options.unknown.push(arg);
144
193
  } else {
145
- // Positional argument - treat as subcommand
146
- if (options.subcommand !== undefined) {
147
- throw new CommandLineParseError(`Unexpected argument: ${arg}`);
148
- }
149
- options.subcommand = arg;
194
+ // Positional argument - not allowed anymore
195
+ throw new CommandLineParseError(`Unexpected argument: ${arg}`);
150
196
  }
151
197
  }
152
198
 
@@ -156,64 +202,110 @@ function parseOptions(args: string[]): ParsedOptions {
156
202
  function buildGenCommand(options: ParsedOptions): ParsedArgs {
157
203
  validateNoUnknownOptions(options, "gen");
158
204
 
159
- if (options.subcommand !== undefined && options.subcommand !== "watch") {
205
+ if (options.ci) {
160
206
  throw new CommandLineParseError(
161
- `Unknown subcommand for 'gen': ${options.subcommand}`,
207
+ `Option --ci is not valid for 'gen' command`,
208
+ );
209
+ }
210
+ if (options.dryRun) {
211
+ throw new CommandLineParseError(
212
+ `Option --dry-run is not valid for 'gen' command`,
213
+ );
214
+ }
215
+ if (options.view) {
216
+ throw new CommandLineParseError(
217
+ `Option --view is not valid for 'gen' command`,
162
218
  );
163
219
  }
164
220
 
165
221
  return {
166
222
  kind: "gen",
167
223
  root: options.root,
168
- subcommand: options.subcommand === "watch" ? "watch" : undefined,
224
+ subcommand: options.watch ? "watch" : undefined,
169
225
  };
170
226
  }
171
227
 
172
228
  function buildFormatCommand(options: ParsedOptions): ParsedArgs {
173
229
  validateNoUnknownOptions(options, "format");
174
230
 
175
- if (options.subcommand !== undefined && options.subcommand !== "check") {
231
+ if (options.watch) {
232
+ throw new CommandLineParseError(
233
+ `Option --watch is not valid for 'format' command`,
234
+ );
235
+ }
236
+ if (options.dryRun) {
176
237
  throw new CommandLineParseError(
177
- `Unknown subcommand for 'format': ${options.subcommand}`,
238
+ `Option --dry-run is not valid for 'format' command`,
239
+ );
240
+ }
241
+ if (options.view) {
242
+ throw new CommandLineParseError(
243
+ `Option --view is not valid for 'format' command`,
178
244
  );
179
245
  }
180
246
 
181
247
  return {
182
248
  kind: "format",
183
249
  root: options.root,
184
- subcommand: options.subcommand === "check" ? "check" : undefined,
250
+ subcommand: options.ci ? "ci" : undefined,
185
251
  };
186
252
  }
187
253
 
188
254
  function buildSnapshotCommand(options: ParsedOptions): ParsedArgs {
189
255
  validateNoUnknownOptions(options, "snapshot");
190
256
 
191
- if (
192
- options.subcommand !== undefined &&
193
- options.subcommand !== "check" &&
194
- options.subcommand !== "view"
195
- ) {
257
+ if (options.watch) {
258
+ throw new CommandLineParseError(
259
+ `Option --watch is not valid for 'snapshot' command`,
260
+ );
261
+ }
262
+
263
+ const activeOptions = [
264
+ options.ci && "--ci",
265
+ options.dryRun && "--dry-run",
266
+ options.view && "--view",
267
+ ].filter(Boolean);
268
+
269
+ if (activeOptions.length > 1) {
196
270
  throw new CommandLineParseError(
197
- `Unknown subcommand for 'snapshot': ${options.subcommand}`,
271
+ `Options ${activeOptions.join(" and ")} cannot be used together`,
198
272
  );
199
273
  }
200
274
 
201
275
  return {
202
276
  kind: "snapshot",
203
277
  root: options.root,
204
- subcommand:
205
- options.subcommand === "check" || options.subcommand === "view"
206
- ? options.subcommand
207
- : undefined,
278
+ subcommand: options.ci
279
+ ? "ci"
280
+ : options.dryRun
281
+ ? "dry-run"
282
+ : options.view
283
+ ? "view"
284
+ : undefined,
208
285
  };
209
286
  }
210
287
 
211
288
  function buildInitCommand(options: ParsedOptions): ParsedArgs {
212
289
  validateNoUnknownOptions(options, "init");
213
290
 
214
- if (options.subcommand !== undefined) {
291
+ if (options.watch) {
292
+ throw new CommandLineParseError(
293
+ `Option --watch is not valid for 'init' command`,
294
+ );
295
+ }
296
+ if (options.ci) {
297
+ throw new CommandLineParseError(
298
+ `Option --ci is not valid for 'init' command`,
299
+ );
300
+ }
301
+ if (options.dryRun) {
302
+ throw new CommandLineParseError(
303
+ `Option --dry-run is not valid for 'init' command`,
304
+ );
305
+ }
306
+ if (options.view) {
215
307
  throw new CommandLineParseError(
216
- `Unknown subcommand for 'init': ${options.subcommand}`,
308
+ `Option --view is not valid for 'init' command`,
217
309
  );
218
310
  }
219
311