diff --git a/packages/sanity/src/_internal/cli/actions/deploy/__tests__/helpers.test.ts b/packages/sanity/src/_internal/cli/actions/deploy/__tests__/helpers.test.ts index 9e255c58644e..502051e15209 100644 --- a/packages/sanity/src/_internal/cli/actions/deploy/__tests__/helpers.test.ts +++ b/packages/sanity/src/_internal/cli/actions/deploy/__tests__/helpers.test.ts @@ -26,7 +26,6 @@ const mockFsPromisesReaddir = mockFsPromises.readdir as unknown as jest.Mock< const mockClient = { request: jest.fn(), config: jest.fn(), - getUrl: jest.fn(), } as unknown as SanityClient const mockClientRequest = mockClient.request as jest.Mock @@ -67,7 +66,7 @@ describe('getOrCreateUserApplication', () => { }) const result = await getOrCreateUserApplication({client: mockClient, context}) - expect(mockClient.request).toHaveBeenCalledWith({ + expect(mockClientRequest).toHaveBeenCalledWith({ uri: '/user-applications', query: {default: 'true'}, }) @@ -86,7 +85,7 @@ describe('getOrCreateUserApplication', () => { context, }) - expect(mockClient.request).toHaveBeenCalledWith({ + expect(mockClientRequest).toHaveBeenCalledWith({ uri: '/user-applications', query: {appHost: 'example.sanity.studio'}, }) @@ -104,7 +103,7 @@ describe('getOrCreateUserApplication', () => { context, }) - expect(mockClient.request).toHaveBeenCalledWith({ + expect(mockClientRequest).toHaveBeenCalledWith({ uri: '/user-applications', method: 'POST', body: {appHost: 'newhost', isDefault: true}, @@ -142,10 +141,6 @@ describe('getOrCreateUserApplication', () => { describe('createDeployment', () => { beforeEach(() => { jest.clearAllMocks() - ;(mockClient.config as jest.Mock).mockReturnValue({token: 'fake-token'}) - ;(mockClient.getUrl as jest.Mock).mockImplementation( - (uri) => `http://example.api.sanity.io${uri}`, - ) }) it('sends the correct request to create a deployment and includes authorization header if token is present', async () => { @@ -153,8 +148,6 @@ describe('createDeployment', () => { const applicationId = 'test-app-id' const version = '1.0.0' - mockFetch.mockResolvedValueOnce(new Response()) - await createDeployment({ client: mockClient, applicationId, @@ -163,23 +156,18 @@ describe('createDeployment', () => { tarball, }) - // Check URL and method - expect(mockClient.getUrl).toHaveBeenCalledWith( - `/user-applications/${applicationId}/deployments`, - ) - expect(mockFetch).toHaveBeenCalledTimes(1) - const url = mockFetch.mock.calls[0][0] as URL - expect(url.toString()).toBe( - 'http://example.api.sanity.io/user-applications/test-app-id/deployments', - ) + expect(mockClientRequest).toHaveBeenCalledTimes(1) // Extract and validate form data - const mockFetchCalls = mockFetch.mock.calls as Parameters[] - const formData = mockFetchCalls[0][1]?.body as unknown as Readable + const mockRequestCalls = mockClientRequest.mock.calls as Parameters[] + const {uri, method, body} = mockRequestCalls[0][0] + + expect(uri).toBe(`/user-applications/${applicationId}/deployments`) + expect(method).toBe('POST') // dump the raw content of the form data into a string let content = '' - for await (const chunk of formData) { + for await (const chunk of body) { content += chunk } @@ -188,10 +176,6 @@ describe('createDeployment', () => { expect(content).toContain('version') expect(content).toContain(version) expect(content).toContain('example chunk') - - // Check Authorization header - const headers = mockFetchCalls[0][1]?.headers as Headers - expect(headers.get('Authorization')).toBe('Bearer fake-token') }) it('streams the tarball contents', async () => { @@ -207,9 +191,6 @@ describe('createDeployment', () => { const mockTarball = Readable.from(createMockStream()) as Gzip const applicationId = 'test-app-id' - - mockFetch.mockResolvedValueOnce(new Response()) - const version = '1.0.0' await createDeployment({ @@ -220,29 +201,15 @@ describe('createDeployment', () => { tarball: mockTarball, }) - // Check URL and method - expect(mockClient.getUrl).toHaveBeenCalledWith( - `/user-applications/${applicationId}/deployments`, - ) - expect(mockFetch).toHaveBeenCalledTimes(1) - const url = mockFetch.mock.calls[0][0] as URL - expect(url.toString()).toBe( - 'http://example.api.sanity.io/user-applications/test-app-id/deployments', - ) - - // Extract and validate form data - const mockFetchCalls = mockFetch.mock.calls as Parameters[] - const requestInit = mockFetchCalls[0][1] as any - - // this is required to enable streaming with the native fetch API - // https://github.com/nodejs/node/issues/46221 - expect(requestInit.duplex).toBe('half') + expect(mockClientRequest).toHaveBeenCalledTimes(1) - const formData = requestInit.body as Readable + const mockRequestCalls = mockClientRequest.mock.calls as Parameters[] + const {body} = mockRequestCalls[0][0] + // Extract and validate form data let emissions = 0 let content = '' - for await (const chunk of formData) { + for await (const chunk of body) { content += chunk emissions++ } diff --git a/packages/sanity/src/_internal/cli/actions/deploy/helpers.ts b/packages/sanity/src/_internal/cli/actions/deploy/helpers.ts index 73c31fac10dc..0b538fda4fae 100644 --- a/packages/sanity/src/_internal/cli/actions/deploy/helpers.ts +++ b/packages/sanity/src/_internal/cli/actions/deploy/helpers.ts @@ -140,30 +140,15 @@ export async function createDeployment({ isAutoUpdating, version, }: CreateDeploymentOptions): Promise { - const config = client.config() - const formData = new FormData() formData.append('isAutoUpdating', isAutoUpdating.toString()) formData.append('version', version) - formData.append('tarball', tarball, {contentType: 'application/gzip'}) - - const url = new URL(client.getUrl(`/user-applications/${applicationId}/deployments`)) - const headers = new Headers({ - ...(config.token && {Authorization: `Bearer ${config.token}`}), - }) + formData.append('tarball', tarball, {contentType: 'application/gzip', filename: 'app.tar.gz'}) - await fetch(url, { + await client.request({ + uri: `/user-applications/${applicationId}/deployments`, method: 'POST', - headers, - // NOTE: - // - the fetch API in node.js supports streams but it's not in the types - // - the PassThrough is required because `form-data` does not fully conform - // to the node.js stream API - // eslint-disable-next-line @typescript-eslint/no-explicit-any body: formData.pipe(new PassThrough()) as any, - // @ts-expect-error the `duplex` param is required in order to send a stream - // https://github.com/nodejs/node/issues/46221#issuecomment-1383246036 - duplex: 'half', }) }