joi icon indicating copy to clipboard operation
joi copied to clipboard

Change browser module export

Open dmackenz opened this issue 5 years ago • 11 comments

Context

  • node version: 12.12.0
  • module version: 17.1.0

What are you trying to achieve or the steps to reproduce ?

The documentation does not make it clear how @hapi/joi/dist/joi-browser.min.js can be imported and used like regular @hapi/joi. I am trying to use Joi in Karma.

// --- What I've tried:
import Joi from '@hapi/joi/dist/joi-browser.min.js';
import * as Joi from '@hapi/joi/dist/joi-browser.min.js';
import '@hapi/joi/dist/joi-browser.min.js';
import { Joi } from '@hapi/joi/dist/joi-browser.min.js';
// ---

export const createSchema = () => {
	return {
		scoresStore: {
			scores: Joi.array().length(4).items(Joi.number().equal(0)).required()
		},
		overallScoreStore: {
			root: Joi.object().required(),
			overallScore: Joi.number().equal(0),
			overallScoreTwo: Joi.number().equal(0)
		}
	};
};

Could someone tell me what the issue is here?

dmackenz avatar Feb 12 '20 20:02 dmackenz

Why are you doing deep imports? import Joi from '@hapi/joi' should be enough.

Marsup avatar Feb 13 '20 09:02 Marsup

@Marsup

import Joi from '@hapi/joi' throws an error when ran with karma and I'm not sure why. It works fine with standalone mocha. This is what led me to try to import joi-browser.min.js because I figured that the fact that I am running in a headless browser was causing the error.

the code I am running:

import Joi from '@hapi/joi';
import RootStore from '../../components/stores/root';

export const createSchema = () => {
	return {
		scoresStore: {
			scores: Joi.array().length(4).items(Joi.number().equal(0)).required()
		}
	};
};

export const validate = (schema, store) => {
	const { error } = Joi.object(schema).validate(store);
	if (error) throw error;
};

describe('Root tests', () => {
	it('test initial schema', (done) => {
		const rootStore = new RootStore();
		const schema = createSchema();
		validate(schema, rootStore);
		done();
	});
});

Here is the error from karma:

START:
13 02 2020 09:43:12.128:INFO [karma-server]: Karma v4.4.1 server started at http://0.0.0.0:9876/
13 02 2020 09:43:12.129:INFO [launcher]: Launching browsers ChromeHeadlessNoSandbox with concurrency unlimited
13 02 2020 09:43:12.137:INFO [launcher]: Starting browser ChromeHeadless
13 02 2020 09:43:12.728:INFO [HeadlessChrome 79.0.3945 (Windows 10.0.0)]: Connected on socket O79s7etaUu6t9GkgAAAA with id 13936121
HeadlessChrome 79.0.3945 (Windows 10.0.0) ERROR
  Uncaught SyntaxError: The requested module '../../node_modules/@hapi/joi/lib/index.js' does not provide an export named 'default'
  at http://localhost:9876/context.html:0:0

  SyntaxError: The requested module '../../node_modules/@hapi/joi/lib/index.js' does not provide an export named 'default'

Finished in 0.881 secs / 0 secs @ 09:43:13 GMT-0500 (Eastern Standard Time)

SUMMARY:
√ 0 tests completed

dmackenz avatar Feb 13 '20 14:02 dmackenz

Oh you're right, we use require for our testing. Hopefully import Joi = require('@hapi/joi') works. This is probably something we should change in the next breaking version.

Marsup avatar Feb 13 '20 15:02 Marsup

So I ended up figuring it out. I ended up doing import '@hapi/joi/dist/joi-browser.min.js' then used joi with a lowercase j every time that I referenced it.

import '@hapi/joi/dist/joi-browser.min.js';
// const joi = require('@hapi/joi');
import RootStore from '../../components/stores/root';

export const createSchema = () => {
	return {
		scoresStore: {
			scores: joi.array().length(4).items(joi.number().equal(0)).required()
		}
	};
};

export const validate = (schema, store) => {
	const { error } = joi.object(schema).validate(store);
	if (error) throw error;
};

describe('Root tests', () => {
	it('test initial schema', (done) => {
		console.log(JSON.stringify(joi));
		const rootStore = new RootStore();
		const schema = createSchema();
		validate(schema, rootStore);
		done();
	});
});

dmackenz avatar Feb 13 '20 18:02 dmackenz

@Marsup how should this be fixed?

hueniverse avatar Feb 13 '20 19:02 hueniverse

By exporting an ES6 compatible module. Basically either set a default property and __esModule to true, or export it as a Joi property dropping the default export. Or both.

Marsup avatar Feb 15 '20 09:02 Marsup

You can find an example output of that in https://babeljs.io/docs/en/babel-plugin-transform-modules-commonjs.

Marsup avatar Feb 15 '20 09:02 Marsup

Hey @hueniverse ,

I can help with this. Let me know if this is okay, so you can assign this issue to me.

BolajiOlajide avatar Jul 27 '20 23:07 BolajiOlajide

I think this lead to others problems too.

In fact, const Tlds = require('@hapi/address/lib/tlds'); doesn't work at all in browser (return an empty object), so we have error thrown for standard documented code (a basic string().email()).

mathieutu avatar Oct 15 '20 21:10 mathieutu

Are there really no plans to support modern JS? Svelte and Vue (vite/rollup) don't support CommonJS.

braebo avatar Jul 08 '21 06:07 braebo

If someone wants to open a PR that fixes it, ideally by offering a separate export so it is not a breaking change (at least initially to allow people to migrate over time), I'll review.

hueniverse avatar Jul 10 '21 07:07 hueniverse