@chappibunny/repolens 0.9.0 → 1.1.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.
@@ -112,6 +112,33 @@ export function shouldPublishToConfluence(config, currentBranch = getCurrentBran
112
112
  });
113
113
  }
114
114
 
115
+ /**
116
+ * Check if current branch should publish to GitHub Wiki
117
+ * Based on config.github_wiki.branches setting
118
+ */
119
+ export function shouldPublishToGitHubWiki(config, currentBranch = getCurrentBranch()) {
120
+ if (!config.github_wiki) {
121
+ return true;
122
+ }
123
+
124
+ if (!config.github_wiki.branches || config.github_wiki.branches.length === 0) {
125
+ return true;
126
+ }
127
+
128
+ return config.github_wiki.branches.some(pattern => {
129
+ if (pattern === currentBranch) {
130
+ return true;
131
+ }
132
+
133
+ if (pattern.includes("*")) {
134
+ const regex = new RegExp("^" + pattern.replace(/\*/g, ".*") + "$");
135
+ return regex.test(currentBranch);
136
+ }
137
+
138
+ return false;
139
+ });
140
+ }
141
+
115
142
  /**
116
143
  * Get branch-qualified page title
117
144
  */
@@ -5,6 +5,8 @@
5
5
  * to prevent abuse and respect API limits.
6
6
  */
7
7
 
8
+ import { warn } from "./logger.js";
9
+
8
10
  /**
9
11
  * Rate limiter class using token bucket algorithm
10
12
  */
