Skip to content

Commit 81896c7

Browse files
authored
fix: handle .NET & Java url schemes (#82)
1 parent c99deb5 commit 81896c7

File tree

5 files changed

+22
-44
lines changed

5 files changed

+22
-44
lines changed

src/tools/fetchDocPage/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ Cache keys are generated from the URL structure to ensure uniqueness:
112112
```typescript
113113
// Example transformation
114114
URL: https://docs.powertools.aws.dev/lambda/python/2.1.0/core/logger/index.md
115-
Key: python/2.1.0/core/logger/index.md
115+
Key: lambda/python/2.1.0/core/logger/index.md
116116
```
117117

118118
### 4. Cache Validation Flow

src/tools/fetchDocPage/schemas.ts

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,9 @@ import { ALLOWED_DOMAIN, runtimes } from '../../constants.ts';
55
* Schema for the input of the tool.
66
*
77
* Used to parse the tool arguments and validate them before calling the tool.
8+
*
9+
* TypeScript and Python runtimes support semantic versioning (x.y.z) or 'latest' in the URL,
10+
* so we validate the URL structure accordingly.
811
*/
912
const schema = {
1013
url: z
@@ -20,11 +23,13 @@ const schema = {
2023
if (!runtimes.includes(runtime as (typeof runtimes)[number])) {
2124
return false;
2225
}
23-
const version = pathParts[2];
24-
const isValidSemver = /^\d+\.\d+\.\d+$/.test(version);
25-
const isLatest = version === 'latest';
26-
if (isValidSemver === false && isLatest === false) {
27-
return false;
26+
if (runtime === 'typescript' || runtime === 'python') {
27+
const version = pathParts[2];
28+
const isValidSemver = /^\d+\.\d+\.\d+$/.test(version);
29+
const isLatest = version === 'latest';
30+
if (isValidSemver === false && isLatest === false) {
31+
return false;
32+
}
2833
}
2934

3035
return true;

src/tools/fetchDocPage/tool.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import { buildResponse } from '../shared/buildResponse.ts';
99
import { name as toolName } from './constants.ts';
1010
import { CacheError } from './errors.ts';
1111
import type { schema } from './schemas.ts';
12-
import { generateCacheKey, getRemotePage, getRemotePageETag } from './utils.ts';
12+
import { getRemotePage, getRemotePageETag } from './utils.ts';
1313

1414
/**
1515
* Fetch a documentation page from remote or local cache.
@@ -37,7 +37,7 @@ const tool = async (props: {
3737
logger.appendKeys({ url: url.toString() });
3838

3939
const cachePath = join(CACHE_BASE_PATH, 'markdown-cache');
40-
const cacheKey = generateCacheKey({ url });
40+
const cacheKey = url.pathname;
4141
logger.debug('Generated cache key', { cacheKey });
4242

4343
try {

src/tools/fetchDocPage/utils.ts

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -76,19 +76,4 @@ const getRemotePageETag = async (url: URL): Promise<string | null> => {
7676
}
7777
};
7878

79-
/**
80-
* Generate a cache key based on the URL of a documentation page.
81-
*
82-
* @param props - options for generating a cache key
83-
* @param props.url - the URL of the documentation page
84-
*/
85-
const generateCacheKey = (props: { url: URL }): string => {
86-
const { url } = props;
87-
const pathParts = url.pathname.split('/').filter(Boolean);
88-
const [_, runtime, version, ...rest] = pathParts;
89-
const pagePath = rest.join('/');
90-
91-
return `${runtime}/${version}/${pagePath}`;
92-
};
93-
94-
export { getRemotePage, getRemotePageETag, generateCacheKey };
79+
export { getRemotePage, getRemotePageETag };

tests/unit/fetchDocPage.test.ts

Lines changed: 8 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import {
1212
import { POWERTOOLS_BASE_URL } from '../../src/constants.ts';
1313
import { schema, tool } from '../../src/tools/fetchDocPage/index.ts';
1414
import {
15-
generateCacheKey,
1615
getRemotePage,
1716
getRemotePageETag,
1817
} from '../../src/tools/fetchDocPage/utils.ts';
@@ -38,6 +37,10 @@ describe('schema', () => {
3837
type: 'semver',
3938
url: `${POWERTOOLS_BASE_URL}/typescript/1.2.4/features/metrics/`,
4039
},
40+
{
41+
type: 'dotnet no version',
42+
url: `${POWERTOOLS_BASE_URL}/dotnet/features/metrics/`,
43+
},
4144
])('parses a valid URL ($type)', ({ url }) => {
4245
// Act
4346
const result = schema.url.parse(url);
@@ -282,21 +285,6 @@ describe('utils', () => {
282285
);
283286
});
284287
});
285-
286-
describe('generateCacheKey', () => {
287-
it('generates a cache key based on the URL', () => {
288-
// Prepare
289-
const url = new URL(
290-
`${POWERTOOLS_BASE_URL}/typescript/latest/features/metrics/index.md`
291-
);
292-
293-
// Act
294-
const cacheKey = generateCacheKey({ url });
295-
296-
// Assess
297-
expect(cacheKey).toBe('typescript/latest/features/metrics/index.md');
298-
});
299-
});
300288
});
301289

302290
describe('tool', () => {
@@ -358,7 +346,7 @@ describe('tool', () => {
358346
data: Buffer.from(expectedContent),
359347
});
360348
const url = new URL(`${baseUrl}metrics/index.md`);
361-
const cacheKey = generateCacheKey({ url });
349+
const cacheKey = url.pathname;
362350

363351
// Act
364352
const result = await tool({ url });
@@ -387,7 +375,7 @@ describe('tool', () => {
387375
// Prepare
388376
mocks.getFromCache.mockRejectedValueOnce(new Error('Cache miss'));
389377
const url = new URL(`${baseUrl}no-etag-for-some-reason.md`);
390-
const cacheKey = generateCacheKey({ url });
378+
const cacheKey = url.pathname;
391379

392380
// Act
393381
const result = await tool({ url });
@@ -413,7 +401,7 @@ describe('tool', () => {
413401
data: Buffer.from('54321'),
414402
});
415403
const url = new URL(`${baseUrl}metrics/index.md`);
416-
const cacheKey = generateCacheKey({ url });
404+
const cacheKey = url.pathname;
417405
const expectedContent =
418406
'Metrics is a feature of PowerTools for TypeScript.';
419407

@@ -453,7 +441,7 @@ describe('tool', () => {
453441
});
454442
mocks.getFromCache.mockRejectedValueOnce(new Error('Cache miss'));
455443
const url = new URL(`${baseUrl}metrics/index.md`);
456-
const cacheKey = generateCacheKey({ url });
444+
const cacheKey = url.pathname;
457445
const expectedContent =
458446
'Metrics is a feature of PowerTools for TypeScript.';
459447

0 commit comments

Comments
 (0)