Skip to content

Commit 98dfd4c

Browse files
fix lint issue
1 parent d7db432 commit 98dfd4c

File tree

2 files changed

+52
-66
lines changed

2 files changed

+52
-66
lines changed

src/domains/services/validation.service.ts

Lines changed: 50 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -47,106 +47,91 @@ interface GitHubFileInfo {
4747
}
4848

4949
/**
50-
* Helper function to validate if a URL is a GitHub blob URL
50+
* Custom GitHub URL resolver for private repositories
5151
*/
52-
const isValidGitHubBlobUrl = (url: string): boolean => {
53-
try {
54-
const parsedUrl = new URL(url);
55-
return (
56-
parsedUrl.hostname === 'github.com' &&
57-
parsedUrl.pathname.split('/')[3] === 'blob'
58-
);
59-
} catch (error) {
60-
return false;
61-
}
62-
};
63-
64-
/**
65-
* Convert GitHub web URL to API URL
66-
*/
67-
const convertGitHubWebUrl = (url: string): string => {
68-
// Remove fragment from URL before processing
69-
const urlWithoutFragment = url.split('#')[0];
70-
71-
// Handle GitHub web URLs like: https://github.com/owner/repo/blob/branch/path
72-
// eslint-disable-next-line no-useless-escape
73-
const githubWebPattern = /^https:\/\/github\.com\/([^\/]+)\/([^\/]+)\/blob\/([^\/]+)\/(.+)$/;
74-
const match = urlWithoutFragment.match(githubWebPattern);
75-
76-
if (match) {
77-
const [, owner, repo, branch, filePath] = match;
78-
return `https://api.github.com/repos/${owner}/${repo}/contents/${filePath}?ref=${branch}`;
79-
}
80-
81-
return url;
82-
};
83-
84-
/**
85-
* Custom resolver for private repositories
86-
*/
87-
const createHttpWithAuthResolver = () => ({
52+
const createGitHubResolver = () => ({
8853
schema: 'https',
8954
order: 1,
9055

56+
canRead: (uri: any) => {
57+
try {
58+
const url = new URL(uri.toString());
59+
return url.hostname === 'raw.githubusercontent.com' ||
60+
url.hostname === 'github.com' ||
61+
url.hostname === 'api.github.com';
62+
} catch (error) {
63+
return false;
64+
}
65+
},
66+
67+
/**
68+
* Convert GitHub web URL to API URL
69+
*/
70+
convertGitHubWebUrl: (url: string): string => {
71+
// Remove fragment from URL before processing
72+
const urlWithoutFragment = url.split('#')[0];
73+
74+
// Handle GitHub web URLs like: https://github.com/owner/repo/blob/branch/path
75+
// eslint-disable-next-line no-useless-escape
76+
const githubWebPattern = /^https:\/\/github\.com\/([^\/]+)\/([^\/]+)\/blob\/([^\/]+)\/(.+)$/;
77+
const match = urlWithoutFragment.match(githubWebPattern);
78+
79+
if (match) {
80+
const [, owner, repo, branch, path] = match;
81+
return `https://api.github.com/repos/${owner}/${repo}/contents/${path}?ref=${branch}`;
82+
}
83+
return url;
84+
},
85+
9186
read: async (uri: any) => {
9287
let url = uri.toString();
93-
88+
const originalUrl = url;
89+
9490
// Default headers
9591
const headers: Record<string, string> = {
96-
'User-Agent': 'AsyncAPI-CLI',
92+
'User-Agent': 'AsyncAPI-CLI'
9793
};
9894

9995
const authInfo = await ConfigService.getAuthForUrl(url);
10096

101-
if (isValidGitHubBlobUrl(url)) {
102-
url = convertGitHubWebUrl(url);
97+
if (url.includes('github.com') && url.includes('/blob/')) {
98+
url = createGitHubResolver().convertGitHubWebUrl(url);
10399
}
104-
105-
// Only require authentication for GitHub URLs
100+
106101
if (authInfo) {
107102
headers['Authorization'] = `${authInfo.authType} ${authInfo.token}`;
108103
Object.assign(headers, authInfo.headers); // merge custom headers
104+
} else {
105+
throw new Error(`Cannot resolve URL: ${url} - No authentication configured for this GitHub repository`);
109106
}
110107

111108
if (url.includes('api.github.com')) {
112109
headers['Accept'] = 'application/vnd.github.v3+json';
113110
const res = await fetch(url, { headers });
114111
if (!res.ok) {
115-
throw new Error(
116-
`Failed to fetch GitHub API URL: ${url} - ${res.statusText}`
117-
);
112+
throw new Error(`Failed to fetch GitHub API URL: ${url} - ${res.statusText}`);
118113
}
119-
const fileInfo = (await res.json()) as GitHubFileInfo;
114+
const fileInfo = await res.json() as GitHubFileInfo;
120115

121116
if (fileInfo.download_url) {
122117
const contentRes = await fetch(fileInfo.download_url, { headers });
123118
if (!contentRes.ok) {
124-
throw new Error(
125-
`Failed to fetch content from download URL: ${fileInfo.download_url} - ${contentRes.statusText}`
126-
);
119+
throw new Error(`Failed to fetch content from download URL: ${fileInfo.download_url} - ${contentRes.statusText}`);
127120
}
128121
return await contentRes.text();
129122
}
130-
throw new Error(
131-
`No download URL found in GitHub API response for: ${url}`
132-
);
123+
throw new Error(`No download URL found in GitHub API response for: ${url}`);
133124
} else if (url.includes('raw.githubusercontent.com')) {
134125
headers['Accept'] = 'application/vnd.github.v3.raw';
135126
const res = await fetch(url, { headers });
136127
if (!res.ok) {
137-
throw new Error(
138-
`Failed to fetch GitHub URL: ${url} - ${res.statusText}`
139-
);
128+
throw new Error(`Failed to fetch GitHub URL: ${url} - ${res.statusText}`);
140129
}
141130
return await res.text();
142131
} else {
143-
const res = await fetch(url, { headers });
144-
if (!res.ok) {
145-
throw new Error(`Failed to fetch URL: ${url} - ${res.statusText}`);
146-
}
147-
return await res.text();
132+
throw new Error(`Unsupported GitHub URL format: ${originalUrl}`);
148133
}
149-
},
134+
}
150135
});
151136

152137
const { writeFile } = promises;
@@ -188,7 +173,7 @@ export class ValidationService extends BaseService {
188173
resolver: {
189174
cache: false,
190175
resolvers: [
191-
createHttpWithAuthResolver(),
176+
createGitHubResolver(),
192177
...(parserOptions.__unstable?.resolver?.resolvers || [])
193178
],
194179
},
@@ -318,7 +303,7 @@ export class ValidationService extends BaseService {
318303
__unstable: {
319304
resolver: {
320305
cache: false,
321-
resolvers: [createHttpWithAuthResolver()],
306+
resolvers: [createGitHubResolver()],
322307
},
323308
},
324309
});
@@ -516,4 +501,4 @@ export class ValidationService extends BaseService {
516501
return 'Unknown';
517502
}
518503
}
519-
}
504+
}

test/unit/services/validation.service.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -226,7 +226,8 @@ describe('ValidationService', () => {
226226

227227
// Should have an invalid-ref diagnostic for the private GitHub URL
228228
const invalidRefDiagnostic = result.data?.diagnostics?.find((d: any) => d.code === 'invalid-ref');
229-
expect(invalidRefDiagnostic).to.not.be.undefined;
229+
// eslint-disable-next-line no-unused-expressions
230+
expect(invalidRefDiagnostic).to.exist;
230231
expect(invalidRefDiagnostic?.message).to.include('Page not found');
231232
expect(invalidRefDiagnostic?.message).to.include('https://github.com/private-org/private-repo/blob/main/schema.yaml');
232233
}

0 commit comments

Comments
 (0)