Skip to content

Commit b6852a4

Browse files
authoredMar 27, 2024··
feat: stable mapSliceZone (previously unstable_mapSliceZone) (#336)
* feat: stable `mapSliceZone` * fix: export deprecated `unstable_mapSliceZone` * test: verify unstable alias
1 parent bd55071 commit b6852a4

File tree

4 files changed

+93
-68
lines changed

4 files changed

+93
-68
lines changed
 

‎src/helpers/unstable_mapSliceZone.ts ‎src/helpers/mapSliceZone.ts

+70-57
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,9 @@ type LazyModule<T> = () => Promise<T | { default: T }>;
1111
*/
1212
type MaybeLazyModule<T> = T | LazyModule<T>;
1313

14+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
15+
type AnyFunction = (...args: any[]) => any;
16+
1417
/**
1518
* Returns the type of a `SliceLike` type.
1619
*
@@ -24,7 +27,7 @@ type ExtractSliceType<TSlice extends SliceLike> = TSlice extends Slice
2427

2528
/**
2629
* The minimum required properties to represent a Prismic Slice from the Prismic
27-
* Rest API V2 for the `unstable_mapSliceZone()` helper.
30+
* Rest API V2 for the `mapSliceZone()` helper.
2831
*
2932
* @typeParam SliceType - Type name of the Slice.
3033
*/
@@ -35,7 +38,7 @@ type SliceLikeRestV2<TSliceType extends string = string> = Pick<
3538

3639
/**
3740
* The minimum required properties to represent a Prismic Slice from the Prismic
38-
* GraphQL API for the `unstable_mapSliceZone()` helper.
41+
* GraphQL API for the `mapSliceZone()` helper.
3942
*
4043
* @typeParam SliceType - Type name of the Slice.
4144
*/
@@ -45,7 +48,7 @@ type SliceLikeGraphQL<TSliceType extends string = string> = {
4548

4649
/**
4750
* The minimum required properties to represent a Prismic Slice for the
48-
* `unstable_mapSliceZone()` helper.
51+
* `mapSliceZone()` helper.
4952
*
5053
* If using Prismic's Rest API V2, use the `Slice` export from
5154
* `@prismicio/client` for a full interface.
@@ -84,11 +87,11 @@ type MappedSliceLike = {
8487

8588
/**
8689
* Arguments for a function mapping content from a Prismic Slice using the
87-
* `unstable_mapSliceZone()` helper.
90+
* `mapSliceZone()` helper.
8891
*
8992
* @typeParam TSlice - The Slice passed as a prop.
90-
* @typeParam TContext - Arbitrary data passed to `unstable_mapSliceZone()` and
91-
* made available to all Slice mappers.
93+
* @typeParam TContext - Arbitrary data passed to `mapSliceZone()` and made
94+
* available to all Slice mappers.
9295
*/
9396
type SliceMapperArgs<
9497
TSlice extends SliceLike = SliceLike,
@@ -116,21 +119,18 @@ type SliceMapperArgs<
116119
>;
117120

118121
/**
119-
* Arbitrary data passed to `unstable_mapSliceZone()` and made available to
120-
* all Slice mappers.
122+
* Arbitrary data passed to `mapSliceZone()` and made available to all Slice
123+
* mappers.
121124
*/
122125
context: TContext;
123126
};
124127

125128
/**
126129
* A record of mappers.
127130
*/
128-
export type Mappers<
129-
TSlice extends SliceLike = SliceLike,
130-
TContext = unknown,
131-
> = {
132-
[P in ExtractSliceType<TSlice>]: MaybeLazyModule<
133-
Mapper<
131+
type SliceMappers<TSlice extends SliceLike = SliceLike, TContext = unknown> = {
132+
[P in ExtractSliceType<TSlice>]?: MaybeLazyModule<
133+
SliceMapper<
134134
Extract<TSlice, SliceLike<P>>,
135135
// eslint-disable-next-line @typescript-eslint/no-explicit-any
136136
any,
@@ -143,60 +143,67 @@ export type Mappers<
143143
* A function that maps a Slice and its metadata to a modified version. The
144144
* return value will replace the Slice in the Slice Zone.
145145
*/
146-
export type Mapper<
146+
export type SliceMapper<
147147
TSlice extends SliceLike = SliceLike,
148148
TMappedSlice extends Record<string, unknown> | undefined | void =
149149
| Record<string, unknown>
150150
| undefined
151151
| void,
152152
TContext = unknown,
153153
> = (
154-
args: MapperArgs<TSlice, TContext>,
154+
args: SliceMapperArgs<TSlice, TContext>,
155155
) => TMappedSlice | Promise<TMappedSlice>;
156156

157-
/**
158-
* Arguments provided to a mapper function.
159-
*/
160-
export type MapperArgs<
161-
TSlice extends SliceLike = SliceLike,
162-
TContext = unknown,
163-
> = SliceMapperArgs<TSlice, TContext>;
164-
165157
/**
166158
* Unwraps a lazily loaded mapper module.
167159
*/
168-
type ResolveLazyMapperModule<TMapper extends Mapper | LazyModule<Mapper>> =
169-
TMapper extends LazyModule<Mapper>
170-
? Awaited<ReturnType<TMapper>> extends {
171-
default: unknown;
172-
}
173-
? Awaited<ReturnType<TMapper>>["default"]
174-
: Awaited<ReturnType<TMapper>>
175-
: TMapper;
160+
type ResolveLazySliceMapperModule<
161+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
162+
TSliceMapper extends SliceMapper<any, any> | LazyModule<SliceMapper>,
163+
> = TSliceMapper extends LazyModule<SliceMapper>
164+
? Awaited<ReturnType<TSliceMapper>> extends {
165+
default: unknown;
166+
}
167+
? Awaited<ReturnType<TSliceMapper>>["default"]
168+
: Awaited<ReturnType<TSliceMapper>>
169+
: TSliceMapper;
176170

177171
/**
178172
* Transforms a Slice into its mapped version.
179173
*/
180174
type MapSliceLike<
181-
TSliceLike extends SliceLike,
182-
TMappers extends Mappers,
175+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
176+
TSliceLike extends SliceLike<any>,
177+
TSliceMappers extends SliceMappers<
178+
SliceLike<ExtractSliceType<TSliceLike>>,
179+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
180+
any
181+
>,
183182
> = TSliceLike extends Slice
184-
? TSliceLike["slice_type"] extends keyof TMappers
185-
? SliceLikeRestV2<TSliceLike["slice_type"]> &
186-
MappedSliceLike &
187-
Awaited<
188-
ReturnType<
189-
ResolveLazyMapperModule<TMappers[TSliceLike["slice_type"]]>
183+
? TSliceLike["slice_type"] extends keyof TSliceMappers
184+
? TSliceMappers[TSliceLike["slice_type"]] extends AnyFunction
185+
? SliceLikeRestV2<TSliceLike["slice_type"]> &
186+
MappedSliceLike &
187+
Awaited<
188+
ReturnType<
189+
ResolveLazySliceMapperModule<
190+
TSliceMappers[TSliceLike["slice_type"]]
191+
>
192+
>
190193
>
191-
>
194+
: TSliceLike
192195
: TSliceLike
193196
: TSliceLike extends SliceLikeGraphQL
194-
? TSliceLike["type"] extends keyof TMappers
195-
? SliceLikeGraphQL<TSliceLike["type"]> &
196-
MappedSliceLike &
197-
Awaited<
198-
ReturnType<ResolveLazyMapperModule<TMappers[TSliceLike["type"]]>>
199-
>
197+
? TSliceLike["type"] extends keyof TSliceMappers
198+
? TSliceMappers[TSliceLike["type"]] extends AnyFunction
199+
? SliceLikeGraphQL<TSliceLike["type"]> &
200+
MappedSliceLike &
201+
Awaited<
202+
ReturnType<
203+
ResolveLazySliceMapperModule<TSliceMappers[TSliceLike["type"]]>
204+
>
205+
>
206+
: TSliceLike
200207
: TSliceLike
201208
: never;
202209

@@ -210,31 +217,34 @@ type MapSliceLike<
210217
* @example
211218
*
212219
* ```typescript
213-
* const mappedSliceZone = await unstable_mapSliceZone(page.data.slices, {
220+
* const mappedSliceZone = await mapSliceZone(page.data.slices, {
214221
* code_block: ({ slice }) => ({
215222
* codeHTML: await highlight(slice.primary.code),
216223
* }),
217224
* });
218225
* ```
219-
*
220-
* @experimental Names and implementations may change in the future.
221-
* `unstable_mapSliceZone()` does not follow SemVer.
222226
*/
223-
export function unstable_mapSliceZone<
227+
export function mapSliceZone<
224228
TSliceLike extends SliceLike,
225-
TMappers extends Mappers,
229+
TSliceMappers extends SliceMappers<TSliceLike, TContext>,
226230
TContext = unknown,
227231
>(
228232
sliceZone: SliceZoneLike<TSliceLike>,
229-
mappers: TMappers,
233+
mappers: TSliceMappers,
230234
context?: TContext,
231-
): Promise<MapSliceLike<TSliceLike, TMappers>[]> {
235+
): Promise<
236+
MapSliceLike<
237+
TSliceLike,
238+
// @ts-expect-error - I don't know how to fix this type
239+
TSliceMappers
240+
>[]
241+
> {
232242
return Promise.all(
233243
sliceZone.map(async (slice, index, slices) => {
234244
const isRestSliceType = "slice_type" in slice;
235245
const sliceType = isRestSliceType ? slice.slice_type : slice.type;
236246

237-
const mapper = mappers[sliceType];
247+
const mapper = mappers[sliceType as keyof typeof mappers];
238248

239249
if (!mapper) {
240250
return slice;
@@ -244,7 +254,10 @@ export function unstable_mapSliceZone<
244254

245255
// `result` may be a mapper function OR a module
246256
// containing a mapper function.
247-
let result = await mapper(mapperArgs);
257+
let result = await mapper(
258+
// @ts-expect-error - I don't know how to fix this type
259+
mapperArgs,
260+
);
248261

249262
// `result` is a module containing a mapper function,
250263
// we need to dig out the mapper function. `result`

‎src/index.ts

+8-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import type {
77
HTMLRichTextFunctionSerializer,
88
HTMLRichTextMapSerializer,
99
} from "./helpers/asHTML";
10+
import { mapSliceZone } from "./helpers/mapSliceZone";
1011

1112
import { filter } from "./filter";
1213

@@ -69,14 +70,20 @@ export { asHTML } from "./helpers/asHTML";
6970
export { asImageSrc } from "./helpers/asImageSrc";
7071
export { asImageWidthSrcSet } from "./helpers/asImageWidthSrcSet";
7172
export { asImagePixelDensitySrcSet } from "./helpers/asImagePixelDensitySrcSet";
72-
export { unstable_mapSliceZone } from "./helpers/unstable_mapSliceZone";
7373
export * as isFilled from "./helpers/isFilled";
7474

75+
/**
76+
* @deprecated Renamed to `mapSliceZone`
77+
*/
78+
const unstable_mapSliceZone = mapSliceZone;
79+
export { mapSliceZone, unstable_mapSliceZone };
80+
7581
// Conversion helper.
7682
export { documentToLinkField } from "./helpers/documentToLinkField";
7783

7884
export type { LinkResolverFunction } from "./helpers/asLink";
7985
export type { AsLinkAttrsConfig } from "./helpers/asLinkAttrs";
86+
export type { SliceMapper } from "./helpers/mapSliceZone";
8087

8188
/**
8289
* @deprecated Renamed to `HTMLRichTextMapSerializer`

‎test/helpers-unstable_mapSliceZone.test.ts ‎test/helpers-mapSliceZone.test.ts

+10-10
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { TestContext, expect, it, vi } from "vitest";
22

3-
import { unstable_mapSliceZone } from "../src";
3+
import { mapSliceZone } from "../src";
44

55
const generateTestData = (ctx: TestContext) => {
66
const model1 = ctx.mock.model.sharedSlice({
@@ -35,7 +35,7 @@ const generateTestData = (ctx: TestContext) => {
3535
it("maps a Slice Zone", async (ctx) => {
3636
const { sliceZone, model1, model2 } = generateTestData(ctx);
3737

38-
const actual = await unstable_mapSliceZone(
38+
const actual = await mapSliceZone(
3939
// @ts-expect-error Remove this comment after v7.3.0 is published.
4040
sliceZone,
4141
{
@@ -53,7 +53,7 @@ it("maps a Slice Zone", async (ctx) => {
5353
it("supports mapping functions that return undefined", async (ctx) => {
5454
const { sliceZone, model1, model2 } = generateTestData(ctx);
5555

56-
const actual = await unstable_mapSliceZone(
56+
const actual = await mapSliceZone(
5757
// @ts-expect-error Remove this comment after v7.3.0 is published.
5858
sliceZone,
5959
{
@@ -71,7 +71,7 @@ it("supports mapping functions that return undefined", async (ctx) => {
7171
it("supports async mapping functions", async (ctx) => {
7272
const { sliceZone, model1, model2 } = generateTestData(ctx);
7373

74-
const actual = await unstable_mapSliceZone(
74+
const actual = await mapSliceZone(
7575
// @ts-expect-error Remove this comment after v7.3.0 is published.
7676
sliceZone,
7777
{
@@ -89,7 +89,7 @@ it("supports async mapping functions", async (ctx) => {
8989
it("supports overriding id and slice_type properties", async (ctx) => {
9090
const { sliceZone, model1, model2 } = generateTestData(ctx);
9191

92-
const actual = await unstable_mapSliceZone(
92+
const actual = await mapSliceZone(
9393
// @ts-expect-error Remove this comment after v7.3.0 is published.
9494
sliceZone,
9595
{
@@ -110,7 +110,7 @@ it("provides Slice data to mapping functions", async (ctx) => {
110110
const mapper1 = vi.fn();
111111
const mapper2 = vi.fn();
112112

113-
await unstable_mapSliceZone(
113+
await mapSliceZone(
114114
// @ts-expect-error Remove this comment after v7.3.0 is published.
115115
sliceZone,
116116
{
@@ -141,7 +141,7 @@ it("supports context", async (ctx) => {
141141

142142
const context = { foo: "bar" };
143143

144-
await unstable_mapSliceZone(
144+
await mapSliceZone(
145145
// @ts-expect-error Remove this comment after v7.3.0 is published.
146146
sliceZone,
147147
{
@@ -168,7 +168,7 @@ it("supports context", async (ctx) => {
168168
it("supports lazy-loaded mapping functions", async (ctx) => {
169169
const { sliceZone, model1, model2 } = generateTestData(ctx);
170170

171-
const actual = await unstable_mapSliceZone(
171+
const actual = await mapSliceZone(
172172
// @ts-expect-error Remove this comment after v7.3.0 is published.
173173
sliceZone,
174174
{
@@ -188,7 +188,7 @@ it("supports lazy-loaded mapping functions", async (ctx) => {
188188
it("skips Slices without a mapping function", async (ctx) => {
189189
const { sliceZone, model1 } = generateTestData(ctx);
190190

191-
const actual = await unstable_mapSliceZone(
191+
const actual = await mapSliceZone(
192192
// @ts-expect-error Remove this comment after v7.3.0 is published.
193193
sliceZone,
194194
{
@@ -205,7 +205,7 @@ it("skips Slices without a mapping function", async (ctx) => {
205205
it("supports GraphQL Slice Zones", async () => {
206206
const sliceZone = [{ type: "foo" }, { type: "bar" }];
207207

208-
const actual = await unstable_mapSliceZone(sliceZone, {
208+
const actual = await mapSliceZone(sliceZone, {
209209
foo: () => ({ foo: "bar" }),
210210
bar: () => ({ baz: "qux" }),
211211
});

‎test/index.test.ts

+5
Original file line numberDiff line numberDiff line change
@@ -102,3 +102,8 @@ it("webhook type mapping", () => {
102102
it("predicate is a temporary alias for filter", () => {
103103
expect(prismic.predicate).toStrictEqual(prismic.filter);
104104
});
105+
106+
// TODO: Remove when we remove support for deprecated `unstable_mapSliceZone` export.
107+
it("unstable_mapSliceZone is a temporary alias for mapSliceZone", () => {
108+
expect(prismic.unstable_mapSliceZone).toStrictEqual(prismic.mapSliceZone);
109+
});

0 commit comments

Comments
 (0)
Please sign in to comment.