rulesync 7.18.1 → 7.19.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/dist/index.cjs CHANGED
@@ -91,6 +91,24 @@ var import_globby = require("globby");
91
91
  // src/utils/logger.ts
92
92
  var import_consola = require("consola");
93
93
 
94
+ // src/types/json-output.ts
95
+ var ErrorCodes = {
96
+ CONFIG_NOT_FOUND: "CONFIG_NOT_FOUND",
97
+ RULESYNC_DIR_NOT_FOUND: "RULESYNC_DIR_NOT_FOUND",
98
+ INVALID_TARGET: "INVALID_TARGET",
99
+ FETCH_FAILED: "FETCH_FAILED",
100
+ WRITE_FAILED: "WRITE_FAILED",
101
+ VALIDATION_FAILED: "VALIDATION_FAILED",
102
+ GENERATION_FAILED: "GENERATION_FAILED",
103
+ IMPORT_FAILED: "IMPORT_FAILED",
104
+ INSTALL_FAILED: "INSTALL_FAILED",
105
+ UPDATE_FAILED: "UPDATE_FAILED",
106
+ GITIGNORE_FAILED: "GITIGNORE_FAILED",
107
+ INIT_FAILED: "INIT_FAILED",
108
+ MCP_FAILED: "MCP_FAILED",
109
+ UNKNOWN_ERROR: "UNKNOWN_ERROR"
110
+ };
111
+
94
112
  // src/utils/vitest.ts
