diff --git a/package-lock.json b/package-lock.json index 65367bcd..8f6ecf8e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -448,6 +448,7 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.726.0.tgz", "integrity": "sha512-5JzTX9jwev7+y2Jkzjz0pd1wobB5JQfPOQF3N2DrJ5Pao0/k6uRYwE4NqB0p0HlGrMTDm7xNq7OSPPIPG575Jw==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", @@ -501,6 +502,7 @@ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.726.1.tgz", "integrity": "sha512-qh9Q9Vu1hrM/wMBOBIaskwnE4GTFaZu26Q6WHwyWNfj7J8a40vBxpW16c2vYXHLBtwRKM1be8uRLkmDwghpiNw==", "license": "Apache-2.0", + "peer": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", @@ -1381,7 +1383,8 @@ "version": "4.20260101.0", "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-4.20260101.0.tgz", "integrity": "sha512-C28o4U1T4dPe8avLv1xMQ4MtSE6G4skbVA3VfVZIrpTqklvO+homKB1uFEtNbuZlaKg+Znv8sjmGQUInTH17gA==", - "license": "MIT OR Apache-2.0" + "license": "MIT OR Apache-2.0", + "peer": true }, "node_modules/@colors/colors": { "version": "1.6.0", @@ -2709,6 +2712,7 @@ "integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@octokit/auth-token": "^6.0.0", "@octokit/graphql": "^9.0.3", @@ -2855,6 +2859,7 @@ "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", "dev": true, "license": "Apache-2.0", + "peer": true, "engines": { "node": ">=8.0.0" } @@ -4992,6 +4997,7 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", + "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -5049,6 +5055,7 @@ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "fast-deep-equal": "^3.1.3", "fast-uri": "^3.0.1", @@ -7353,6 +7360,7 @@ "integrity": "sha512-sjc7Y8cUD1IlwYcTS9qPSvGjAC8Ne9LctpxKKu3x/1IC9bnOg98Zy6GxEJUfr1NojMgVPlyANXYns8oE2c1TAA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.6.1", @@ -10397,6 +10405,7 @@ "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", "dev": true, "license": "MIT", + "peer": true, "bin": { "marked": "bin/marked.js" }, @@ -10947,6 +10956,7 @@ "integrity": "sha512-UczzB+0nnwGotYSgllfARAqWCJ5e/skuV2K/l+Zyck/H6pJIhLXuBnz+6vn2i211o7DtbE78HQtsYEKICHGI+g==", "dev": true, "license": "MIT", + "peer": true, "funding": { "type": "opencollective", "url": "https://opencollective.com/mobx" @@ -13502,6 +13512,7 @@ "dev": true, "inBundle": true, "license": "MIT", + "peer": true, "engines": { "node": ">=12" }, @@ -14617,6 +14628,7 @@ "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==", "dev": true, "license": "MIT", + "peer": true, "engines": { "node": ">=0.10.0" } @@ -14627,6 +14639,7 @@ "integrity": "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -15240,6 +15253,7 @@ "integrity": "sha512-6qGjWccl5yoyugHt3jTgztJ9Y0JVzyH8/Voc/D8PlLat9pwxQYXz7W1Dpnq5h0/G5GCYGUaDSlYcyk3AMh5A6g==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@semantic-release/commit-analyzer": "^13.0.1", "@semantic-release/error": "^4.0.0", @@ -16618,6 +16632,7 @@ "integrity": "sha512-1v/e3Dl1BknC37cXMhwGomhO8AkYmN41CqyX9xhUDxry1ns3BFQy2lLDRQXJRdVVWB9OHemv/53xaStimvWyuA==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "@emotion/is-prop-valid": "1.2.2", "@emotion/unitless": "0.8.1", @@ -17349,6 +17364,7 @@ "integrity": "sha512-i7qRCmY42zmCwnYlh9H2SvLEypEFGye5iRmEMKjcGi7zk9UquigRjFtTLz0TYqr0ZGLZhaMHl/foy1bZR+Cwlw==", "dev": true, "license": "MIT", + "peer": true, "dependencies": { "pathe": "^2.0.3" } @@ -17802,6 +17818,7 @@ "dev": true, "hasInstallScript": true, "license": "Apache-2.0", + "peer": true, "bin": { "workerd": "bin/workerd" }, diff --git a/src/storage/version/put.js b/src/storage/version/put.js index aa1d5de4..ba1e6e7c 100644 --- a/src/storage/version/put.js +++ b/src/storage/version/put.js @@ -354,5 +354,6 @@ export async function postObjectVersion(req, env, daCtx) { // no body } const label = reqJSON?.label; - return /* await */ postObjectVersionWithLabel(label, env, daCtx); + if (!label) return { status: 400, error: 'label is required' }; + return postObjectVersionWithLabel(label, env, daCtx); } diff --git a/test/storage/version/put.test.js b/test/storage/version/put.test.js index 7d16ef76..c2f145f5 100644 --- a/test/storage/version/put.test.js +++ b/test/storage/version/put.test.js @@ -2927,7 +2927,37 @@ describe('Version Put', () => { }); describe('postObjectVersion with no JSON body', () => { - it('handles req.json() throwing (no body) and creates version with undefined label', async () => { + it('returns 400 when req.json() throws (no body)', async () => { + const { postObjectVersion } = await esmock('../../../src/storage/version/put.js', {}); + + const req = { + json: () => { + throw new Error('no body'); + }, + }; + const daCtx = { + bucket: 'b', org: 'o', key: 'r/doc.html', ext: 'html', users: [], + }; + const resp = await postObjectVersion(req, {}, daCtx); + + assert.strictEqual(resp.status, 400); + assert.strictEqual(resp.error, 'label is required'); + }); + + it('returns 400 when request body has label: null', async () => { + const { postObjectVersion } = await esmock('../../../src/storage/version/put.js', {}); + + const req = { json: async () => ({ label: null }) }; + const daCtx = { + bucket: 'b', org: 'o', key: 'r/doc.html', ext: 'html', users: [], + }; + const resp = await postObjectVersion(req, {}, daCtx); + + assert.strictEqual(resp.status, 400); + assert.strictEqual(resp.error, 'label is required'); + }); + + it('returns 201 when a valid label is provided', async () => { const mockGetObject = async () => ({ body: 'content', contentType: 'text/html', @@ -2954,20 +2984,13 @@ describe('Version Put', () => { '../../../src/storage/utils/config.js': { default: () => ({}) }, }); - // req.json() throws → label is undefined → postObjectVersionWithLabel(undefined, ...) - const req = { - json: () => { - throw new Error('no body'); - }, - }; + const req = { json: async () => ({ label: 'My snapshot' }) }; const daCtx = { bucket: 'b', org: 'o', key: 'r/doc.html', ext: 'html', users: [], }; const resp = await postObjectVersion(req, {}, daCtx); - // No label means shouldCreateVersionObject is false → versionCreated stays false → 500 - assert.strictEqual(resp.status, 500); - assert.strictEqual(resp.error, 'Version was not created'); + assert.strictEqual(resp.status, 201); }); });