Skip to content

Commit

Permalink
feat: support nested groups
Browse files Browse the repository at this point in the history
  • Loading branch information
bapmrl committed Jun 5, 2024
1 parent a653884 commit 9c8a96c
Show file tree
Hide file tree
Showing 14 changed files with 121 additions and 36 deletions.
8 changes: 4 additions & 4 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@
},
"devDependencies": {
"@prismicio/mock": "^0.3.1",
"@prismicio/types-internal": "^2.4.0",
"@prismicio/types-internal": "^2.5.0-alpha.4",
"@size-limit/preset-small-lib": "^9.0.0",
"@trivago/prettier-plugin-sort-imports": "^4.2.0",
"@typescript-eslint/eslint-plugin": "^6.7.4",
Expand Down
6 changes: 4 additions & 2 deletions src/helpers/isFilled.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { ContentRelationshipField } from "../types/value/contentRelationshi
import type { DateField } from "../types/value/date";
import type { AnyOEmbed, EmbedField } from "../types/value/embed";
import type { GeoPointField } from "../types/value/geoPoint";
import type { GroupField } from "../types/value/group";
import type { GroupField, NestedGroupField } from "../types/value/group";
import type { ImageField, ImageFieldImage } from "../types/value/image";
import type { IntegrationField } from "../types/value/integration";
import type { KeyTextField } from "../types/value/keyText";
Expand Down Expand Up @@ -273,7 +273,9 @@ export const integrationFields = integrationField;
*
* @returns `true` if `group` contains at least one item, `false` otherwise.
*/
export const group = <Fields extends Record<string, AnyRegularField>>(
export const group = <
Fields extends Record<string, AnyRegularField | NestedGroupField>,
>(
group: GroupField<Fields> | null | undefined,
): group is GroupField<Fields, "filled"> => {
return isNonNullish(group) && isNonEmptyArray(group);
Expand Down
8 changes: 6 additions & 2 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -221,7 +221,7 @@ export type { GeoPointField } from "./types/value/geoPoint";
type IntegrationFields = IntegrationField;
export { IntegrationField, IntegrationFields };

export type { GroupField } from "./types/value/group";
export type { GroupField, NestedGroupField } from "./types/value/group";

export type { SliceZone } from "./types/value/sliceZone";
export type { Slice } from "./types/value/slice";
Expand Down Expand Up @@ -283,7 +283,10 @@ export {
CustomTypeModelIntegrationField,
CustomTypeModelIntegrationFieldsField,
};
export type { CustomTypeModelGroupField } from "./types/model/group";
export type {
CustomTypeModelGroupField,
CustomTypeModelNestedGroupField,
} from "./types/model/group";
export type {
CustomTypeModelSliceZoneField,
CustomTypeModelSliceLabel,
Expand All @@ -304,6 +307,7 @@ export type { CustomTypeModelSeparatorField } from "./types/model/separator";
export type {
CustomTypeModelField,
CustomTypeModelFieldForGroup,
CustomTypeModelFieldForNestedGroup,
CustomTypeModelFieldForSlicePrimary,
} from "./types/model/types";

Expand Down
15 changes: 15 additions & 0 deletions src/types/model/group.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import type {
CustomTypeModelFieldForGroup,
CustomTypeModelFieldForNestedGroup,
CustomTypeModelFieldType,
} from "./types";

Expand All @@ -22,3 +23,17 @@ export interface CustomTypeModelGroupField<
fields?: Fields;
};
}

/**
* A nested group custom type field.
*
* More details: {@link https://prismic.io/docs/group}
*
* @typeParam Fields - A record of fields that can be repeated.
*/
export type CustomTypeModelNestedGroupField<
Fields extends Record<string, CustomTypeModelFieldForNestedGroup> = Record<
string,
CustomTypeModelFieldForNestedGroup
>,
> = CustomTypeModelGroupField<Fields>;
8 changes: 4 additions & 4 deletions src/types/model/sharedSliceVariation.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type {
CustomTypeModelFieldForGroup,
CustomTypeModelFieldForNestedGroup,
CustomTypeModelFieldForSlicePrimary,
} from "./types";

Expand All @@ -17,10 +17,10 @@ export interface SharedSliceModelVariation<
string,
CustomTypeModelFieldForSlicePrimary
> = Record<string, CustomTypeModelFieldForSlicePrimary>,
ItemFields extends Record<string, CustomTypeModelFieldForGroup> = Record<
ItemFields extends Record<
string,
CustomTypeModelFieldForGroup
>,
CustomTypeModelFieldForNestedGroup
> = Record<string, CustomTypeModelFieldForNestedGroup>,
> {
id: ID;
name: string;
Expand Down
20 changes: 10 additions & 10 deletions src/types/model/slice.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import type { CustomTypeModelFieldForGroup } from "./types";
import type { CustomTypeModelFieldForNestedGroup } from "./types";

import type { CustomTypeModelGroupField } from "./group";
import type { CustomTypeModelNestedGroupField } from "./group";
import type { CustomTypeModelSliceType } from "./sliceZone";

/**
Expand All @@ -12,14 +12,14 @@ import type { CustomTypeModelSliceType } from "./sliceZone";
* @typeParam RepeatFields - A record of fields that can be repeated.
*/
export interface CustomTypeModelSlice<
NonRepeatFields extends Record<string, CustomTypeModelFieldForGroup> = Record<
NonRepeatFields extends Record<
string,
CustomTypeModelFieldForGroup
>,
RepeatFields extends Record<string, CustomTypeModelFieldForGroup> = Record<
CustomTypeModelFieldForNestedGroup
> = Record<string, CustomTypeModelFieldForNestedGroup>,
RepeatFields extends Record<
string,
CustomTypeModelFieldForGroup
>,
CustomTypeModelFieldForNestedGroup
> = Record<string, CustomTypeModelFieldForNestedGroup>,
> {
type: typeof CustomTypeModelSliceType.Slice;
fieldset?: string | null;
Expand All @@ -46,5 +46,5 @@ export const CustomTypeModelSliceDisplay = {
* @deprecated - Legacy slice type. Do not use.
*/
export type CustomTypeModelLegacySlice =
| CustomTypeModelGroupField
| CustomTypeModelFieldForGroup;
| CustomTypeModelNestedGroupField
| CustomTypeModelFieldForNestedGroup;
16 changes: 13 additions & 3 deletions src/types/model/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ import type { CustomTypeModelContentRelationshipField } from "./contentRelations
import type { CustomTypeModelDateField } from "./date";
import type { CustomTypeModelEmbedField } from "./embed";
import type { CustomTypeModelGeoPointField } from "./geoPoint";
import type { CustomTypeModelGroupField } from "./group";
import type {
CustomTypeModelGroupField,
CustomTypeModelNestedGroupField,
} from "./group";
import type { CustomTypeModelImageField } from "./image";
import type { CustomTypeModelIntegrationField } from "./integration";
import type { CustomTypeModelKeyTextField } from "./keyText";
Expand Down Expand Up @@ -65,19 +68,26 @@ export type CustomTypeModelField =
| CustomTypeModelUIDField
| CustomTypeModelGroupField
| CustomTypeModelSliceZoneField
| CustomTypeModelFieldForGroup;
| CustomTypeModelFieldForNestedGroup;

/**
* Any custom type field that is valid for a slice's primary section.
*/
export type CustomTypeModelFieldForSlicePrimary =
| CustomTypeModelGroupField
| CustomTypeModelFieldForGroup;
| CustomTypeModelFieldForNestedGroup;

/**
* Any custom type field that is valid for a group field.
*/
export type CustomTypeModelFieldForGroup =
| CustomTypeModelNestedGroupField
| CustomTypeModelFieldForNestedGroup;

/**
* Any custom type field that is valid for a nested group field.
*/
export type CustomTypeModelFieldForNestedGroup =
| CustomTypeModelBooleanField
| CustomTypeModelColorField
| CustomTypeModelDateField
Expand Down
15 changes: 14 additions & 1 deletion src/types/value/group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,22 @@ import type { AnyRegularField, FieldState } from "./types";
* More details: {@link https://prismic.io/docs/group}
*/
export type GroupField<
Fields extends Record<string, AnyRegularField | NestedGroupField> = Record<
string,
AnyRegularField | NestedGroupField
>,
State extends FieldState = FieldState,
> = State extends "empty" ? [] : [Fields, ...Fields[]];

/**
* A nested group field.
*
* More details: {@link https://prismic.io/docs/group}
*/
export type NestedGroupField<
Fields extends Record<string, AnyRegularField> = Record<
string,
AnyRegularField
>,
State extends FieldState = FieldState,
> = State extends "empty" ? [] : [Fields, ...Fields[]];
> = GroupField<Fields, State>;
32 changes: 32 additions & 0 deletions test/types/customType-group.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,38 @@ expectType<
},
});

/**
* Supports nested groups.
*/
expectType<
prismic.CustomTypeModelGroupField<{
foo: prismic.CustomTypeModelNestedGroupField<{
bar: prismic.CustomTypeModelBooleanField;
}>;
}>
>({
type: prismic.CustomTypeModelFieldType.Group,
config: {
label: "string",
fields: {
foo: {
type: prismic.CustomTypeModelFieldType.Group,
config: {
label: "string",
fields: {
bar: {
type: prismic.CustomTypeModelFieldType.Boolean,
config: {
label: "string",
},
},
},
},
},
},
},
});

/**
* `@prismicio/types` extends `@prismicio/types-internal`
*/
Expand Down
6 changes: 6 additions & 0 deletions test/types/customType.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,12 @@ expectType<
prismic.CustomTypeModelLinkToMediaField
>
>(true);
expectType<
TypeOf<
prismic.CustomTypeModelFieldForGroup,
prismic.CustomTypeModelNestedGroupField
>
>(true);
expectType<
TypeOf<
prismic.CustomTypeModelFieldForGroup,
Expand Down
11 changes: 5 additions & 6 deletions test/types/fields-group.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,14 @@ expectType<prismic.GroupField<{ boolean: prismic.BooleanField }>>([
},
]);

/**
* Supports nested groups.
*/
expectType<prismic.GroupField<{ group: prismic.NestedGroupField }>>([]);

/**
* Custom fields may only contain group-compatible fields.
*/
expectType<
prismic.GroupField<// @ts-expect-error - Groups are invalid within group fields.
{
group: prismic.GroupField;
}>
>([]);
expectType<
prismic.GroupField<// @ts-expect-error - Slice Zones are invalid within group fields.
{
Expand Down
5 changes: 3 additions & 2 deletions test/types/fields.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import * as prismic from "../../src";
};

/**
* AnyRegularField supports any field compatible with a Group.
* AnyRegularField supports any field compatible with a nested Group.
*/
expectType<TypeOf<prismic.AnyRegularField, prismic.BooleanField>>(true);
expectType<TypeOf<prismic.AnyRegularField, prismic.ColorField>>(true);
Expand All @@ -41,10 +41,11 @@ expectType<TypeOf<prismic.AnyRegularField, prismic.TimestampField>>(true);
expectType<TypeOf<prismic.AnyRegularField, prismic.TitleField>>(true);

/**
* AnyRegularField excludes any fields not compatible with a Group.
* AnyRegularField excludes any fields not compatible with a nested Group.
*/
expectType<TypeOf<prismic.AnyRegularField, prismic.SliceZone>>(false);
expectType<TypeOf<prismic.AnyRegularField, prismic.GroupField>>(false);
expectType<TypeOf<prismic.AnyRegularField, prismic.NestedGroupField>>(false);

/**
* AnySlicePrimaryField supports any field compatible with a slice's primary
Expand Down
5 changes: 4 additions & 1 deletion test/types/helpers-isFilled.types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -517,7 +517,10 @@ type IntegrationFieldData = { foo: string };
* Group
*/

type GroupDefault = Record<string, prismic.AnyRegularField>;
type GroupDefault = Record<
string,
prismic.AnyRegularField | prismic.NestedGroupField
>;

// Default
(value: prismic.GroupField) => {
Expand Down

0 comments on commit 9c8a96c

Please sign in to comment.