next-sanity
Advanced tools
Comparing version 0.4.1-beta.0 to 0.5.0
export interface Aborter { | ||
abort(): void; | ||
signal?: AbortSignal; | ||
signal: AbortSignal; | ||
} | ||
export declare function getAborter(): Aborter; |
@@ -11,2 +11,2 @@ import { CurrentUser } from './types'; | ||
}; | ||
export declare function getCurrentUser(projectId: string, abort?: Aborter): Promise<CurrentUser | null>; | ||
export declare function getCurrentUser(projectId: string, abort: Aborter): Promise<CurrentUser | null>; |
export * from './types'; | ||
export { createClient } from './client'; | ||
export { createImageUrlBuilder } from './imageUrlBuilder'; | ||
export { createCurrentUserHook } from './currentUser'; | ||
export { createPreviewSubscriptionHook } from './useSubscription'; | ||
export { createPortableTextComponent } from './portableText'; | ||
export { default as groq } from 'groq'; |
@@ -27,7 +27,3 @@ 'use strict'; | ||
var sanityClient = _interopDefault(require('@sanity/client')); | ||
var getImageUrlBuilder = _interopDefault(require('@sanity/image-url')); | ||
var React = require('react'); | ||
var React__default = _interopDefault(React); | ||
var useDeepCompareEffect = require('use-deep-compare-effect'); | ||
var SanityPortableText = _interopDefault(require('@sanity/block-content-to-react')); | ||
var react = require('react'); | ||
var groq = _interopDefault(require('groq')); | ||
@@ -39,21 +35,48 @@ | ||
function createImageUrlBuilder(_ref) { | ||
var projectId = _ref.projectId, | ||
dataset = _ref.dataset; | ||
return getImageUrlBuilder({ | ||
projectId: projectId, | ||
dataset: dataset | ||
function _defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
function _createClass(Constructor, protoProps, staticProps) { | ||
if (protoProps) _defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) _defineProperties(Constructor, staticProps); | ||
Object.defineProperty(Constructor, "prototype", { | ||
writable: false | ||
}); | ||
return Constructor; | ||
} | ||
var MockAbortController = /*#__PURE__*/function () { | ||
function MockAbortController() { | ||
this._signal = { | ||
aborted: false | ||
}; | ||
} | ||
var _proto = MockAbortController.prototype; | ||
_proto.abort = function abort() { | ||
this._signal.aborted = true; | ||
}; | ||
_createClass(MockAbortController, [{ | ||
key: "signal", | ||
get: function get() { | ||
return this._signal; | ||
} | ||
}]); | ||
return MockAbortController; | ||
}(); | ||
function getAborter() { | ||
return typeof AbortController === 'undefined' ? { | ||
signal: undefined, | ||
abort: noop | ||
} : new AbortController(); | ||
return typeof AbortController === 'undefined' ? new MockAbortController() : new AbortController(); | ||
} | ||
function noop() {// intentional noop | ||
} | ||
function createCurrentUserHook(_ref) { | ||
@@ -68,3 +91,3 @@ var projectId = _ref.projectId; | ||
credentials: 'include', | ||
signal: abort == null ? void 0 : abort.signal | ||
signal: abort.signal | ||
}).then(function (res) { | ||
@@ -74,4 +97,2 @@ return res.json(); | ||
return res != null && res.id ? res : null; | ||
}).catch(function (err) { | ||
return err.name === 'AbortError' ? null : Promise.reject(err); | ||
}); | ||
@@ -81,15 +102,17 @@ } | ||
function useCurrentUser(projectId) { | ||
var _useState = React.useState(), | ||
var _useState = react.useState(), | ||
data = _useState[0], | ||
setUser = _useState[1]; | ||
var _useState2 = React.useState(), | ||
var _useState2 = react.useState(), | ||
error = _useState2[0], | ||
setError = _useState2[1]; | ||
React.useEffect(function () { | ||
react.useEffect(function () { | ||
var aborter = getAborter(); | ||
getCurrentUser(projectId, aborter).then(setUser).catch(setError); | ||
getCurrentUser(projectId, aborter).then(setUser).catch(function (err) { | ||
return err.name !== 'AbortError' && setError(err); | ||
}); | ||
return function () { | ||
return aborter.abort(); | ||
aborter.abort(); | ||
}; | ||
@@ -108,3 +131,2 @@ }, [projectId]); | ||
dataset = _ref.dataset, | ||
useGroqBeta = _ref.useGroqBeta, | ||
_ref$documentLimit = _ref.documentLimit, | ||
@@ -134,6 +156,15 @@ documentLimit = _ref$documentLimit === void 0 ? 3000 : _ref$documentLimit; | ||
function getStore() { | ||
function getStore(abort) { | ||
if (!store) { | ||
store = new Promise(function (resolve) { resolve(_interopNamespace(require('@sanity/groq-store'))); }).then(function (_ref2) { | ||
var groqStore = _ref2.groqStore; | ||
// Skip creating the groq store if we've been unmounted to save memory and reduce gc pressure | ||
if (abort.signal.aborted) { | ||
var error = new Error('Cancelling groq store creation'); // This ensures we can skip it in the catch block same way | ||
error.name = 'AbortError'; | ||
return Promise.reject(error); | ||
} | ||
return groqStore({ | ||
@@ -143,3 +174,2 @@ projectId: projectId, | ||
documentLimit: documentLimit, | ||
useGroqBeta: useGroqBeta, | ||
listen: true, | ||
@@ -160,3 +190,2 @@ overlayDrafts: true, | ||
query = options.query, | ||
params = options.params, | ||
initialData = options.initialData, | ||
@@ -166,21 +195,20 @@ _options$enabled = options.enabled, | ||
var _useState = React.useState(), | ||
var _useState = react.useState(), | ||
error = _useState[0], | ||
setError = _useState[1]; | ||
var _useState2 = React.useState(false), | ||
var _useState2 = react.useState(false), | ||
loading = _useState2[0], | ||
setLoading = _useState2[1]; | ||
var _useState3 = React.useState(), | ||
var _useState3 = react.useState(), | ||
data = _useState3[0], | ||
setData = _useState3[1]; // Use "deep" dependency comparison because params are often not _referentially_ equal, | ||
setData = _useState3[1]; | ||
var params = useParams(options.params); // Use "deep" dependency comparison because params are often not _referentially_ equal, | ||
// but contains the same shallow properties, eg `{"slug": "some-slug"}` | ||
useDeepCompareEffect.useDeepCompareEffectNoCheck(function () { | ||
react.useEffect(function () { | ||
if (!enabled) { | ||
return function () { | ||
/* intentional noop */ | ||
}; | ||
return; | ||
} | ||
@@ -199,3 +227,5 @@ | ||
throw new Error('Not authenticated - preview not available'); | ||
}).then(getStore).then(function (store) { | ||
}).then(function () { | ||
return getStore(aborter); | ||
}).then(function (store) { | ||
subscription = store.subscribe(query, params, function (err, result) { | ||
@@ -208,5 +238,8 @@ if (err) { | ||
}); | ||
}).catch(setError).finally(function () { | ||
}).catch(function (err) { | ||
return err.name === 'AbortError' ? null : setError(err); | ||
}).finally(function () { | ||
return setLoading(false); | ||
}); | ||
}); // eslint-disable-next-line consistent-return | ||
return function () { | ||
@@ -225,15 +258,12 @@ if (subscription) { | ||
}; | ||
} | ||
} // Return params that are stable with deep equal as long as the key order is the same | ||
function createPortableTextComponent(_ref) { | ||
var projectId = _ref.projectId, | ||
dataset = _ref.dataset, | ||
serializers = _ref.serializers; | ||
return function PortableText(props) { | ||
return React__default.createElement(SanityPortableText, Object.assign({ | ||
projectId: projectId, | ||
dataset: dataset, | ||
serializers: serializers | ||
}, props)); | ||
}; | ||
function useParams(params) { | ||
var stringifiedParams = react.useMemo(function () { | ||
return JSON.stringify(params); | ||
}, [params]); | ||
return react.useMemo(function () { | ||
return JSON.parse(stringifiedParams); | ||
}, [stringifiedParams]); | ||
} | ||
@@ -244,5 +274,3 @@ | ||
exports.createCurrentUserHook = createCurrentUserHook; | ||
exports.createImageUrlBuilder = createImageUrlBuilder; | ||
exports.createPortableTextComponent = createPortableTextComponent; | ||
exports.createPreviewSubscriptionHook = createPreviewSubscriptionHook; | ||
//# sourceMappingURL=next-sanity.cjs.development.js.map |
@@ -1,2 +0,2 @@ | ||
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var t=e(require("@sanity/client")),r=e(require("@sanity/image-url")),n=require("react"),o=e(n),i=require("use-deep-compare-effect"),a=e(require("@sanity/block-content-to-react")),u=e(require("groq"));function c(){return"undefined"==typeof AbortController?{signal:void 0,abort:s}:new AbortController}function s(){}function f(e,t){return fetch("https://"+e+".api.sanity.io/v1/users/me",{credentials:"include",signal:null==t?void 0:t.signal}).then((function(e){return e.json()})).then((function(e){return null!=e&&e.id?e:null})).catch((function(e){return"AbortError"===e.name?null:Promise.reject(e)}))}var l={};exports.groq=u,exports.createClient=function(e){return t(e)},exports.createCurrentUserHook=function(e){var t=e.projectId;return function(){return function(e){var t=n.useState(),r=t[0],o=t[1],i=n.useState(),a=i[0],u=i[1];return n.useEffect((function(){var t=c();return f(e,t).then(o).catch(u),function(){return t.abort()}}),[e]),{data:r,error:a,loading:null!==r||!a}}(t)}},exports.createImageUrlBuilder=function(e){return r({projectId:e.projectId,dataset:e.dataset})},exports.createPortableTextComponent=function(e){var t=e.projectId,r=e.dataset,n=e.serializers;return function(e){return o.createElement(a,Object.assign({projectId:t,dataset:r,serializers:n},e))}},exports.createPreviewSubscriptionHook=function(e){var t,r=e.projectId,o=e.dataset,a=e.useGroqBeta,u=e.documentLimit,s=void 0===u?3e3:u;return function(e,t){void 0===t&&(t={});var o=t.params;return function(e){var t=e.getStore,r=e.projectId,o=e.query,a=e.params,u=e.initialData,s=e.enabled,l=void 0!==s&&s,d=n.useState(),p=d[0],v=d[1],b=n.useState(!1),h=b[0],m=b[1],g=n.useState(),j=g[0],y=g[1];return i.useDeepCompareEffectNoCheck((function(){if(!l)return function(){};m(!0);var e,n=c();return f(r,n).then((function(e){if(!e)throw console.warn("Not authenticated - preview not available"),new Error("Not authenticated - preview not available")})).then(t).then((function(t){e=t.subscribe(o,a,(function(e,t){e?v(e):y(t)}))})).catch(v).finally((function(){return m(!1)})),function(){e&&e.unsubscribe(),n.abort()}}),[t,o,a,l]),{data:void 0===j?u:j,loading:h,error:p}}({getStore:d,projectId:r,query:e,params:void 0===o?l:o,initialData:t.initialData,enabled:!!t.enabled&&"undefined"!=typeof window})};function d(){return t||(t=new Promise((function(e){e(function(e){if(e&&e.__esModule)return e;var t={};return e&&Object.keys(e).forEach((function(r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})})),t.default=e,t}(require("@sanity/groq-store")))})).then((function(e){return(0,e.groqStore)({projectId:r,dataset:o,documentLimit:s,useGroqBeta:a,listen:!0,overlayDrafts:!0,subscriptionThrottleMs:10})}))),t}}; | ||
"use strict";function e(e){return e&&"object"==typeof e&&"default"in e?e.default:e}Object.defineProperty(exports,"__esModule",{value:!0});var t=e(require("@sanity/client")),r=require("react"),n=e(require("groq")),o=function(){function e(){this._signal={aborted:!1}}var t,r;return e.prototype.abort=function(){this._signal.aborted=!0},t=e,(r=[{key:"signal",get:function(){return this._signal}}])&&function(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}(t.prototype,r),Object.defineProperty(t,"prototype",{writable:!1}),e}();function i(){return"undefined"==typeof AbortController?new o:new AbortController}function u(e,t){return fetch("https://"+e+".api.sanity.io/v1/users/me",{credentials:"include",signal:t.signal}).then((function(e){return e.json()})).then((function(e){return null!=e&&e.id?e:null}))}var a={};exports.groq=n,exports.createClient=function(e){return t(e)},exports.createCurrentUserHook=function(e){var t=e.projectId;return function(){return function(e){var t=r.useState(),n=t[0],o=t[1],a=r.useState(),c=a[0],f=a[1];return r.useEffect((function(){var t=i();return u(e,t).then(o).catch((function(e){return"AbortError"!==e.name&&f(e)})),function(){t.abort()}}),[e]),{data:n,error:c,loading:null!==n||!c}}(t)}},exports.createPreviewSubscriptionHook=function(e){var t,n=e.projectId,o=e.dataset,c=e.documentLimit,f=void 0===c?3e3:c;return function(e,t){void 0===t&&(t={});var o=t.params;return function(e){var t=e.getStore,n=e.projectId,o=e.query,a=e.initialData,c=e.enabled,f=void 0!==c&&c,s=r.useState(),l=s[0],d=s[1],b=r.useState(!1),p=b[0],v=b[1],g=r.useState(),y=g[0],h=g[1],m=function(e){var t=r.useMemo((function(){return JSON.stringify(e)}),[e]);return r.useMemo((function(){return JSON.parse(t)}),[t])}(e.params);return r.useEffect((function(){if(f){v(!0);var e,r=i();return u(n,r).then((function(e){if(!e)throw console.warn("Not authenticated - preview not available"),new Error("Not authenticated - preview not available")})).then((function(){return t(r)})).then((function(t){e=t.subscribe(o,m,(function(e,t){e?d(e):h(t)}))})).catch((function(e){return"AbortError"===e.name?null:d(e)})).finally((function(){return v(!1)})),function(){e&&e.unsubscribe(),r.abort()}}}),[t,o,m,f]),{data:void 0===y?a:y,loading:p,error:l}}({getStore:s,projectId:n,query:e,params:void 0===o?a:o,initialData:t.initialData,enabled:!!t.enabled&&"undefined"!=typeof window})};function s(e){return t||(t=new Promise((function(e){e(function(e){if(e&&e.__esModule)return e;var t={};return e&&Object.keys(e).forEach((function(r){var n=Object.getOwnPropertyDescriptor(e,r);Object.defineProperty(t,r,n.get?n:{enumerable:!0,get:function(){return e[r]}})})),t.default=e,t}(require("@sanity/groq-store")))})).then((function(t){var r=t.groqStore;if(e.signal.aborted){var i=new Error("Cancelling groq store creation");return i.name="AbortError",Promise.reject(i)}return r({projectId:n,dataset:o,documentLimit:f,listen:!0,overlayDrafts:!0,subscriptionThrottleMs:10})}))),t}}; | ||
//# sourceMappingURL=next-sanity.cjs.production.min.js.map |
import sanityClient from '@sanity/client'; | ||
import getImageUrlBuilder from '@sanity/image-url'; | ||
import React, { useState, useEffect } from 'react'; | ||
import { useDeepCompareEffectNoCheck } from 'use-deep-compare-effect'; | ||
import SanityPortableText from '@sanity/block-content-to-react'; | ||
import { useState, useEffect, useMemo } from 'react'; | ||
export { default as groq } from 'groq'; | ||
@@ -12,21 +9,48 @@ | ||
function createImageUrlBuilder(_ref) { | ||
var projectId = _ref.projectId, | ||
dataset = _ref.dataset; | ||
return getImageUrlBuilder({ | ||
projectId: projectId, | ||
dataset: dataset | ||
function _defineProperties(target, props) { | ||
for (var i = 0; i < props.length; i++) { | ||
var descriptor = props[i]; | ||
descriptor.enumerable = descriptor.enumerable || false; | ||
descriptor.configurable = true; | ||
if ("value" in descriptor) descriptor.writable = true; | ||
Object.defineProperty(target, descriptor.key, descriptor); | ||
} | ||
} | ||
function _createClass(Constructor, protoProps, staticProps) { | ||
if (protoProps) _defineProperties(Constructor.prototype, protoProps); | ||
if (staticProps) _defineProperties(Constructor, staticProps); | ||
Object.defineProperty(Constructor, "prototype", { | ||
writable: false | ||
}); | ||
return Constructor; | ||
} | ||
var MockAbortController = /*#__PURE__*/function () { | ||
function MockAbortController() { | ||
this._signal = { | ||
aborted: false | ||
}; | ||
} | ||
var _proto = MockAbortController.prototype; | ||
_proto.abort = function abort() { | ||
this._signal.aborted = true; | ||
}; | ||
_createClass(MockAbortController, [{ | ||
key: "signal", | ||
get: function get() { | ||
return this._signal; | ||
} | ||
}]); | ||
return MockAbortController; | ||
}(); | ||
function getAborter() { | ||
return typeof AbortController === 'undefined' ? { | ||
signal: undefined, | ||
abort: noop | ||
} : new AbortController(); | ||
return typeof AbortController === 'undefined' ? new MockAbortController() : new AbortController(); | ||
} | ||
function noop() {// intentional noop | ||
} | ||
function createCurrentUserHook(_ref) { | ||
@@ -41,3 +65,3 @@ var projectId = _ref.projectId; | ||
credentials: 'include', | ||
signal: abort == null ? void 0 : abort.signal | ||
signal: abort.signal | ||
}).then(function (res) { | ||
@@ -47,4 +71,2 @@ return res.json(); | ||
return res != null && res.id ? res : null; | ||
}).catch(function (err) { | ||
return err.name === 'AbortError' ? null : Promise.reject(err); | ||
}); | ||
@@ -64,5 +86,7 @@ } | ||
var aborter = getAborter(); | ||
getCurrentUser(projectId, aborter).then(setUser).catch(setError); | ||
getCurrentUser(projectId, aborter).then(setUser).catch(function (err) { | ||
return err.name !== 'AbortError' && setError(err); | ||
}); | ||
return function () { | ||
return aborter.abort(); | ||
aborter.abort(); | ||
}; | ||
@@ -81,3 +105,2 @@ }, [projectId]); | ||
dataset = _ref.dataset, | ||
useGroqBeta = _ref.useGroqBeta, | ||
_ref$documentLimit = _ref.documentLimit, | ||
@@ -107,6 +130,15 @@ documentLimit = _ref$documentLimit === void 0 ? 3000 : _ref$documentLimit; | ||
function getStore() { | ||
function getStore(abort) { | ||
if (!store) { | ||
store = import('@sanity/groq-store').then(function (_ref2) { | ||
var groqStore = _ref2.groqStore; | ||
// Skip creating the groq store if we've been unmounted to save memory and reduce gc pressure | ||
if (abort.signal.aborted) { | ||
var error = new Error('Cancelling groq store creation'); // This ensures we can skip it in the catch block same way | ||
error.name = 'AbortError'; | ||
return Promise.reject(error); | ||
} | ||
return groqStore({ | ||
@@ -116,3 +148,2 @@ projectId: projectId, | ||
documentLimit: documentLimit, | ||
useGroqBeta: useGroqBeta, | ||
listen: true, | ||
@@ -133,3 +164,2 @@ overlayDrafts: true, | ||
query = options.query, | ||
params = options.params, | ||
initialData = options.initialData, | ||
@@ -149,11 +179,10 @@ _options$enabled = options.enabled, | ||
data = _useState3[0], | ||
setData = _useState3[1]; // Use "deep" dependency comparison because params are often not _referentially_ equal, | ||
setData = _useState3[1]; | ||
var params = useParams(options.params); // Use "deep" dependency comparison because params are often not _referentially_ equal, | ||
// but contains the same shallow properties, eg `{"slug": "some-slug"}` | ||
useDeepCompareEffectNoCheck(function () { | ||
useEffect(function () { | ||
if (!enabled) { | ||
return function () { | ||
/* intentional noop */ | ||
}; | ||
return; | ||
} | ||
@@ -172,3 +201,5 @@ | ||
throw new Error('Not authenticated - preview not available'); | ||
}).then(getStore).then(function (store) { | ||
}).then(function () { | ||
return getStore(aborter); | ||
}).then(function (store) { | ||
subscription = store.subscribe(query, params, function (err, result) { | ||
@@ -181,5 +212,8 @@ if (err) { | ||
}); | ||
}).catch(setError).finally(function () { | ||
}).catch(function (err) { | ||
return err.name === 'AbortError' ? null : setError(err); | ||
}).finally(function () { | ||
return setLoading(false); | ||
}); | ||
}); // eslint-disable-next-line consistent-return | ||
return function () { | ||
@@ -198,18 +232,15 @@ if (subscription) { | ||
}; | ||
} | ||
} // Return params that are stable with deep equal as long as the key order is the same | ||
function createPortableTextComponent(_ref) { | ||
var projectId = _ref.projectId, | ||
dataset = _ref.dataset, | ||
serializers = _ref.serializers; | ||
return function PortableText(props) { | ||
return React.createElement(SanityPortableText, Object.assign({ | ||
projectId: projectId, | ||
dataset: dataset, | ||
serializers: serializers | ||
}, props)); | ||
}; | ||
function useParams(params) { | ||
var stringifiedParams = useMemo(function () { | ||
return JSON.stringify(params); | ||
}, [params]); | ||
return useMemo(function () { | ||
return JSON.parse(stringifiedParams); | ||
}, [stringifiedParams]); | ||
} | ||
export { createClient, createCurrentUserHook, createImageUrlBuilder, createPortableTextComponent, createPreviewSubscriptionHook }; | ||
export { createClient, createCurrentUserHook, createPreviewSubscriptionHook }; | ||
//# sourceMappingURL=next-sanity.esm.js.map |
import { ProjectConfig } from './types'; | ||
declare type Params = Record<string, unknown>; | ||
interface SubscriptionOptions<R = any> { | ||
enabled?: boolean; | ||
params?: Record<string, unknown>; | ||
params?: Params; | ||
initialData?: R; | ||
} | ||
export declare function createPreviewSubscriptionHook({ projectId, dataset, useGroqBeta, documentLimit, }: ProjectConfig & { | ||
export declare function createPreviewSubscriptionHook({ projectId, dataset, documentLimit, }: ProjectConfig & { | ||
documentLimit?: number; | ||
useGroqBeta?: boolean; | ||
}): <R = any>(query: string, options?: SubscriptionOptions<R>) => { | ||
@@ -11,0 +11,0 @@ data: R; |
{ | ||
"name": "next-sanity", | ||
"description": "Sanity.io toolkit for Next.js", | ||
"version": "0.4.1-beta.0", | ||
"version": "0.5.0", | ||
"author": "Sanity.io <hello@sanity.io>", | ||
@@ -28,10 +28,9 @@ "license": "MIT", | ||
"dependencies": { | ||
"@sanity/block-content-to-react": "^3.0.0", | ||
"@sanity/client": "^2.23.1", | ||
"@sanity/groq-store": "^0.3.0-beta.0", | ||
"@sanity/image-url": "^1.0.1", | ||
"groq": "^2.15.0", | ||
"use-deep-compare-effect": "^1.6.1" | ||
"@sanity/client": "^3.0.6", | ||
"@sanity/groq-store": "^0.3.0", | ||
"groq": "^2.15.0" | ||
}, | ||
"devDependencies": { | ||
"@async-fn/jest": "^1.5.3", | ||
"@testing-library/react-hooks": "^7.0.2", | ||
"@types/jest": "^27.0.0", | ||
@@ -38,0 +37,0 @@ "@types/react": "^17.0.17", |
@@ -8,4 +8,2 @@ # next-sanity | ||
- Client-side live real-time preview for authenticated users | ||
- URL-helper for Sanity’s image pipeline | ||
- Rich-text component for Portable Text | ||
- GROQ syntax highlighting | ||
@@ -22,2 +20,3 @@ | ||
- [Example: Minimal blog post template](#example-minimal-blog-post-template) | ||
- [Migrate](#migrate) | ||
- [License](#license) | ||
@@ -28,5 +27,5 @@ | ||
```sh | ||
$ npm install next-sanity | ||
$ npm install next-sanity @portabletext/react @sanity/image-url | ||
// or | ||
$ yarn add next-sanity | ||
$ yarn add next-sanity @portabletext/react @sanity/image-url | ||
``` | ||
@@ -89,8 +88,4 @@ | ||
// lib/sanity.js | ||
import { | ||
createImageUrlBuilder, | ||
createPortableTextComponent, | ||
createPreviewSubscriptionHook, | ||
createCurrentUserHook, | ||
} from 'next-sanity' | ||
import {createPreviewSubscriptionHook, createCurrentUserHook} from 'next-sanity' | ||
import createImageUrlBuilder from '@sanity/image-url' | ||
import {config} from './config' | ||
@@ -107,10 +102,2 @@ | ||
// Set up Portable Text serialization | ||
export const PortableText = createPortableTextComponent({ | ||
...config, | ||
// Serializers passed to @sanity/block-content-to-react | ||
// (https://github.com/sanity-io/block-content-to-react) | ||
serializers: {}, | ||
}) | ||
// Helper function for using the current logged in user account | ||
@@ -148,3 +135,4 @@ export const useCurrentUser = createCurrentUserHook(config) | ||
import {groq} from 'next-sanity' | ||
import {usePreviewSubscription, urlFor, PortableText} from '../../lib/sanity' | ||
import {PortableText} from '@portabletext/react' | ||
import {usePreviewSubscription, urlFor} from '../../lib/sanity' | ||
import {getClient} from '../../lib/sanity.server' | ||
@@ -187,3 +175,3 @@ | ||
</figure> | ||
<PortableText blocks={body} /> | ||
<PortableText value={body} /> | ||
</article> | ||
@@ -218,4 +206,45 @@ ) | ||
## Migrate | ||
### From `v0.4` | ||
#### `createPortableTextComponent` is removed | ||
This utility used to wrap `@sanity/block-content-to-react`. It's encouraged to upgrade to `@portabletext/react`. | ||
```sh | ||
$ npm install @portabletext/react | ||
// or | ||
$ yarn add @portabletext/react | ||
``` | ||
```diff | ||
-import { createPortableTextComponent } from 'next-sanity' | ||
+import { PortableText as PortableTextComponent } from '@portabletext/react' | ||
-export const PortableText = createPortableTextComponent({ serializers: {} }) | ||
+export const PortableText = (props) => <PortableTextComponent components={{}} {...props} /> | ||
``` | ||
Please note that the `serializers` and `components` are not 100% equivalent. | ||
[Check the full migration guide.](https://github.com/portabletext/react-portabletext/blob/main/MIGRATING.md) | ||
#### `createImageUrlBuilder` is removed | ||
This utility is no longer wrapped by `next-sanity` and you'll need to install the dependency yourself: | ||
```sh | ||
$ npm install @sanity/image-url | ||
// or | ||
$ yarn add @sanity/image-url | ||
``` | ||
```diff | ||
-import { createImageUrlBuilder } from 'next-sanity' | ||
+import createImageUrlBuilder from '@sanity/image-url' | ||
``` | ||
## License | ||
MIT-licensed. See LICENSE. |
export interface Aborter { | ||
abort(): void | ||
signal?: AbortSignal | ||
signal: AbortSignal | ||
} | ||
class MockAbortController { | ||
_signal = {aborted: false} | ||
get signal() { | ||
return this._signal as AbortSignal | ||
} | ||
abort() { | ||
this._signal.aborted = true | ||
} | ||
} | ||
export function getAborter(): Aborter { | ||
return typeof AbortController === 'undefined' | ||
? {signal: undefined, abort: noop} | ||
? new MockAbortController() | ||
: new AbortController() | ||
} | ||
function noop() { | ||
// intentional noop | ||
} |
@@ -9,10 +9,9 @@ import {useEffect, useState} from 'react' | ||
export function getCurrentUser(projectId: string, abort?: Aborter): Promise<CurrentUser | null> { | ||
export function getCurrentUser(projectId: string, abort: Aborter): Promise<CurrentUser | null> { | ||
return fetch(`https://${projectId}.api.sanity.io/v1/users/me`, { | ||
credentials: 'include', | ||
signal: abort?.signal, | ||
signal: abort.signal, | ||
}) | ||
.then((res) => res.json()) | ||
.then((res) => (res?.id ? res : null)) | ||
.catch((err: Error) => (err.name === 'AbortError' ? null : Promise.reject(err))) | ||
} | ||
@@ -26,4 +25,9 @@ | ||
const aborter = getAborter() | ||
getCurrentUser(projectId, aborter).then(setUser).catch(setError) | ||
return () => aborter.abort() | ||
getCurrentUser(projectId, aborter) | ||
.then(setUser) | ||
.catch((err: Error) => err.name !== 'AbortError' && setError(err)) | ||
return () => { | ||
aborter.abort() | ||
} | ||
}, [projectId]) | ||
@@ -30,0 +34,0 @@ |
export * from './types' | ||
export {createClient} from './client' | ||
export {createImageUrlBuilder} from './imageUrlBuilder' | ||
export {createCurrentUserHook} from './currentUser' | ||
export {createPreviewSubscriptionHook} from './useSubscription' | ||
export {createPortableTextComponent} from './portableText' | ||
export {default as groq} from 'groq' |
@@ -1,13 +0,13 @@ | ||
import {useState} from 'react' | ||
import {useState, useEffect, useMemo} from 'react' | ||
import {GroqStore, Subscription} from '@sanity/groq-store' | ||
import {useDeepCompareEffectNoCheck as useDeepCompareEffect} from 'use-deep-compare-effect' | ||
import {ProjectConfig} from './types' | ||
import {getCurrentUser} from './currentUser' | ||
import {getAborter} from './aborter' | ||
import {getAborter, Aborter} from './aborter' | ||
const EMPTY_PARAMS = {} | ||
type Params = Record<string, unknown> | ||
interface SubscriptionOptions<R = any> { | ||
enabled?: boolean | ||
params?: Record<string, unknown> | ||
params?: Params | ||
initialData?: R | ||
@@ -19,5 +19,4 @@ } | ||
dataset, | ||
useGroqBeta, | ||
documentLimit = 3000, | ||
}: ProjectConfig & {documentLimit?: number; useGroqBeta?: boolean}) { | ||
}: ProjectConfig & {documentLimit?: number}) { | ||
// Only construct/setup the store when `getStore()` is called | ||
@@ -41,10 +40,17 @@ let store: Promise<GroqStore> | ||
function getStore() { | ||
function getStore(abort: Aborter) { | ||
if (!store) { | ||
store = import('@sanity/groq-store').then(({groqStore}) => | ||
groqStore({ | ||
store = import('@sanity/groq-store').then(({groqStore}) => { | ||
// Skip creating the groq store if we've been unmounted to save memory and reduce gc pressure | ||
if (abort.signal.aborted) { | ||
const error = new Error('Cancelling groq store creation') | ||
// This ensures we can skip it in the catch block same way | ||
error.name = 'AbortError' | ||
return Promise.reject(error) | ||
} | ||
return groqStore({ | ||
projectId, | ||
dataset, | ||
documentLimit, | ||
useGroqBeta, | ||
listen: true, | ||
@@ -54,3 +60,3 @@ overlayDrafts: true, | ||
}) | ||
) | ||
}) | ||
} | ||
@@ -62,21 +68,20 @@ return store | ||
function useQuerySubscription<R = any>(options: { | ||
getStore: () => Promise<GroqStore> | ||
getStore: (abort: Aborter) => Promise<GroqStore> | ||
projectId: string | ||
query: string | ||
params: Record<string, unknown> | ||
params: Params | ||
initialData: R | ||
enabled: boolean | ||
}) { | ||
const {getStore, projectId, query, params, initialData, enabled = false} = options | ||
const {getStore, projectId, query, initialData, enabled = false} = options | ||
const [error, setError] = useState<Error>() | ||
const [loading, setLoading] = useState(false) | ||
const [data, setData] = useState<R>() | ||
const params = useParams(options.params) | ||
// Use "deep" dependency comparison because params are often not _referentially_ equal, | ||
// but contains the same shallow properties, eg `{"slug": "some-slug"}` | ||
useDeepCompareEffect(() => { | ||
useEffect(() => { | ||
if (!enabled) { | ||
return () => { | ||
/* intentional noop */ | ||
} | ||
return | ||
} | ||
@@ -98,3 +103,3 @@ | ||
}) | ||
.then(getStore) | ||
.then(() => getStore(aborter)) | ||
.then((store) => { | ||
@@ -109,5 +114,6 @@ subscription = store.subscribe(query, params, (err, result) => { | ||
}) | ||
.catch(setError) | ||
.catch((err: Error) => (err.name === 'AbortError' ? null : setError(err))) | ||
.finally(() => setLoading(false)) | ||
// eslint-disable-next-line consistent-return | ||
return () => { | ||
@@ -128,1 +134,7 @@ if (subscription) { | ||
} | ||
// Return params that are stable with deep equal as long as the key order is the same | ||
function useParams(params: Params): Params { | ||
const stringifiedParams = useMemo(() => JSON.stringify(params), [params]) | ||
return useMemo(() => JSON.parse(stringifiedParams), [stringifiedParams]) | ||
} |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
New author
Supply chain riskA new npm collaborator published a version of the package for the first time. New collaborators are usually benign additions to a project, but do indicate a change to the security surface area of a package.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
67558
4
685
243
18
22
4
- Removed@sanity/image-url@^1.0.1
- Removeduse-deep-compare-effect@^1.6.1
- Removed@babel/runtime@7.26.0(transitive)
- Removed@rexxars/eventsource-polyfill@1.0.0(transitive)
- Removed@sanity/block-content-to-hyperscript@3.0.0(transitive)
- Removed@sanity/block-content-to-react@3.0.0(transitive)
- Removed@sanity/client@2.23.2(transitive)
- Removed@sanity/eventsource@2.23.0(transitive)
- Removed@sanity/generate-help-url@0.140.02.18.0(transitive)
- Removed@sanity/image-url@0.140.221.1.0(transitive)
- Removed@sanity/observable@2.0.9(transitive)
- Removedbrowser-split@0.0.0(transitive)
- Removedclass-list@0.1.1(transitive)
- Removeddecompress-response@3.3.0(transitive)
- Removeddeep-assign@2.0.0(transitive)
- Removeddequal@2.0.3(transitive)
- Removedget-it@5.2.1(transitive)
- Removedhtml-element@2.3.1(transitive)
- Removedhyperscript@2.0.2(transitive)
- Removedindexof@0.0.1(transitive)
- Removedis-obj@1.0.1(transitive)
- Removedmimic-response@1.0.1(transitive)
- Removedprop-types@15.8.1(transitive)
- Removedreact-is@16.13.1(transitive)
- Removedregenerator-runtime@0.14.1(transitive)
- Removeduse-deep-compare-effect@1.8.1(transitive)
Updated@sanity/client@^3.0.6
Updated@sanity/groq-store@^0.3.0