From efd4a1d3080038a3861f2c62a9f898a24157b338 Mon Sep 17 00:00:00 2001 From: Cody Olsen Date: Fri, 20 Sep 2024 13:11:18 +0200 Subject: [PATCH] feat(live): add experimental `includeDrafts` option --- package-lock.json | 4 ++-- package.json | 2 +- src/data/live.ts | 35 ++++++++++++++++++++++++----- test/live.test.ts | 56 +++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 89 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index ce77c8d6..a41505c5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@sanity/client", - "version": "6.21.3", + "version": "6.21.4-canary.2", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@sanity/client", - "version": "6.21.3", + "version": "6.21.4-canary.2", "license": "MIT", "dependencies": { "@sanity/eventsource": "^5.0.2", diff --git a/package.json b/package.json index c3a3aafe..2674bef1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@sanity/client", - "version": "6.21.3", + "version": "6.21.4-canary.2", "description": "Client for retrieving, creating and patching data from Sanity.io", "keywords": [ "sanity", diff --git a/src/data/live.ts b/src/data/live.ts index 57261a8f..bd719e5c 100644 --- a/src/data/live.ts +++ b/src/data/live.ts @@ -18,8 +18,14 @@ export class LiveClient { /** * Requires `apiVersion` to be `2021-03-26` or later. */ - events(): Observable { - const apiVersion = this.#client.config().apiVersion.replace(/^v/, '') + events({ + includeDrafts = false, + }: { + /** @alpha this API is experimental and may change or even be removed */ + includeDrafts?: boolean + } = {}): Observable { + const {apiVersion: _apiVersion, token} = this.#client.config() + const apiVersion = _apiVersion.replace(/^v/, '') if (apiVersion !== 'X' && apiVersion < requiredApiVersion) { throw new Error( `The live events API requires API version ${requiredApiVersion} or later. ` + @@ -27,10 +33,29 @@ export class LiveClient { `Please update your API version to use this feature.`, ) } + if (includeDrafts && !token) { + throw new Error( + `The live events API requires a token when 'includeDrafts: true'. Please update your client configuration. The token should have the lowest possible access role.`, + ) + } + if (includeDrafts && apiVersion !== 'X') { + throw new Error( + `The live events API requires API version X when 'includeDrafts: true'. This API is experimental and may change or even be removed.`, + ) + } const path = _getDataUrl(this.#client, 'live/events') const url = new URL(this.#client.getUrl(path, false)) + if (includeDrafts) { + url.searchParams.set('includeDrafts', 'true') + } const listenFor = ['restart', 'message'] as const + const esOptions: EventSourceInit & {headers?: Record} = {} + if (includeDrafts && token) { + esOptions.headers = { + Authorization: `Bearer ${token}`, + } + } return new Observable((observer) => { let es: InstanceType | undefined @@ -83,8 +108,8 @@ export class LiveClient { async function getEventSource() { const EventSourceImplementation: typeof EventSource = - typeof EventSource === 'undefined' - ? ((await import('@sanity/eventsource')).default as typeof EventSource) + typeof EventSource === 'undefined' || esOptions.headers + ? ((await import('@sanity/eventsource')).default as unknown as typeof EventSource) : EventSource // If the listener has been unsubscribed from before we managed to load the module, @@ -93,7 +118,7 @@ export class LiveClient { return } - const evs = new EventSourceImplementation(url.toString()) + const evs = new EventSourceImplementation(url.toString(), esOptions) evs.addEventListener('error', onError) for (const type of listenFor) { evs.addEventListener(type, onMessage) diff --git a/test/live.test.ts b/test/live.test.ts index a6bc9721..e11a3941 100644 --- a/test/live.test.ts +++ b/test/live.test.ts @@ -64,6 +64,19 @@ describe.skipIf(typeof EdgeRuntime === 'string' || typeof document !== 'undefine `[Error: The live events API requires API version 2021-03-26 or later. The current API version is 2020-01-01. Please update your API version to use this feature.]`, ) }) + test('requires token when includeDrafts is true', () => { + const client = getClient({apiVersion: 'vX', port: 1234}) + expect(() => client.live.events({includeDrafts: true})).toThrowErrorMatchingInlineSnapshot( + `[Error: The live events API requires a token when 'includeDrafts: true'. Please update your client configuration. The token should have the lowest possible access role.]`, + ) + }) + test('requires apiVersion X when includeDrafts is true', () => { + const client = getClient({apiVersion: 'v2021-03-26', token: 'abc123', port: 1234}) + expect(() => client.live.events({includeDrafts: true})).toThrowErrorMatchingInlineSnapshot( + `[Error: The live events API requires API version X when 'includeDrafts: true'. This API is experimental and may change or even be removed.]`, + ) + }) + test('can listen for tags', async () => { expect.assertions(2) @@ -102,6 +115,49 @@ describe.skipIf(typeof EdgeRuntime === 'string' || typeof document !== 'undefine } }) + test('can listen for tags with includeDrafts', async () => { + expect.assertions(2) + + const eventData = { + tags: ['tag1', 'tag2'], + } + + const {server, client} = await testSse( + ({request, channel}) => { + expect(request.url, 'url should be correct').toEqual( + `/vX/data/live/events/prod?includeDrafts=true`, + ) + + channel!.send({id: '123', data: eventData}) + process.nextTick(() => channel!.close()) + }, + {token: 'abc123'}, + ) + + try { + await new Promise((resolve, reject) => { + const subscription = client.live.events({includeDrafts: true}).subscribe({ + next: (msg) => { + expect(msg, 'event data should be correct').toEqual({ + ...eventData, + id: '123', + type: 'message', + }) + + subscription.unsubscribe() + resolve() + }, + error: (err) => { + subscription.unsubscribe() + reject(err) + }, + }) + }) + } finally { + server.close() + } + }) + test('supports restart events', async () => { expect.assertions(1)