Skip to content
This repository has been archived by the owner on Mar 26, 2024. It is now read-only.

feat(v1): custom declarations #303

Open
wants to merge 8 commits into
base: alpha
Choose a base branch
from

Conversation

ochicf
Copy link
Contributor

@ochicf ochicf commented Jun 8, 2023

I've started this branch from #299, so that should be merged first.


The intent of this PR is to allow to configure declarations in the configuration file so they are included in the generated types. This only covers the possibility of ADDING declarations, not alter the generated ones.

Possible use cases:

  • add types that are not inferred from the schema itself
  • add types derived from the generated types

The declarations configuration can be:

/**
 * Custom declarations to be added to the generated types
 */
declarations?:
  | (string | t.TSModuleDeclaration)[]
  | ((context: {
      t: typeof t;
      normalizedSchemas: Sanity.SchemaDef.Schema[];
      generateTypeName: GenerateTypesOptions['generateTypeName'];
      generateWorkspaceName: GenerateTypesOptions['generateWorkspaceName'];
      defaultGenerateTypeName: typeof defaultGenerateTypeName;
      getWorkspaceName: (normalizedSchema: Sanity.SchemaDef.Schema) => string;
    }) =>
      | (string | t.TSModuleDeclaration)[]
      | Promise<(string | t.TSModuleDeclaration)[]>);

The above allows to directly pass declarations (as strings or with babel's t helpers for typesafety), or a function that returns the very same. This can be used to add more complex logic to generate types derived from the schemas (see exmaples below).


Example 1:

Add a static type (this would help us solve the #298 issue):

const config: SanityCodegenConfig = {
  // ... other
  declarations: [
    /* ts */ `
      namespace Sanity {
        type Reference<T> =
          | T
          | {
            _type: "reference";
            _ref: string;
        };
      }
    `,
  ],
};

Example 2:

Generate a new Documents type for each schema, which is a union of all types in that schema:

const config: SanityCodegenConfig = {
  // ... other
  declarations: ({
    t,
    normalizedSchemas,
    getWorkspaceName,
    getTypeName,
  }) =>
    normalizedSchemas.flatMap((normalizedSchema) => [
      t.tsModuleDeclaration(
        t.identifier('Sanity'),
        t.tsModuleDeclaration(
          t.identifier(getWorkspaceName(normalizedSchema)),
          t.tsModuleDeclaration(
            t.identifier('Schema'),
            t.tsModuleBlock([
              t.tsTypeAliasDeclaration(
                t.identifier('Documents'),
                undefined,
                t.tsUnionType(
                  normalizedSchema.documents.map((node) =>
                    t.tsTypeReference(t.identifier(getTypeName(node))),
                  ),
                ),
              ),
            ]),
          ),
        ),
      ),
    ]),
};

That yields something like:

namespace Sanity.Default.Schema {
  type Documents = Book | Editorial;
}

@ricokahler please let me know your thoughts on this, I'm finding it pretty useful!

@vercel
Copy link

vercel bot commented Jun 8, 2023

@ochicf is attempting to deploy a commit to the Rico Kahler Team on Vercel.

A member of the Team first needs to authorize it.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant