attio 0.0.1-experimental.20241001 → 0.0.1-experimental.20241002

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,7 +11,7 @@ export function startGraphqlServer(sendBack) {
11
11
  const startServer = async () => {
12
12
  const currentFilePath = fileURLToPath(import.meta.url);
13
13
  const currentDirPath = dirname(currentFilePath);
14
- const schemaPath = path.resolve(currentDirPath, "..", "schema.graphql");
14
+ const schemaPath = path.resolve(currentDirPath, "..", "..", "schema.graphql");
15
15
  const schemaString = fs.readFileSync(schemaPath, "utf8");
16
16
  const port = await findAvailablePort(8700);
17
17
  const schema = buildSchema(schemaString);
@@ -1,5 +1,4 @@
1
1
  export { useDialog } from "./use-dialog.js";
2
- export { runQuery } from "./run-query.js";
3
2
  export { useAsyncCache, AsyncCacheConfig, AsyncFunction } from "./use-async-cache.js";
4
3
  export { useQuery } from "./use-query.js";
5
4
  export { useRecord } from "./use-record.js";
@@ -1,5 +1,6 @@
1
- export declare function useQuery<T>(
1
+ import { Query } from "../run-query";
2
+ export declare function useQuery<Variables, Result>(
2
3
  /** GraphQL query */
3
- query: string,
4
+ query: Query<Variables, Result>,
4
5
  /** GraphQL query variables */
5
- variableValues?: Record<string, any>): T;
6
+ variableValues?: Variables): Result;
@@ -1,5 +1,6 @@
1
1
  export * from "./hooks/index.js";
2
2
  export * from "./components/index.js";
3
+ export { runQuery, Query } from "./run-query.js";
3
4
  export * as Forms from "./forms/index.js";
4
5
  export { FormArray } from "./forms/array.js";
5
6
  export { FormNumber } from "./forms/number.js";
@@ -2,3 +2,7 @@
2
2
  * Imperatively runs a GraphQL query.
3
3
  */
4
4
  export declare function runQuery(query: string, variableValues?: Record<string, any>): Promise<any>;
5
+ export type Query<Variables, Result> = {
6
+ __data: Result;
7
+ __variables: Variables;
8
+ } & string;
@@ -53,6 +53,14 @@ export default function Dev({ options: { debug } }) {
53
53
  React.createElement(Text, null,
54
54
  "Env: ",
55
55
  JSON.stringify(snapshot.children.env?.getSnapshot().value))),
56
+ React.createElement(Box, null,
57
+ React.createElement(Text, null,
58
+ "Code Gen:",
59
+ " ",
60
+ JSON.stringify(snapshot.children["code-gen"]?.getSnapshot()?.value),
61
+ " ",
62
+ snapshot.children["code-gen"]?.getSnapshot().context.error
63
+ ?.message)),
56
64
  snapshot.context.devVersion?.app_id && (React.createElement(Box, null,
57
65
  React.createElement(Text, null,
58
66
  "App ID: ",
@@ -0,0 +1,151 @@
1
+ import fs from "fs";
2
+ import { parse, visit, validate, print, OperationTypeNode, isObjectType, isListType, isNonNullType, isInputObjectType, isEnumType, getNamedType, } from "graphql";
3
+ import path from "path";
4
+ import { format } from "prettier";
5
+ function findGraphQLFiles(dir) {
6
+ const files = [];
7
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
8
+ for (const entry of entries) {
9
+ const fullPath = path.join(dir, entry.name);
10
+ if (entry.isDirectory()) {
11
+ files.push(...findGraphQLFiles(fullPath));
12
+ }
13
+ else if (entry.isFile() && path.extname(entry.name) === ".graphql") {
14
+ files.push(fullPath);
15
+ }
16
+ }
17
+ return files;
18
+ }
19
+ function generateEnumTypeDefinition(type) {
20
+ const values = type
21
+ .getValues()
22
+ .map((v) => `'${v.name}'`)
23
+ .join(" | ");
24
+ return values;
25
+ }
26
+ function generateTypeDefinition(type) {
27
+ if (isNonNullType(type)) {
28
+ return generateTypeDefinition(type.ofType);
29
+ }
30
+ if (isListType(type)) {
31
+ return `${generateTypeDefinition(type.ofType)}`;
32
+ }
33
+ if (isObjectType(type) || isInputObjectType(type)) {
34
+ return type.name;
35
+ }
36
+ if (isEnumType(type)) {
37
+ return generateEnumTypeDefinition(type);
38
+ }
39
+ switch (type.name) {
40
+ case "Int":
41
+ case "Float":
42
+ return "number";
43
+ case "String":
44
+ case "ID":
45
+ return "string";
46
+ case "Boolean":
47
+ return "boolean";
48
+ default:
49
+ return "any";
50
+ }
51
+ }
52
+ function generateInputObjectTypeDefinition(type) {
53
+ const fields = Object.values(type.getFields())
54
+ .map((field) => `${field.name}: ${generateTypeDefinition(field.type)}`)
55
+ .join(", ");
56
+ return `{ ${fields} }`;
57
+ }
58
+ function generateTypeDefinitionFromSelectionSet(selectionSet, parentType) {
59
+ const fieldDefinitions = selectionSet.selections
60
+ .map((selection) => {
61
+ if (selection.kind === "Field") {
62
+ const field = parentType.getFields()[selection.name.value];
63
+ if (!field) {
64
+ throw new Error(`Field ${selection.name.value} not found in type ${parentType.name}`);
65
+ }
66
+ let fieldType = field.type;
67
+ let fieldTypeDefinition = "";
68
+ if (selection.selectionSet) {
69
+ if (isObjectType(getNamedType(fieldType))) {
70
+ fieldTypeDefinition = generateTypeDefinitionFromSelectionSet(selection.selectionSet, getNamedType(fieldType));
71
+ }
72
+ }
73
+ else {
74
+ fieldTypeDefinition = generateTypeDefinition(fieldType);
75
+ }
76
+ return `${selection.name.value}: ${fieldTypeDefinition}${isListType(fieldType) ? "[]" : ""}`;
77
+ }
78
+ return "";
79
+ })
80
+ .filter(Boolean);
81
+ return `{${fieldDefinitions.join(",")}}`;
82
+ }
83
+ function generateReturnType(selectionSet, schema) {
84
+ const queryType = schema.getQueryType();
85
+ if (!queryType) {
86
+ throw new Error("Query type not found in schema");
87
+ }
88
+ return generateTypeDefinitionFromSelectionSet(selectionSet, queryType);
89
+ }
90
+ function generateOperationFunction(graphqlFileName, operationName, variableDefinitions, schema, selectionSet) {
91
+ const typeName = `${operationName.charAt(0).toUpperCase() + operationName.slice(1)}`;
92
+ const returnType = generateReturnType(selectionSet, schema);
93
+ let input;
94
+ if (variableDefinitions.length === 1) {
95
+ const varDef = variableDefinitions[0];
96
+ const varType = schema.getType(print(varDef.type).replace(/[!]/g, ""));
97
+ const varTypeString = isInputObjectType(varType)
98
+ ? generateInputObjectTypeDefinition(varType)
99
+ : generateTypeDefinition(varType);
100
+ input = `export type ${typeName}Variables = ${varTypeString}`;
101
+ }
102
+ else {
103
+ const variables = variableDefinitions
104
+ .map((def) => {
105
+ const varType = schema.getType(print(def.type).replace(/[!]/g, ""));
106
+ const varTypeString = isInputObjectType(varType)
107
+ ? generateInputObjectTypeDefinition(varType)
108
+ : generateTypeDefinition(varType);
109
+ return `${def.variable.name.value}: ${varTypeString}`;
110
+ })
111
+ .join(", ");
112
+ input = `export interface ${typeName}Variables { ${variables} }`;
113
+ }
114
+ return `
115
+ declare module "./${graphqlFileName}" {
116
+ ${input}
117
+
118
+ export interface ${typeName}Result ${returnType}
119
+
120
+ const value: Query<${typeName}Variables, ${typeName}Result>
121
+ export default value
122
+ }
123
+ `;
124
+ }
125
+ export async function generateOperationFromQuery(graphqlFileName, query, schema) {
126
+ const ast = parse(query);
127
+ let operations = "";
128
+ const validationErrors = validate(schema, ast);
129
+ if (validationErrors.length > 0) {
130
+ throw new Error(`Validation errors: ${validationErrors.map((e) => e.message).join("\n")}`);
131
+ }
132
+ visit(ast, {
133
+ OperationDefinition(node) {
134
+ if (node.name && node.operation === OperationTypeNode.QUERY) {
135
+ const operationName = node.name.value;
136
+ const variableDefinitions = node.variableDefinitions || [];
137
+ operations += generateOperationFunction(graphqlFileName, operationName, variableDefinitions, schema, node.selectionSet);
138
+ }
139
+ },
140
+ });
141
+ return format(operations, { parser: "typescript" });
142
+ }
143
+ export async function generateOperations(rootDir, schema) {
144
+ const graphqlFiles = findGraphQLFiles(rootDir);
145
+ let operations = "";
146
+ for (const file of graphqlFiles) {
147
+ const content = fs.readFileSync(file, "utf-8");
148
+ operations += await generateOperationFromQuery(path.basename(file), content, schema);
149
+ }
150
+ return format(operations, { parser: "typescript" });
151
+ }
@@ -0,0 +1,109 @@
1
+ import { isObjectType, isInputObjectType, isScalarType, isEnumType, isListType, isNonNullType, } from "graphql";
2
+ import { format } from "prettier";
3
+ function countTypeUsages(schema) {
4
+ const typeUsages = new Map();
5
+ Object.values(schema.getTypeMap()).forEach((type) => {
6
+ if ((isObjectType(type) || isInputObjectType(type)) && !type.name.startsWith("__")) {
7
+ Object.values(type.getFields()).forEach((field) => {
8
+ let fieldType = field.type;
9
+ while (isListType(fieldType) || isNonNullType(fieldType)) {
10
+ fieldType = fieldType.ofType;
11
+ }
12
+ if (isObjectType(fieldType) || isInputObjectType(fieldType)) {
13
+ const usage = typeUsages.get(fieldType.name) || { count: 0, type: fieldType };
14
+ usage.count++;
15
+ typeUsages.set(fieldType.name, usage);
16
+ }
17
+ });
18
+ }
19
+ });
20
+ return typeUsages;
21
+ }
22
+ function generateFieldType(type, schema, typeUsages, seenTypes = new Set()) {
23
+ if (isListType(type)) {
24
+ return `Array<${generateFieldType(type.ofType, schema, typeUsages, seenTypes)}>`;
25
+ }
26
+ if (isNonNullType(type)) {
27
+ return generateFieldType(type.ofType, schema, typeUsages, seenTypes);
28
+ }
29
+ if (isScalarType(type)) {
30
+ switch (type.name) {
31
+ case "ID":
32
+ case "String":
33
+ return "string";
34
+ case "Int":
35
+ case "Float":
36
+ return "number";
37
+ case "Boolean":
38
+ return "boolean";
39
+ default:
40
+ return "any";
41
+ }
42
+ }
43
+ if (isEnumType(type)) {
44
+ return type
45
+ .getValues()
46
+ .map((v) => `'${v.name}'`)
47
+ .join(" | ");
48
+ }
49
+ if (isObjectType(type) || isInputObjectType(type)) {
50
+ const usage = typeUsages.get(type.name);
51
+ if (usage && usage.count > 1) {
52
+ return type.name;
53
+ }
54
+ if (seenTypes.has(type.name)) {
55
+ return type.name;
56
+ }
57
+ seenTypes.add(type.name);
58
+ const fields = type.getFields();
59
+ let inlineType = "{";
60
+ Object.entries(fields).forEach(([fieldName, field]) => {
61
+ const fieldType = generateFieldType(field.type, schema, typeUsages, new Set(seenTypes));
62
+ inlineType += `${fieldName}: ${fieldType};`;
63
+ });
64
+ inlineType += "}";
65
+ return inlineType;
66
+ }
67
+ return "any";
68
+ }
69
+ function generateDocComment(description) {
70
+ if (!description)
71
+ return "";
72
+ const lines = description.split("\n");
73
+ if (lines.length === 1) {
74
+ return `/** ${description} */`;
75
+ }
76
+ return `/**\n * ${lines.join("\n * ")}\n */`;
77
+ }
78
+ function generateType(type, schema, typeUsages) {
79
+ let typeString = "";
80
+ const typeComment = generateDocComment(type.description ?? "");
81
+ if (typeComment) {
82
+ typeString += `${typeComment}\n`;
83
+ }
84
+ typeString += `export type ${type.name.charAt(0).toUpperCase() + type.name.slice(1)} = {`;
85
+ const fields = type.getFields();
86
+ Object.entries(fields).forEach(([fieldName, field]) => {
87
+ typeString += "\n";
88
+ const fieldComment = generateDocComment(field.description);
89
+ if (fieldComment) {
90
+ typeString += `${fieldComment}\n`;
91
+ }
92
+ const fieldType = generateFieldType(field.type, schema, typeUsages);
93
+ typeString += `${fieldName}: ${fieldType};`;
94
+ });
95
+ typeString += "\n};";
96
+ return typeString;
97
+ }
98
+ export async function generateTypesFromSchema(schema) {
99
+ const typeUsages = countTypeUsages(schema);
100
+ let types = "";
101
+ const typeMap = schema.getTypeMap();
102
+ Object.values(typeMap).forEach((type) => {
103
+ if ((isObjectType(type) || isInputObjectType(type)) && !type.name.startsWith("__")) {
104
+ types += generateType(type, schema, typeUsages);
105
+ types += "\n\n";
106
+ }
107
+ });
108
+ return await format(types, { parser: "typescript" });
109
+ }
@@ -0,0 +1,65 @@
1
+ import { codeFrameColumns } from "@babel/code-frame";
2
+ import fs from "fs";
3
+ import { parse, validateSchema, buildASTSchema } from "graphql";
4
+ import { validateSDL } from "graphql/validation/validate.js";
5
+ function formatGraphQlError(e, source, filename) {
6
+ if (e.locations?.length) {
7
+ return `${e.message}\n\n${filename}:${e.locations[0].line}\n\n${e.locations
8
+ .map(({ line, column }) => codeFrameColumns(source, {
9
+ start: { line, column },
10
+ }))
11
+ .join(`\n\n`)}\n`;
12
+ }
13
+ else {
14
+ throw e;
15
+ }
16
+ }
17
+ export function parseSchemaString(schemaString, schemaPath) {
18
+ let parsedSchema;
19
+ try {
20
+ parsedSchema = parse(schemaString);
21
+ }
22
+ catch (ex) {
23
+ throw Object.assign(new Error(formatGraphQlError(ex, schemaString, schemaPath)), {
24
+ code: `GRAPHQL_SYNTAX_ERROR`,
25
+ });
26
+ }
27
+ parsedSchema = {
28
+ ...parsedSchema,
29
+ definitions: parsedSchema.definitions
30
+ .slice()
31
+ .sort((a, b) => {
32
+ if (!a.name)
33
+ return -1;
34
+ if (!b.name)
35
+ return 1;
36
+ if (a.name.value.toLowerCase() > b.name.value.toLowerCase())
37
+ return 1;
38
+ if (a.name.value.toLowerCase() < b.name.value.toLowerCase())
39
+ return -1;
40
+ return 0;
41
+ }),
42
+ };
43
+ const sdlValidationErrors = validateSDL(parsedSchema);
44
+ if (sdlValidationErrors.length) {
45
+ throw Object.assign(new Error(formatGraphQlError(sdlValidationErrors[0], schemaString, schemaPath)), {
46
+ code: `GRAPHQL_SCHEMA_ERROR`,
47
+ });
48
+ }
49
+ const schema = buildASTSchema(parsedSchema, { assumeValid: false, assumeValidSDL: false });
50
+ const schemaValidationErrors = validateSchema(schema);
51
+ if (schemaValidationErrors.length > 0) {
52
+ throw Object.assign(new Error(formatGraphQlError(schemaValidationErrors[0], schemaString, schemaPath)), {
53
+ code: `GRAPHQL_SCHEMA_ERROR`,
54
+ });
55
+ }
56
+ return {
57
+ source: schemaString,
58
+ documentNode: parsedSchema,
59
+ schema,
60
+ };
61
+ }
62
+ export function parseSchema(schemaPath) {
63
+ const schemaString = fs.readFileSync(schemaPath, "utf-8");
64
+ return parseSchemaString(schemaString, schemaPath);
65
+ }
@@ -0,0 +1,4 @@
1
+ declare module "*.graphql" {
2
+ const value: string
3
+ export default value
4
+ }
@@ -0,0 +1,102 @@
1
+ import { sendTo, assign, setup, fromCallback } from "xstate";
2
+ import { parseSchema } from "../graphql/parse-schema.js";
3
+ import { findNodeModulesPath } from "../util/find-node-modules-path.js";
4
+ import { updateOperationTypes } from "../util/update-operation-types.js";
5
+ export const codeGenMachine = setup({
6
+ types: {
7
+ context: {},
8
+ events: {},
9
+ input: {},
10
+ },
11
+ guards: {
12
+ "all finished": (_, params) => params.finished.length === 2,
13
+ },
14
+ actors: {
15
+ loadSchema: fromCallback(({ sendBack }) => {
16
+ const loadSchema = async () => {
17
+ try {
18
+ const path = await findNodeModulesPath(["schema.graphql"]);
19
+ if (!path) {
20
+ sendBack({ type: "Error", error: new Error("No schema found") });
21
+ return;
22
+ }
23
+ const { schema } = parseSchema(path);
24
+ sendBack({ type: "Schema Loaded", schema });
25
+ }
26
+ catch (error) {
27
+ sendBack({ type: "Error", error });
28
+ }
29
+ };
30
+ loadSchema();
31
+ }),
32
+ generateOperations: fromCallback(({ sendBack, input }) => {
33
+ updateOperationTypes(input.schema)
34
+ .then(() => sendBack({ type: "Done" }))
35
+ .catch((error) => sendBack({ type: "Error", error }));
36
+ }),
37
+ },
38
+ actions: {
39
+ clearFinished: assign({
40
+ finished: [],
41
+ }),
42
+ setOperationsFinished: assign({
43
+ finished: (_, params) => params.finished.concat("operations.ts"),
44
+ }),
45
+ setError: assign({
46
+ error: (_, params) => params.error,
47
+ }),
48
+ setSchema: assign({
49
+ schema: (_, params) => params.schema,
50
+ }),
51
+ raiseDone: sendTo(({ context }) => context.parentRef, { type: "Code Generation Done" }),
52
+ },
53
+ }).createMachine({
54
+ id: "GraphQL Code Generation Machine",
55
+ context: ({ input }) => ({
56
+ schema: null,
57
+ finished: [],
58
+ parentRef: input.parentRef,
59
+ }),
60
+ states: {
61
+ "Load Schema": {
62
+ on: {
63
+ "Error": {
64
+ target: "Errored",
65
+ actions: { type: "setError", params: ({ event }) => event },
66
+ },
67
+ "Schema Loaded": {
68
+ target: "Generating Operations",
69
+ actions: { type: "setSchema", params: ({ event }) => event },
70
+ reenter: true,
71
+ },
72
+ },
73
+ invoke: {
74
+ src: "loadSchema",
75
+ },
76
+ },
77
+ "Done": {
78
+ entry: "raiseDone",
79
+ },
80
+ "Errored": {},
81
+ "Generating Operations": {
82
+ on: {
83
+ Done: {
84
+ target: "Done",
85
+ },
86
+ Error: {
87
+ target: "Errored",
88
+ actions: { type: "setError", params: ({ event }) => event },
89
+ },
90
+ },
91
+ invoke: {
92
+ src: "generateOperations",
93
+ input: ({ context }) => ({ schema: context.schema }),
94
+ },
95
+ },
96
+ },
97
+ initial: "Load Schema",
98
+ on: {
99
+ Change: ".Load Schema",
100
+ },
101
+ description: `Generates operations typescript types`,
102
+ });
@@ -9,6 +9,7 @@ import { startUpload } from "../api/start-upload.js";
9
9
  import { loadAppConfigFile } from "../util/app-config.js";
10
10
  import { loadDeveloperConfig, loadInitialDeveloperConfig, } from "../util/load-developer-config.js";
11
11
  import { loadEnv } from "../util/load-env.js";
12
+ import { codeGenMachine } from "./code-gen-machine.js";
12
13
  import { envMachine } from "./env-machine.js";
13
14
  import { jsMachine } from "./js-machine.js";
14
15
  import { tsMachine } from "./ts-machine.js";
@@ -22,10 +23,11 @@ export const devMachine = setup({
22
23
  "have dev version": ({ context }) => Boolean(context.devVersion),
23
24
  },
24
25
  actors: {
25
- javascript: jsMachine,
26
- typescript: tsMachine,
27
- env: envMachine,
28
- loadConfig: fromCallback(({ sendBack }) => {
26
+ "javascript": jsMachine,
27
+ "typescript": tsMachine,
28
+ "env": envMachine,
29
+ "code-gen": codeGenMachine,
30
+ "loadConfig": fromCallback(({ sendBack }) => {
29
31
  const config = loadInitialDeveloperConfig();
30
32
  if (typeof config === "string") {
31
33
  sendBack({ type: "Initialization Error", error: config });
@@ -33,12 +35,12 @@ export const devMachine = setup({
33
35
  }
34
36
  sendBack({ type: "Initialized", config });
35
37
  }),
36
- listenForGraphqlOpen: fromCallback(({ input }) => {
38
+ "listenForGraphqlOpen": fromCallback(({ input }) => {
37
39
  readline.emitKeypressEvents(process.stdin);
38
40
  if (process.stdin.isTTY) {
39
41
  process.stdin.setRawMode(true);
40
42
  }
41
- const handleKeyPress = (str, key) => {
43
+ const handleKeyPress = (_, key) => {
42
44
  if (key.name?.toLowerCase() === "o") {
43
45
  open(`http://localhost:${input.graphqlPort}/graphql`);
44
46
  }
@@ -51,7 +53,7 @@ export const devMachine = setup({
51
53
  }
52
54
  };
53
55
  }),
54
- prepareUpload: fromCallback(({ sendBack }) => {
56
+ "prepareUpload": fromCallback(({ sendBack }) => {
55
57
  const prepareUpload = async () => {
56
58
  const config = await loadDeveloperConfig();
57
59
  if (typeof config === "string")
@@ -76,7 +78,7 @@ export const devMachine = setup({
76
78
  error: typeof error === "string" ? new Error(error) : error,
77
79
  }));
78
80
  }),
79
- upload: fromCallback(({ sendBack, input: { config: { token, developer_slug: developerSlug }, contents, devVersion: { app_id: appId, app_dev_version_id: devVersionId }, }, }) => {
81
+ "upload": fromCallback(({ sendBack, input: { config: { token, developer_slug: developerSlug }, contents, devVersion: { app_id: appId, app_dev_version_id: devVersionId }, }, }) => {
80
82
  const upload = async () => {
81
83
  const { client_bundle_upload_url, server_bundle_upload_url, app_dev_version_bundle_id: bundleId, } = await startUpload({
82
84
  token,
@@ -114,7 +116,7 @@ export const devMachine = setup({
114
116
  };
115
117
  upload().catch((error) => sendBack({ type: "Upload Error", error }));
116
118
  }),
117
- watch: fromCallback(({ sendBack }) => {
119
+ "watch": fromCallback(({ sendBack }) => {
118
120
  const watcher = chokidar.watch([
119
121
  "src/app",
120
122
  "src/assets",
@@ -129,7 +131,7 @@ export const devMachine = setup({
129
131
  watcher.close();
130
132
  };
131
133
  }),
132
- graphql: fromCallback(({ sendBack }) => startGraphqlServer(sendBack)),
134
+ "graphql": fromCallback(({ sendBack }) => startGraphqlServer(sendBack)),
133
135
  },
134
136
  actions: {
135
137
  clearUploadError: assign({ uploadError: undefined }),
@@ -137,6 +139,10 @@ export const devMachine = setup({
137
139
  enqueue.sendTo("javascript", event);
138
140
  enqueue.sendTo("typescript", event);
139
141
  enqueue.sendTo("env", event);
142
+ enqueue.sendTo("code-gen", event);
143
+ }),
144
+ sendCodeGenerationDone: enqueueActions(({ enqueue }) => {
145
+ enqueue.sendTo("typescript", { type: "Change" });
140
146
  }),
141
147
  setConfig: assign({
142
148
  config: (_, params) => params.config,
@@ -180,6 +186,11 @@ export const devMachine = setup({
180
186
  id: "env",
181
187
  input: ({ self }) => ({ parentRef: self }),
182
188
  },
189
+ {
190
+ src: "code-gen",
191
+ id: "code-gen",
192
+ input: ({ self }) => ({ parentRef: self }),
193
+ },
183
194
  { src: "watch" },
184
195
  ],
185
196
  states: {
@@ -276,6 +287,17 @@ export const devMachine = setup({
276
287
  Watching: {},
277
288
  },
278
289
  initial: "Validating",
290
+ on: {
291
+ "Change": {
292
+ target: "TypeScript",
293
+ actions: "sendChange",
294
+ },
295
+ "Code Generation Done": {
296
+ target: "TypeScript",
297
+ description: `Re-enter TypeScript build when code generation is complete`,
298
+ actions: "sendCodeGenerationDone",
299
+ },
300
+ },
279
301
  },
280
302
  Graphql: {
281
303
  invoke: {
@@ -52,7 +52,7 @@ export const jsMachine = setup({
52
52
  }),
53
53
  write,
54
54
  outfile: path.resolve("dist", "index.js"),
55
- loader: { ".png": "dataurl" },
55
+ loader: { ".png": "dataurl", ".graphql": "text" },
56
56
  });
57
57
  return {
58
58
  rebuild: async () => {