Skip to content

Commit 06ccddc

Browse files
committed
Generate types and check prepare targets when the CLI runs typegen.js
Add typegen.js, which Shopify CLI runs instead of graphql-code-generator when this package has it (Shopify/cli#8829). It generates the function's types with the codegen plugins this package depends on, gives each prepare result's variables its run query's variables type, and exits non-zero, failing the build, when a prepare target returns variables its run query doesn't accept. The check is moved here from Shopify/cli#8829: it follows what the prepare export returns, ignoring type annotations and casts, and validates it against the run query's variable definitions.
1 parent 4b121d0 commit 06ccddc

7 files changed

Lines changed: 949 additions & 46 deletions

File tree

‎.changeset/custom-scalar-overrides.md‎

Lines changed: 0 additions & 5 deletions
This file was deleted.

‎.changeset/prepare-variables.md‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@shopify/shopify_function": minor
3+
---
4+
5+
Check a JavaScript function's prepare targets when its types are generated. With a Shopify CLI that runs this package's `typegen.js`, the types are generated with this package's codegen plugins, a prepare result's `variables` has its run query's variables type, and the build fails when a prepare target returns variables its run query doesn't accept. Also adds `@shopify/shopify_function/codegen`, a plugin to use instead of `typescript` when running codegen yourself.

‎README.md‎

Lines changed: 25 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -4,59 +4,43 @@ This repository contains the source code for the [`@shopify/shopify_function`][p
44

55
[package]: https://npm.im/@shopify/shopify_function
66

7-
## Typing a prepare target's variables
7+
## Prepare targets
88

9-
A prepare target returns the variables for its run target's input query. The schema types them as `JSON`, so the generated type is `unknown` and nothing checks them against the run query.
9+
A prepare target returns the variables for its run target's input query. With a Shopify CLI that includes [Shopify/cli#8829](https://github.com/Shopify/cli/pull/8829), this package generates the function's types and checks those variables whenever the CLI generates types: `shopify app function typegen`, and every function build, including `shopify app dev` and `shopify app deploy`. No configuration is needed.
1010

11-
`@shopify/shopify_function/codegen` generates the same types as the `typescript` codegen plugin, and takes `customScalarOverrides` to give a custom scalar field of an input object another type. Use it instead of `typescript` in the function's `package.json`, and give the prepare result's `variables` the run query's variables type:
11+
- **Types:** the prepare result's `variables` has the run query's variables type, so editors report mismatches as you type.
12+
- **Checks:** the build fails when a prepare target returns variables its run query doesn't accept:
1213

13-
```json
14-
"codegen": {
15-
"schema": "schema.graphql",
16-
"documents": "src/*.graphql",
17-
"generates": {
18-
"./generated/api.ts": {
19-
"plugins": ["@shopify/shopify_function/codegen", "typescript-operations"]
20-
}
21-
},
22-
"config": {
23-
"omitOperationSuffix": true,
24-
"customScalarOverrides": {
25-
"CartValidationsGeneratePrepareResult.variables": "CartValidationsGenerateRunInputVariables"
26-
}
27-
}
28-
}
14+
```
15+
The function extension "delivery-customization" returns prepare variables its run query doesn't accept
16+
src/cart_delivery_options_transform_prepare.js:26:23 `variables.ruleQueri` isn't declared by src/cart_delivery_options_transform_run.graphql
2917
```
3018

31-
`typescript-operations` generates `CartValidationsGenerateRunInputVariables` for the run query, `query CartValidationsGenerateRunInput($ruleSetHandle: String! = "rules-default") { ... }`.
19+
The check follows what the prepare export returns through local helpers, conditionals, `??`, `||` and re-exports, and ignores type annotations and casts. It reports:
3220

33-
The prepare target's return type then checks its variables:
21+
- variables the run query doesn't declare, and required variables that are missing;
22+
- values of the wrong type, including enum values, list elements and input object fields;
23+
- `null` or `undefined` where the variable can't take them.
3424

35-
```js
36-
// @ts-check
37-
/** @returns {import("../generated/api").CartValidationsGeneratePrepareResult} */
38-
export function cartValidationsGeneratePrepare(input) {
39-
return { variables: { ruleSetHandle: "rules-custom" } };
40-
}
41-
```
25+
Values it can't follow fail too: values typed `any` or `unknown`, such as parsed JSON; objects with arbitrary keys; and variables changed or passed on after they're created. Check and narrow such values before returning them.
4226

43-
A prepare target that no longer matches its run query is a type error:
27+
The types are generated with the codegen plugins this package depends on, not whichever versions the app's package manager hoists.
4428

45-
| Mismatch | Type error in the prepare target |
46-
| --- | --- |
47-
| A variable was renamed or removed | Unknown property |
48-
| A required variable was added, or a default removed | Missing property |
49-
| A value has the wrong type, or is `null` for a required variable | Type isn't assignable |
29+
### Running codegen yourself
5030

51-
- Keys are `"InputObject.field"`, and the field's type must be a custom scalar. Lists and nullability are kept, and oneOf variants work too.
52-
- An override that isn't a custom scalar field of an input object fails codegen.
53-
- Without `customScalarOverrides`, the generated types are the same as `typescript`'s.
31+
To type the variables when running GraphQL Codegen yourself, use `@shopify/shopify_function/codegen` instead of the `typescript` plugin. It generates the same types, and takes `customScalarOverrides` to give a custom scalar field of an input object another type:
5432

55-
### Limits
33+
```json
34+
"plugins": ["@shopify/shopify_function/codegen", "typescript-operations"],
35+
"config": {
36+
"omitOperationSuffix": true,
37+
"customScalarOverrides": {
38+
"CartValidationsGeneratePrepareResult.variables": "CartValidationsGenerateRunInputVariables"
39+
}
40+
}
41+
```
5642

57-
- Editors and `tsc` report the errors, but `shopify app function build` doesn't type-check, so a mismatch still builds. JavaScript files need `// @ts-check`, as in the function templates, or `checkJs`.
58-
- `String`, `ID`, and custom scalars mapped to `string` (such as `Handle`) are the same TypeScript type, so switching between them isn't an error.
59-
- An object literal is checked for unknown keys. A value built elsewhere is checked for missing and mistyped variables, but not for extra keys.
43+
Keys are `"InputObject.field"`, and the field's type must be a custom scalar. Lists and nullability are kept.
6044

6145
## Development
6246

0 commit comments

Comments
 (0)