Meteor 3: Import Anomaly?

I’m updating my app to Meteor 3. It uses ApolloGraphQL. I previously used swydo:ddp-apollo to interact with Apollo. But, swydo:ddp-apollo appears to require fibers. So, I’m following the Meteor create --apollo sample app. I’ve duplicated all the relevant code from it to my app.

I’m having a little anomaly with imports.

The Meteor create --apollo sample app includes this structure:

├── imports
│ ├── apollo
│ │ ├── resolvers.js
│ │ └── schema.graphql
├── server
│ ├── apollo.js
│ ├── init.js
│ └── synced-cron
│ ├── cron.js
│ └── main.js
└── settings.json

The file apollo.js includes this line:

import typeDefs from '/imports/apollo/schema.graphql';

…and it runs as expected without error.

My app includes the same structure:

├── imports
│ ├── apollo
│ │ ├── resolvers.js
│ │ └── schema.graphql
├── server
│ ├── apollo.js
└── settings.json

The file apollo.js includes this line:

import typeDefs from '/imports/apollo/schema.graphql';

When I run it, I get the error:

Cannot find module ‘/imports/apollo/schema.graphql’

…in apollo.js on that line.

What am I missing?

Update - it turns out this has something to do with the Meteor package swydo:graphql. The Meteor create --apollo sample app shows the same import error if I remove that package.

Which is odd because the code in that app doesn’t seem to be using ‘swydo:ddp-apollo’. :thinking:

Realated:

The swydo packages don’t seem to be updated for 3.0. With the graphql package that one is a build module that allows for processing of .graphql files. swydo:ddp-apollo will depend on it.

I posted to swydo issues in January asking if it would be updated to support Meteor 3, and there has been no reply yet.

I’ve been working on using the ApolloGraphQL-recommended methods of connecting client and server. It successfully reads my graphql files. But I haven’t gotten Meteor.userId() stored in context yet.

Here’s my current draft code:

STARTUP, E.G. IN SERVER/MAIN.JS

import { ApolloServer } from '@apollo/server';
import { getUser } from 'meteor/apollo';
import {WebApp} from "meteor/webapp";
import express from 'express';
import {json} from 'body-parser';
import {startStandaloneServer} from "@apollo/server/standalone";

//APOLLO
import {getQueryResults, getUserData, resolvers} from "./api/resolvers";
import typeDefs from "./api/schema";

const server = new ApolloServer({
	typeDefs,
	resolvers,
});

const { url } = await startStandaloneServer(server, {
	listen: { port: 4000 },
});

console.log(`🚀  Server ready at: ${url}`);

SCHEMA.JS

One of the imports above makes it possible for this to be read without the use of swydo-apollo.

// Adding #graphql to the beginning of a template literal provides GraphQL syntax
// highlighting in supporting IDEs.

const typeDefs = `#graphql

scalar JSON
scalar DATETIME

type StatusResponse {
	id: String
	result: Boolean
	statusResponseMsg: String
	resolverName: String
	payload: JSON
}
[....]

APOLLO CLIENT

import { ApolloClient, InMemoryCache } from '@apollo/client';
import {localHostStringForHTTPS} from "../both";

const cache = new InMemoryCache();
let uri_local = localHostStringForHTTPS;
uri_local = uri_local.includes('3000') ? uri_local.replace('3000', '4000') : uri_local + ':4000';
const client = new ApolloClient({
	// Provide required constructor fields
	cache: cache,
	uri: uri_local,

	// Provide some optional constructor fields
	name: 'react-web-client',
	version: '1.3',
	queryDeduplication: false,
	defaultOptions: {
		watchQuery: {
			fetchPolicy: 'cache-and-network',
		},
	},
});

export default client;

It seems to be almost working, except for context. It successfully hits my resolvers and returns the result.

It requires swydo:graphql, so that you can import .graphql files.

Interesting… if I use this:

const { url } = await startStandaloneServer(server, {
    context: async ({ req }) => ({ token: '12345' }),
    listen: { port: 4000 },
});

… ‘12345’ shows up in context in my resolver.

But if I run this:

import { getUser } from 'meteor/apollo';
[.....]
const { url } = await startStandaloneServer(server, {
    context: async ({ req }) => ({ token: getUser() }),
    listen: { port: 4000 },
});

… context shows up in my resolver looking like this:

I just have to figure out how to modify this:

const { url } = await startStandaloneServer(server, {
    context: async ({ req }) => ({ token: getUser() }),
    listen: { port: 4000 },
});

…so that the value is resolved before it gets to my server. :thinking:

Hey… if I run:

const { url } = await startStandaloneServer(server, {
    context: async ({ req }) => {
        const token = await getUser();
        return { token };
    },
    listen: { port: 4000 },
});

…with a breakpoint on the line return { token }; token is undefined.

Does import { getUser } from 'meteor/apollo'; not work in Meteor 3.0? Is there an alternative way I can get the Meteor user here?

Better check the getUser() code in meteor/apollo. With fibers out, it might require additional checks to identify the user

1 Like