fastify-autoroutes icon indicating copy to clipboard operation
fastify-autoroutes copied to clipboard

Don't working ES module type

Open MushiX opened this issue 2 years ago • 4 comments

Versions

fastify-autoroute: 2.1.3 node: 18.1.0 os: docker [Alpine] terminal: sh

Expected Behavior

Working autorouting

Actual Behavior

Not working everything

Steps to Reproduce

import fastifyFramework from 'fastify';
import fastifyAutoRoutes from 'fastify-autoroutes'
import fastifyStatic from "@fastify/static";
import fastifyCors from '@fastify/cors';
import path from 'path';
import {dirname} from 'path';
import {fileURLToPath} from 'url';

const __dirname = dirname(fileURLToPath(import.meta.url));

const fastify = fastifyFramework({
	logger: process.env.ENVIRONMENT !== 'production',
});

fastify.register(fastifyAutoRoutes, {
	dir: '../src/routes',
});

fastify.register(fastifyCors, {
	origin: true,
	credentials: true
});

fastify.register(fastifyStatic, {
	root: path.join(__dirname, 'public'),
	prefix: '/public/'
});

const start = async () => {
	try {
		await fastify.listen(80, '0.0.0.0');
	} catch (e) {
		fastify.log.error(e);
		setTimeout(start, 5000);
	}
}
await start();
{
  "name": "deal",
  "version": "0.0.1",
  "type": "module",
  "scripts": {
    "dev": "nodemon index.js",
    "start": "node index.js"
  },
  "dependencies": {
    "@fastify/cors": "^7.0.0",
    "@fastify/static": "^5.0.2",
    "fastify": "^3.29.0",
    "fastify-autoroutes": "^2.1.3"
  }
}

SCREENSHOT ERROR

image

MushiX avatar May 06 '22 18:05 MushiX

I have the same problem when i have "type": "module" not working

emil-1996 avatar May 06 '22 19:05 emil-1996

i have to build aslo for es modules (mjs),

right now i am using typescript to build the package and i don't know if i can output mjs with it, without using another transpiler (like babel).

right now the workaround is to use "commonjs" type.

GiovanniCardamone avatar May 07 '22 10:05 GiovanniCardamone

I convert your code to es

import fastifyPlugin from 'fastify-plugin';
import glob from 'glob-promise';
import process from 'process';
import path from 'path';
import fs from 'fs';

export const ERROR_LABEL = 'fastify-autoroutes';

async function loadModule(name, path) {
	const module = await import(path);

	if (typeof module === 'function') {
		return module;
	}
	if (typeof module === 'object' && 'default' in module && typeof module.default === 'function') {
		return module.default;
	}
	throw new Error(`${exports.ERROR_LABEL}: invalid route module definition (${name}) ${path}. Must export a function`);
}

export default fastifyPlugin(async (fastify, options, next) => {
	const {dir, prefix: routePrefix} = {
		...options, dir: options.dir || './routes', prefix: options.prefix || '',
	}

	let dirPath;

	if (path.isAbsolute(dir)) {
		dirPath = dir
	} else if (path.isAbsolute(process.argv[1])) {
		dirPath = path.join(process.argv[1], dir)
	} else {
		dirPath = path.join(process.cwd(), process.argv[1], dir)
	}

	if (!fs.existsSync(dirPath)) {
		return next(new Error(`${ERROR_LABEL} dir ${dirPath} does not exists`))
	}

	if (!fs.statSync(dirPath).isDirectory()) {
		return next(new Error(`${ERROR_LABEL} dir ${dirPath} must be a directory`))
	}

	let routes = await glob(`${dirPath}/**/[!.]*.{ts,js}`)
	const routesModules = {}

	// glob returns ../../, but windows returns ..\..\
	routes = routes.map((route) => path.normalize(route).replace(/\\/g, '/'))
	dirPath = path.normalize(dirPath).replace(/\\/g, '/')

	// console.log({ routes })

	for (const route of routes) {
		let routeName = route
			.replace(dirPath, '')
			.replace('.js', '')
			.replace('.ts', '')
			.replace('index', '')
			.split('/')
			.map((part) => part.replace(/{(.+)}/g, ':$1'))
			.join('/')

		routeName = !routeName ? '/' : `${routePrefix}${routeName}`

		// console.log({ routeName })

		routesModules[routeName] = (await loadModule(routeName, route))(fastify)
	}

	for (let [url, module] of Object.entries(routesModules)) {
		for (const [method, options] of Object.entries(module)) {
			if (url.endsWith('/') && url !== '/') {
				url = url.slice(0, -1)
			}
			fastify.route({
				method: method.toUpperCase(), url: url, ...options,
			})
		}
	}
}, {
	fastify: '>=3.0.0', name: 'fastify-autoroutes',
})

It's working for me, but if you add support es (native) I would like prefer use your solution

emil-1996 avatar May 07 '22 10:05 emil-1996

i have to add a build step to produce both (commonjs, es module) output. In this way, node can pick module by itself.

I can't replace this or i will break any other commonjs application

GiovanniCardamone avatar May 07 '22 12:05 GiovanniCardamone