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

Test exporting schemas, fix schema exporting #1935

Merged
merged 34 commits into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
1c61547
Infrastructure for checking exported schema
benjie Feb 2, 2024
a649e0a
Add runExportable method to tamedevil, use it to make plan resolver e…
benjie Feb 2, 2024
49fd8af
docs(changeset): Add `te.runExportable` method, instead of simply cal…
benjie Feb 2, 2024
f31b19f
Remove tests that load the generated files (because Jest can't handle…
benjie Feb 2, 2024
f0e4bab
First export snapshot
benjie Feb 2, 2024
71672e4
More schema exports
benjie Feb 2, 2024
26f9e4b
Fix runExportable
benjie Feb 2, 2024
33eb8e3
Handle missing parseLiteral in GraphQLScalarType construction
benjie Feb 2, 2024
ade3774
Reference a module
benjie Feb 2, 2024
08dad89
Use node 20
benjie Feb 2, 2024
fc650c4
Add a task
benjie Feb 2, 2024
fc34392
Add more export snapshots
benjie Feb 2, 2024
e20e66e
docs(changeset): Make even more of the schema exportable, including h…
benjie Feb 2, 2024
3e8fcf5
Ignore new exports from linting
benjie Feb 2, 2024
50c0cbb
Beginnings of more tests for exported schemas
benjie Feb 2, 2024
57bd887
Fix critical bug in graphile-export
benjie Feb 2, 2024
2cd52b4
Ensure we're cleaning up scopes
benjie Feb 2, 2024
0ff5412
Make enum table codec exportable
benjie Feb 2, 2024
e0a37fe
Fix bug in graphile-export variables by using tamedevil reservedWords
benjie Feb 2, 2024
9ba0c2c
Update snapshots
benjie Feb 2, 2024
d190a14
Lint
benjie Feb 2, 2024
b0c13e5
Back to node 18
benjie Feb 2, 2024
8ea67f8
docs(changeset): Fix lots of things related to exporting a schema wit…
benjie Feb 2, 2024
3bfc730
Fix mocha under node20
benjie Feb 2, 2024
18d83ad
Back to transpile-only
benjie Feb 2, 2024
59a6714
Some types
benjie Feb 2, 2024
bfac42e
Snapshots aren't sufficiently stable yet
benjie Feb 2, 2024
f78f496
Reorder
benjie Feb 2, 2024
0919300
Check exported schema matches pre-export schema
benjie Feb 2, 2024
fc590e4
Lint
benjie Feb 2, 2024
96a19d0
Use our own copy of reservedWords
benjie Feb 2, 2024
8d5b7f3
Lint
benjie Feb 2, 2024
85e3665
Use Node 20 in CI
benjie Feb 2, 2024
3e2b5b4
Increase timeouts for CI
benjie Feb 2, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changeset/five-mangos-walk.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"tamedevil": patch
---

Add `te.runExportable` method, instead of simply calling the generated factory,
it exports it in a way that's compatible with `graphile-export`.
9 changes: 9 additions & 0 deletions .changeset/thick-monkeys-buy.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"graphile-build-pg": patch
"graphile-build": patch
"postgraphile": patch
"graphile-export": patch
"tamedevil": patch
---

Fix lots of things related to exporting a schema with `graphile-export`.
8 changes: 8 additions & 0 deletions .changeset/twelve-windows-shake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"graphile-build-pg": patch
"graphile-build": patch
"postgraphile": patch
---

Make even more of the schema exportable, including handling scalars with no
parseLiteral definition.
4 changes: 4 additions & 0 deletions .eslintignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ node_modules
/graphile-build/graphile-build-pg/webpacked
/graphile-build/graphile-build-pg/exported-schema-for-webpack.mjs
/graphile-build/graphile-build-pg/schema-export-output.mjs
**/__tests__/**/*.1.graphql
**/__tests__/**/*.json5
**/__tests__/**/*.mermaid
**/__tests__/**/*.export.mjs
/wal2json
dist
CHANGELOG.md
Expand Down
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
**/__tests__/**/*.1.graphql linguist-vendored
**/__tests__/**/*.json5 linguist-vendored
**/__tests__/**/*.mermaid linguist-vendored
**/__tests__/**/*.export.mjs linguist-vendored
*/website/** linguist-documentation
2 changes: 1 addition & 1 deletion .github/workflows/test-base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
fail-fast: false
matrix:
postgres-version: [12] #, 11, 13, 14, 15]
node-version: [16.14] #, 18.x]
node-version: [20.x] #, 18.x]

services:
postgres:
Expand Down
2 changes: 1 addition & 1 deletion .nvmrc
Original file line number Diff line number Diff line change
@@ -1 +1 @@
18
20
2 changes: 1 addition & 1 deletion grafast/grafast/.mocharc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ check-leaks: true
extension:
- ts
node-option:
- "loader=ts-node/esm/transpile-only"
- "require=ts-node/register/transpile-only"
16 changes: 9 additions & 7 deletions grafast/grafast/__tests__/awkward-identifiers-test.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import { expect } from "chai";
import { parse } from "graphql";
import { ExecutionResult, parse } from "graphql";
import { it } from "mocha";

import {
access,
constant,
type ExecutableStep,
execute,
type FieldArgs,
grafastSync,
makeGrafastSchema,
} from "../dist/index.js";
Expand All @@ -30,19 +32,19 @@ const schema = makeGrafastSchema({
},
},
Obj: {
o($o) {
o($o: ExecutableStep) {
return $o;
},
a($o) {
a($o: ExecutableStep) {
return access($o, "a");
},
b($o) {
b($o: ExecutableStep) {
return access($o, "b");
},
echoNumber(_, { $nr }) {
echoNumber(_, { $nr }: FieldArgs) {
return $nr;
},
echoString(_, { $str }) {
echoString(_, { $str }: FieldArgs) {
return $str;
},
},
Expand Down Expand Up @@ -94,6 +96,6 @@ it("ok", () => {
},
{},
true,
);
) as any;
expect(JSON.stringify(JSON.parse(result2.data), null, 2)).to.equal(expected);
});
24 changes: 15 additions & 9 deletions graphile-build/graphile-build-pg/src/plugins/PgEnumTablesPlugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,7 @@ Original error: ${e.message}
}
},
async processIntrospection(info, event) {
const { EXPORTABLE } = info;
const { introspection, serviceName } = event;
for (const pgClass of introspection.classes) {
const pgNamespace = pgClass.getNamespace();
Expand Down Expand Up @@ -331,16 +332,21 @@ Original error: ${e.message}
};

// Build the codec
const codec = enumCodec({
name: info.inflection.enumTableCodec({
serviceName,
pgClass,
pgConstraint,
}),
identifier: originalCodec.sqlType,
values,
extensions,
const name = info.inflection.enumTableCodec({
serviceName,
pgClass,
pgConstraint,
});
const codec = EXPORTABLE(
(enumCodec, extensions, name, originalCodec, values) =>
enumCodec({
name,
identifier: originalCodec.sqlType,
values,
extensions,
}),
[enumCodec, extensions, name, originalCodec, values],
);

// Associate this constraint with our new codec
info.state.codecByPgConstraint.set(pgConstraint, codec);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1046,7 +1046,6 @@ function addRelations(
]);

const functionLines: TE[] = [];
const prefixLines: TE[] = [];
if (isMutationPayload) {
functionLines.push(
te`return function PgRelationsPlugin_mutation_payload_relation($in) {`,
Expand Down Expand Up @@ -1136,10 +1135,7 @@ function addRelations(
}

functionLines.push(te.cache`}`);
return te.run`${te.join(prefixLines, "\n")}${te.join(
functionLines,
"\n",
)}`;
return te.runExportable`${te.join(functionLines, "\n")}`;
};
const singleRecordPlan = makePlanResolver("singleRecord");
const listPlan = makePlanResolver("list");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@ export const PgRowByUniquePlugin: GraphileConfig.Plugin = {
* more performant, but it also makes the code nicer to
* read in the exported code.
*/
// TODO: Use `te.runExportable` instead and give the resource a name!
// eslint-disable-next-line graphile-export/exhaustive-deps
EXPORTABLE(
te.run`\
Expand Down
2 changes: 2 additions & 0 deletions graphile-build/graphile-build/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ import type { PluginHook } from "graphile-config";

import type { GatherPluginContext } from "./interfaces.js";
import type { NewWithHooksFunction } from "./newWithHooks/index.js";
import { EXPORTABLE } from "./utils.js";

// export globals for TypeDoc
export { GraphileBuild, GraphileConfig };
Expand Down Expand Up @@ -209,6 +210,7 @@ const gatherBase = (
inflection,
resolvedPreset,
grafast,
EXPORTABLE,
};
pluginContext.set(plugin, context);
if (spec.namespace != null) {
Expand Down
4 changes: 4 additions & 0 deletions graphile-build/graphile-build/src/interfaces.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import type { AsyncHooks } from "graphile-config";

import type { EXPORTABLE } from "./utils.js";

/**
* The details in the 'info' object passed as the first argument to all gather
* hooks and helpers.
Expand Down Expand Up @@ -55,4 +57,6 @@ export interface GatherPluginContext<
*/
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
grafast: typeof import("grafast");

EXPORTABLE: typeof EXPORTABLE;
}
25 changes: 25 additions & 0 deletions graphile-build/graphile-build/src/newWithHooks/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,13 @@ import {
GraphQLSchema,
GraphQLUnionType,
isNamedType,
valueFromASTUntyped,
} from "grafast/graphql";
import { inspect } from "util";

import type { ScopeForType, SpecForType } from "../global.js";
import type SchemaBuilder from "../SchemaBuilder.js";
import { EXPORTABLE } from "../utils.js";

const isString = (str: unknown): str is string => typeof str === "string";

Expand Down Expand Up @@ -57,6 +59,14 @@ export type NewWithHooksFunction = <
scope: ScopeForType<TType>,
) => TType;

const identity = EXPORTABLE(
() =>
function identity<T>(value: T): T {
return value;
},
[],
);

/**
* Returns a 'newWithHooks' function suitable for creating GraphQL types with
* the graphile-build plugin system applied.
Expand Down Expand Up @@ -691,6 +701,21 @@ export function makeNewWithHooks({ builder }: MakeNewWithHooksOptions): {
`|${rawSpec.name}`,
);

// parseLiteral in GraphQL defaults to a dynamic function; that's not
// exportable... So we must handle this ourselves.
if (!finalSpec.parseValue) {
finalSpec.parseValue = identity;
}
if (!finalSpec.parseLiteral) {
const parseValue = finalSpec.parseValue!;
finalSpec.parseLiteral = EXPORTABLE(
(parseValue, valueFromASTUntyped) => (node, variables) => {
return parseValue(valueFromASTUntyped(node, variables));
},
[parseValue, valueFromASTUntyped],
);
}

const Self = new GraphQLScalarType(finalSpec);
return Self;
}
Expand Down
18 changes: 18 additions & 0 deletions postgraphile/postgraphile/__tests__/schema/v4/core.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,18 @@
import { writeFile } from "fs/promises";
import type { PromiseOrDirect } from "grafast";
import type { GraphQLSchema } from "grafast/graphql";
import { lexicographicSortSchema, printSchema } from "grafast/graphql";
import { makeSchema } from "graphile-build";
import { exportSchemaAsString } from "graphile-export";
import type { PoolClient } from "pg";

import AmberPreset from "../../../src/presets/amber.js";
import type { V4Options } from "../../../src/presets/v4.js";
import { makeV4Preset } from "../../../src/presets/v4.js";
import { snapshot, withPoolClientTransaction } from "../../helpers.js";

jest.setTimeout(30000);

let countByPath = Object.create(null);

export const test =
Expand Down Expand Up @@ -77,4 +81,18 @@ export const test =
if (finalCheck) {
await finalCheck(schema);
}
// Now check the schema exports
const { code: exportString } = await exportSchemaAsString(schema, {
mode: "typeDefs",
prettier: true,
modules: {
jsonwebtoken: await import("jsonwebtoken"),
},
});
const executableSchemaPath = `${testPath.replace(/\.test\.[jt]s$/, "")}${
sort || i > 1 ? `.${i}` : ""
}.export.mjs`;
// Cannot rely on snapshot until this is more stable
await writeFile(executableSchemaPath, exportString.trim() + "\n");
//await snapshot(exportString.trim() + "\n", executableSchemaPath);
});
Loading
Loading