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

Service binding not work in miniflare 3 #625

Open
madawei2699 opened this issue Jul 9, 2023 · 9 comments
Open

Service binding not work in miniflare 3 #625

madawei2699 opened this issue Jul 9, 2023 · 9 comments

Comments

@madawei2699
Copy link

Hi,

I can't setup the service binding with miniflare 3, here is my test code:

import { Miniflare } from "miniflare";

const mf = new Miniflare({
  host: "0.0.0.0",
  port: 8787,
	workers: [
		{
			name: "my-invest-gateway",
			serviceBindings: {
				AUTH: 'my-invest-auth',
				async CHAT(request) {
          // `request` is the incoming `Request` object.
          return new Response('');
        },
			},
			scriptPath: './index.ts',
		},
		{
			name: "my-invest-auth",
			script: `
				addEventListener('fetch', event => {
					event.respondWith(new Response('Hello world'));
				});
			`,
		},
	],
});

afterAll(() => {
	mf.dispose();
});

describe('Chat', () => {
	test('GET /chat', async () => {
		const res = await mf.dispatchFetch('http://127.0.0.1:8787/chat/hello/jack')
		expect(res.status).toBe(200)
		const body = await res.text()
		expect(body).toEqual('Hello, world!')
	})
})

and here is my code:

import { Context, Hono } from 'hono'
import { logger } from 'hono/logger'

type Bindings = {
  AUTH: Fetcher;
  CHAT: Fetcher;
}

const app = new Hono<{ Bindings: Bindings }>()
app.use('*', logger())

// API routes

const chat = new Hono()

chat.get('/hello/:user', async (c: Context) => {
	console.log(JSON.stringify(c.env));
	// TODO: check if the user exists
	const authResponse = await c.env.AUTH.fetch(c.req.raw.clone());
	const authBody = await authResponse.json();
	console.log(`authResponse: ${JSON.stringify(authBody)}`);
	if (authResponse.status !== 200) {
		return authResponse;
	}
  return await c.env.CHAT.fetch(c.req.raw, {
		headers: {
      'X-Auth-Header': 'abcd',
      'X-User-Agent': 'gateway',
    },
	});
});

app.route('/chat', chat)

export default app

when I run npm run test, there is an error:

 MiniflareCoreError [ERR_SERVICE_NOT_MOUNTED]: Service "my-invest-auth" for binding "AUTH" not found.
    Make sure "my-invest-auth" is mounted so Miniflare knows where to find it.
@mrbbot
Copy link
Contributor

mrbbot commented Jul 10, 2023

Hey! 👋 ERR_SERVICE_NOT_MOUNTED will only be thrown by Miniflare 2. Could you double check the version of Miniflare you've got installed? It's possible multiple versions are installed and the wrong one is being picked up? Running npm why miniflare may help here.


Unrelated, but you'll also want to import Response from miniflare in your test to make sure you're using the right implementation:

import { Miniflare, Response } from "miniflare";

@madawei2699
Copy link
Author

Hi @mrbbot Thanks, but the version is 3.2.
image

@mrbbot
Copy link
Contributor

mrbbot commented Jul 11, 2023

Hmmm, very strange. A few other things to try:

  • Remove your node_modules folder and rerun npm install
  • Check you haven't got jest-environment-miniflare installed (this hasn't been upgraded to Miniflare 3 yet). Could you share your Jest config here too?
  • Run the node REPL in your project then require.resolve("miniflare") and share that here. This should show us where Miniflare is being loaded from.

@madawei2699
Copy link
Author

Hi, @mrbbot Thanks!

package.json file:

{
	"name": "my-invest-gateway",
	"version": "0.0.1",
	"private": true,
	"main": "src/index.ts",
	"scripts": {
		"deploy": "wrangler deploy src/index.ts",
		"dev": "wrangler dev src/index.ts --local",
		"test": "jest"
	},
	"dependencies": {
		"@cfworker/uuid": "^1.12.4",
		"hono": "^3.1.5"
	},
	"devDependencies": {
		"@cloudflare/workers-types": "^4.20230518.0 ",
		"@types/jest": "^29.5.2",
		"esbuild": "^0.15.1",
		"esbuild-jest": "^0.5.0",
		"jest": "^29.1.2",
		"jest-environment-miniflare": "^2.6.0",
		"miniflare": "^3.20230628.0",
		"wrangler": "^3.0.0"
	}
}

