miniflare icon indicating copy to clipboard operation
miniflare copied to clipboard

Service binding not work in miniflare 3

Open madawei2699 opened this issue 1 year ago • 9 comments

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.

madawei2699 avatar Jul 09 '23 14:07 madawei2699

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";

mrbbot avatar Jul 10 '23 12:07 mrbbot

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

madawei2699 avatar Jul 10 '23 23:07 madawei2699

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.

mrbbot avatar Jul 11 '23 09:07 mrbbot

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'
> 

madawei2699 avatar Jul 12 '23 13:07 madawei2699

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.

mrbbot avatar Jul 14 '23 10:07 mrbbot

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.

madawei2699 avatar Jul 14 '23 15:07 madawei2699

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

AbdallahAbis avatar Jul 24 '23 12:07 AbdallahAbis

@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?

mrbbot avatar Nov 07 '23 12:11 mrbbot