diff --git a/.changepacks/changepack_log_KuqHZb0J7TpXTO4Yn7W6O.json b/.changepacks/changepack_log_KuqHZb0J7TpXTO4Yn7W6O.json new file mode 100644 index 0000000..dd7ae71 --- /dev/null +++ b/.changepacks/changepack_log_KuqHZb0J7TpXTO4Yn7W6O.json @@ -0,0 +1 @@ +{"changes":{"packages/fetch/package.json":"Patch"},"note":"Fix missing method issue","date":"2026-03-06T12:21:47.966654100Z"} \ No newline at end of file diff --git a/packages/fetch/src/__tests__/url-map.test.ts b/packages/fetch/src/__tests__/url-map.test.ts index 2a32e98..b3c7501 100644 --- a/packages/fetch/src/__tests__/url-map.test.ts +++ b/packages/fetch/src/__tests__/url-map.test.ts @@ -64,7 +64,7 @@ test.each([ ] as const)('getApiEndpointInfo returns default for non-existent key: %s -> %s', async (key, expected, envValue) => { process.env.DEVUP_API_URL_MAP = envValue const { getApiEndpointInfo } = await import(`../url-map`) - expect(getApiEndpointInfo(key, '')).toEqual(expected) + expect(getApiEndpointInfo(key, '', 'GET')).toEqual(expected) }) test.each([ @@ -73,7 +73,7 @@ test.each([ ] as const)('getApiEndpointInfo works with empty URL map: %s -> %s', async (key, expected, envValue) => { process.env.DEVUP_API_URL_MAP = envValue const { getApiEndpointInfo } = await import(`../url-map?t=${random}`) - expect(getApiEndpointInfo(key, 'foo').url).toBe(expected) + expect(getApiEndpointInfo(key, 'foo', 'GET').url).toBe(expected) }) test.each([ @@ -82,7 +82,19 @@ test.each([ ] as const)('getApiEndpointInfo works with empty URL map: %s -> %s', async (key, expected, envValue) => { process.env.DEVUP_API_URL_MAP = envValue const { getApiEndpointInfo } = await import(`../url-map?t=${random}`) - expect(getApiEndpointInfo(key, 'foo')).toEqual(expected) + expect(getApiEndpointInfo(key, 'foo', 'GET')).toEqual(expected) +}) + +test.each([ + [['GET', 'anyKey'], '{}'], + [['POST', 'anyKey'], '{}'], + [['PUT', 'anyKey'], '{}'], + [['DELETE', 'anyKey'], '{}'], + [['PATCH', 'anyKey'], '{}'], +] as const)('getApiEndpointInfo works with empty URL map: %s -> %s', async (key, envValue) => { + process.env.DEVUP_API_URL_MAP = envValue + const { getApiEndpointInfo } = await import(`../url-map?t=${random}`) + expect(getApiEndpointInfo(key[1], 'foo', key[0]).method).toEqual(key[0]) }) test.each([ @@ -91,7 +103,7 @@ test.each([ ] as const)('getApiEndpointInfo works when DEVUP_API_URL_MAP is not set: %s -> %s', async (key, expected) => { delete process.env.DEVUP_API_URL_MAP const { getApiEndpointInfo } = await import(`../url-map?t=${random}`) - expect(getApiEndpointInfo(key, 'foo').url).toBe(expected) + expect(getApiEndpointInfo(key, 'foo', 'GET').url).toBe(expected) }) test.each([ @@ -100,145 +112,5 @@ test.each([ ] as const)('getApiEndpointInfo works when DEVUP_API_URL_MAP is not set: %s -> %s', async (key, expected) => { delete process.env.DEVUP_API_URL_MAP const { getApiEndpointInfo } = await import(`../url-map?t=${random}`) - expect(getApiEndpointInfo(key, 'foo').url).toBe(expected) + expect(getApiEndpointInfo(key, 'foo', 'GET').url).toBe(expected) }) - -// test.each([ -// ['anyKey', { method: 'GET', url: 'anyKey' }], -// ['test', { method: 'GET', url: 'test' }], -// ] as const)('getApiEndpointInfo works when DEVUP_API_URL_MAP is not set: %s -> %s', async (key, expected) => { -// delete process.env.DEVUP_API_URL_MAP -// const { getApiEndpointInfo } = await import(`../url-map?t=1`) -// expect(getApiEndpointInfo(key, 'foo')).toEqual(expected) -// }) - -// test('getApiEndpointInfo handles key that exists but url property is missing', async () => { -// const urlMapWithoutUrl = { -// testKey: { method: 'GET' as const }, -// } -// process.env.DEVUP_API_URL_MAP = JSON.stringify(urlMapWithoutUrl) -// const { getApiEndpointInfo } = await import( -// `../url-map` -// ) -// // When url property is missing, optional chaining returns undefined, so key is returned -// expect(getApiEndpointInfo('testKey', 'foo').url).toBe('testKey') -// }) - -// test('DEVUP_API_URL_MAP constant is exported and accessible', async () => { -// const testUrlMap = { -// '': { testKey: { method: 'GET' as const, url: '/test' } }, -// } -// process.env.DEVUP_API_URL_MAP = JSON.stringify(testUrlMap) -// const urlMapModule = await import( -// `../url-map` -// ) -// expect(urlMapModule).toHaveProperty('DEVUP_API_URL_MAP') -// expect(typeof urlMapModule.DEVUP_API_URL_MAP).toBe('object') -// // Directly access the constant to ensure it's covered -// const urlMap = urlMapModule.DEVUP_API_URL_MAP -// expect(urlMap).toEqual(testUrlMap) -// // Verify it's used by getApiEndpointInfo function -// expect(urlMapModule.getApiEndpointInfo('testKey', 'foo').url).toBe('/test') -// }) - -// test('DEVUP_API_URL_MAP uses fallback when env var is undefined', async () => { -// delete process.env.DEVUP_API_URL_MAP -// const urlMapModule = await import( -// `../url-map` -// ) -// // Directly access the constant to ensure the fallback path is covered -// const urlMap = urlMapModule.DEVUP_API_URL_MAP -// expect(urlMap).toEqual({}) -// expect(urlMapModule.getApiEndpointInfo('anyKey', 'foo').url).toBe('anyKey') -// // Explicitly call getApiEndpointInfo to ensure it's covered -// const result = urlMapModule.getApiEndpointInfo('anyKey', 'foo') -// expect(result).toEqual({ -// method: 'GET', -// url: 'anyKey', -// }) -// // Also test that the function exists and is callable -// expect(typeof urlMapModule.getApiEndpointInfo).toBe('function') -// }) - -// test('DEVUP_API_URL_MAP uses fallback when env var is empty string', async () => { -// process.env.DEVUP_API_URL_MAP = '' -// const urlMapModule = await import( -// `../url-map` -// ) -// // Directly access the constant to ensure the fallback path is covered -// const urlMap = urlMapModule.DEVUP_API_URL_MAP -// expect(urlMap).toEqual({}) -// expect(urlMapModule.getApiEndpointInfo('anyKey', 'foo').url).toBe('anyKey') -// expect(urlMapModule.getApiEndpointInfo('anyKey', 'foo')).toEqual({ -// method: 'GET', -// url: 'anyKey', -// }) -// }) - -// test('getApiEndpointInfo handles key where DEVUP_API_URL_MAP[key] exists but url is undefined', async () => { -// const urlMapWithUndefinedUrl = { -// testKey: { method: 'GET' as const }, -// } -// process.env.DEVUP_API_URL_MAP = JSON.stringify(urlMapWithUndefinedUrl) -// const { getApiEndpointInfo } = await import( -// `../url-map` -// ) -// // When url property is missing, optional chaining returns undefined, so key is returned -// expect(getApiEndpointInfo('testKey', 'foo').url).toBe('testKey') -// }) - -// test('getApiEndpointInfo handles key where DEVUP_API_URL_MAP[key] exists but url is null', async () => { -// const urlMapWithNullUrl = { -// testKey: { method: 'GET' as const, url: null as unknown as string }, -// } -// process.env.DEVUP_API_URL_MAP = JSON.stringify(urlMapWithNullUrl) -// const { getApiEndpointInfo } = await import( -// `../url-map` -// ) -// // When url is null, optional chaining returns null, so key is returned -// expect(getApiEndpointInfo('testKey', 'foo').url).toBe('testKey') -// }) - -// test('getApiEndpointInfo handles key where DEVUP_API_URL_MAP[key] exists but url is empty string', async () => { -// const urlMapWithEmptyUrl = { -// testKey: { method: 'GET' as const, url: '' }, -// } -// process.env.DEVUP_API_URL_MAP = JSON.stringify(urlMapWithEmptyUrl) -// const { getApiEndpointInfo } = await import( -// `../url-map` -// ) -// // When url is empty string, it's falsy, so key is returned -// expect(getApiEndpointInfo('testKey', 'foo').url).toBe('testKey') -// }) - -// test('getApiEndpointInfo returns default when key does not exist in map (explicit coverage for line 10)', async () => { -// const urlMap = { existingKey: { method: 'POST' as const, url: '/existing' } } -// process.env.DEVUP_API_URL_MAP = JSON.stringify(urlMap) -// const { getApiEndpointInfo } = await import( -// `../url-map` -// ) -// // Explicitly test the if(!result) branch to ensure line 10 is covered -// const result = getApiEndpointInfo('nonExistentKeyInMap', 'foo') -// expect(result).toEqual({ method: 'GET', url: 'nonExistentKeyInMap' }) -// expect(result.method).toBe('GET') -// expect(result.url).toBe('nonExistentKeyInMap') -// }) - -// test('getApiEndpointInfo returns result when key exists with url (explicit coverage for lines 12-13)', async () => { -// const urlMap = { -// '': { -// testKey: { method: 'PUT' as const, url: '/test/url' }, -// }, -// } -// process.env.DEVUP_API_URL_MAP = JSON.stringify(urlMap) -// const { getApiEndpointInfo } = await import( -// `../url-map?t=${Date.now()+Math.random()}` -// ) -// // Explicitly test the result.url ||= key and return result path (lines 12-13) -// const result = getApiEndpointInfo('testKey', 'foo') -// expect(result).toEqual({ method: 'PUT', url: '/test/url' }) -// expect(result.method).toBe('PUT') -// expect(result.url).toBe('/test/url') -// // Verify that url was not changed (since it already exists) -// expect(result.url).not.toBe('testKey') -// }) diff --git a/packages/fetch/src/api.ts b/packages/fetch/src/api.ts index 19da778..556e58f 100644 --- a/packages/fetch/src/api.ts +++ b/packages/fetch/src/api.ts @@ -223,7 +223,12 @@ export class DevupApi> { ): Promise< DevupApiResponse, ExtractValue> > { - const { method, url, bodyType } = getApiEndpointInfo(path, this.serverName) + const { method, url, bodyType } = getApiEndpointInfo( + path, + this.serverName, + (options[0]?.method as 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH') || + 'GET', + ) const { middleware = [], query, diff --git a/packages/fetch/src/url-map.ts b/packages/fetch/src/url-map.ts index fd663d7..4909495 100644 --- a/packages/fetch/src/url-map.ts +++ b/packages/fetch/src/url-map.ts @@ -8,9 +8,10 @@ export const DEVUP_API_URL_MAP: Record< export function getApiEndpointInfo( key: string, serverName: string, + method: 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH', ): UrlMapValue { const result = DEVUP_API_URL_MAP[serverName]?.[key] ?? { - method: 'GET', + method, url: key, } result.url ||= key