jest.config.js

module.exports = {
  transform: {
    '^.+\\.(ts|tsx)$': 'esbuild-jest',
  },
  testEnvironment: 'miniflare',
}

node REPL:

Welcome to Node.js v18.15.0.
Type ".help" for more information.
> require.resolve("miniflare")
'~/myInvestGateway/node_modules/miniflare/dist/src/index.js'
> 

@mrbbot
Copy link
Contributor

mrbbot commented Jul 14, 2023

Ah, when using Miniflare's API for testing (new Miniflare(...)), you shouldn't set testEnvironment: 'miniflare' in your Jest config. This runs your tests inside a workers environment, rather than the Node.js environment Miniflare expects. Removing testEnvironment: 'miniflare' from your config should fix the issue.

@madawei2699
Copy link
Author

Thanks @mrbbot But it still can't test 😢

> [email protected] test
> jest

  console.error
    service core:user:my-invest-gateway: Uncaught SyntaxError: Cannot use import statement outside a module

      at Interface.<anonymous> (node_modules/miniflare/src/runtime/index.ts:58:39)

  console.error
      at core:user:my-invest-gateway:1

      at Interface.<anonymous> (node_modules/miniflare/src/runtime/index.ts:58:39)

 FAIL  src/index.test.ts
  Chat
    ✕ GET /chat (154 ms)

  ● Chat › GET /chat

    MiniflareCoreError [ERR_RUNTIME_FAILURE]: The Workers runtime failed to start. There is likely additional logging output above.

      29 | afterAll(() => {
      30 |      mf.dispose();
    > 31 | });
         |              ^
      32 |
      33 | describe('Chat', () => {
      34 |      test('GET /chat', async () => {

      at Miniflare.#assembleAndUpdateConfig (node_modules/miniflare/src/index.ts:853:13)
      at Miniflare.#init (node_modules/miniflare/src/index.ts:537:5)
      at Mutex.runWith (node_modules/miniflare/src/shared/sync.ts:63:48)
      at Miniflare.#waitForReady (node_modules/miniflare/src/index.ts:880:5)
      at Miniflare.dispatchFetch (node_modules/miniflare/src/index.ts:928:5)
      at Object.<anonymous> (src/index.test.ts:31:17)

Test Suites: 1 failed, 1 total
Tests:       1 failed, 1 total
Snapshots:   0 total
Time:        0.548 s, estimated 1 s
Ran all test suites.
node:internal/process/promises:288
            triggerUncaughtException(err, true /* fromPromise */);
            ^

MiniflareCoreError [ERR_RUNTIME_FAILURE]: The Workers runtime failed to start. There is likely additional logging output above.

Even I add "type": "module" to package.json file and rename the jest.config.js to jest.config.cjs, the same error.

@AbdallahAbis
Copy link

Same issue!
Screenshot 2023-07-24 at 13 33 56
Screenshot 2023-07-24 at 13 34 15

if I remove testEnvironment: "miniflare", I lose the miniflare methodes such as getMiniflareFetchMock

@mrbbot
Copy link
Contributor

mrbbot commented Nov 7, 2023

@madawei2699 apologies for not following up here! This got completely buried in my inbox. 😢 If you're still working on this project, you'll need to build your TypeScript source code first, then point Miniflare to the built output. npx wrangler build should do this for you. Replace scriptPath: "src/index.ts" with scriptPath: "dist/index.js", modules: true (assuming wrangler build produces a file called dist/index.js)

@AbdallahAbis if this is still an issue for you, would you be able to create a new GitHub issue?

@daliborgogic
Copy link

Similar issue with service binding #782

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants