Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Admin API GraphQL Codegen does not generate types for scalars #1154

Open
4 of 5 tasks
sleepdotexe opened this issue Jul 4, 2024 · 3 comments
Open
4 of 5 tasks

Admin API GraphQL Codegen does not generate types for scalars #1154

sleepdotexe opened this issue Jul 4, 2024 · 3 comments

Comments

@sleepdotexe
Copy link

Issue summary

Before opening this issue, I have:

  • Upgraded to the latest version of the relevant packages
    • @shopify/* package and version:
      • @shopify/api-codegen-preset@1.0.0
      • @shopify/shopify-api@11.0.0
    • Node version: v20.9.0
    • Operating system: macOS Monterey
  • Set { logger: { level: LogSeverity.Debug } } in my configuration, when applicable
  • Found a reliable way to reproduce the problem that indicates it's a problem with the package
  • Looked for similar issues in this repository
  • Checked that this isn't an issue with a Shopify API

I am using the GraphQL Codegen to automatically generate TypeScript types for my Shopify queries. I am running into issues using properties that have Scalar types, as these are shown as type any. For example, Product['created_at'] has type any, when it really should be string since it has the scalar type of DateTime which is an extension of a string.

The helper functions from @shopify/api-codegen-preset don't seem to provide scalar types by default, nor any way to manually provide these types. Since these types are managed by Shopify and relate specifically to the API, it would make the most sense to me for these to be automatically provided by the helper setup functions.

According to https://the-guild.dev/graphql/codegen/plugins/typescript/typescript#scalars, it should theoretically be possible to provide scalars to the codegen.

Here is an example .graphqlrc.ts:

import { ApiType, shopifyApiProject } from '@shopify/api-codegen-preset';

import CONSTANTS from './utils/constants';

const docs = [
	'./utils/shopify/queries/**/*.{js,ts,jsx,tsx}',
	'./utils/shopify/mutations/**/*.{js,ts,jsx,tsx}',
	'./utils/shopify/fragments/**/*.{js,ts,jsx,tsx}',
];

const { apiVersion } = CONSTANTS.shopify; // ApiVersion.January24

export default {
	schema: `./types/shopify/admin-${apiVersion}.schema.json`,
	documents: docs,
	projects: {
		default: shopifyApiProject({
			apiType: ApiType.Admin,
			apiVersion: apiVersion,
			documents: docs,
			outputDir: './types/shopify',
		}),
	},
};

Expected behavior

Using the .graphqlrc.ts above, the inbuilt Shopify Scalars should be automatically generated in admin.types.d.ts like so:

/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  ID: { input: string; output: string; }
  String: { input: string; output: string; }
  Boolean: { input: boolean; output: boolean; }
  Int: { input: number; output: number; }
  Float: { input: number; output: number; }
  ARN: { input: any; output: any; }
  Date: { input: string; output: string; }
  DateTime: { input: string; output: string; }
  Decimal: { input: string; output: string; }
  FormattedString: { input: string; output: string; }
  HTML: { input: string; output: string; }
  JSON: { input: any; output: any; }
  Money: { input: string; output: string; }
  StorefrontID: { input: string; output: string; }
  URL: { input: string; output: string; }
  UnsignedInt64: { input: string; output: string; }
  UtcOffset: { input: string; output: string; }
};

...Which allows the properties to have correct types in files.

products[0].createdAt
            ^----- `createdAt: string | undefined`

Actual behavior

The Shopify scalars have types of any.

/** All built-in and custom scalars, mapped to their actual values */
export type Scalars = {
  ID: { input: string; output: string; }
  String: { input: string; output: string; }
  Boolean: { input: boolean; output: boolean; }
  Int: { input: number; output: number; }
  Float: { input: number; output: number; }
  ARN: { input: any; output: any; }
  Date: { input: any; output: any; }
  DateTime: { input: any; output: any; }
  Decimal: { input: any; output: any; }
  FormattedString: { input: any; output: any; }
  HTML: { input: any; output: any; }
  JSON: { input: any; output: any; }
  Money: { input: any; output: any; }
  StorefrontID: { input: any; output: any; }
  URL: { input: any; output: any; }
  UnsignedInt64: { input: any; output: any; }
  UtcOffset: { input: any; output: any; }
};

...Which means properties are not typed correctly.

products[0].createdAt
            ^----- `createdAt: any`

Steps to reproduce the problem

  1. Set up a typescript project using the Admin GraphQL API and codegen as per these instructions.
  2. Use the .graphqlrc.ts file as outlined above in this issue.
  3. Attempt to use a scalar property (eg. Product['createdAt']).

Debug logs

There is a temporary solution I've found – after using the shopifyApiProject() helper function, I managed to manually force the config to include scalars like so:

const outputDir = './types/shopify';
const { apiVersion } = CONSTANTS.shopify;

const setup: ReturnType<typeof shopifyApiProject> & {
	extensions: {
		codegen: { generates: { [key: string]: { config?: { scalars?: any } } } };
	};
} = shopifyApiProject({
	apiType: ApiType.Admin,
	apiVersion: apiVersion,
	documents: docs,
	outputDir,
});

setup.extensions.codegen.generates[`${outputDir}/admin.types.d.ts`].config = {
	minify: true,
	scalars: {
		Color: 'string',
		Date: 'string',
		DateTime: 'string',
		Decimal: 'string',
		FormattedString: 'string',
		HTML: 'string',
		Money: 'string',
		StorefrontID: 'string',
		URL: 'string',
		UnsignedInt64: 'string',
		UtcOffset: 'string',
	},
};

export default {
	schema: `${outputDir}/admin-${apiVersion}.schema.json`,
	documents: docs,
	projects: {
		default: setup,
	},
};

This seems to work, as the admin.types.d.ts file now includes the expected types for scalars. However it's not my favourite solution since it relies on hardcoding the scalar types, and also updating them if they are change (or new scalars are added) in future. Additionally, I have to mutate the setup object and provide a hack-y union type to keep type safety.

Could we have these scalars included by default? And if not, could we at least have a documented option added to the shopifyApiProject helper function that allows us to manually provide these without the workaround?

@matteodepalo
Copy link
Contributor

Hi @sleepdotexe this is a great issue description and a good suggestion. We'll take a look at what we can add to shopifyApiProject, but in the meanwhile I'm glad that your workaround is working for you.

Copy link
Contributor

github-actions bot commented Sep 3, 2024

We're labeling this issue as stale because there hasn't been any activity on it for 60 days. While the issue will stay open and we hope to resolve it, this helps us prioritize community requests.

You can add a comment to remove the label if it's still relevant, and we can re-evaluate it.

@StepanMynarik
Copy link

+1

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

No branches or pull requests

3 participants