Skip to content

Commit 3d0a386

Browse files
authoredMar 4, 2024··
feat!: add listStores method (#149)
1 parent 5ad27eb commit 3d0a386

11 files changed

+472
-113
lines changed
 

Diff for: ‎.eslintrc.cjs

+1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ module.exports = {
2323
'unicorn/prefer-ternary': 'off',
2424
'no-unused-vars': 'off',
2525
'@typescript-eslint/no-unused-vars': ['error', { ignoreRestSiblings: true }],
26+
'func-style': 'off',
2627
},
2728
overrides: [
2829
...overrides,

Diff for: ‎src/backend/list_stores.ts

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
export interface ListStoresResponse {
2+
stores: string[]
3+
next_cursor?: string
4+
}

Diff for: ‎src/client.ts

+18-10
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ interface MakeStoreRequestOptions {
1212
metadata?: Metadata
1313
method: HTTPMethod
1414
parameters?: Record<string, string>
15-
storeName: string
15+
storeName?: string
1616
}
1717

1818
export interface ClientOptions {
@@ -31,7 +31,7 @@ interface GetFinalRequestOptions {
3131
metadata?: Metadata
3232
method: string
3333
parameters?: Record<string, string>
34-
storeName: string
34+
storeName?: string
3535
}
3636

3737
export class Client {
@@ -70,6 +70,16 @@ export class Client {
7070
const encodedMetadata = encodeMetadata(metadata)
7171
const consistency = opConsistency ?? this.consistency
7272

73+
let urlPath = `/${this.siteID}`
74+
75+
if (storeName) {
76+
urlPath += `/${storeName}`
77+
}
78+
79+
if (key) {
80+
urlPath += `/${key}`
81+
}
82+
7383
if (this.edgeURL) {
7484
if (consistency === 'strong' && !this.uncachedEdgeURL) {
7585
throw new BlobsConsistencyError()
@@ -83,8 +93,7 @@ export class Client {
8393
headers[METADATA_HEADER_INTERNAL] = encodedMetadata
8494
}
8595

86-
const path = key ? `/${this.siteID}/${storeName}/${key}` : `/${this.siteID}/${storeName}`
87-
const url = new URL(path, consistency === 'strong' ? this.uncachedEdgeURL : this.edgeURL)
96+
const url = new URL(urlPath, consistency === 'strong' ? this.uncachedEdgeURL : this.edgeURL)
8897

8998
for (const key in parameters) {
9099
url.searchParams.set(key, parameters[key])
@@ -97,23 +106,22 @@ export class Client {
97106
}
98107

99108
const apiHeaders: Record<string, string> = { authorization: `Bearer ${this.token}` }
100-
const url = new URL(`/api/v1/blobs/${this.siteID}/${storeName}`, this.apiURL ?? 'https://api.netlify.com')
109+
const url = new URL(`/api/v1/blobs${urlPath}`, this.apiURL ?? 'https://api.netlify.com')
101110

102111
for (const key in parameters) {
103112
url.searchParams.set(key, parameters[key])
104113
}
105114

106-
// If there is no key, we're dealing with the list endpoint, which is
107-
// implemented directly in the Netlify API.
108-
if (key === undefined) {
115+
// If there is no store name, we're listing stores. If there's no key,
116+
// we're listing blobs. Both operations are implemented directly in the
117+
// Netlify API.
118+
if (storeName === undefined || key === undefined) {
109119
return {
110120
headers: apiHeaders,
111121
url: url.toString(),
112122
}
113123
}
114124

115-
url.pathname += `/${key}`
116-
117125
if (encodedMetadata) {
118126
apiHeaders[METADATA_HEADER_EXTERNAL] = encodedMetadata
119127
}

Diff for: ‎src/consistency.test.ts

+9-9
Original file line numberDiff line numberDiff line change
@@ -52,17 +52,17 @@ describe('Consistency configuration', () => {
5252
.get({
5353
headers: { authorization: `Bearer ${edgeToken}` },
5454
response: new Response(value),
55-
url: `${uncachedEdgeURL}/${siteID}/production/${key}`,
55+
url: `${uncachedEdgeURL}/${siteID}/site:production/${key}`,
5656
})
5757
.head({
5858
headers: { authorization: `Bearer ${edgeToken}` },
5959
response: new Response(null, { headers }),
60-
url: `${uncachedEdgeURL}/${siteID}/production/${key}`,
60+
url: `${uncachedEdgeURL}/${siteID}/site:production/${key}`,
6161
})
6262
.get({
6363
headers: { authorization: `Bearer ${edgeToken}` },
6464
response: new Response(value, { headers }),
65-
url: `${uncachedEdgeURL}/${siteID}/production/${key}`,
65+
url: `${uncachedEdgeURL}/${siteID}/site:production/${key}`,
6666
})
6767

6868
globalThis.fetch = mockStore.fetch
@@ -107,17 +107,17 @@ describe('Consistency configuration', () => {
107107
.get({
108108
headers: { authorization: `Bearer ${edgeToken}` },
109109
response: new Response(value),
110-
url: `${uncachedEdgeURL}/${siteID}/production/${key}`,
110+
url: `${uncachedEdgeURL}/${siteID}/site:production/${key}`,
111111
})
112112
.head({
113113
headers: { authorization: `Bearer ${edgeToken}` },
114114
response: new Response(null, { headers }),
115-
url: `${uncachedEdgeURL}/${siteID}/production/${key}`,
115+
url: `${uncachedEdgeURL}/${siteID}/site:production/${key}`,
116116
})
117117
.get({
118118
headers: { authorization: `Bearer ${edgeToken}` },
119119
response: new Response(value, { headers }),
120-
url: `${uncachedEdgeURL}/${siteID}/production/${key}`,
120+
url: `${uncachedEdgeURL}/${siteID}/site:production/${key}`,
121121
})
122122

123123
globalThis.fetch = mockStore.fetch
@@ -213,17 +213,17 @@ describe('Consistency configuration', () => {
213213
.get({
214214
headers: { authorization: `Bearer ${edgeToken}` },
215215
response: new Response(value),
216-
url: `${uncachedEdgeURL}/${siteID}/production/${key}`,
216+
url: `${uncachedEdgeURL}/${siteID}/site:production/${key}`,
217217
})
218218
.head({
219219
headers: { authorization: `Bearer ${edgeToken}` },
220220
response: new Response(null, { headers }),
221-
url: `${edgeURL}/${siteID}/production/${key}`,
221+
url: `${edgeURL}/${siteID}/site:production/${key}`,
222222
})
223223
.get({
224224
headers: { authorization: `Bearer ${edgeToken}` },
225225
response: new Response(value, { headers }),
226-
url: `${edgeURL}/${siteID}/production/${key}`,
226+
url: `${edgeURL}/${siteID}/site:production/${key}`,
227227
})
228228

229229
globalThis.fetch = mockStore.fetch

Diff for: ‎src/lambda_compat.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,12 @@ describe('With edge credentials', () => {
4848
.get({
4949
headers: { authorization: `Bearer ${edgeToken}` },
5050
response: new Response(value),
51-
url: `${edgeURL}/${siteID}/production/${key}`,
51+
url: `${edgeURL}/${siteID}/site:production/${key}`,
5252
})
5353
.get({
5454
headers: { authorization: `Bearer ${edgeToken}` },
5555
response: new Response(value),
56-
url: `${edgeURL}/${siteID}/production/${key}`,
56+
url: `${edgeURL}/${siteID}/site:production/${key}`,
5757
})
5858

5959
globalThis.fetch = mockStore.fetch

Diff for: ‎src/list.test.ts

+22-22
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ describe('list', () => {
5959
next_cursor: 'cursor_1',
6060
}),
6161
),
62-
url: `https://api.netlify.com/api/v1/blobs/${siteID}/${storeName}`,
62+
url: `https://api.netlify.com/api/v1/blobs/${siteID}/site:${storeName}`,
6363
})
6464
.get({
6565
headers: { authorization: `Bearer ${apiToken}` },
@@ -83,7 +83,7 @@ describe('list', () => {
8383
next_cursor: 'cursor_2',
8484
}),
8585
),
86-
url: `https://api.netlify.com/api/v1/blobs/${siteID}/${storeName}?cursor=cursor_1`,
86+
url: `https://api.netlify.com/api/v1/blobs/${siteID}/site:${storeName}?cursor=cursor_1`,
8787
})
8888
.get({
8989
headers: { authorization: `Bearer ${apiToken}` },
@@ -100,7 +100,7 @@ describe('list', () => {
100100
directories: [],
101101
}),
102102
),
103-
url: `https://api.netlify.com/api/v1/blobs/${siteID}/${storeName}?cursor=cursor_2`,
103+
url: `https://api.netlify.com/api/v1/blobs/${siteID}/site:${storeName}?cursor=cursor_2`,
104104
})
105105

106106
globalThis.fetch = mockStore.fetch
@@ -148,7 +148,7 @@ describe('list', () => {
148148
next_cursor: 'cursor_1',
149149
}),
150150
),
151-
url: `https://api.netlify.com/api/v1/blobs/${siteID}/${storeName}?directories=true`,
151+
url: `https://api.netlify.com/api/v1/blobs/${siteID}/site:${storeName}?directories=true`,
152152
})
153153
.get({
154154
headers: { authorization: `Bearer ${apiToken}` },
@@ -172,7 +172,7 @@ describe('list', () => {
172172
next_cursor: 'cursor_2',
173173
}),
174174
),
175-
url: `https://api.netlify.com/api/v1/blobs/${siteID}/${storeName}?directories=true&cursor=cursor_1`,
175+
url: `https://api.netlify.com/api/v1/blobs/${siteID}/site:${storeName}?directories=true&cursor=cursor_1`,
176176
})
177177
.get({
178178
headers: { authorization: `Bearer ${apiToken}` },
@@ -189,7 +189,7 @@ describe('list', () => {
189189
directories: ['dir3'],
190190
}),
191191
),
192-
url: `https://api.netlify.com/api/v1/blobs/${siteID}/${storeName}?directories=true&cursor=cursor_2`,
192+
url: `https://api.netlify.com/api/v1/blobs/${siteID}/site:${storeName}?directories=true&cursor=cursor_2`,
193193
})
194194
.get({
195195
headers: { authorization: `Bearer ${apiToken}` },
@@ -206,7 +206,7 @@ describe('list', () => {
206206
directories: [],
207207
}),
208208
),
209-
url: `https://api.netlify.com/api/v1/blobs/${siteID}/${storeName}?prefix=dir2%2F&directories=true`,
209+
url: `https://api.netlify.com/api/v1/blobs/${siteID}/site:${storeName}?prefix=dir2%2F&directories=true`,
210210
})
211211

212212
globalThis.fetch = mockStore.fetch
@@ -258,7 +258,7 @@ describe('list', () => {
258258
],
259259
}),
260260
),
261-
url: `https://api.netlify.com/api/v1/blobs/${siteID}/${storeName}?prefix=group%2F`,
261+
url: `https://api.netlify.com/api/v1/blobs/${siteID}/site:${storeName}?prefix=group%2F`,
262262
})
263263

264264
globalThis.fetch = mockStore.fetch
@@ -303,7 +303,7 @@ describe('list', () => {
303303
next_cursor: 'cursor_2',
304304
}),
305305
),
306-
url: `https://api.netlify.com/api/v1/blobs/${siteID}/${storeName}`,
306+
url: `https://api.netlify.com/api/v1/blobs/${siteID}/site:${storeName}`,
307307
})
308308
.get({
309309
headers: { authorization: `Bearer ${apiToken}` },
@@ -319,7 +319,7 @@ describe('list', () => {
319319
],
320320
}),
321321
),
322-
url: `https://api.netlify.com/api/v1/blobs/${siteID}/${storeName}?cursor=cursor_2`,
322+
url: `https://api.netlify.com/api/v1/blobs/${siteID}/site:${storeName}?cursor=cursor_2`,
323323
})
324324

325325
globalThis.fetch = mockStore.fetch
@@ -373,7 +373,7 @@ describe('list', () => {
373373
next_cursor: 'cursor_1',
374374
}),
375375
),
376-
url: `${edgeURL}/${siteID}/${storeName}`,
376+
url: `${edgeURL}/${siteID}/site:${storeName}`,
377377
})
378378
.get({
379379
headers: { authorization: `Bearer ${edgeToken}` },
@@ -397,7 +397,7 @@ describe('list', () => {
397397
next_cursor: 'cursor_2',
398398
}),
399399
),
400-
url: `${edgeURL}/${siteID}/${storeName}?cursor=cursor_1`,
400+
url: `${edgeURL}/${siteID}/site:${storeName}?cursor=cursor_1`,
401401
})
402402
.get({
403403
headers: { authorization: `Bearer ${edgeToken}` },
@@ -414,7 +414,7 @@ describe('list', () => {
414414
directories: [],
415415
}),
416416
),
417-
url: `${edgeURL}/${siteID}/${storeName}?cursor=cursor_2`,
417+
url: `${edgeURL}/${siteID}/site:${storeName}?cursor=cursor_2`,
418418
})
419419
.get({
420420
headers: { authorization: `Bearer ${edgeToken}` },
@@ -431,7 +431,7 @@ describe('list', () => {
431431
directories: [],
432432
}),
433433
),
434-
url: `${edgeURL}/${siteID}/${storeName}?prefix=dir2%2F`,
434+
url: `${edgeURL}/${siteID}/site:${storeName}?prefix=dir2%2F`,
435435
})
436436

437437
globalThis.fetch = mockStore.fetch
@@ -487,7 +487,7 @@ describe('list', () => {
487487
next_cursor: 'cursor_1',
488488
}),
489489
),
490-
url: `${edgeURL}/${siteID}/${storeName}?directories=true`,
490+
url: `${edgeURL}/${siteID}/site:${storeName}?directories=true`,
491491
})
492492
.get({
493493
headers: { authorization: `Bearer ${edgeToken}` },
@@ -511,7 +511,7 @@ describe('list', () => {
511511
next_cursor: 'cursor_2',
512512
}),
513513
),
514-
url: `${edgeURL}/${siteID}/${storeName}?directories=true&cursor=cursor_1`,
514+
url: `${edgeURL}/${siteID}/site:${storeName}?directories=true&cursor=cursor_1`,
515515
})
516516
.get({
517517
headers: { authorization: `Bearer ${edgeToken}` },
@@ -528,7 +528,7 @@ describe('list', () => {
528528
directories: ['dir3'],
529529
}),
530530
),
531-
url: `${edgeURL}/${siteID}/${storeName}?directories=true&cursor=cursor_2`,
531+
url: `${edgeURL}/${siteID}/site:${storeName}?directories=true&cursor=cursor_2`,
532532
})
533533
.get({
534534
headers: { authorization: `Bearer ${edgeToken}` },
@@ -545,7 +545,7 @@ describe('list', () => {
545545
directories: [],
546546
}),
547547
),
548-
url: `${edgeURL}/${siteID}/${storeName}?prefix=dir2%2F&directories=true`,
548+
url: `${edgeURL}/${siteID}/site:${storeName}?prefix=dir2%2F&directories=true`,
549549
})
550550

