next-sanity 5.4.3 → 5.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -7,6 +7,9 @@ var webhook = require('@sanity/webhook');
7
7
  var readBody = require('./readBody.cjs');
8
8
  async function parseBody(req, secret) {
9
9
  let waitForContentLakeEventualConsistency = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
10
+ if (typeof EdgeRuntime !== "undefined") {
11
+ throw new TypeError("The edge runtime isn't supported. You'll have to use the 'nodejs' runtime until the underlying `@sanity/webhook` package is updated to support it.");
12
+ }
10
13
  return "text" in req ? parseAppBody(req, secret, waitForContentLakeEventualConsistency) : parsePageBody(req, secret, waitForContentLakeEventualConsistency);
11
14
  }
12
15
  async function parsePageBody(req, secret) {
@@ -15,26 +18,43 @@ async function parsePageBody(req, secret) {
15
18
  if (Array.isArray(signature)) {
16
19
  signature = signature[0];
17
20
  }
21
+ if (!signature) {
22
+ console.error("Missing signature header");
23
+ return {
24
+ body: null,
25
+ isValidSignature: null
26
+ };
27
+ }
28
+ if (req.readableEnded) {
29
+ throw new Error("Request already ended and the POST body can't be read. Have you setup `export {config} from 'next-sanity/webhook' in your webhook API handler?`");
30
+ }
18
31
  const body = await readBody._readBody(req);
19
32
  const validSignature = secret ? webhook.isValidSignature(body, signature, secret.trim()) : null;
20
33
  if (validSignature !== false && waitForContentLakeEventualConsistency) {
21
34
  await new Promise(resolve => setTimeout(resolve, 1e3));
22
35
  }
23
36
  return {
24
- body: body.trim() && JSON.parse(body),
37
+ body: body.trim() ? JSON.parse(body) : null,
25
38
  isValidSignature: validSignature
26
39
  };
27
40
  }
28
41
  async function parseAppBody(req, secret) {
29
42
  let waitForContentLakeEventualConsistency = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
30
43
  const signature = req.headers.get(webhook.SIGNATURE_HEADER_NAME);
44
+ if (!signature) {
45
+ console.error("Missing signature header");
46
+ return {
47
+ body: null,
48
+ isValidSignature: null
49
+ };
50
+ }
31
51
  const body = await req.text();
32
52
  const validSignature = secret ? webhook.isValidSignature(body, signature, secret.trim()) : null;
33
53
  if (validSignature !== false && waitForContentLakeEventualConsistency) {
34
54
  await new Promise(resolve => setTimeout(resolve, 1e3));
35
55
  }
36
56
  return {
37
- body: body.trim() && JSON.parse(body),
57
+ body: body.trim() ? JSON.parse(body) : null,
38
58
  isValidSignature: validSignature
39
59
  };
40
60
  }
@@ -1 +1 @@
1
- {"version":3,"file":"parseBody.cjs","sources":["../../src/webhook/parseBody.ts"],"sourcesContent":["import type {SanityDocument} from '@sanity/types'\nimport {isValidSignature, SIGNATURE_HEADER_NAME} from '@sanity/webhook'\nimport type {NextApiRequest} from 'next'\nimport type {NextRequest} from 'next/server'\n\nimport {_readBody as readBody} from './readBody'\n\n/** @public */\nexport type ParsedBody<T> = {\n /**\n * If a secret is given then it returns a boolean. If no secret is provided then no validation is done on the signature, and it'll return `null`\n */\n isValidSignature: boolean | null\n body: T\n}\n\n/**\n * @deprecated Use `ParsedBody` instead\n * @public\n */\nexport type ParseBody<Body = SanityDocument> = ParsedBody<Body>\n/**\n * Handles parsing the body JSON, and validating its signature. Also waits for Content Lake eventual consistency so you can run your queries\n * without worrying about getting stale data.\n * @public\n */\nexport async function parseBody<Body = SanityDocument>(\n req: NextApiRequest,\n secret?: string,\n waitForContentLakeEventualConsistency?: boolean,\n): Promise<ParsedBody<Body>>\n/**\n * Handles parsing the body JSON, and validating its signature. Also waits for Content Lake eventual consistency so you can run your queries\n * without worrying about getting stale data.\n * @public\n */\nexport async function parseBody<Body = SanityDocument>(\n req: NextRequest,\n secret?: string,\n waitForContentLakeEventualConsistency?: boolean,\n): Promise<ParsedBody<Body>>\n/**\n * Handles parsing the body JSON, and validating its signature. Also waits for Content Lake eventual consistency so you can run your queries\n * without worrying about getting stale data.\n * @public\n */\n// eslint-disable-next-line require-await\nexport async function parseBody<Body = SanityDocument>(\n req: NextApiRequest | NextRequest,\n secret?: string,\n waitForContentLakeEventualConsistency: boolean = true,\n): Promise<ParsedBody<Body>> {\n return 'text' in req\n ? parseAppBody(req, secret, waitForContentLakeEventualConsistency)\n : parsePageBody(req, secret, waitForContentLakeEventualConsistency)\n}\n\nasync function parsePageBody<Body = SanityDocument>(\n req: NextApiRequest,\n secret?: string,\n waitForContentLakeEventualConsistency: boolean = true,\n): Promise<ParsedBody<Body>> {\n let signature = req.headers[SIGNATURE_HEADER_NAME]!\n if (Array.isArray(signature)) {\n signature = signature[0]\n }\n\n const body = await readBody(req)\n const validSignature = secret ? isValidSignature(body, signature, secret.trim()) : null\n\n if (validSignature !== false && waitForContentLakeEventualConsistency) {\n await new Promise((resolve) => setTimeout(resolve, 1000))\n }\n\n return {\n body: body.trim() && JSON.parse(body),\n isValidSignature: validSignature,\n }\n}\n\n/**\n * @deprecated Use `ParsedBody` instead\n * @public\n */\nexport type ParseAppBody<Body = SanityDocument> = ParsedBody<Body>\n/**\n * Handles parsing the body JSON, and validating its signature. Also waits for Content Lake eventual consistency so you can run your queries\n * without worrying about getting stale data.\n * @deprecated Use `parseBody` instead\n * @public\n */\nexport async function parseAppBody<Body = SanityDocument>(\n req: NextRequest,\n secret?: string,\n waitForContentLakeEventualConsistency: boolean = true,\n): Promise<ParsedBody<Body>> {\n const signature = req.headers.get(SIGNATURE_HEADER_NAME)!\n\n const body = await req.text()\n const validSignature = secret ? isValidSignature(body, signature, secret.trim()) : null\n\n if (validSignature !== false && waitForContentLakeEventualConsistency) {\n await new Promise((resolve) => setTimeout(resolve, 1000))\n }\n\n return {\n body: body.trim() && JSON.parse(body),\n isValidSignature: validSignature,\n }\n}\n"],"names":["parseBody","req","secret","waitForContentLakeEventualConsistency","arguments","length","undefined","parseAppBody","parsePageBody","signature","headers","SIGNATURE_HEADER_NAME","Array","isArray","body","readBody","validSignature","isValidSignature","trim","Promise","resolve","setTimeout","JSON","parse","get","text"],"mappings":";;;;;;;AA+CA,eAAsBA,SACpBA,CAAAC,GAAA,EACAC,MACA,EAC2B;EAAA,IAD3BC,qCAAA,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAiD,IACtB;EACpB,OAAA,MAAA,IAAUH,GACb,GAAAM,YAAA,CAAaN,GAAK,EAAAC,MAAA,EAAQC,qCAAqC,CAC/D,GAAAK,aAAA,CAAcP,GAAK,EAAAC,MAAA,EAAQC,qCAAqC,CAAA;AACtE;AAEA,eAAeK,aACbA,CAAAP,GAAA,EACAC,MACA,EAC2B;EAAA,IAD3BC,qCAAA,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAiD,IACtB;EACvB,IAAAK,SAAA,GAAYR,GAAI,CAAAS,OAAA,CAAQC,OAAqB,CAAAA,qBAAA,CAAA;EAC7C,IAAAC,KAAA,CAAMC,OAAQ,CAAAJ,SAAS,CAAG,EAAA;IAC5BA,SAAA,GAAYA,UAAU,CAAC,CAAA;EACzB;EAEM,MAAAK,IAAA,GAAO,MAAMC,kBAAA,CAASd,GAAG,CAAA;EACzB,MAAAe,cAAA,GAAiBd,SAASe,OAAAA,CAAAA,gBAAiB,CAAAH,IAAA,EAAML,WAAWP,MAAO,CAAAgB,IAAA,EAAM,CAAI,GAAA,IAAA;EAE/E,IAAAF,cAAA,KAAmB,SAASb,qCAAuC,EAAA;IACrE,MAAM,IAAIgB,OAAQ,CAACC,WAAYC,UAAW,CAAAD,OAAA,EAAS,GAAI,CAAC,CAAA;EAC1D;EAEO,OAAA;IACLN,MAAMA,IAAK,CAAAI,IAAA,CAAA,CAAU,IAAAI,IAAA,CAAKC,MAAMT,IAAI,CAAA;IACpCG,gBAAkB,EAAAD;EAAA,CACpB;AACF;AAaA,eAAsBT,YACpBA,CAAAN,GAAA,EACAC,MACA,EAC2B;EAAA,IAD3BC,qCAAA,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAiD,IACtB;EAC3B,MAAMK,SAAY,GAAAR,GAAA,CAAIS,OAAQ,CAAAc,GAAA,CAAIb,OAAqB,CAAAA,qBAAA,CAAA;EAEjD,MAAAG,IAAA,GAAO,MAAMb,GAAA,CAAIwB,IAAK,EAAA;EACtB,MAAAT,cAAA,GAAiBd,SAASe,OAAAA,CAAAA,gBAAiB,CAAAH,IAAA,EAAML,WAAWP,MAAO,CAAAgB,IAAA,EAAM,CAAI,GAAA,IAAA;EAE/E,IAAAF,cAAA,KAAmB,SAASb,qCAAuC,EAAA;IACrE,MAAM,IAAIgB,OAAQ,CAACC,WAAYC,UAAW,CAAAD,OAAA,EAAS,GAAI,CAAC,CAAA;EAC1D;EAEO,OAAA;IACLN,MAAMA,IAAK,CAAAI,IAAA,CAAA,CAAU,IAAAI,IAAA,CAAKC,MAAMT,IAAI,CAAA;IACpCG,gBAAkB,EAAAD;EAAA,CACpB;AACF;;"}
1
+ {"version":3,"file":"parseBody.cjs","sources":["../../src/webhook/parseBody.ts"],"sourcesContent":["import type {SanityDocument} from '@sanity/types'\nimport {isValidSignature, SIGNATURE_HEADER_NAME} from '@sanity/webhook'\nimport type {NextApiRequest} from 'next'\nimport type {NextRequest} from 'next/server'\n\nimport {_readBody as readBody} from './readBody'\n\n/** @public */\nexport type ParsedBody<T> = {\n /**\n * If a secret is given then it returns a boolean. If no secret is provided then no validation is done on the signature, and it'll return `null`\n */\n isValidSignature: boolean | null\n body: T | null\n}\n\n/**\n * @deprecated Use `ParsedBody` instead\n * @public\n */\nexport type ParseBody<Body = SanityDocument> = ParsedBody<Body>\n/**\n * Handles parsing the body JSON, and validating its signature. Also waits for Content Lake eventual consistency so you can run your queries\n * without worrying about getting stale data.\n * @public\n */\nexport async function parseBody<Body = SanityDocument>(\n req: NextApiRequest,\n secret?: string,\n waitForContentLakeEventualConsistency?: boolean,\n): Promise<ParsedBody<Body>>\n/**\n * Handles parsing the body JSON, and validating its signature. Also waits for Content Lake eventual consistency so you can run your queries\n * without worrying about getting stale data.\n * @public\n */\nexport async function parseBody<Body = SanityDocument>(\n req: NextRequest,\n secret?: string,\n waitForContentLakeEventualConsistency?: boolean,\n): Promise<ParsedBody<Body>>\n/**\n * Handles parsing the body JSON, and validating its signature. Also waits for Content Lake eventual consistency so you can run your queries\n * without worrying about getting stale data.\n * @public\n */\n// eslint-disable-next-line require-await\nexport async function parseBody<Body = SanityDocument>(\n req: NextApiRequest | NextRequest,\n secret?: string,\n waitForContentLakeEventualConsistency: boolean = true,\n): Promise<ParsedBody<Body>> {\n // @ts-expect-error -- add global typings for EdgeRuntime\n if (typeof EdgeRuntime !== 'undefined') {\n throw new TypeError(\n `The edge runtime isn't supported. You'll have to use the 'nodejs' runtime until the underlying \\`@sanity/webhook\\` package is updated to support it.`,\n )\n }\n return 'text' in req\n ? parseAppBody(req, secret, waitForContentLakeEventualConsistency)\n : parsePageBody(req, secret, waitForContentLakeEventualConsistency)\n}\n\nasync function parsePageBody<Body = SanityDocument>(\n req: NextApiRequest,\n secret?: string,\n waitForContentLakeEventualConsistency: boolean = true,\n): Promise<ParsedBody<Body>> {\n let signature = req.headers[SIGNATURE_HEADER_NAME]\n if (Array.isArray(signature)) {\n signature = signature[0]\n }\n if (!signature) {\n console.error('Missing signature header')\n return {body: null, isValidSignature: null}\n }\n\n if (req.readableEnded) {\n throw new Error(\n `Request already ended and the POST body can't be read. Have you setup \\`export {config} from 'next-sanity/webhook' in your webhook API handler?\\``,\n )\n }\n\n const body = await readBody(req)\n const validSignature = secret ? isValidSignature(body, signature, secret.trim()) : null\n\n if (validSignature !== false && waitForContentLakeEventualConsistency) {\n await new Promise((resolve) => setTimeout(resolve, 1000))\n }\n\n return {\n body: body.trim() ? JSON.parse(body) : null,\n isValidSignature: validSignature,\n }\n}\n\n/**\n * @deprecated Use `ParsedBody` instead\n * @public\n */\nexport type ParseAppBody<Body = SanityDocument> = ParsedBody<Body>\n/**\n * Handles parsing the body JSON, and validating its signature. Also waits for Content Lake eventual consistency so you can run your queries\n * without worrying about getting stale data.\n * @deprecated Use `parseBody` instead\n * @public\n */\nexport async function parseAppBody<Body = SanityDocument>(\n req: NextRequest,\n secret?: string,\n waitForContentLakeEventualConsistency: boolean = true,\n): Promise<ParsedBody<Body>> {\n const signature = req.headers.get(SIGNATURE_HEADER_NAME)!\n if (!signature) {\n console.error('Missing signature header')\n return {body: null, isValidSignature: null}\n }\n\n const body = await req.text()\n const validSignature = secret ? isValidSignature(body, signature, secret.trim()) : null\n\n if (validSignature !== false && waitForContentLakeEventualConsistency) {\n await new Promise((resolve) => setTimeout(resolve, 1000))\n }\n\n return {\n body: body.trim() ? JSON.parse(body) : null,\n isValidSignature: validSignature,\n }\n}\n"],"names":["parseBody","req","secret","waitForContentLakeEventualConsistency","arguments","length","undefined","EdgeRuntime","TypeError","parseAppBody","parsePageBody","signature","headers","SIGNATURE_HEADER_NAME","Array","isArray","console","error","body","isValidSignature","readableEnded","Error","readBody","validSignature","trim","Promise","resolve","setTimeout","JSON","parse","get","text"],"mappings":";;;;;;;AA+CA,eAAsBA,SACpBA,CAAAC,GAAA,EACAC,MACA,EAC2B;EAAA,IAD3BC,qCAAA,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAiD,IACtB;EAEvB,IAAA,OAAOG,gBAAgB,WAAa,EAAA;IACtC,MAAM,IAAIC,SAAA,CACR,oJAAA,CACF;EACF;EACO,OAAA,MAAA,IAAUP,GACb,GAAAQ,YAAA,CAAaR,GAAK,EAAAC,MAAA,EAAQC,qCAAqC,CAC/D,GAAAO,aAAA,CAAcT,GAAK,EAAAC,MAAA,EAAQC,qCAAqC,CAAA;AACtE;AAEA,eAAeO,aACbA,CAAAT,GAAA,EACAC,MACA,EAC2B;EAAA,IAD3BC,qCAAA,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAiD,IACtB;EACvB,IAAAO,SAAA,GAAYV,GAAI,CAAAW,OAAA,CAAQC,OAAqB,CAAAA,qBAAA,CAAA;EAC7C,IAAAC,KAAA,CAAMC,OAAQ,CAAAJ,SAAS,CAAG,EAAA;IAC5BA,SAAA,GAAYA,UAAU,CAAC,CAAA;EACzB;EACA,IAAI,CAACA,SAAW,EAAA;IACdK,OAAA,CAAQC,MAAM,0BAA0B,CAAA;IACxC,OAAO;MAACC,IAAA,EAAM,IAAM;MAAAC,gBAAA,EAAkB;IAAI,CAAA;EAC5C;EAEA,IAAIlB,IAAImB,aAAe,EAAA;IACrB,MAAM,IAAIC,KAAA,CACR,iJAAA,CACF;EACF;EAEM,MAAAH,IAAA,GAAO,MAAMI,kBAAA,CAASrB,GAAG,CAAA;EACzB,MAAAsB,cAAA,GAAiBrB,SAASiB,OAAAA,CAAAA,gBAAiB,CAAAD,IAAA,EAAMP,WAAWT,MAAO,CAAAsB,IAAA,EAAM,CAAI,GAAA,IAAA;EAE/E,IAAAD,cAAA,KAAmB,SAASpB,qCAAuC,EAAA;IACrE,MAAM,IAAIsB,OAAQ,CAACC,WAAYC,UAAW,CAAAD,OAAA,EAAS,GAAI,CAAC,CAAA;EAC1D;EAEO,OAAA;IACLR,MAAMA,IAAK,CAAAM,IAAA,KAASI,IAAK,CAAAC,KAAA,CAAMX,IAAI,CAAI,GAAA,IAAA;IACvCC,gBAAkB,EAAAI;EAAA,CACpB;AACF;AAaA,eAAsBd,YACpBA,CAAAR,GAAA,EACAC,MACA,EAC2B;EAAA,IAD3BC,qCAAA,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAiD,IACtB;EAC3B,MAAMO,SAAY,GAAAV,GAAA,CAAIW,OAAQ,CAAAkB,GAAA,CAAIjB,OAAqB,CAAAA,qBAAA,CAAA;EACvD,IAAI,CAACF,SAAW,EAAA;IACdK,OAAA,CAAQC,MAAM,0BAA0B,CAAA;IACxC,OAAO;MAACC,IAAA,EAAM,IAAM;MAAAC,gBAAA,EAAkB;IAAI,CAAA;EAC5C;EAEM,MAAAD,IAAA,GAAO,MAAMjB,GAAA,CAAI8B,IAAK,EAAA;EACtB,MAAAR,cAAA,GAAiBrB,SAASiB,OAAAA,CAAAA,gBAAiB,CAAAD,IAAA,EAAMP,WAAWT,MAAO,CAAAsB,IAAA,EAAM,CAAI,GAAA,IAAA;EAE/E,IAAAD,cAAA,KAAmB,SAASpB,qCAAuC,EAAA;IACrE,MAAM,IAAIsB,OAAQ,CAACC,WAAYC,UAAW,CAAAD,OAAA,EAAS,GAAI,CAAC,CAAA;EAC1D;EAEO,OAAA;IACLR,MAAMA,IAAK,CAAAM,IAAA,KAASI,IAAK,CAAAC,KAAA,CAAMX,IAAI,CAAI,GAAA,IAAA;IACvCC,gBAAkB,EAAAI;EAAA,CACpB;AACF;;"}
@@ -2,6 +2,9 @@ import { isValidSignature, SIGNATURE_HEADER_NAME } from '@sanity/webhook';
2
2
  import { _readBody } from './readBody.js';
3
3
  async function parseBody(req, secret) {
4
4
  let waitForContentLakeEventualConsistency = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
5
+ if (typeof EdgeRuntime !== "undefined") {
6
+ throw new TypeError("The edge runtime isn't supported. You'll have to use the 'nodejs' runtime until the underlying `@sanity/webhook` package is updated to support it.");
7
+ }
5
8
  return "text" in req ? parseAppBody(req, secret, waitForContentLakeEventualConsistency) : parsePageBody(req, secret, waitForContentLakeEventualConsistency);
6
9
  }
7
10
  async function parsePageBody(req, secret) {
@@ -10,26 +13,43 @@ async function parsePageBody(req, secret) {
10
13
  if (Array.isArray(signature)) {
11
14
  signature = signature[0];
12
15
  }
16
+ if (!signature) {
17
+ console.error("Missing signature header");
18
+ return {
19
+ body: null,
20
+ isValidSignature: null
21
+ };
22
+ }
23
+ if (req.readableEnded) {
24
+ throw new Error("Request already ended and the POST body can't be read. Have you setup `export {config} from 'next-sanity/webhook' in your webhook API handler?`");
25
+ }
13
26
  const body = await _readBody(req);
14
27
  const validSignature = secret ? isValidSignature(body, signature, secret.trim()) : null;
15
28
  if (validSignature !== false && waitForContentLakeEventualConsistency) {
16
29
  await new Promise(resolve => setTimeout(resolve, 1e3));
17
30
  }
18
31
  return {
19
- body: body.trim() && JSON.parse(body),
32
+ body: body.trim() ? JSON.parse(body) : null,
20
33
  isValidSignature: validSignature
21
34
  };
22
35
  }
23
36
  async function parseAppBody(req, secret) {
24
37
  let waitForContentLakeEventualConsistency = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : true;
25
38
  const signature = req.headers.get(SIGNATURE_HEADER_NAME);
39
+ if (!signature) {
40
+ console.error("Missing signature header");
41
+ return {
42
+ body: null,
43
+ isValidSignature: null
44
+ };
45
+ }
26
46
  const body = await req.text();
27
47
  const validSignature = secret ? isValidSignature(body, signature, secret.trim()) : null;
28
48
  if (validSignature !== false && waitForContentLakeEventualConsistency) {
29
49
  await new Promise(resolve => setTimeout(resolve, 1e3));
30
50
  }
31
51
  return {
32
- body: body.trim() && JSON.parse(body),
52
+ body: body.trim() ? JSON.parse(body) : null,
33
53
  isValidSignature: validSignature
34
54
  };
35
55
  }
@@ -1 +1 @@
1
- {"version":3,"file":"parseBody.js","sources":["../../src/webhook/parseBody.ts"],"sourcesContent":["import type {SanityDocument} from '@sanity/types'\nimport {isValidSignature, SIGNATURE_HEADER_NAME} from '@sanity/webhook'\nimport type {NextApiRequest} from 'next'\nimport type {NextRequest} from 'next/server'\n\nimport {_readBody as readBody} from './readBody'\n\n/** @public */\nexport type ParsedBody<T> = {\n /**\n * If a secret is given then it returns a boolean. If no secret is provided then no validation is done on the signature, and it'll return `null`\n */\n isValidSignature: boolean | null\n body: T\n}\n\n/**\n * @deprecated Use `ParsedBody` instead\n * @public\n */\nexport type ParseBody<Body = SanityDocument> = ParsedBody<Body>\n/**\n * Handles parsing the body JSON, and validating its signature. Also waits for Content Lake eventual consistency so you can run your queries\n * without worrying about getting stale data.\n * @public\n */\nexport async function parseBody<Body = SanityDocument>(\n req: NextApiRequest,\n secret?: string,\n waitForContentLakeEventualConsistency?: boolean,\n): Promise<ParsedBody<Body>>\n/**\n * Handles parsing the body JSON, and validating its signature. Also waits for Content Lake eventual consistency so you can run your queries\n * without worrying about getting stale data.\n * @public\n */\nexport async function parseBody<Body = SanityDocument>(\n req: NextRequest,\n secret?: string,\n waitForContentLakeEventualConsistency?: boolean,\n): Promise<ParsedBody<Body>>\n/**\n * Handles parsing the body JSON, and validating its signature. Also waits for Content Lake eventual consistency so you can run your queries\n * without worrying about getting stale data.\n * @public\n */\n// eslint-disable-next-line require-await\nexport async function parseBody<Body = SanityDocument>(\n req: NextApiRequest | NextRequest,\n secret?: string,\n waitForContentLakeEventualConsistency: boolean = true,\n): Promise<ParsedBody<Body>> {\n return 'text' in req\n ? parseAppBody(req, secret, waitForContentLakeEventualConsistency)\n : parsePageBody(req, secret, waitForContentLakeEventualConsistency)\n}\n\nasync function parsePageBody<Body = SanityDocument>(\n req: NextApiRequest,\n secret?: string,\n waitForContentLakeEventualConsistency: boolean = true,\n): Promise<ParsedBody<Body>> {\n let signature = req.headers[SIGNATURE_HEADER_NAME]!\n if (Array.isArray(signature)) {\n signature = signature[0]\n }\n\n const body = await readBody(req)\n const validSignature = secret ? isValidSignature(body, signature, secret.trim()) : null\n\n if (validSignature !== false && waitForContentLakeEventualConsistency) {\n await new Promise((resolve) => setTimeout(resolve, 1000))\n }\n\n return {\n body: body.trim() && JSON.parse(body),\n isValidSignature: validSignature,\n }\n}\n\n/**\n * @deprecated Use `ParsedBody` instead\n * @public\n */\nexport type ParseAppBody<Body = SanityDocument> = ParsedBody<Body>\n/**\n * Handles parsing the body JSON, and validating its signature. Also waits for Content Lake eventual consistency so you can run your queries\n * without worrying about getting stale data.\n * @deprecated Use `parseBody` instead\n * @public\n */\nexport async function parseAppBody<Body = SanityDocument>(\n req: NextRequest,\n secret?: string,\n waitForContentLakeEventualConsistency: boolean = true,\n): Promise<ParsedBody<Body>> {\n const signature = req.headers.get(SIGNATURE_HEADER_NAME)!\n\n const body = await req.text()\n const validSignature = secret ? isValidSignature(body, signature, secret.trim()) : null\n\n if (validSignature !== false && waitForContentLakeEventualConsistency) {\n await new Promise((resolve) => setTimeout(resolve, 1000))\n }\n\n return {\n body: body.trim() && JSON.parse(body),\n isValidSignature: validSignature,\n }\n}\n"],"names":["parseBody","req","secret","waitForContentLakeEventualConsistency","arguments","length","undefined","parseAppBody","parsePageBody","signature","headers","SIGNATURE_HEADER_NAME","Array","isArray","body","readBody","validSignature","isValidSignature","trim","Promise","resolve","setTimeout","JSON","parse","get","text"],"mappings":";;AA+CA,eAAsBA,SACpBA,CAAAC,GAAA,EACAC,MACA,EAC2B;EAAA,IAD3BC,qCAAA,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAiD,IACtB;EACpB,OAAA,MAAA,IAAUH,GACb,GAAAM,YAAA,CAAaN,GAAK,EAAAC,MAAA,EAAQC,qCAAqC,CAC/D,GAAAK,aAAA,CAAcP,GAAK,EAAAC,MAAA,EAAQC,qCAAqC,CAAA;AACtE;AAEA,eAAeK,aACbA,CAAAP,GAAA,EACAC,MACA,EAC2B;EAAA,IAD3BC,qCAAA,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAiD,IACtB;EACvB,IAAAK,SAAA,GAAYR,GAAI,CAAAS,OAAA,CAAQC,qBAAqB,CAAA;EAC7C,IAAAC,KAAA,CAAMC,OAAQ,CAAAJ,SAAS,CAAG,EAAA;IAC5BA,SAAA,GAAYA,UAAU,CAAC,CAAA;EACzB;EAEM,MAAAK,IAAA,GAAO,MAAMC,SAAA,CAASd,GAAG,CAAA;EACzB,MAAAe,cAAA,GAAiBd,SAASe,gBAAiB,CAAAH,IAAA,EAAML,WAAWP,MAAO,CAAAgB,IAAA,EAAM,CAAI,GAAA,IAAA;EAE/E,IAAAF,cAAA,KAAmB,SAASb,qCAAuC,EAAA;IACrE,MAAM,IAAIgB,OAAQ,CAACC,WAAYC,UAAW,CAAAD,OAAA,EAAS,GAAI,CAAC,CAAA;EAC1D;EAEO,OAAA;IACLN,MAAMA,IAAK,CAAAI,IAAA,CAAA,CAAU,IAAAI,IAAA,CAAKC,MAAMT,IAAI,CAAA;IACpCG,gBAAkB,EAAAD;EAAA,CACpB;AACF;AAaA,eAAsBT,YACpBA,CAAAN,GAAA,EACAC,MACA,EAC2B;EAAA,IAD3BC,qCAAA,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAiD,IACtB;EAC3B,MAAMK,SAAY,GAAAR,GAAA,CAAIS,OAAQ,CAAAc,GAAA,CAAIb,qBAAqB,CAAA;EAEjD,MAAAG,IAAA,GAAO,MAAMb,GAAA,CAAIwB,IAAK,EAAA;EACtB,MAAAT,cAAA,GAAiBd,SAASe,gBAAiB,CAAAH,IAAA,EAAML,WAAWP,MAAO,CAAAgB,IAAA,EAAM,CAAI,GAAA,IAAA;EAE/E,IAAAF,cAAA,KAAmB,SAASb,qCAAuC,EAAA;IACrE,MAAM,IAAIgB,OAAQ,CAACC,WAAYC,UAAW,CAAAD,OAAA,EAAS,GAAI,CAAC,CAAA;EAC1D;EAEO,OAAA;IACLN,MAAMA,IAAK,CAAAI,IAAA,CAAA,CAAU,IAAAI,IAAA,CAAKC,MAAMT,IAAI,CAAA;IACpCG,gBAAkB,EAAAD;EAAA,CACpB;AACF;"}
1
+ {"version":3,"file":"parseBody.js","sources":["../../src/webhook/parseBody.ts"],"sourcesContent":["import type {SanityDocument} from '@sanity/types'\nimport {isValidSignature, SIGNATURE_HEADER_NAME} from '@sanity/webhook'\nimport type {NextApiRequest} from 'next'\nimport type {NextRequest} from 'next/server'\n\nimport {_readBody as readBody} from './readBody'\n\n/** @public */\nexport type ParsedBody<T> = {\n /**\n * If a secret is given then it returns a boolean. If no secret is provided then no validation is done on the signature, and it'll return `null`\n */\n isValidSignature: boolean | null\n body: T | null\n}\n\n/**\n * @deprecated Use `ParsedBody` instead\n * @public\n */\nexport type ParseBody<Body = SanityDocument> = ParsedBody<Body>\n/**\n * Handles parsing the body JSON, and validating its signature. Also waits for Content Lake eventual consistency so you can run your queries\n * without worrying about getting stale data.\n * @public\n */\nexport async function parseBody<Body = SanityDocument>(\n req: NextApiRequest,\n secret?: string,\n waitForContentLakeEventualConsistency?: boolean,\n): Promise<ParsedBody<Body>>\n/**\n * Handles parsing the body JSON, and validating its signature. Also waits for Content Lake eventual consistency so you can run your queries\n * without worrying about getting stale data.\n * @public\n */\nexport async function parseBody<Body = SanityDocument>(\n req: NextRequest,\n secret?: string,\n waitForContentLakeEventualConsistency?: boolean,\n): Promise<ParsedBody<Body>>\n/**\n * Handles parsing the body JSON, and validating its signature. Also waits for Content Lake eventual consistency so you can run your queries\n * without worrying about getting stale data.\n * @public\n */\n// eslint-disable-next-line require-await\nexport async function parseBody<Body = SanityDocument>(\n req: NextApiRequest | NextRequest,\n secret?: string,\n waitForContentLakeEventualConsistency: boolean = true,\n): Promise<ParsedBody<Body>> {\n // @ts-expect-error -- add global typings for EdgeRuntime\n if (typeof EdgeRuntime !== 'undefined') {\n throw new TypeError(\n `The edge runtime isn't supported. You'll have to use the 'nodejs' runtime until the underlying \\`@sanity/webhook\\` package is updated to support it.`,\n )\n }\n return 'text' in req\n ? parseAppBody(req, secret, waitForContentLakeEventualConsistency)\n : parsePageBody(req, secret, waitForContentLakeEventualConsistency)\n}\n\nasync function parsePageBody<Body = SanityDocument>(\n req: NextApiRequest,\n secret?: string,\n waitForContentLakeEventualConsistency: boolean = true,\n): Promise<ParsedBody<Body>> {\n let signature = req.headers[SIGNATURE_HEADER_NAME]\n if (Array.isArray(signature)) {\n signature = signature[0]\n }\n if (!signature) {\n console.error('Missing signature header')\n return {body: null, isValidSignature: null}\n }\n\n if (req.readableEnded) {\n throw new Error(\n `Request already ended and the POST body can't be read. Have you setup \\`export {config} from 'next-sanity/webhook' in your webhook API handler?\\``,\n )\n }\n\n const body = await readBody(req)\n const validSignature = secret ? isValidSignature(body, signature, secret.trim()) : null\n\n if (validSignature !== false && waitForContentLakeEventualConsistency) {\n await new Promise((resolve) => setTimeout(resolve, 1000))\n }\n\n return {\n body: body.trim() ? JSON.parse(body) : null,\n isValidSignature: validSignature,\n }\n}\n\n/**\n * @deprecated Use `ParsedBody` instead\n * @public\n */\nexport type ParseAppBody<Body = SanityDocument> = ParsedBody<Body>\n/**\n * Handles parsing the body JSON, and validating its signature. Also waits for Content Lake eventual consistency so you can run your queries\n * without worrying about getting stale data.\n * @deprecated Use `parseBody` instead\n * @public\n */\nexport async function parseAppBody<Body = SanityDocument>(\n req: NextRequest,\n secret?: string,\n waitForContentLakeEventualConsistency: boolean = true,\n): Promise<ParsedBody<Body>> {\n const signature = req.headers.get(SIGNATURE_HEADER_NAME)!\n if (!signature) {\n console.error('Missing signature header')\n return {body: null, isValidSignature: null}\n }\n\n const body = await req.text()\n const validSignature = secret ? isValidSignature(body, signature, secret.trim()) : null\n\n if (validSignature !== false && waitForContentLakeEventualConsistency) {\n await new Promise((resolve) => setTimeout(resolve, 1000))\n }\n\n return {\n body: body.trim() ? JSON.parse(body) : null,\n isValidSignature: validSignature,\n }\n}\n"],"names":["parseBody","req","secret","waitForContentLakeEventualConsistency","arguments","length","undefined","EdgeRuntime","TypeError","parseAppBody","parsePageBody","signature","headers","SIGNATURE_HEADER_NAME","Array","isArray","console","error","body","isValidSignature","readableEnded","Error","readBody","validSignature","trim","Promise","resolve","setTimeout","JSON","parse","get","text"],"mappings":";;AA+CA,eAAsBA,SACpBA,CAAAC,GAAA,EACAC,MACA,EAC2B;EAAA,IAD3BC,qCAAA,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAiD,IACtB;EAEvB,IAAA,OAAOG,gBAAgB,WAAa,EAAA;IACtC,MAAM,IAAIC,SAAA,CACR,oJAAA,CACF;EACF;EACO,OAAA,MAAA,IAAUP,GACb,GAAAQ,YAAA,CAAaR,GAAK,EAAAC,MAAA,EAAQC,qCAAqC,CAC/D,GAAAO,aAAA,CAAcT,GAAK,EAAAC,MAAA,EAAQC,qCAAqC,CAAA;AACtE;AAEA,eAAeO,aACbA,CAAAT,GAAA,EACAC,MACA,EAC2B;EAAA,IAD3BC,qCAAA,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAiD,IACtB;EACvB,IAAAO,SAAA,GAAYV,GAAI,CAAAW,OAAA,CAAQC,qBAAqB,CAAA;EAC7C,IAAAC,KAAA,CAAMC,OAAQ,CAAAJ,SAAS,CAAG,EAAA;IAC5BA,SAAA,GAAYA,UAAU,CAAC,CAAA;EACzB;EACA,IAAI,CAACA,SAAW,EAAA;IACdK,OAAA,CAAQC,MAAM,0BAA0B,CAAA;IACxC,OAAO;MAACC,IAAA,EAAM,IAAM;MAAAC,gBAAA,EAAkB;IAAI,CAAA;EAC5C;EAEA,IAAIlB,IAAImB,aAAe,EAAA;IACrB,MAAM,IAAIC,KAAA,CACR,iJAAA,CACF;EACF;EAEM,MAAAH,IAAA,GAAO,MAAMI,SAAA,CAASrB,GAAG,CAAA;EACzB,MAAAsB,cAAA,GAAiBrB,SAASiB,gBAAiB,CAAAD,IAAA,EAAMP,WAAWT,MAAO,CAAAsB,IAAA,EAAM,CAAI,GAAA,IAAA;EAE/E,IAAAD,cAAA,KAAmB,SAASpB,qCAAuC,EAAA;IACrE,MAAM,IAAIsB,OAAQ,CAACC,WAAYC,UAAW,CAAAD,OAAA,EAAS,GAAI,CAAC,CAAA;EAC1D;EAEO,OAAA;IACLR,MAAMA,IAAK,CAAAM,IAAA,KAASI,IAAK,CAAAC,KAAA,CAAMX,IAAI,CAAI,GAAA,IAAA;IACvCC,gBAAkB,EAAAI;EAAA,CACpB;AACF;AAaA,eAAsBd,YACpBA,CAAAR,GAAA,EACAC,MACA,EAC2B;EAAA,IAD3BC,qCAAA,GAAAC,SAAA,CAAAC,MAAA,QAAAD,SAAA,QAAAE,SAAA,GAAAF,SAAA,MAAiD,IACtB;EAC3B,MAAMO,SAAY,GAAAV,GAAA,CAAIW,OAAQ,CAAAkB,GAAA,CAAIjB,qBAAqB,CAAA;EACvD,IAAI,CAACF,SAAW,EAAA;IACdK,OAAA,CAAQC,MAAM,0BAA0B,CAAA;IACxC,OAAO;MAACC,IAAA,EAAM,IAAM;MAAAC,gBAAA,EAAkB;IAAI,CAAA;EAC5C;EAEM,MAAAD,IAAA,GAAO,MAAMjB,GAAA,CAAI8B,IAAK,EAAA;EACtB,MAAAR,cAAA,GAAiBrB,SAASiB,gBAAiB,CAAAD,IAAA,EAAMP,WAAWT,MAAO,CAAAsB,IAAA,EAAM,CAAI,GAAA,IAAA;EAE/E,IAAAD,cAAA,KAAmB,SAASpB,qCAAuC,EAAA;IACrE,MAAM,IAAIsB,OAAQ,CAACC,WAAYC,UAAW,CAAAD,OAAA,EAAS,GAAI,CAAC,CAAA;EAC1D;EAEO,OAAA;IACLR,MAAMA,IAAK,CAAAM,IAAA,KAASI,IAAK,CAAAC,KAAA,CAAMX,IAAI,CAAI,GAAA,IAAA;IACvCC,gBAAkB,EAAAI;EAAA,CACpB;AACF;"}
package/dist/webhook.d.ts CHANGED
@@ -61,7 +61,7 @@ export declare type ParsedBody<T> = {
61
61
  * If a secret is given then it returns a boolean. If no secret is provided then no validation is done on the signature, and it'll return `null`
62
62
  */
63
63
  isValidSignature: boolean | null
64
- body: T
64
+ body: T | null
65
65
  }
66
66
 
67
67
  export {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-sanity",
3
- "version": "5.4.3",
3
+ "version": "5.4.4",
4
4
  "description": "Sanity.io toolkit for Next.js",
5
5
  "keywords": [
6
6
  "sanity",
@@ -174,15 +174,15 @@
174
174
  "singleQuote": true
175
175
  },
176
176
  "dependencies": {
177
- "@sanity/preview-kit": "3.1.3",
178
- "@sanity/webhook": "3.0.0",
177
+ "@sanity/preview-kit": "3.1.4",
178
+ "@sanity/webhook": "3.0.1",
179
179
  "groq": "^3.0.0"
180
180
  },
181
181
  "devDependencies": {
182
- "@next/bundle-analyzer": "^13.4.18",
183
- "@next/eslint-plugin-next": "13.4.18",
182
+ "@next/bundle-analyzer": "^13.4.19",
183
+ "@next/eslint-plugin-next": "13.4.19",
184
184
  "@rollup/plugin-url": "^8.0.1",
185
- "@sanity/client": "6.4.8",
185
+ "@sanity/client": "6.4.9",
186
186
  "@sanity/eslint-config-studio": "^3.0.0",
187
187
  "@sanity/image-url": "^1.0.2",
188
188
  "@sanity/pkg-utils": "^2.4.6",
@@ -206,7 +206,7 @@
206
206
  "jest": "^29.6.2",
207
207
  "jest-environment-jsdom": "^29.6.2",
208
208
  "ls-engines": "^0.9.0",
209
- "next": "13.4.18",
209
+ "next": "13.4.19",
210
210
  "postcss": "^8.4.28",
211
211
  "prettier": "^3.0.2",
212
212
  "prettier-plugin-packagejson": "^2.4.5",
@@ -224,7 +224,7 @@
224
224
  "url-loader": "^4.1.1"
225
225
  },
226
226
  "peerDependencies": {
227
- "@sanity/client": "^6.4.8",
227
+ "@sanity/client": "^6.4.9",
228
228
  "@sanity/icons": "^2.0.0",
229
229
  "@sanity/types": "^3.0.0",
230
230
  "@sanity/ui": "^1.0.0",
@@ -11,7 +11,7 @@ export type ParsedBody<T> = {
11
11
  * If a secret is given then it returns a boolean. If no secret is provided then no validation is done on the signature, and it'll return `null`
12
12
  */
13
13
  isValidSignature: boolean | null
14
- body: T
14
+ body: T | null
15
15
  }
16
16
 
17
17
  /**
@@ -50,6 +50,12 @@ export async function parseBody<Body = SanityDocument>(
50
50
  secret?: string,
51
51
  waitForContentLakeEventualConsistency: boolean = true,
52
52
  ): Promise<ParsedBody<Body>> {
53
+ // @ts-expect-error -- add global typings for EdgeRuntime
54
+ if (typeof EdgeRuntime !== 'undefined') {
55
+ throw new TypeError(
56
+ `The edge runtime isn't supported. You'll have to use the 'nodejs' runtime until the underlying \`@sanity/webhook\` package is updated to support it.`,
57
+ )
58
+ }
53
59
  return 'text' in req
54
60
  ? parseAppBody(req, secret, waitForContentLakeEventualConsistency)
55
61
  : parsePageBody(req, secret, waitForContentLakeEventualConsistency)
@@ -60,10 +66,20 @@ async function parsePageBody<Body = SanityDocument>(
60
66
  secret?: string,
61
67
  waitForContentLakeEventualConsistency: boolean = true,
62
68
  ): Promise<ParsedBody<Body>> {
63
- let signature = req.headers[SIGNATURE_HEADER_NAME]!
69
+ let signature = req.headers[SIGNATURE_HEADER_NAME]
64
70
  if (Array.isArray(signature)) {
65
71
  signature = signature[0]
66
72
  }
73
+ if (!signature) {
74
+ console.error('Missing signature header')
75
+ return {body: null, isValidSignature: null}
76
+ }
77
+
78
+ if (req.readableEnded) {
79
+ throw new Error(
80
+ `Request already ended and the POST body can't be read. Have you setup \`export {config} from 'next-sanity/webhook' in your webhook API handler?\``,
81
+ )
82
+ }
67
83
 
68
84
  const body = await readBody(req)
69
85
  const validSignature = secret ? isValidSignature(body, signature, secret.trim()) : null
@@ -73,7 +89,7 @@ async function parsePageBody<Body = SanityDocument>(
73
89
  }
74
90
 
75
91
  return {
76
- body: body.trim() && JSON.parse(body),
92
+ body: body.trim() ? JSON.parse(body) : null,
77
93
  isValidSignature: validSignature,
78
94
  }
79
95
  }
@@ -95,6 +111,10 @@ export async function parseAppBody<Body = SanityDocument>(
95
111
  waitForContentLakeEventualConsistency: boolean = true,
96
112
  ): Promise<ParsedBody<Body>> {
97
113
  const signature = req.headers.get(SIGNATURE_HEADER_NAME)!
114
+ if (!signature) {
115
+ console.error('Missing signature header')
116
+ return {body: null, isValidSignature: null}
117
+ }
98
118
 
99
119
  const body = await req.text()
100
120
  const validSignature = secret ? isValidSignature(body, signature, secret.trim()) : null
@@ -104,7 +124,7 @@ export async function parseAppBody<Body = SanityDocument>(
104
124
  }
105
125
 
106
126
  return {
107
- body: body.trim() && JSON.parse(body),
127
+ body: body.trim() ? JSON.parse(body) : null,
108
128
  isValidSignature: validSignature,
109
129
  }
110
130
  }