Skip to content

Commit f5e9ad1

Browse files
committed
fix: support deferred path params for empty route arg values
1 parent 16d8ed2 commit f5e9ad1

3 files changed

Lines changed: 65 additions & 6 deletions

File tree

src/index.ts

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,22 @@ function withContextSignal(
114114
}
115115
}
116116

117+
function resolvePathSegmentFromCallArg(body: unknown): string | undefined {
118+
if (typeof body !== 'object' || body === null) return undefined
119+
120+
const entries = Object.entries(body as Record<string, unknown>)
121+
if (entries.length === 0) return undefined
122+
123+
const [paramName, paramValue] = entries[0]
124+
125+
// Keep dynamic placeholder when call-site intentionally passes an empty value.
126+
if (paramValue === '' || paramValue == null) {
127+
return `:${paramName}`
128+
}
129+
130+
return String(paramValue)
131+
}
132+
117133
interface ProxyContext {
118134
raw: any
119135
prefix: QueryKey
@@ -288,9 +304,9 @@ function createEdenTQProxy(
288304
)
289305
},
290306
apply(_, __, [body]) {
291-
if (typeof body === 'object' && body !== null) {
292-
const paramValue = Object.values(body)[0] as string
293-
return createEdenTQProxy(ctx, [...paths, paramValue])
307+
const paramSegment = resolvePathSegmentFromCallArg(body)
308+
if (paramSegment !== undefined) {
309+
return createEdenTQProxy(ctx, [...paths, paramSegment])
294310
}
295311
return createEdenTQProxy(ctx, paths)
296312
}
@@ -400,9 +416,9 @@ function createEdenTQUtilsProxy(
400416
)
401417
},
402418
apply(_, __, [body]) {
403-
if (typeof body === 'object' && body !== null) {
404-
const paramValue = Object.values(body)[0] as string
405-
return createEdenTQUtilsProxy(ctx, [...paths, paramValue])
419+
const paramSegment = resolvePathSegmentFromCallArg(body)
420+
if (paramSegment !== undefined) {
421+
return createEdenTQUtilsProxy(ctx, [...paths, paramSegment])
406422
}
407423
return createEdenTQUtilsProxy(ctx, paths)
408424
}

test/tanstack-query-advanced.test.ts

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -234,6 +234,17 @@ describe('EdenTQ Utils', () => {
234234
expect(data).toEqual({ id: '42', name: 'John' })
235235
})
236236

237+
it('supports deferred params in utils route calls', async () => {
238+
const queryClient = new QueryClient()
239+
const utils = createEdenTQUtils(eden, queryClient)
240+
241+
const data = await utils.user({ id: '' }).get.ensureData({
242+
params: { id: 'deferred-42' }
243+
})
244+
245+
expect(data).toEqual({ id: 'deferred-42', name: 'John' })
246+
})
247+
237248
it('cancel cancels in-flight queries', async () => {
238249
const queryClient = new QueryClient()
239250
const utils = createEdenTQUtils(eden, queryClient)

test/tanstack-query-real-world.test.ts

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,25 @@ describe('Real-world API patterns', () => {
142142

143143
expect(options.queryKey).toEqual(['cases', caseId, 'share-links'])
144144
})
145+
146+
it('supports deferred path params when placeholder value is empty', async () => {
147+
const caseId = 'case-deferred-query'
148+
149+
const options = eden.cases({ id: '' })['share-links'].get.queryOptions({
150+
params: { id: caseId }
151+
})
152+
153+
expect(options.queryKey).toEqual([
154+
'eden',
155+
'get',
156+
['cases', ':id', 'share-links'],
157+
{ id: caseId },
158+
null
159+
])
160+
161+
const result = await options.queryFn()
162+
expect(result.data[0].url).toContain(`/${caseId}/`)
163+
})
145164
})
146165

147166
describe('Create Share Link Mutation', () => {
@@ -177,6 +196,19 @@ describe('Real-world API patterns', () => {
177196
contact: { id: string; email: string | null; name: string } | null
178197
}>()
179198
})
199+
200+
it('uses mutation params when placeholder value is empty', async () => {
201+
const caseId = 'case-deferred-mutation'
202+
203+
const options = eden.cases({ id: '' })['share-link'].post.mutationOptions()
204+
const result = await options.mutationFn({
205+
params: { id: caseId },
206+
body: { expiresInDays: 7 }
207+
})
208+
209+
expect(result.url).toContain(`/${caseId}/`)
210+
expect(result.expiresInDays).toBe(7)
211+
})
180212
})
181213

182214
describe('Revoke Share Link Mutation', () => {

0 commit comments

Comments
 (0)