551551
globalThis.fetch = mockStore.fetch
@@ -598,7 +598,7 @@ describe('list', () => {
598598
],
599599
}),
600600
),
601-
url: `${edgeURL}/${siteID}/${storeName}?prefix=group%2F`,
601+
url: `${edgeURL}/${siteID}/site:${storeName}?prefix=group%2F`,
602602
})
603603

604604
globalThis.fetch = mockStore.fetch
@@ -644,7 +644,7 @@ describe('list', () => {
644644
next_cursor: 'cursor_2',
645645
}),
646646
),
647-
url: `${edgeURL}/${siteID}/${storeName}`,
647+
url: `${edgeURL}/${siteID}/site:${storeName}`,
648648
})
649649
.get({
650650
headers: { authorization: `Bearer ${edgeToken}` },
@@ -667,7 +667,7 @@ describe('list', () => {
667667
next_cursor: 'cursor_3',
668668
}),
669669
),
670-
url: `${edgeURL}/${siteID}/${storeName}?cursor=cursor_2`,
670+
url: `${edgeURL}/${siteID}/site:${storeName}?cursor=cursor_2`,
671671
})
672672
.get({
673673
headers: { authorization: `Bearer ${edgeToken}` },
@@ -683,7 +683,7 @@ describe('list', () => {
683683
],
684684
}),
685685
),
686-
url: `${edgeURL}/${siteID}/${storeName}?cursor=cursor_3`,
686+
url: `${edgeURL}/${siteID}/site:${storeName}?cursor=cursor_3`,
687687
})
688688

689689
globalThis.fetch = mockStore.fetch

0 commit comments

Comments
 (0)
Please sign in to comment.