bktide 1.0.1755559112 → 1.0.1755639164

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 (32) hide show
  1. package/README.md +42 -0
  2. package/dist/commands/ShowBuild.js +31 -5
  3. package/dist/commands/ShowBuild.js.map +1 -1
  4. package/dist/formatters/build-detail/PlainTextFormatter.js +533 -180
  5. package/dist/formatters/build-detail/PlainTextFormatter.js.map +1 -1
  6. package/dist/formatters/builds/PlainTextFormatter.js +4 -2
  7. package/dist/formatters/builds/PlainTextFormatter.js.map +1 -1
  8. package/dist/formatters/pipelines/PlainTextFormatter.js +3 -6
  9. package/dist/formatters/pipelines/PlainTextFormatter.js.map +1 -1
  10. package/dist/graphql/fragments/index.js +3 -0
  11. package/dist/graphql/fragments/index.js.map +1 -0
  12. package/dist/graphql/fragments/jobs.js +112 -0
  13. package/dist/graphql/fragments/jobs.js.map +1 -0
  14. package/dist/graphql/queries.js +35 -53
  15. package/dist/graphql/queries.js.map +1 -1
  16. package/dist/index.js +1 -0
  17. package/dist/index.js.map +1 -1
  18. package/dist/scripts/extract-data-patterns.js +118 -0
  19. package/dist/scripts/extract-data-patterns.js.map +1 -0
  20. package/dist/services/BuildkiteClient.js +109 -32
  21. package/dist/services/BuildkiteClient.js.map +1 -1
  22. package/dist/services/BuildkiteRestClient.js +8 -7
  23. package/dist/services/BuildkiteRestClient.js.map +1 -1
  24. package/dist/test-helpers/DataProfiler.js +307 -0
  25. package/dist/test-helpers/DataProfiler.js.map +1 -0
  26. package/dist/test-helpers/PatternMockGenerator.js +590 -0
  27. package/dist/test-helpers/PatternMockGenerator.js.map +1 -0
  28. package/dist/ui/theme.js +193 -8
  29. package/dist/ui/theme.js.map +1 -1
  30. package/dist/utils/terminal-links.js +165 -0
  31. package/dist/utils/terminal-links.js.map +1 -0
  32. package/package.json +19 -3