@@ -193,7 +195,7 @@ export async function executeNotionRequest(fn, options = {}) {
193
195
  if (options.onRetry) {
194
196
  options.onRetry(attempt, maxRetries, delay, error);
195
197
  } else {
196
- console.warn(
198
+ warn(
197
199
  `Notion API retry ${attempt}/${maxRetries} after ${Math.round(delay)}ms (${error.message})`
198
200
  );
199
201
  }
@@ -221,7 +223,7 @@ export async function executeAIRequest(fn, options = {}) {
221
223
  if (options.onRetry) {
222
224
  options.onRetry(attempt, maxRetries, delay, error);
223
225
  } else {
224
- console.warn(
226
+ warn(
225
227
  `AI API retry ${attempt}/${maxRetries} after ${Math.round(delay)}ms (${error.message})`
226
228
  );
227
229
  }
@@ -33,8 +33,10 @@ export function initTelemetry() {
33
33
  const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
34
34
  const version = packageJson.version || "unknown";
35
35
 
36
+ const dsn = process.env.REPOLENS_SENTRY_DSN || "https://082083dbf5899ed7e65dfd9b8dc72f90@o4511014913703936.ingest.de.sentry.io/4511014919209040";
37
+
36
38
  Sentry.init({
37
- dsn: "https://082083dbf5899ed7e65dfd9b8dc72f90@o4511014913703936.ingest.de.sentry.io/4511014919209040", // TODO: Replace with actual DSN
39
+ dsn,
38
40
 
39
41
  // Release tracking
40
42
  release: `repolens@${version}`,
@@ -412,8 +414,10 @@ function ensureSentryForFeedback() {
412
414
  const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
413
415
  const version = packageJson.version || "unknown";
414
416
 
417
+ const dsn = process.env.REPOLENS_SENTRY_DSN || "https://082083dbf5899ed7e65dfd9b8dc72f90@o4511014913703936.ingest.de.sentry.io/4511014919209040";
418
+
415
419
  Sentry.init({
416
- dsn: "https://082083dbf5899ed7e65dfd9b8dc72f90@o4511014913703936.ingest.de.sentry.io/4511014919209040",
420
+ dsn,
417
421
  release: `repolens@${version}`,
418
422
  environment: process.env.NODE_ENV || "production",
419
423
  sampleRate: 1.0, // Always send feedback
@@ -104,7 +104,7 @@ export async function checkForUpdates() {
104
104
  }
105
105
 
106
106
  function showUpdateMessage(current, latest) {
107
- console.log("");
107
+ info("");
108
108
  warn("┌────────────────────────────────────────────────────────────┐");
109
109
  warn("│ 📦 Update Available │");
110
110
  warn("├────────────────────────────────────────────────────────────┤");
@@ -118,7 +118,7 @@ function showUpdateMessage(current, latest) {
118
118
  warn("│ │");
119
119
  warn("│ Release notes: https://github.com/CHAPIBUNNY/repolens │");
120
120
  warn("└────────────────────────────────────────────────────────────┘");
121
- console.log("");
121
+ info("");
122
122
  }
123
123
 
124
124
  export async function forceCheckForUpdates() {
@@ -103,13 +103,13 @@ function validateScanConfig(scan) {
103
103
  }
104
104
  }
105
105
 
106
- if (scan.exclude) {
107
- if (!Array.isArray(scan.exclude)) {
108
- errors.push("scan.exclude must be an array of glob patterns");
106
+ if (scan.ignore) {
107
+ if (!Array.isArray(scan.ignore)) {
108
+ errors.push("scan.ignore must be an array of glob patterns");
109
109
  } else {
110
- for (const pattern of scan.exclude) {
110
+ for (const pattern of scan.ignore) {
111
111
  if (typeof pattern !== "string") {
112
- errors.push(`Invalid pattern in scan.exclude: ${pattern} (must be string)`);
112
+ errors.push(`Invalid pattern in scan.ignore: ${pattern} (must be string)`);
113
113
  continue; // Skip further checks if not a string
114
114
  }
115
115
  }
@@ -135,7 +135,7 @@ function validatePublishers(publishers) {
135
135
  return errors;
136
136
  }
137
137
 
138
- const validPublishers = ["notion", "markdown", "confluence"];
138
+ const validPublishers = ["notion", "markdown", "confluence", "github_wiki"];
139
139
 
140
140
  if (Array.isArray(publishers)) {
141
141
  for (const pub of publishers) {
@@ -207,33 +207,34 @@ function checkNotionWarnings(notion) {
207
207
  }
208
208
 
209
209
  /**
210
- * Validate domains configuration
210
+ * Validate domains configuration (object format: { key: { match: [], description? } })
211
211
  */
212
212
  function validateDomains(domains) {
213
213
  const errors = [];
214
214
 
215
- if (!Array.isArray(domains)) {
216
- errors.push("domains must be an array");
215
+ if (typeof domains !== "object" || Array.isArray(domains)) {
216
+ errors.push("domains must be an object");
217
217
  return errors;
218
218
  }
219
219
 
220
- for (const domain of domains) {
221
- if (!domain.name || typeof domain.name !== "string") {
222
- errors.push("Each domain must have a 'name' field (string)");
220
+ for (const [key, domain] of Object.entries(domains)) {
221
+ if (typeof domain !== "object" || Array.isArray(domain)) {
222
+ errors.push(`domains.${key} must be an object`);
223
+ continue;
223
224
  }
224
225
 
225
- if (!domain.patterns || !Array.isArray(domain.patterns)) {
226
- errors.push(`Domain '${domain.name}' must have 'patterns' array`);
226
+ if (!domain.match || !Array.isArray(domain.match)) {
227
+ errors.push(`domains.${key} must have a 'match' array`);
227
228
  } else {
228
- for (const pattern of domain.patterns) {
229
+ for (const pattern of domain.match) {
229
230
  if (typeof pattern !== "string") {
230
- errors.push(`Invalid pattern in domain '${domain.name}': ${pattern}`);
231
+ errors.push(`Invalid pattern in domains.${key}.match: ${pattern}`);
231
232
  }
232
233
  }
233
234
  }
234
235
 
235
236
  if (domain.description && typeof domain.description !== "string") {
236
- errors.push(`Domain '${domain.name}' description must be a string`);
237
+ errors.push(`domains.${key}.description must be a string`);
237
238
  }
238
239
  }
239
240
 
@@ -319,17 +320,25 @@ function checkForInjection(config) {
319
320
  });
320
321
  }
321
322
 
322
- // Check domain patterns
323
- if (config.domains && Array.isArray(config.domains)) {
324
- config.domains.forEach((domain, i) => {
325
- if (domain.patterns && Array.isArray(domain.patterns)) {
326
- domain.patterns.forEach((pattern, j) => {
323
+ if (config.scan?.ignore && Array.isArray(config.scan.ignore)) {
324
+ config.scan.ignore.forEach((pattern, i) => {
325
+ if (typeof pattern === "string") {
326
+ checkString(pattern, `scan.ignore[${i}]`);
327
+ }
328
+ });
329
+ }
330
+
331
+ // Check domain patterns (object format: { key: { match: [] } })
332
+ if (config.domains && typeof config.domains === "object" && !Array.isArray(config.domains)) {
333
+ for (const [domainKey, domain] of Object.entries(config.domains)) {
334
+ if (domain.match && Array.isArray(domain.match)) {
335
+ domain.match.forEach((pattern, j) => {
327
336
  if (typeof pattern === "string") {
328
- checkString(pattern, `domains[${i}].patterns[${j}]`);
337
+ checkString(pattern, `domains.${domainKey}.match[${j}]`);
329
338
  }
330
339
  });
331
340
  }
332
- });
341
+ }
333
342
  }
334
343
 
335
344
  return errors;