Skip to content

Commit

Permalink
perf: reduce generated types for select by respecting interfaceName (
Browse files Browse the repository at this point in the history
…#9870)

This PR can significantly reduce your `payload-types.ts` file if you
have sharable fields / blocks that use the `interfaceName` property.
Previously we didn't respect it for select types.

Before:
```ts
export interface Collection1Select<T extends boolean = true> {
  testing?: T;
  title?: T;
  meta?:
    | T
    | {
        title?: T;
        description?: T;
        id?: T;
      };
  blocks?:
    | T
    | {
        block1?:
          | T
          | {
              b1title?: T;
              b1description?: T;
              id?: T;
              blockName?: T;
            };
        block2?:
          | T
          | {
              b2title?: T;
              b2description?: T;
              id?: T;
              blockName?: T;
            };
      };
  updatedAt?: T;
  createdAt?: T;
}
```
After:
```ts
export interface Collection1Select<T extends boolean = true> {
  testing?: T;
  title?: T;
  meta?: T | SharedMetaArraySelect<T>;
  blocks?:
    | T
    | {
        block1?: T | SharedMetaBlockSelect<T>;
        block2?: T | AnotherSharedBlockSelect<T>;
      };
  updatedAt?: T;
  createdAt?: T;
}

/**
 * This interface was referenced by `Config`'s JSON-Schema
 * via the `definition` "SharedMetaArray_select".
 */
export interface SharedMetaArraySelect<T extends boolean = true> {
  title?: T;
  description?: T;
  id?: T;
}
/**
 * This interface was referenced by `Config`'s JSON-Schema
 * via the `definition` "SharedMetaBlock_select".
 */
export interface SharedMetaBlockSelect<T extends boolean = true> {
  b1title?: T;
  b1description?: T;
  id?: T;
  blockName?: T;
}
/**
 * This interface was referenced by `Config`'s JSON-Schema
 * via the `definition` "AnotherSharedBlock_select".
 */
export interface AnotherSharedBlockSelect<T extends boolean = true> {
  b2title?: T;
  b2description?: T;
  id?: T;
  blockName?: T;
}
```

Regenerated all the types in `/test`. The diff is noticeable for
`fields` -
https://github.com/payloadcms/payload/pull/9870/files#diff-95beaac24c72c7bd60933e325cdcd94a4c3630a1ce22fabad624ec80cc74fc8c
  • Loading branch information
r1tsuu authored Dec 16, 2024
1 parent 727fba7 commit 26a10ed
Show file tree
Hide file tree
Showing 7 changed files with 409 additions and 652 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -178,6 +178,7 @@ export interface PayloadMigration {
export interface PostsSelect {
text?: boolean;
number?: boolean;
sharedGroup?: boolean | SharedGroup;
group?:
| boolean
| {
Expand Down Expand Up @@ -451,6 +452,7 @@ export interface PayloadMigration {
export interface PostsSelect<T extends boolean = true> {
text?: T;
number?: T;
sharedGroup?: T | SharedGroup<T>;
group?:
| T
| {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,14 @@ export const addSelectGenericsToGeneratedTypes = ({
// add generic to the interface
newLine = line.replace(/(export interface\s+\w+)(\s*\{)/g, '$1<T extends boolean = true>$2')
} else {
// replace booleans with T on the line
newLine = line.replace(/(?<!\?)\bboolean\b/g, 'T')
newLine = line
// replace booleans with T on the line
.replace(/(?<!\?)\bboolean\b/g, 'T')
// replace interface names like CtaBlock to CtaBlock<T>
.replace(
/\b(\w+)\s*\|\s*(\w+)\b/g,
(_match, left, right) => `${left} | ${right}<${left}>`,
)

if (line === '}') {
isSelectTypeToken = false
Expand Down
48 changes: 43 additions & 5 deletions packages/payload/src/utilities/configToJSONSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -643,7 +643,13 @@ export function entityToJSONSchema(
}
}

export function fieldsToSelectJSONSchema({ fields }: { fields: FlattenedField[] }): JSONSchema4 {
export function fieldsToSelectJSONSchema({
fields,
interfaceNameDefinitions,
}: {
fields: FlattenedField[]
interfaceNameDefinitions: Map<string, JSONSchema4>
}): JSONSchema4 {
const schema: JSONSchema4 = {
type: 'object',
additionalProperties: false,
Expand All @@ -654,16 +660,32 @@ export function fieldsToSelectJSONSchema({ fields }: { fields: FlattenedField[]
switch (field.type) {
case 'array':
case 'group':
case 'tab':
case 'tab': {
let fieldSchema: JSONSchema4 = fieldsToSelectJSONSchema({
fields: field.flattenedFields,
interfaceNameDefinitions,
})

if (field.interfaceName) {
const definition = `${field.interfaceName}_select`
interfaceNameDefinitions.set(definition, fieldSchema)

fieldSchema = {
$ref: `#/definitions/${definition}`,
}
}

schema.properties[field.name] = {
oneOf: [
{
type: 'boolean',
},
fieldsToSelectJSONSchema({ fields: field.flattenedFields }),
fieldSchema,
],
}

break
}

case 'blocks': {
const blocksSchema: JSONSchema4 = {
Expand All @@ -673,12 +695,25 @@ export function fieldsToSelectJSONSchema({ fields }: { fields: FlattenedField[]
}

for (const block of field.blocks) {
let blockSchema = fieldsToSelectJSONSchema({
fields: block.flattenedFields,
interfaceNameDefinitions,
})

if (block.interfaceName) {
const definition = `${block.interfaceName}_select`
interfaceNameDefinitions.set(definition, blockSchema)
blockSchema = {
$ref: `#/definitions/${definition}`,
}
}

blocksSchema.properties[block.slug] = {
oneOf: [
{
type: 'boolean',
},
fieldsToSelectJSONSchema({ fields: block.flattenedFields }),
blockSchema,
],
}
}
Expand Down Expand Up @@ -900,7 +935,10 @@ export function configToJSONSchema(
defaultIDType,
collectionIDFieldTypes,
)
const select = fieldsToSelectJSONSchema({ fields: entity.flattenedFields })
const select = fieldsToSelectJSONSchema({
fields: entity.flattenedFields,
interfaceNameDefinitions,
})

if (type === 'global') {
select.properties.globalType = {
Expand Down
46 changes: 23 additions & 23 deletions test/auth/payload-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ export interface Config {
'payload-migrations': PayloadMigrationsSelect<false> | PayloadMigrationsSelect<true>;
};
db: {
defaultIDType: number;
defaultIDType: string;
};
globals: {};
globalsSelect: {};
Expand Down Expand Up @@ -135,7 +135,7 @@ export interface PublicUserAuthOperations {
* via the `definition` "users".
*/
export interface User {
id: number;
id: string;
adminOnlyField?: string | null;
roles: ('admin' | 'editor' | 'moderator' | 'user' | 'viewer')[];
namedSaveToJWT?: string | null;
Expand Down Expand Up @@ -175,7 +175,7 @@ export interface User {
* via the `definition` "partial-disable-locale-strategies".
*/
export interface PartialDisableLocaleStrategy {
id: number;
id: string;
updatedAt: string;
createdAt: string;
email: string;
Expand All @@ -192,7 +192,7 @@ export interface PartialDisableLocaleStrategy {
* via the `definition` "api-keys".
*/
export interface ApiKey {
id: number;
id: string;
updatedAt: string;
createdAt: string;
enableAPIKey?: boolean | null;
Expand All @@ -204,7 +204,7 @@ export interface ApiKey {
* via the `definition` "public-users".
*/
export interface PublicUser {
id: number;
id: string;
updatedAt: string;
createdAt: string;
email: string;
Expand All @@ -223,8 +223,8 @@ export interface PublicUser {
* via the `definition` "relationsCollection".
*/
export interface RelationsCollection {
id: number;
rel?: (number | null) | User;
id: string;
rel?: (string | null) | User;
text?: string | null;
updatedAt: string;
createdAt: string;
Expand All @@ -234,45 +234,45 @@ export interface RelationsCollection {
* via the `definition` "payload-locked-documents".
*/
export interface PayloadLockedDocument {
id: number;
id: string;
document?:
| ({
relationTo: 'users';
value: number | User;
value: string | User;
} | null)
| ({
relationTo: 'partial-disable-locale-strategies';
value: number | PartialDisableLocaleStrategy;
value: string | PartialDisableLocaleStrategy;
} | null)
| ({
relationTo: 'api-keys';
value: number | ApiKey;
value: string | ApiKey;
} | null)
| ({
relationTo: 'public-users';
value: number | PublicUser;
value: string | PublicUser;
} | null)
| ({
relationTo: 'relationsCollection';
value: number | RelationsCollection;
value: string | RelationsCollection;
} | null);
globalSlug?: string | null;
user:
| {
relationTo: 'users';
value: number | User;
value: string | User;
}
| {
relationTo: 'partial-disable-locale-strategies';
value: number | PartialDisableLocaleStrategy;
value: string | PartialDisableLocaleStrategy;
}
| {
relationTo: 'api-keys';
value: number | ApiKey;
value: string | ApiKey;
}
| {
relationTo: 'public-users';
value: number | PublicUser;
value: string | PublicUser;
};
updatedAt: string;
createdAt: string;
Expand All @@ -282,23 +282,23 @@ export interface PayloadLockedDocument {
* via the `definition` "payload-preferences".
*/
export interface PayloadPreference {
id: number;
id: string;
user:
| {
relationTo: 'users';
value: number | User;
value: string | User;
}
| {
relationTo: 'partial-disable-locale-strategies';
value: number | PartialDisableLocaleStrategy;
value: string | PartialDisableLocaleStrategy;
}
| {
relationTo: 'api-keys';
value: number | ApiKey;
value: string | ApiKey;
}
| {
relationTo: 'public-users';
value: number | PublicUser;
value: string | PublicUser;
};
key?: string | null;
value?:
Expand All @@ -318,7 +318,7 @@ export interface PayloadPreference {
* via the `definition` "payload-migrations".
*/
export interface PayloadMigration {
id: number;
id: string;
name?: string | null;
batch?: number | null;
updatedAt: string;
Expand Down
4 changes: 4 additions & 0 deletions test/fields/collections/Blocks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ export const getBlocksField = (prefix?: string): BlocksField => ({
blocks: [
{
slug: prefix ? `${prefix}Content` : 'content',
interfaceName: prefix ? `${prefix}ContentBlock` : 'ContentBlock',
fields: [
{
name: 'text',
Expand All @@ -26,6 +27,7 @@ export const getBlocksField = (prefix?: string): BlocksField => ({
},
{
slug: prefix ? `${prefix}Number` : 'number',
interfaceName: prefix ? `${prefix}NumberBlock` : 'NumberBlock',
fields: [
{
name: 'number',
Expand All @@ -36,6 +38,7 @@ export const getBlocksField = (prefix?: string): BlocksField => ({
},
{
slug: prefix ? `${prefix}SubBlocks` : 'subBlocks',
interfaceName: prefix ? `${prefix}SubBlocksBlock` : 'SubBlocksBlock',
fields: [
{
type: 'collapsible',
Expand Down Expand Up @@ -73,6 +76,7 @@ export const getBlocksField = (prefix?: string): BlocksField => ({
},
{
slug: prefix ? `${prefix}Tabs` : 'tabs',
interfaceName: prefix ? `${prefix}TabsBlock` : 'TabsBlock',
fields: [
{
type: 'tabs',
Expand Down
Loading

0 comments on commit 26a10ed

Please sign in to comment.