11import * as fs from "fs" ;
22import * as path from "path" ;
33import * as pg from "pg" ;
4+ //import * as vm from "node:vm";
5+
46import { promisify } from "util" ;
5- import { ExecutionArgs , parse , validate } from "graphql" ;
7+ import { ExecutionArgs , GraphQLSchema , parse , validate } from "graphql" ;
68import { withPgClient , withPgPool } from "../helpers" ;
79import { PgConditionArgumentPlugin } from "graphile-build-pg" ;
810import { postgraphilePresetAmber } from "postgraphile/presets/amber" ;
@@ -13,9 +15,49 @@ import CustomOperatorsPlugin from "./../customOperatorsPlugin";
1315import { execute , hookArgs } from "grafast" ;
1416import { SchemaResult } from "graphile-build" ;
1517import { makeWithPgClientViaPgClientAlreadyInTransaction } from "@dataplan/pg/adaptors/pg" ;
18+ import { exportSchemaAsString } from "graphile-export" ;
19+ import _module = require( "module" ) ;
20+ import { dirname } from "path" ;
21+ const { Module, builtinModules } = _module ;
22+ import { transformSync } from "@babel/core" ;
1623
1724// TODO: remove this once Grafast gets it's planning under control :D
18- jest . setTimeout ( 30000 ) ;
25+ jest . setTimeout ( 3000000 ) ;
26+ /*
27+ const vmEval = (code: string) => {
28+ const context = {} as GraphQLSchema;
29+ // Load the module with the dyanamic script.
30+ vm.runInNewContext(code, vm.createContext(context));
31+ console.log("Returning context: ", JSON.stringify(context, null, 2));
32+ return context;
33+ };
34+ */
35+ let cachedSchema = { } as GraphQLSchema ;
36+ let haveCache = false ;
37+ const vmEval = ( code : string ) => {
38+ if ( ! haveCache ) {
39+ const filename = "exported-v5-schema.mjs" ;
40+ // Load the module with the dyanamic script.
41+ const replacementModule = new Module ( filename , this ) ;
42+ replacementModule . filename = filename ;
43+ // @ts -ignore
44+ replacementModule . paths = Module . _nodeModulePaths ( dirname ( filename ) ) ;
45+ const commonJScode = transformSync ( code , {
46+ filename,
47+ compact : true ,
48+ plugins : [ "@babel/plugin-transform-runtime" ] ,
49+ } ) ;
50+ // @ts -ignore
51+ replacementModule . _compile ( commonJScode . code , filename ) ;
52+ replacementModule . loaded = true ;
53+ cachedSchema = replacementModule . exports . schema as GraphQLSchema ;
54+ haveCache = true ;
55+ console . log ( "Schema import done - no cache" ) ;
56+ } else {
57+ console . log ( "Schema import done - from cache" ) ;
58+ }
59+ return cachedSchema ;
60+ } ;
1961
2062const createPostGraphileSchema = async (
2163 pool : pg . Pool ,
@@ -44,7 +86,23 @@ const createPostGraphileSchema = async (
4486 ] ,
4587 } ;
4688 const params = await makeSchema ( preset ) ;
47- return params ;
89+ if ( process . env . TEST_EXPORTED_SCHEMA ) {
90+ return {
91+ ...params ,
92+ schema : vmEval (
93+ (
94+ await exportSchemaAsString ( params . schema , {
95+ mode : "graphql-js" ,
96+ // or:
97+ // mode: "typeDefs",
98+ modules : { } ,
99+ } )
100+ ) . code
101+ ) ,
102+ } ;
103+ } else {
104+ return params ;
105+ }
48106} ;
49107
50108const readFile = promisify ( fs . readFile ) ;
@@ -146,67 +204,73 @@ beforeAll(async () => {
146204
147205for ( const queryFileName of queryFileNames ) {
148206 // eslint-disable-next-line jest/valid-title
149- test ( queryFileName , async ( ) => {
150- // Read the query from the file system.
151- const query = await readFile (
152- path . resolve ( queriesDir , queryFileName ) ,
153- "utf8"
154- ) ;
155- // Get the appropriate GraphQL schema for this fixture. We want to test
156- // some specific fixtures against a schema configured slightly
157- // differently.
158- const gqlSchemaByQueryFileName : {
159- [ queryFileName : string ] : SchemaResult ;
160- } = {
161- "addConnectionFilterOperator.graphql" :
162- gqlSchemas . addConnectionFilterOperator ,
163- "dynamicJsonTrue.graphql" : gqlSchemas . dynamicJson ,
164- "types.cidr.graphql" : gqlSchemas . networkScalars ,
165- "types.macaddr.graphql" : gqlSchemas . networkScalars ,
166- "arrayTypes.cidrArray.graphql" : gqlSchemas . networkScalars ,
167- "arrayTypes.macaddrArray.graphql" : gqlSchemas . networkScalars ,
168- "relations.graphql" : gqlSchemas . relations ,
169- "simpleCollections.graphql" : gqlSchemas . simpleCollections ,
170- "nullAndEmptyAllowed.graphql" : gqlSchemas . nullAndEmptyAllowed ,
171- } ;
172- const { schema, resolvedPreset } =
173- queryFileName in gqlSchemaByQueryFileName
174- ? gqlSchemaByQueryFileName [ queryFileName ]
175- : gqlSchemas . normal ;
176-
177- const document = parse ( query ) ;
178- const errors = validate ( schema , document ) ;
179- if ( errors . length > 0 ) {
180- throw new Error (
181- `GraphQL validation errors:\n${ errors . map ( ( e ) => e . message ) . join ( "\n" ) } `
207+ test (
208+ queryFileName ,
209+ async ( ) => {
210+ // Read the query from the file system.
211+ const query = await readFile (
212+ path . resolve ( queriesDir , queryFileName ) ,
213+ "utf8"
182214 ) ;
183- }
184- const args : ExecutionArgs = {
185- schema ,
186- document ,
187- } ;
188- await hookArgs ( args , resolvedPreset , { } ) ;
189- //const pgSubscriber = new PgSubscriber(pool);
190- const result = ( await withPgClient ( async ( pgClient ) => {
191- // We must override the context because we didn't use a pool above and so
192- // we need to add our own client
193-
194- // NOTE: the withPgClient needed on context is **VERY DIFFERENT** to our
195- // withPgClient test helper. We should rename our test helper ;)
196- const contextWithPgClient =
197- makeWithPgClientViaPgClientAlreadyInTransaction ( pgClient , false ) ;
198- try {
199- args . contextValue = {
200- pgSettings : ( args . contextValue as any ) . pgSettings ,
201- withPgClient : contextWithPgClient ,
202- //pgSubscriber,
203- } ;
215+ // Get the appropriate GraphQL schema for this fixture. We want to test
216+ // some specific fixtures against a schema configured slightly
217+ // differently.
218+ const gqlSchemaByQueryFileName : {
219+ [ queryFileName : string ] : SchemaResult ;
220+ } = {
221+ "addConnectionFilterOperator.graphql" :
222+ gqlSchemas . addConnectionFilterOperator ,
223+ "dynamicJsonTrue.graphql" : gqlSchemas . dynamicJson ,
224+ "types.cidr.graphql" : gqlSchemas . networkScalars ,
225+ "types.macaddr.graphql" : gqlSchemas . networkScalars ,
226+ "arrayTypes.cidrArray.graphql" : gqlSchemas . networkScalars ,
227+ "arrayTypes.macaddrArray.graphql" : gqlSchemas . networkScalars ,
228+ "relations.graphql" : gqlSchemas . relations ,
229+ "simpleCollections.graphql" : gqlSchemas . simpleCollections ,
230+ "nullAndEmptyAllowed.graphql" : gqlSchemas . nullAndEmptyAllowed ,
231+ } ;
232+ const { schema , resolvedPreset } =
233+ queryFileName in gqlSchemaByQueryFileName
234+ ? gqlSchemaByQueryFileName [ queryFileName ]
235+ : gqlSchemas . normal ;
204236
205- return ( await execute ( args ) ) as any ;
206- } finally {
207- contextWithPgClient . release ?.( ) ;
237+ const document = parse ( query ) ;
238+ const errors = validate ( schema , document ) ;
239+ if ( errors . length > 0 ) {
240+ throw new Error (
241+ `GraphQL validation errors:\n${ errors
242+ . map ( ( e ) => e . message )
243+ . join ( "\n" ) } `
244+ ) ;
208245 }
209- } ) ) as any ;
210- expect ( result ) . toMatchSnapshot ( ) ;
211- } ) ;
246+ const args : ExecutionArgs = {
247+ schema,
248+ document,
249+ } ;
250+ await hookArgs ( args , resolvedPreset , { } ) ;
251+ //const pgSubscriber = new PgSubscriber(pool);
252+ const result = ( await withPgClient ( async ( pgClient ) => {
253+ // We must override the context because we didn't use a pool above and so
254+ // we need to add our own client
255+
256+ // NOTE: the withPgClient needed on context is **VERY DIFFERENT** to our
257+ // withPgClient test helper. We should rename our test helper ;)
258+ const contextWithPgClient =
259+ makeWithPgClientViaPgClientAlreadyInTransaction ( pgClient , false ) ;
260+ try {
261+ args . contextValue = {
262+ pgSettings : ( args . contextValue as any ) . pgSettings ,
263+ withPgClient : contextWithPgClient ,
264+ //pgSubscriber,
265+ } ;
266+
267+ return ( await execute ( args ) ) as any ;
268+ } finally {
269+ contextWithPgClient . release ?.( ) ;
270+ }
271+ } ) ) as any ;
272+ expect ( result ) . toMatchSnapshot ( ) ;
273+ } ,
274+ 100000000
275+ ) ;
212276}
0 commit comments