95
113
  function isEnvTest() {
96
114
  return process.env.NODE_ENV === "test";
@@ -98,16 +116,24 @@ function isEnvTest() {
98
116
 
99
117
  // src/utils/logger.ts
100
118
  var Logger = class {
119
+ /**
120
+ * Create a new Logger instance
121
+ */
122
+ constructor(_version = "0.0.0") {
123
+ this._version = _version;
124
+ }
101
125
  _verbose = false;
102
126
  _silent = false;
127
+ _jsonMode = false;
128
+ _jsonOutputDone = false;
129
+ _commandName = "";
130
+ _jsonData = {};
103
131
  console = import_consola.consola.withDefaults({
104
132
  tag: "rulesync"
105
133
  });
106
134
  /**
107
135
  * Configure logger with verbose and silent mode settings.
108
136
  * Handles conflicting flags where silent takes precedence.
109
- * @param verbose - Enable verbose logging
110
- * @param silent - Enable silent mode (suppresses all output except errors)
111
137
  */
112
138
  configure({ verbose, silent }) {
113
139
  if (verbose && silent) {
@@ -123,34 +149,117 @@ var Logger = class {
123
149
  get silent() {
124
150
  return this._silent;
125
151
  }
152
+ /**
153
+ * Enable JSON output mode
154
+ */
155
+ setJsonMode(enabled, command) {
156
+ this._jsonMode = enabled;
157
+ this._jsonOutputDone = false;
158
+ this._commandName = command;
159
+ if (enabled) {
160
+ this._jsonData = {};
161
+ }
162
+ }
163
+ /**
164
+ * Check if JSON mode is enabled
165
+ */
166
+ get jsonMode() {
167
+ return this._jsonMode;
168
+ }
169
+ /**
170
+ * Capture data for JSON output
171
+ */
172
+ captureData(key, value) {
173
+ if (this._jsonMode) {
174
+ this._jsonData[key] = value;
175
+ }
176
+ }
177
+ /**
178
+ * Get captured JSON data
179
+ */
180
+ getJsonData() {
181
+ return { ...this._jsonData };
182
+ }
183
+ /**
184
+ * Output final JSON result
185
+ */
186
+ outputJson(success, error) {
187
+ if (!this._jsonMode || this._jsonOutputDone) return;
188
+ this._jsonOutputDone = true;
189
+ const output = {
190
+ success,
191
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
192
+ command: this._commandName,
193
+ version: this._version
194
+ };
195
+ if (success) {
196
+ output.data = this._jsonData;
197
+ } else if (error) {
198
+ output.error = {
199
+ code: error.code,
200
+ message: error.message
201
+ };
202
+ if (error.details) {
203
+ output.error.details = error.details;
204
+ }
205
+ if (error.stack) {
206
+ output.error.stack = error.stack;
207
+ }
208
+ }
209
+ const jsonStr = JSON.stringify(output, null, 2);
210
+ if (success) {
211
+ console.log(jsonStr);
212
+ } else {
213
+ console.error(jsonStr);
214
+ }
215
+ }
126
216
  info(message, ...args) {
127
217
  if (isEnvTest() || this._silent) return;
218
+ if (this._jsonMode) return;
128
219
  this.console.info(message, ...args);
129
220
  }
130
- // Success (always shown unless silent)
131
221
  success(message, ...args) {
132
222
  if (isEnvTest() || this._silent) return;
223
+ if (this._jsonMode) return;
133
224
  this.console.success(message, ...args);
134
225
  }
135
- // Warning (always shown unless silent)
136
226
  warn(message, ...args) {
137
227
  if (isEnvTest() || this._silent) return;
228
+ if (this._jsonMode) return;
138
229
  this.console.warn(message, ...args);
139
230
  }
140
- // Error (always shown, even in silent mode)
141
- error(message, ...args) {
231
+ error(message, code, ...args) {
142
232
  if (isEnvTest()) return;
143
- this.console.error(message, ...args);
233
+ const errorMessage = message instanceof Error ? message.message : message;
234
+ if (this._jsonMode) {
235
+ const errorInfo = {
236
+ code: code || ErrorCodes.UNKNOWN_ERROR,
237
+ message: errorMessage
238
+ };
239
+ if (this._verbose && message instanceof Error && message.stack) {
240
+ errorInfo.stack = message.stack;
241
+ }
242
+ this.outputJson(false, errorInfo);
243
+ } else {
244
+ this.console.error(errorMessage, ...args);
245
+ }
144
246
  }
145
- // Debug level (shown only in verbose mode)
146
247
  debug(message, ...args) {
147
248
  if (isEnvTest() || this._silent) return;
249
+ if (this._jsonMode) return;
148
250
  if (this._verbose) {
149
251
  this.console.info(message, ...args);
150
252
  }
151
253
  }
254
+ /**
255
+ * Get the internal console instance (for testing only)
256
+ * @internal
257
+ */
258
+ _getConsole() {
259
+ return this.console;
260
+ }
152
261
  };
153
- var logger = new Logger();
262
+ var logger = new Logger("0.0.0");
154
263
 
155
264
  // src/utils/file.ts
156
265
  async function ensureDir(dirPath) {
@@ -3312,7 +3421,9 @@ var CLAUDE_HOOK_EVENTS = [
3312
3421
  "preCompact",
3313
3422
  "permissionRequest",
3314
3423
  "notification",
3315
- "setup"
3424
+ "setup",
3425
+ "worktreeCreate",
3426
+ "worktreeRemove"
3316
3427
  ];
3317
3428
  var OPENCODE_HOOK_EVENTS = [
3318
3429
  "sessionStart",
@@ -3379,7 +3490,9 @@ var CANONICAL_TO_CLAUDE_EVENT_NAMES = {
3379
3490
  preCompact: "PreCompact",
3380
3491
  permissionRequest: "PermissionRequest",
3381
3492
  notification: "Notification",
3382
- setup: "Setup"
3493
+ setup: "Setup",
3494
+ worktreeCreate: "WorktreeCreate",
3495
+ worktreeRemove: "WorktreeRemove"
3383
3496
  };
3384
3497
  var CLAUDE_TO_CANONICAL_EVENT_NAMES = Object.fromEntries(
3385
3498
  Object.entries(CANONICAL_TO_CLAUDE_EVENT_NAMES).map(([k, v]) => [v, k])
@@ -3505,7 +3618,13 @@ function canonicalToToolHooks({
3505
3618
  else byMatcher.set(key, [def]);
3506
3619
  }
3507
3620
  const entries = [];
3621
+ const isNoMatcherEvent = converterConfig.noMatcherEvents?.has(eventName) ?? false;
3508
3622
  for (const [matcherKey, defs] of byMatcher) {
3623
+ if (isNoMatcherEvent && matcherKey) {
3624
+ logger.warn(
3625
+ `matcher "${matcherKey}" on "${eventName}" hook will be ignored \u2014 this event does not support matchers`
3626
+ );
3627
+ }
3509
3628
  const hooks = defs.map((def) => {
3510
3629
  const commandText = def.command;
3511
3630
  const trimmedCommand = typeof commandText === "string" ? commandText.trimStart() : void 0;
@@ -3518,7 +3637,8 @@ function canonicalToToolHooks({
3518
3637
  ...def.prompt !== void 0 && def.prompt !== null && { prompt: def.prompt }
3519
3638
  };
3520
3639
  });
3521
- entries.push(matcherKey ? { matcher: matcherKey, hooks } : { hooks });
3640
+ const includeMatcher = matcherKey && !isNoMatcherEvent;
3641
+ entries.push(includeMatcher ? { matcher: matcherKey, hooks } : { hooks });
3522
3642
  }
3523
3643
  result[toolEventName] = entries;
3524
3644
  }
@@ -3656,12 +3776,14 @@ var ToolHooks = class extends ToolFile {
3656
3776
  };
3657
3777
 
3658
3778
  // src/features/hooks/claudecode-hooks.ts
3779
+ var CLAUDE_NO_MATCHER_EVENTS = /* @__PURE__ */ new Set(["worktreeCreate", "worktreeRemove"]);
3659
3780
  var CLAUDE_CONVERTER_CONFIG = {
3660
3781
  supportedEvents: CLAUDE_HOOK_EVENTS,
3661
3782
  canonicalToToolEventNames: CANONICAL_TO_CLAUDE_EVENT_NAMES,
3662
3783
  toolToCanonicalEventNames: CLAUDE_TO_CANONICAL_EVENT_NAMES,
3663
3784
  projectDirVar: "$CLAUDE_PROJECT_DIR",
3664
- prefixDotRelativeCommandsOnly: true
3785
+ prefixDotRelativeCommandsOnly: true,
3786
+ noMatcherEvents: CLAUDE_NO_MATCHER_EVENTS
3665
3787
  };
3666
3788
  var ClaudecodeHooks = class _ClaudecodeHooks extends ToolHooks {
3667
3789
  constructor(params) {
package/dist/index.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  generate,
7
7
  importFromTool,
8
8
  logger
9
- } from "./chunk-JP3BFD7L.js";
9
+ } from "./chunk-J2ZF4SHC.js";
10
10
 
11
11
  // src/index.ts
12
12
  async function generate2(options = {}) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rulesync",
3
- "version": "7.18.1",
3
+ "version": "7.19.0",
4
4
  "description": "Unified AI rules management CLI tool that generates configuration files for various AI development tools",
5
5
  "keywords": [
6
6
  "ai",
@@ -57,7 +57,7 @@
57
57
  "consola": "3.4.2",
58
58
  "effect": "3.19.19",
59
59
  "es-toolkit": "1.45.1",
60
- "fastmcp": "3.33.0",
60
+ "fastmcp": "3.34.0",
61
61
  "globby": "16.1.1",
62
62
  "gray-matter": "4.0.3",
63
63
  "js-yaml": "4.1.1",
@@ -67,26 +67,26 @@
67
67
  "zod": "4.3.6"
68
68
  },
69
69
  "devDependencies": {
70
- "@anthropic-ai/claude-agent-sdk": "0.2.69",
71
- "@eslint/js": "9.39.2",
70
+ "@anthropic-ai/claude-agent-sdk": "0.2.74",
71
+ "@eslint/js": "9.39.4",
72
72
  "@openrouter/sdk": "0.9.11",
73
73
  "@secretlint/secretlint-rule-preset-recommend": "11.3.1",
74
74
  "@tsconfig/node24": "24.0.4",
75
75
  "@types/js-yaml": "4.0.9",
76
- "@types/node": "25.3.3",
77
- "@typescript/native-preview": "7.0.0-dev.20260304.1",
76
+ "@types/node": "25.4.0",
77
+ "@typescript/native-preview": "7.0.0-dev.20260312.1",
78
78
  "@vitest/coverage-v8": "4.0.18",
79
79
  "cspell": "9.7.0",
80
- "eslint": "9.39.2",
80
+ "eslint": "9.39.4",
81
81
  "eslint-plugin-import": "2.32.0",
82
82
  "eslint-plugin-no-type-assertion": "1.3.0",
83
- "eslint-plugin-oxlint": "1.51.0",
83
+ "eslint-plugin-oxlint": "1.53.0",
84
84
  "eslint-plugin-strict-dependencies": "1.3.31",
85
85
  "eslint-plugin-zod-import": "0.3.0",
86
- "knip": "5.85.0",
87
- "lint-staged": "16.3.2",
88
- "oxfmt": "0.36.0",
89
- "oxlint": "1.51.0",
86
+ "knip": "5.86.0",
87
+ "lint-staged": "16.3.3",
88
+ "oxfmt": "0.39.0",
89
+ "oxlint": "1.54.0",
90
90
  "repomix": "1.12.0",
91
91
  "resend": "6.9.3",
92
92
  "secretlint": "11.3.1",
@@ -95,7 +95,7 @@
95
95
  "tsup": "8.5.1",
96
96
  "tsx": "4.21.0",
97
97
  "typescript": "5.9.3",
98
- "typescript-eslint": "8.56.1",
98
+ "typescript-eslint": "8.57.0",
99
99
  "vitepress": "1.6.4",
100
100
  "vitest": "4.0.18"
101
101
  },