@@ -1 +1 @@
1
- {"version":3,"file":"BuildkiteRestClient.js","sourceRoot":"/","sources":["services/BuildkiteRestClient.ts"],"names":[],"mappings":"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","sourcesContent":["import fetch from 'node-fetch';\nimport { CacheManager } from './CacheManager.js';\nimport { createHash } from 'crypto';\nimport { logger } from './logger.js';\n\nexport interface BuildkiteRestClientOptions {\n baseUrl?: string;\n caching?: boolean;\n cacheTTLs?: Partial<{\n builds: number;\n default: number;\n }>;\n debug?: boolean;\n}\n\nexport interface RateLimitInfo {\n remaining: number;\n limit: number;\n reset: number;\n}\n\n/**\n * BuildkiteRestClient provides methods to interact with the Buildkite REST API\n */\nexport class BuildkiteRestClient {\n private token: string;\n private baseUrl: string = 'https://api.buildkite.com/v2';\n private cacheManager: CacheManager | null = null;\n private debug: boolean = false;\n private rateLimitInfo: RateLimitInfo | null = null;\n\n /**\n * Create a new BuildkiteRestClient\n * @param token Your Buildkite API token\n * @param options Configuration options\n */\n constructor(token: string, options?: BuildkiteRestClientOptions) {\n this.token = token;\n this.debug = options?.debug || false;\n \n if (options?.baseUrl) {\n this.baseUrl = options.baseUrl;\n }\n \n // Initialize cache if caching is enabled\n if (options?.caching !== false) {\n this.cacheManager = new CacheManager(options?.cacheTTLs, this.debug);\n // Initialize cache and set token hash (async, but we don't wait)\n this.initCache();\n }\n }\n \n /**\n * Initialize cache asynchronously\n */\n private async initCache(): Promise<void> {\n if (this.cacheManager) {\n await this.cacheManager.init();\n await this.cacheManager.setTokenHash(this.token);\n }\n }\n \n /**\n * Generate a cache key for a REST endpoint\n */\n private generateCacheKey(endpoint: string, params?: Record<string, string>): string {\n const paramsString = params ? JSON.stringify(params) : '';\n return `REST:${endpoint}:${this.hashString(paramsString)}`;\n }\n \n /**\n * Hash a string using SHA256\n */\n private hashString(str: string): string {\n return createHash('sha256').update(str).digest('hex');\n }\n\n /**\n * Get cache type from endpoint\n */\n private getCacheTypeFromEndpoint(endpoint: string): string {\n if (endpoint.includes('/builds')) {\n return 'builds';\n }\n return 'default';\n }\n\n /**\n * Make a GET request to the Buildkite REST API\n * @param endpoint The API endpoint\n * @param params Query parameters\n * @returns The API response\n */\n private async get<T = any>(endpoint: string, params?: Record<string, string>): Promise<T> {\n const url = new URL(`${this.baseUrl}${endpoint}`);\n \n // Add query parameters\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, value);\n }\n });\n }\n \n // Generate cache key\n const cacheKey = this.generateCacheKey(endpoint, params);\n const cacheType = this.getCacheTypeFromEndpoint(endpoint);\n \n // Check cache first if enabled\n if (this.cacheManager) {\n const cached = await this.cacheManager.get(cacheKey, cacheType as any);\n if (cached) {\n if (this.debug) {\n logger.debug(`✅ Served from cache: REST ${endpoint}`);\n }\n return cached as T;\n }\n }\n\n const startTime = process.hrtime.bigint();\n if (this.debug) {\n logger.debug(`🕒 Starting REST API request: GET ${endpoint}`);\n logger.debug(`🕒 Request URL: ${url.toString()}`);\n if (params) {\n logger.debug(`🕒 Request params: ${JSON.stringify(params)}`);\n }\n }\n \n try {\n const response = await fetch(url.toString(), {\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n },\n });\n\n // Update rate limit info from headers\n this.rateLimitInfo = {\n remaining: parseInt(response.headers.get('RateLimit-Remaining') || '0'),\n limit: parseInt(response.headers.get('RateLimit-Limit') || '0'),\n reset: parseInt(response.headers.get('RateLimit-Reset') || '0'),\n };\n\n if (this.debug) {\n logger.debug('Rate limit info:', this.rateLimitInfo);\n }\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage = `API request failed with status ${response.status}: ${errorText}`;\n \n // Try to parse the error as JSON for more details\n try {\n const errorJson = JSON.parse(errorText);\n if (errorJson.message) {\n errorMessage = `API request failed: ${errorJson.message}`;\n }\n if (errorJson.errors && Array.isArray(errorJson.errors)) {\n errorMessage += `\\nErrors: ${errorJson.errors.map((e: any) => e.message).join(', ')}`;\n }\n } catch (e) {\n // If parsing fails, use the original error text\n }\n \n // Check if this is an authentication error\n const isAuthError = this.isAuthenticationError(response.status, errorMessage);\n if (isAuthError && this.debug) {\n logger.debug('Authentication error detected, not caching result');\n }\n \n throw new Error(errorMessage);\n }\n \n const data = await response.json() as T;\n \n // Cache the response if caching is enabled\n if (this.cacheManager) {\n await this.cacheManager.set(cacheKey, data, cacheType as any);\n }\n \n const endTime = process.hrtime.bigint();\n const duration = Number(endTime - startTime) / 1000000; // Convert to milliseconds\n if (this.debug) {\n logger.debug(`✅ REST API request completed: GET ${endpoint} (${duration.toFixed(2)}ms)`);\n }\n \n return data;\n } catch (error: unknown) {\n if (this.debug) {\n logger.error('Error in get request:', error);\n }\n throw error;\n }\n }\n\n /**\n * Check if an error is an authentication error\n */\n private isAuthenticationError(status: number, message: string): boolean {\n // Check for HTTP status codes that indicate auth issues\n if (status === 401 || status === 403) {\n return true;\n }\n \n // Check error message for auth-related keywords\n const lowerMessage = message.toLowerCase();\n return lowerMessage.includes('unauthorized') || \n lowerMessage.includes('authentication') || \n lowerMessage.includes('permission') ||\n lowerMessage.includes('invalid token');\n }\n\n /**\n * Get the current rate limit information\n * @returns Current rate limit information or null if not available\n */\n public getRateLimitInfo(): RateLimitInfo | null {\n return this.rateLimitInfo;\n }\n\n /**\n * Get builds from an organization filtered by specific parameters\n * @param org Organization slug\n * @param params Query parameters\n * @returns List of builds\n */\n public async getBuilds(org: string, params?: {\n creator?: string; // Creator's user ID, email or API access token\n pipeline?: string;\n branch?: string;\n commit?: string;\n state?: string;\n per_page?: string;\n page?: string;\n }): Promise<any[]> {\n const endpoint = `/organizations/${org}/builds`;\n const startTime = process.hrtime.bigint();\n if (this.debug) {\n logger.debug(`🕒 Fetching builds for organization: ${org}`);\n }\n \n const builds = await this.get<any[]>(endpoint, params as Record<string, string>);\n \n const endTime = process.hrtime.bigint();\n const duration = Number(endTime - startTime) / 1000000; // Convert to milliseconds\n if (this.debug) {\n logger.debug(`✅ Retrieved ${builds.length} builds for ${org} (${duration.toFixed(2)}ms)`);\n }\n \n return builds;\n }\n\n\n\n public async hasBuildAccess(org: string): Promise<boolean> {\n try {\n await this.getBuilds(org, { per_page: '1' });\n return true;\n } catch (error) {\n return false;\n }\n }\n \n /**\n * Check if the current user has access to an organization\n * @param org Organization slug\n * @returns True if the user has access, false otherwise\n */\n public async hasOrganizationAccess(org: string): Promise<boolean> {\n try {\n const endpoint = `/organizations/${org}`;\n await this.get(endpoint);\n return true;\n } catch (error) {\n if (this.debug) {\n logger.debug(`User does not have access to organization: ${org}`);\n }\n return false;\n }\n }\n \n /**\n * Clear all cache entries\n */\n public async clearCache(): Promise<void> {\n if (this.cacheManager) {\n await this.cacheManager.clear();\n }\n }\n\n /**\n * Invalidate a specific cache type\n */\n public async invalidateCache(type: string): Promise<void> {\n if (this.cacheManager) {\n await this.cacheManager.invalidateType(type);\n }\n }\n} "]}
1
+ {"version":3,"file":"BuildkiteRestClient.js","sourceRoot":"/","sources":["services/BuildkiteRestClient.ts"],"names":[],"mappings":"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","sourcesContent":["import fetch from 'node-fetch';\nimport { CacheManager } from './CacheManager.js';\nimport { createHash } from 'crypto';\nimport { logger } from './logger.js';\nimport { getProgressIcon } from '../ui/theme.js';\n\nexport interface BuildkiteRestClientOptions {\n baseUrl?: string;\n caching?: boolean;\n cacheTTLs?: Partial<{\n builds: number;\n default: number;\n }>;\n debug?: boolean;\n}\n\nexport interface RateLimitInfo {\n remaining: number;\n limit: number;\n reset: number;\n}\n\n/**\n * BuildkiteRestClient provides methods to interact with the Buildkite REST API\n */\nexport class BuildkiteRestClient {\n private token: string;\n private baseUrl: string = 'https://api.buildkite.com/v2';\n private cacheManager: CacheManager | null = null;\n private debug: boolean = false;\n private rateLimitInfo: RateLimitInfo | null = null;\n\n /**\n * Create a new BuildkiteRestClient\n * @param token Your Buildkite API token\n * @param options Configuration options\n */\n constructor(token: string, options?: BuildkiteRestClientOptions) {\n this.token = token;\n this.debug = options?.debug || false;\n \n if (options?.baseUrl) {\n this.baseUrl = options.baseUrl;\n }\n \n // Initialize cache if caching is enabled\n if (options?.caching !== false) {\n this.cacheManager = new CacheManager(options?.cacheTTLs, this.debug);\n // Initialize cache and set token hash (async, but we don't wait)\n this.initCache();\n }\n }\n \n /**\n * Initialize cache asynchronously\n */\n private async initCache(): Promise<void> {\n if (this.cacheManager) {\n await this.cacheManager.init();\n await this.cacheManager.setTokenHash(this.token);\n }\n }\n \n /**\n * Generate a cache key for a REST endpoint\n */\n private generateCacheKey(endpoint: string, params?: Record<string, string>): string {\n const paramsString = params ? JSON.stringify(params) : '';\n return `REST:${endpoint}:${this.hashString(paramsString)}`;\n }\n \n /**\n * Hash a string using SHA256\n */\n private hashString(str: string): string {\n return createHash('sha256').update(str).digest('hex');\n }\n\n /**\n * Get cache type from endpoint\n */\n private getCacheTypeFromEndpoint(endpoint: string): string {\n if (endpoint.includes('/builds')) {\n return 'builds';\n }\n return 'default';\n }\n\n /**\n * Make a GET request to the Buildkite REST API\n * @param endpoint The API endpoint\n * @param params Query parameters\n * @returns The API response\n */\n private async get<T = any>(endpoint: string, params?: Record<string, string>): Promise<T> {\n const url = new URL(`${this.baseUrl}${endpoint}`);\n \n // Add query parameters\n if (params) {\n Object.entries(params).forEach(([key, value]) => {\n if (value !== undefined && value !== null) {\n url.searchParams.append(key, value);\n }\n });\n }\n \n // Generate cache key\n const cacheKey = this.generateCacheKey(endpoint, params);\n const cacheType = this.getCacheTypeFromEndpoint(endpoint);\n \n // Check cache first if enabled\n if (this.cacheManager) {\n const cached = await this.cacheManager.get(cacheKey, cacheType as any);\n if (cached) {\n if (this.debug) {\n logger.debug(`${getProgressIcon('SUCCESS_LOG')} Served from cache: REST ${endpoint}`);\n }\n return cached as T;\n }\n }\n\n const startTime = process.hrtime.bigint();\n if (this.debug) {\n logger.debug(`${getProgressIcon('STARTING')} Starting REST API request: GET ${endpoint}`);\n logger.debug(`${getProgressIcon('STARTING')} Request URL: ${url.toString()}`);\n if (params) {\n logger.debug(`${getProgressIcon('STARTING')} Request params: ${JSON.stringify(params)}`);\n }\n }\n \n try {\n const response = await fetch(url.toString(), {\n headers: {\n 'Authorization': `Bearer ${this.token}`,\n 'Content-Type': 'application/json',\n },\n });\n\n // Update rate limit info from headers\n this.rateLimitInfo = {\n remaining: parseInt(response.headers.get('RateLimit-Remaining') || '0'),\n limit: parseInt(response.headers.get('RateLimit-Limit') || '0'),\n reset: parseInt(response.headers.get('RateLimit-Reset') || '0'),\n };\n\n if (this.debug) {\n logger.debug('Rate limit info:', this.rateLimitInfo);\n }\n\n if (!response.ok) {\n const errorText = await response.text();\n let errorMessage = `API request failed with status ${response.status}: ${errorText}`;\n \n // Try to parse the error as JSON for more details\n try {\n const errorJson = JSON.parse(errorText);\n if (errorJson.message) {\n errorMessage = `API request failed: ${errorJson.message}`;\n }\n if (errorJson.errors && Array.isArray(errorJson.errors)) {\n errorMessage += `\\nErrors: ${errorJson.errors.map((e: any) => e.message).join(', ')}`;\n }\n } catch (e) {\n // If parsing fails, use the original error text\n }\n \n // Check if this is an authentication error\n const isAuthError = this.isAuthenticationError(response.status, errorMessage);\n if (isAuthError && this.debug) {\n logger.debug('Authentication error detected, not caching result');\n }\n \n throw new Error(errorMessage);\n }\n \n const data = await response.json() as T;\n \n // Cache the response if caching is enabled\n if (this.cacheManager) {\n await this.cacheManager.set(cacheKey, data, cacheType as any);\n }\n \n const endTime = process.hrtime.bigint();\n const duration = Number(endTime - startTime) / 1000000; // Convert to milliseconds\n if (this.debug) {\n logger.debug(`${getProgressIcon('SUCCESS_LOG')} REST API request completed: GET ${endpoint} (${duration.toFixed(2)}ms)`);\n }\n \n return data;\n } catch (error: unknown) {\n if (this.debug) {\n logger.error('Error in get request:', error);\n }\n throw error;\n }\n }\n\n /**\n * Check if an error is an authentication error\n */\n private isAuthenticationError(status: number, message: string): boolean {\n // Check for HTTP status codes that indicate auth issues\n if (status === 401 || status === 403) {\n return true;\n }\n \n // Check error message for auth-related keywords\n const lowerMessage = message.toLowerCase();\n return lowerMessage.includes('unauthorized') || \n lowerMessage.includes('authentication') || \n lowerMessage.includes('permission') ||\n lowerMessage.includes('invalid token');\n }\n\n /**\n * Get the current rate limit information\n * @returns Current rate limit information or null if not available\n */\n public getRateLimitInfo(): RateLimitInfo | null {\n return this.rateLimitInfo;\n }\n\n /**\n * Get builds from an organization filtered by specific parameters\n * @param org Organization slug\n * @param params Query parameters\n * @returns List of builds\n */\n public async getBuilds(org: string, params?: {\n creator?: string; // Creator's user ID, email or API access token\n pipeline?: string;\n branch?: string;\n commit?: string;\n state?: string;\n per_page?: string;\n page?: string;\n }): Promise<any[]> {\n const endpoint = `/organizations/${org}/builds`;\n const startTime = process.hrtime.bigint();\n if (this.debug) {\n logger.debug(`${getProgressIcon('STARTING')} Fetching builds for organization: ${org}`);\n }\n \n const builds = await this.get<any[]>(endpoint, params as Record<string, string>);\n \n const endTime = process.hrtime.bigint();\n const duration = Number(endTime - startTime) / 1000000; // Convert to milliseconds\n if (this.debug) {\n logger.debug(`${getProgressIcon('SUCCESS_LOG')} Retrieved ${builds.length} builds for ${org} (${duration.toFixed(2)}ms)`);\n }\n \n return builds;\n }\n\n\n\n public async hasBuildAccess(org: string): Promise<boolean> {\n try {\n await this.getBuilds(org, { per_page: '1' });\n return true;\n } catch (error) {\n return false;\n }\n }\n \n /**\n * Check if the current user has access to an organization\n * @param org Organization slug\n * @returns True if the user has access, false otherwise\n */\n public async hasOrganizationAccess(org: string): Promise<boolean> {\n try {\n const endpoint = `/organizations/${org}`;\n await this.get(endpoint);\n return true;\n } catch (error) {\n if (this.debug) {\n logger.debug(`User does not have access to organization: ${org}`);\n }\n return false;\n }\n }\n \n /**\n * Clear all cache entries\n */\n public async clearCache(): Promise<void> {\n if (this.cacheManager) {\n await this.cacheManager.clear();\n }\n }\n\n /**\n * Invalidate a specific cache type\n */\n public async invalidateCache(type: string): Promise<void> {\n if (this.cacheManager) {\n await this.cacheManager.invalidateType(type);\n }\n }\n} "]}
@@ -0,0 +1,307 @@
1
+ /**
2
+ * DataProfiler extracts statistical patterns from real data without storing sensitive information
3
+ */
4
+ export class DataProfiler {
5
+ profileBuilds(builds) {
6
+ if (!builds || builds.length === 0) {
7
+ return this.getEmptyBuildPatterns();
8
+ }
9
+ return {
10
+ states: this.getDistribution(builds.map(b => b.state)),
11
+ branches: this.analyzeBranches(builds.map(b => b.branch || 'unknown')),
12
+ messagePatterns: this.analyzeMessages(builds.map(b => b.message || '')),
13
+ numberRange: {
14
+ min: Math.min(...builds.map(b => b.number || 0)),
15
+ max: Math.max(...builds.map(b => b.number || 0))
16
+ },
17
+ duration: this.analyzeDurations(builds),
18
+ jobCounts: this.getDistribution(builds.map(b => b.jobs?.edges?.length || 0)),
19
+ annotationCounts: this.getDistribution(builds.map(b => b.annotations?.edges?.length || 0)),
20
+ creatorPatterns: this.analyzeCreators(builds)
21
+ };
22
+ }
23
+ profilePipelines(pipelines) {
24
+ if (!pipelines || pipelines.length === 0) {
25
+ return this.getEmptyPipelinePatterns();
26
+ }
27
+ const names = pipelines.map(p => p.name || '');
28
+ const slugs = pipelines.map(p => p.slug || '');
29
+ return {
30
+ slugFormats: this.analyzeSlugFormats(slugs),
31
+ nameLength: {
32
+ min: Math.min(...names.map(n => n.length)),
33
+ max: Math.max(...names.map(n => n.length)),
34
+ average: names.reduce((acc, n) => acc + n.length, 0) / names.length
35
+ },
36
+ defaultBranches: this.getDistribution(pipelines.map(p => p.defaultBranch || 'main')),
37
+ hasDescription: pipelines.filter(p => p.description).length / pipelines.length,
38
+ repositoryProviders: this.getDistribution(pipelines.map(p => this.extractRepoProvider(p.repository?.url))),
39
+ visibility: this.getDistribution(pipelines.map(p => p.visibility || 'PRIVATE'))
40
+ };
41
+ }
42
+ profileJobs(jobs) {
43
+ if (!jobs || jobs.length === 0) {
44
+ return this.getEmptyJobPatterns();
45
+ }
46
+ return {
47
+ states: this.getDistribution(jobs.map(j => j.__typename || 'JobTypeCommand')),
48
+ labelPatterns: this.analyzeJobLabels(jobs),
49
+ exitStatusDistribution: this.getDistribution(jobs.map(j => 'exitStatus' in j ? j.exitStatus : null)),
50
+ retryRates: {
51
+ automatic: jobs.filter(j => 'retriedAutomatically' in j && j.retriedAutomatically).length / jobs.length,
52
+ manual: jobs.filter(j => 'retriedManually' in j && j.retriedManually).length / jobs.length
53
+ },
54
+ parallelGroups: this.getDistribution(jobs.map(j => 'parallelGroupTotal' in j ? j.parallelGroupTotal || 1 : 1)),
55
+ durationPatterns: this.analyzeJobDurations(jobs)
56
+ };
57
+ }
58
+ profileOrganizations(orgs) {
59
+ if (!orgs || orgs.length === 0) {
60
+ return this.getEmptyOrganizationPatterns();
61
+ }
62
+ const names = orgs.map(o => o.name || '');
63
+ const slugs = orgs.map(o => o.slug || '');
64
+ return {
65
+ slugFormats: this.analyzeSlugFormats(slugs),
66
+ nameLength: {
67
+ min: Math.min(...names.map(n => n.length)),
68
+ max: Math.max(...names.map(n => n.length)),
69
+ average: names.reduce((acc, n) => acc + n.length, 0) / names.length
70
+ },
71
+ pipelineCount: this.getDistribution(orgs.map(o => o.pipelines?.edges?.length || 0)),
72
+ memberCount: this.getDistribution(orgs.map(o => o.members?.edges?.length || 0))
73
+ };
74
+ }
75
+ getDistribution(values) {
76
+ const counts = new Map();
77
+ values.forEach(v => counts.set(v, (counts.get(v) || 0) + 1));
78
+ const total = values.length;
79
+ const distribution = {
80
+ values: Array.from(counts.entries()).map(([value, count]) => ({
81
+ value,
82
+ frequency: count / total,
83
+ count
84
+ })).sort((a, b) => b.frequency - a.frequency),
85
+ total
86
+ };
87
+ return distribution;
88
+ }
89
+ analyzeBranches(branches) {
90
+ const formats = {
91
+ feature: branches.filter(b => b.startsWith('feature/')).length / branches.length,
92
+ bugfix: branches.filter(b => b.startsWith('bugfix/') || b.startsWith('fix/')).length / branches.length,
93
+ release: branches.filter(b => b.match(/^release\/\d+\.\d+/)).length / branches.length,
94
+ main: branches.filter(b => ['main', 'master', 'develop'].includes(b)).length / branches.length,
95
+ custom: 0
96
+ };
97
+ formats.custom = 1 - (formats.feature + formats.bugfix + formats.release + formats.main);
98
+ return {
99
+ common: this.getDistribution(this.getCommonPrefixes(branches)),
100
+ formats,
101
+ averageLength: branches.reduce((acc, b) => acc + b.length, 0) / branches.length
102
+ };
103
+ }
104
+ analyzeMessages(messages) {
105
+ const nonEmpty = messages.filter(m => m.length > 0);
106
+ if (nonEmpty.length === 0) {
107
+ return {
108
+ averageLength: 0,
109
+ hasEmoji: 0,
110
+ conventionalCommits: 0,
111
+ commonPrefixes: { values: [], total: 0 },
112
+ githubRefs: 0,
113
+ jiraRefs: 0,
114
+ multiline: 0
115
+ };
116
+ }
117
+ return {
118
+ averageLength: nonEmpty.reduce((acc, m) => acc + m.length, 0) / nonEmpty.length,
119
+ hasEmoji: nonEmpty.filter(m => /[🎉🚀✨🔧📦👷‍♂️🐛⚡️✅💚🔥]/.test(m)).length / nonEmpty.length,
120
+ conventionalCommits: nonEmpty.filter(m => /^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.+\))?:/.test(m)).length / nonEmpty.length,
121
+ commonPrefixes: this.getDistribution(this.getCommonPrefixes(nonEmpty)),
122
+ githubRefs: nonEmpty.filter(m => /#\d+/.test(m)).length / nonEmpty.length,
123
+ jiraRefs: nonEmpty.filter(m => /[A-Z]{2,}-\d+/.test(m)).length / nonEmpty.length,
124
+ multiline: nonEmpty.filter(m => m.includes('\n')).length / nonEmpty.length
125
+ };
126
+ }
127
+ analyzeDurations(builds) {
128
+ const durations = builds
129
+ .filter(b => b.startedAt && b.finishedAt)
130
+ .map(b => new Date(b.finishedAt).getTime() - new Date(b.startedAt).getTime());
131
+ if (durations.length === 0) {
132
+ return { min: 0, max: 0, median: 0, p95: 0, average: 0 };
133
+ }
134
+ durations.sort((a, b) => a - b);
135
+ return {
136
+ min: durations[0],
137
+ max: durations[durations.length - 1],
138
+ median: durations[Math.floor(durations.length / 2)],
139
+ p95: durations[Math.floor(durations.length * 0.95)],
140
+ average: durations.reduce((acc, d) => acc + d, 0) / durations.length
141
+ };
142
+ }
143
+ analyzeJobDurations(jobs) {
144
+ const durations = jobs
145
+ .filter(j => 'startedAt' in j && 'finishedAt' in j)
146
+ .map(j => {
147
+ const job = j; // Type assertion for jobs with these fields
148
+ if (job.startedAt && job.finishedAt) {
149
+ return new Date(job.finishedAt).getTime() - new Date(job.startedAt).getTime();
150
+ }
151
+ return null;
152
+ })
153
+ .filter((d) => d !== null);
154
+ if (durations.length === 0) {
155
+ return { min: 0, max: 0, median: 0, p95: 0, average: 0 };
156
+ }
157
+ durations.sort((a, b) => a - b);
158
+ return {
159
+ min: durations[0],
160
+ max: durations[durations.length - 1],
161
+ median: durations[Math.floor(durations.length / 2)],
162
+ p95: durations[Math.floor(durations.length * 0.95)],
163
+ average: durations.reduce((acc, d) => acc + d, 0) / durations.length
164
+ };
165
+ }
166
+ analyzeCreators(builds) {
167
+ const creators = builds.map(b => b.createdBy);
168
+ const emails = creators
169
+ .map(c => c?.email || '')
170
+ .filter(e => e.length > 0);
171
+ const domains = emails.map(e => e.split('@')[1] || 'unknown');
172
+ const names = creators.map(c => c?.name || 'unknown');
173
+ return {
174
+ nameFormats: this.getDistribution(names.map(n => this.classifyNameFormat(n))),
175
+ domains: this.getDistribution(domains),
176
+ botUsers: creators.filter(c => c?.name?.toLowerCase().includes('bot') ||
177
+ c?.email?.toLowerCase().includes('bot') ||
178
+ c?.name?.toLowerCase().includes('[bot]')).length / creators.length
179
+ };
180
+ }
181
+ analyzeSlugFormats(slugs) {
182
+ const formats = slugs.map(s => {
183
+ if (s.includes('-'))
184
+ return 'kebab-case';
185
+ if (s.includes('_'))
186
+ return 'snake_case';
187
+ if (s.match(/[A-Z]/))
188
+ return 'camelCase';
189
+ return 'lowercase';
190
+ });
191
+ return this.getDistribution(formats);
192
+ }
193
+ analyzeJobLabels(jobs) {
194
+ const labels = jobs
195
+ .map(j => 'label' in j ? j.label : null)
196
+ .filter((l) => l !== null);
197
+ // Extract common patterns
198
+ const patterns = labels.map(l => {
199
+ // Replace common variables with placeholders
200
+ return l
201
+ .replace(/\d+\.\d+\.\d+/g, ':version')
202
+ .replace(/node-\d+/gi, 'node-:version')
203
+ .replace(/python-\d+\.\d+/gi, 'python-:version')
204
+ .replace(/ruby-\d+\.\d+/gi, 'ruby-:version')
205
+ .replace(/(linux|ubuntu|macos|windows|darwin)/gi, ':os')
206
+ .replace(/(test|tests|spec|specs)/gi, ':test')
207
+ .replace(/\b[a-f0-9]{7,40}\b/g, ':sha');
208
+ });
209
+ return this.getDistribution(patterns);
210
+ }
211
+ getCommonPrefixes(strings, maxLength = 50) {
212
+ const prefixes = [];
213
+ strings.forEach(str => {
214
+ const words = str.split(/[\s\-_/:]+/).filter(w => w.length > 0);
215
+ if (words.length > 0) {
216
+ prefixes.push(words[0].substring(0, maxLength));
217
+ }
218
+ });
219
+ return prefixes;
220
+ }
221
+ extractRepoProvider(url) {
222
+ if (!url)
223
+ return 'unknown';
224
+ if (url.includes('github.com'))
225
+ return 'github';
226
+ if (url.includes('gitlab.com'))
227
+ return 'gitlab';
228
+ if (url.includes('bitbucket.org'))
229
+ return 'bitbucket';
230
+ if (url.includes('git'))
231
+ return 'git';
232
+ return 'other';
233
+ }
234
+ classifyNameFormat(name) {
235
+ if (name.includes(' '))
236
+ return 'full-name';
237
+ if (name.includes('.'))
238
+ return 'dotted';
239
+ if (name.includes('-'))
240
+ return 'hyphenated';
241
+ if (name.includes('_'))
242
+ return 'underscored';
243
+ if (name.match(/^[a-z]+$/))
244
+ return 'lowercase';
245
+ if (name.match(/^[A-Z]+$/))
246
+ return 'uppercase';
247
+ return 'mixed';
248
+ }
249
+ // Empty pattern generators for fallback
250
+ getEmptyBuildPatterns() {
251
+ return {
252
+ states: { values: [], total: 0 },
253
+ branches: {
254
+ common: { values: [], total: 0 },
255
+ formats: { feature: 0, bugfix: 0, release: 0, main: 0, custom: 0 },
256
+ averageLength: 0
257
+ },
258
+ messagePatterns: {
259
+ averageLength: 0,
260
+ hasEmoji: 0,
261
+ conventionalCommits: 0,
262
+ commonPrefixes: { values: [], total: 0 },
263
+ githubRefs: 0,
264
+ jiraRefs: 0,
265
+ multiline: 0
266
+ },
267
+ numberRange: { min: 0, max: 0 },
268
+ duration: { min: 0, max: 0, median: 0, p95: 0, average: 0 },
269
+ jobCounts: { values: [], total: 0 },
270
+ annotationCounts: { values: [], total: 0 },
271
+ creatorPatterns: {
272
+ nameFormats: { values: [], total: 0 },
273
+ domains: { values: [], total: 0 },
274
+ botUsers: 0
275
+ }
276
+ };
277
+ }
278
+ getEmptyPipelinePatterns() {
279
+ return {
280
+ slugFormats: { values: [], total: 0 },
281
+ nameLength: { min: 0, max: 0, average: 0 },
282
+ defaultBranches: { values: [], total: 0 },
283
+ hasDescription: 0,
284
+ repositoryProviders: { values: [], total: 0 },
285
+ visibility: { values: [], total: 0 }
286
+ };
287
+ }
288
+ getEmptyJobPatterns() {
289
+ return {
290
+ states: { values: [], total: 0 },
291
+ labelPatterns: { values: [], total: 0 },
292
+ exitStatusDistribution: { values: [], total: 0 },
293
+ retryRates: { automatic: 0, manual: 0 },
294
+ parallelGroups: { values: [], total: 0 },
295
+ durationPatterns: { min: 0, max: 0, median: 0, p95: 0, average: 0 }
296
+ };
297
+ }
298
+ getEmptyOrganizationPatterns() {
299
+ return {
300
+ slugFormats: { values: [], total: 0 },
301
+ nameLength: { min: 0, max: 0, average: 0 },
302
+ pipelineCount: { values: [], total: 0 },
303
+ memberCount: { values: [], total: 0 }
304
+ };
305
+ }
306
+ }
307
+ //# sourceMappingURL=DataProfiler.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DataProfiler.js","sourceRoot":"/","sources":["test-helpers/DataProfiler.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * DataProfiler extracts statistical patterns from real data without storing sensitive information\n */\n\nimport type { \n Build, \n Pipeline, \n Organization, \n Job,\n BuildStates\n} from '../../src/graphql/generated/graphql.js';\n\nexport interface Distribution<T> {\n values: Array<{\n value: T;\n frequency: number;\n count: number;\n }>;\n total?: number;\n}\n\nexport interface BuildPatterns {\n states: Distribution<BuildStates>;\n branches: BranchPatterns;\n messagePatterns: MessagePatterns;\n numberRange: { min: number; max: number };\n duration: DurationPatterns;\n jobCounts: Distribution<number>;\n annotationCounts: Distribution<number>;\n creatorPatterns: CreatorPatterns;\n}\n\nexport interface BranchPatterns {\n common: Distribution<string>;\n formats: {\n feature: number;\n bugfix: number;\n release: number;\n main: number;\n custom: number;\n };\n averageLength: number;\n}\n\nexport interface MessagePatterns {\n averageLength: number;\n hasEmoji: number;\n conventionalCommits: number;\n commonPrefixes: Distribution<string>;\n githubRefs: number;\n jiraRefs: number;\n multiline: number;\n}\n\nexport interface DurationPatterns {\n min: number;\n max: number;\n median: number;\n p95: number;\n average: number;\n}\n\nexport interface CreatorPatterns {\n nameFormats: Distribution<string>;\n domains: Distribution<string>;\n botUsers: number;\n}\n\nexport interface PipelinePatterns {\n slugFormats: Distribution<string>;\n nameLength: { min: number; max: number; average: number };\n defaultBranches: Distribution<string>;\n hasDescription: number;\n repositoryProviders: Distribution<string>;\n visibility: Distribution<string>;\n}\n\nexport interface JobPatterns {\n states: Distribution<string>;\n labelPatterns: Distribution<string>;\n exitStatusDistribution: Distribution<number | null>;\n retryRates: {\n automatic: number;\n manual: number;\n };\n parallelGroups: Distribution<number>;\n durationPatterns: DurationPatterns;\n}\n\nexport interface OrganizationPatterns {\n slugFormats: Distribution<string>;\n nameLength: { min: number; max: number; average: number };\n pipelineCount: Distribution<number>;\n memberCount: Distribution<number>;\n}\n\nexport interface DataPatterns {\n builds: BuildPatterns;\n pipelines: PipelinePatterns;\n jobs: JobPatterns;\n organizations: OrganizationPatterns;\n extracted: string;\n sampleSize: {\n builds: number;\n pipelines: number;\n jobs: number;\n organizations: number;\n };\n}\n\nexport class DataProfiler {\n profileBuilds(builds: Build[]): BuildPatterns {\n if (!builds || builds.length === 0) {\n return this.getEmptyBuildPatterns();\n }\n\n return {\n states: this.getDistribution(builds.map(b => b.state)),\n branches: this.analyzeBranches(builds.map(b => b.branch || 'unknown')),\n messagePatterns: this.analyzeMessages(builds.map(b => b.message || '')),\n numberRange: {\n min: Math.min(...builds.map(b => b.number || 0)),\n max: Math.max(...builds.map(b => b.number || 0))\n },\n duration: this.analyzeDurations(builds),\n jobCounts: this.getDistribution(\n builds.map(b => b.jobs?.edges?.length || 0)\n ),\n annotationCounts: this.getDistribution(\n builds.map(b => b.annotations?.edges?.length || 0)\n ),\n creatorPatterns: this.analyzeCreators(builds)\n };\n }\n\n profilePipelines(pipelines: Pipeline[]): PipelinePatterns {\n if (!pipelines || pipelines.length === 0) {\n return this.getEmptyPipelinePatterns();\n }\n\n const names = pipelines.map(p => p.name || '');\n const slugs = pipelines.map(p => p.slug || '');\n\n return {\n slugFormats: this.analyzeSlugFormats(slugs),\n nameLength: {\n min: Math.min(...names.map(n => n.length)),\n max: Math.max(...names.map(n => n.length)),\n average: names.reduce((acc, n) => acc + n.length, 0) / names.length\n },\n defaultBranches: this.getDistribution(\n pipelines.map(p => p.defaultBranch || 'main')\n ),\n hasDescription: pipelines.filter(p => p.description).length / pipelines.length,\n repositoryProviders: this.getDistribution(\n pipelines.map(p => this.extractRepoProvider(p.repository?.url))\n ),\n visibility: this.getDistribution(\n pipelines.map(p => p.visibility || 'PRIVATE')\n )\n };\n }\n\n profileJobs(jobs: Job[]): JobPatterns {\n if (!jobs || jobs.length === 0) {\n return this.getEmptyJobPatterns();\n }\n\n return {\n states: this.getDistribution(jobs.map(j => j.__typename || 'JobTypeCommand')),\n labelPatterns: this.analyzeJobLabels(jobs),\n exitStatusDistribution: this.getDistribution(\n jobs.map(j => 'exitStatus' in j ? (j.exitStatus as number | null) : null)\n ),\n retryRates: {\n automatic: jobs.filter(j => 'retriedAutomatically' in j && j.retriedAutomatically).length / jobs.length,\n manual: jobs.filter(j => 'retriedManually' in j && j.retriedManually).length / jobs.length\n },\n parallelGroups: this.getDistribution(\n jobs.map(j => 'parallelGroupTotal' in j ? j.parallelGroupTotal || 1 : 1)\n ),\n durationPatterns: this.analyzeJobDurations(jobs)\n };\n }\n\n profileOrganizations(orgs: Organization[]): OrganizationPatterns {\n if (!orgs || orgs.length === 0) {\n return this.getEmptyOrganizationPatterns();\n }\n\n const names = orgs.map(o => o.name || '');\n const slugs = orgs.map(o => o.slug || '');\n\n return {\n slugFormats: this.analyzeSlugFormats(slugs),\n nameLength: {\n min: Math.min(...names.map(n => n.length)),\n max: Math.max(...names.map(n => n.length)),\n average: names.reduce((acc, n) => acc + n.length, 0) / names.length\n },\n pipelineCount: this.getDistribution(\n orgs.map(o => o.pipelines?.edges?.length || 0)\n ),\n memberCount: this.getDistribution(\n orgs.map(o => o.members?.edges?.length || 0)\n )\n };\n }\n\n private getDistribution<T>(values: T[]): Distribution<T> {\n const counts = new Map<T, number>();\n values.forEach(v => counts.set(v, (counts.get(v) || 0) + 1));\n \n const total = values.length;\n const distribution: Distribution<T> = {\n values: Array.from(counts.entries()).map(([value, count]) => ({\n value,\n frequency: count / total,\n count\n })).sort((a, b) => b.frequency - a.frequency),\n total\n };\n \n return distribution;\n }\n\n private analyzeBranches(branches: string[]): BranchPatterns {\n const formats = {\n feature: branches.filter(b => b.startsWith('feature/')).length / branches.length,\n bugfix: branches.filter(b => b.startsWith('bugfix/') || b.startsWith('fix/')).length / branches.length,\n release: branches.filter(b => b.match(/^release\\/\\d+\\.\\d+/)).length / branches.length,\n main: branches.filter(b => ['main', 'master', 'develop'].includes(b)).length / branches.length,\n custom: 0\n };\n \n formats.custom = 1 - (formats.feature + formats.bugfix + formats.release + formats.main);\n\n return {\n common: this.getDistribution(this.getCommonPrefixes(branches)),\n formats,\n averageLength: branches.reduce((acc, b) => acc + b.length, 0) / branches.length\n };\n }\n\n private analyzeMessages(messages: string[]): MessagePatterns {\n const nonEmpty = messages.filter(m => m.length > 0);\n if (nonEmpty.length === 0) {\n return {\n averageLength: 0,\n hasEmoji: 0,\n conventionalCommits: 0,\n commonPrefixes: { values: [], total: 0 },\n githubRefs: 0,\n jiraRefs: 0,\n multiline: 0\n };\n }\n\n return {\n averageLength: nonEmpty.reduce((acc, m) => acc + m.length, 0) / nonEmpty.length,\n hasEmoji: nonEmpty.filter(m => /[🎉🚀✨🔧📦👷‍♂️🐛⚡️✅💚🔥]/.test(m)).length / nonEmpty.length,\n conventionalCommits: nonEmpty.filter(m => \n /^(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\\(.+\\))?:/.test(m)\n ).length / nonEmpty.length,\n commonPrefixes: this.getDistribution(this.getCommonPrefixes(nonEmpty)),\n githubRefs: nonEmpty.filter(m => /#\\d+/.test(m)).length / nonEmpty.length,\n jiraRefs: nonEmpty.filter(m => /[A-Z]{2,}-\\d+/.test(m)).length / nonEmpty.length,\n multiline: nonEmpty.filter(m => m.includes('\\n')).length / nonEmpty.length\n };\n }\n\n private analyzeDurations(builds: Build[]): DurationPatterns {\n const durations = builds\n .filter(b => b.startedAt && b.finishedAt)\n .map(b => new Date(b.finishedAt!).getTime() - new Date(b.startedAt!).getTime());\n \n if (durations.length === 0) {\n return { min: 0, max: 0, median: 0, p95: 0, average: 0 };\n }\n \n durations.sort((a, b) => a - b);\n \n return {\n min: durations[0],\n max: durations[durations.length - 1],\n median: durations[Math.floor(durations.length / 2)],\n p95: durations[Math.floor(durations.length * 0.95)],\n average: durations.reduce((acc, d) => acc + d, 0) / durations.length\n };\n }\n\n private analyzeJobDurations(jobs: Job[]): DurationPatterns {\n const durations = jobs\n .filter(j => 'startedAt' in j && 'finishedAt' in j)\n .map(j => {\n const job = j as any; // Type assertion for jobs with these fields\n if (job.startedAt && job.finishedAt) {\n return new Date(job.finishedAt).getTime() - new Date(job.startedAt).getTime();\n }\n return null;\n })\n .filter((d): d is number => d !== null);\n \n if (durations.length === 0) {\n return { min: 0, max: 0, median: 0, p95: 0, average: 0 };\n }\n \n durations.sort((a, b) => a - b);\n \n return {\n min: durations[0],\n max: durations[durations.length - 1],\n median: durations[Math.floor(durations.length / 2)],\n p95: durations[Math.floor(durations.length * 0.95)],\n average: durations.reduce((acc, d) => acc + d, 0) / durations.length\n };\n }\n\n private analyzeCreators(builds: Build[]): CreatorPatterns {\n const creators = builds.map(b => b.createdBy);\n const emails = creators\n .map(c => c?.email || '')\n .filter(e => e.length > 0);\n \n const domains = emails.map(e => e.split('@')[1] || 'unknown');\n const names = creators.map(c => c?.name || 'unknown');\n \n return {\n nameFormats: this.getDistribution(\n names.map(n => this.classifyNameFormat(n))\n ),\n domains: this.getDistribution(domains),\n botUsers: creators.filter(c => \n c?.name?.toLowerCase().includes('bot') ||\n c?.email?.toLowerCase().includes('bot') ||\n c?.name?.toLowerCase().includes('[bot]')\n ).length / creators.length\n };\n }\n\n private analyzeSlugFormats(slugs: string[]): Distribution<string> {\n const formats = slugs.map(s => {\n if (s.includes('-')) return 'kebab-case';\n if (s.includes('_')) return 'snake_case';\n if (s.match(/[A-Z]/)) return 'camelCase';\n return 'lowercase';\n });\n \n return this.getDistribution(formats);\n }\n\n private analyzeJobLabels(jobs: Job[]): Distribution<string> {\n const labels = jobs\n .map(j => 'label' in j ? j.label : null)\n .filter((l): l is string => l !== null);\n \n // Extract common patterns\n const patterns = labels.map(l => {\n // Replace common variables with placeholders\n return l\n .replace(/\\d+\\.\\d+\\.\\d+/g, ':version')\n .replace(/node-\\d+/gi, 'node-:version')\n .replace(/python-\\d+\\.\\d+/gi, 'python-:version')\n .replace(/ruby-\\d+\\.\\d+/gi, 'ruby-:version')\n .replace(/(linux|ubuntu|macos|windows|darwin)/gi, ':os')\n .replace(/(test|tests|spec|specs)/gi, ':test')\n .replace(/\\b[a-f0-9]{7,40}\\b/g, ':sha');\n });\n \n return this.getDistribution(patterns);\n }\n\n private getCommonPrefixes(strings: string[], maxLength = 50): string[] {\n const prefixes: string[] = [];\n \n strings.forEach(str => {\n const words = str.split(/[\\s\\-_/:]+/).filter(w => w.length > 0);\n if (words.length > 0) {\n prefixes.push(words[0].substring(0, maxLength));\n }\n });\n \n return prefixes;\n }\n\n private extractRepoProvider(url?: string): string {\n if (!url) return 'unknown';\n if (url.includes('github.com')) return 'github';\n if (url.includes('gitlab.com')) return 'gitlab';\n if (url.includes('bitbucket.org')) return 'bitbucket';\n if (url.includes('git')) return 'git';\n return 'other';\n }\n\n private classifyNameFormat(name: string): string {\n if (name.includes(' ')) return 'full-name';\n if (name.includes('.')) return 'dotted';\n if (name.includes('-')) return 'hyphenated';\n if (name.includes('_')) return 'underscored';\n if (name.match(/^[a-z]+$/)) return 'lowercase';\n if (name.match(/^[A-Z]+$/)) return 'uppercase';\n return 'mixed';\n }\n\n // Empty pattern generators for fallback\n private getEmptyBuildPatterns(): BuildPatterns {\n return {\n states: { values: [], total: 0 },\n branches: {\n common: { values: [], total: 0 },\n formats: { feature: 0, bugfix: 0, release: 0, main: 0, custom: 0 },\n averageLength: 0\n },\n messagePatterns: {\n averageLength: 0,\n hasEmoji: 0,\n conventionalCommits: 0,\n commonPrefixes: { values: [], total: 0 },\n githubRefs: 0,\n jiraRefs: 0,\n multiline: 0\n },\n numberRange: { min: 0, max: 0 },\n duration: { min: 0, max: 0, median: 0, p95: 0, average: 0 },\n jobCounts: { values: [], total: 0 },\n annotationCounts: { values: [], total: 0 },\n creatorPatterns: {\n nameFormats: { values: [], total: 0 },\n domains: { values: [], total: 0 },\n botUsers: 0\n }\n };\n }\n\n private getEmptyPipelinePatterns(): PipelinePatterns {\n return {\n slugFormats: { values: [], total: 0 },\n nameLength: { min: 0, max: 0, average: 0 },\n defaultBranches: { values: [], total: 0 },\n hasDescription: 0,\n repositoryProviders: { values: [], total: 0 },\n visibility: { values: [], total: 0 }\n };\n }\n\n private getEmptyJobPatterns(): JobPatterns {\n return {\n states: { values: [], total: 0 },\n labelPatterns: { values: [], total: 0 },\n exitStatusDistribution: { values: [], total: 0 },\n retryRates: { automatic: 0, manual: 0 },\n parallelGroups: { values: [], total: 0 },\n durationPatterns: { min: 0, max: 0, median: 0, p95: 0, average: 0 }\n };\n }\n\n private getEmptyOrganizationPatterns(): OrganizationPatterns {\n return {\n slugFormats: { values: [], total: 0 },\n nameLength: { min: 0, max: 0, average: 0 },\n pipelineCount: { values: [], total: 0 },\n memberCount: { values: [], total: 0 }\n };\n }\n}\n"]}