Dynamic module import in Ember CLI - ember.js

I have a bunch of modules defined in an Ember CLI app and each starts with the same path. I would like to import the modules into a module in the app. For example, I could write:
import post1 from 'posts/1';
import post2 from 'posts/2';
import post3 from 'posts/3';
export default Em.ObjectController.extend({
posts: Em.A(post1, post2, post3),
});
However, I do not know the module names because they are created/named on the fly by a precompiler. All I know is that the path always begins with the same string. In this case, posts.
Is there a way to import all modules that begin with a particular path? For example, how can I do something like the following:
import posts from 'posts/*';
// or
registry['posts'].forEach(postId, i) {
var path = 'posts/' + postId;
import i from path;
}
Each of the modules I want to find and import has exported an object.
I have been through the ES6 module transpiler docs but can't find much.

The ES6 spec doesn't allow you to dynamically import modules using the import keyword. All importing and exporting using the module syntax must be done statically. However, it does provide a programmatic API that you can use to dynamically import modules. This article has a great summary of it (as well as a great summary of the rest of ES6 modules).
My suggestion would be to wrap Ember's loader API in a ES6 compliant wrapper. For instance, Ember-CLI uses the require() function to get modules, so you could do something like this:
window.System = window.System || {};
window.System['import'] = function(moduleName) {
return Ember.RSVP.Promise.resolve(window.require(moduleName));
}
// ...
System.import('my-app/posts/' + postNumber).then(function(postModule) {
// ...
});
You could also use the Ember require() function directly, my way just protects you in the likely event that Ember changes their module loader.

Related

Cannot use import statement outside a module - Vuex testing quasar

how are you ?
I'm having a issue in testing Vuex stuff with Quasar.
Testing components is working normally, but when I started to test my store, I got it.
spec file:
/test/jest/__tests__/store/auth/mutations.spec.js
import { store } from 'src/store';
import { mutations } from 'src/store/auth';
import mutations from 'src/store/auth/mutations';
All those ways I tried to import my store stuff, I got this error:
({"Object.<anonymous>":function(module,exports,require,__dirname,__filename,global,jest){import { store } from 'quasar/wrappers';
SyntaxError: Cannot use import statement outside a module
how can I import my store in my spec files?
import { store } from 'src/store';
import { mutations } from 'src/store/auth';
import mutations from 'src/store/auth/mutations';
just use require
const store = require('src/store');
const mutations = require('src/store/auth)';
const mutations = require('src/store/auth/mutations');
you need
type=module in package.json to use import
Your problem is that import statements are not supported by plain JavaScript, therefore neither by Node. import is an addition called ES Modules. Since Jest runs your tests in Node, you are getting SyntaxError since import { store } from 'quasar/wrappers' is invalid JS syntax.
The solution is that you need to tell Jest to use Babel (or similar tool) to transform your test file before trying to execute it in Node.
This requires some configuration in your jest.config.js, and also you'd need to install babel-jest, babel and related packages and create a .babelrc or babel.config.js to tell Babel what to do with your test files exactly.
The actual right configuration may depend on many factors, but as a starting point refer to these:
https://jestjs.io/docs/en/getting-started#using-babel
https://jestjs.io/docs/en/configuration#transform-objectstring-pathtotransformer--pathtotransformer-object
https://github.com/facebook/jest/tree/master/packages/babel-jest#setup
Also I'd recommend to consider using Quasar CLI, which gives you a handy way to automatically set up Jest for your Quasar project, including a simple example test you can use as a starting reference: https://testing.quasar.dev/

Is there any "ember-moment-shim" alternative for dayJS?

ember-moment-shim is an ember addon that generates the locales conditionally based on Moment.js and Moment-Timezone.
Any tools or processes to accomplish the same with just DayJs instead.
Ref: https://github.com/jasonmit/ember-cli-moment-shim
UPDATE:
I want to lazy load or dynamically load the dayJs locales based on the requirement. And every time you need to load a locale, you need to import it like
import fr from 'dayjs/locale/fr'
just that it would be a different locale every time and could change on refresh based on the settings from API response.
ember-auto-import throws following Error
Uncaught SyntaxError: Cannot use import statement outside a module*
Addons like ember-cli-moment-shim are no longer required to use libraries from NPM instead you can use them directly after installing ember-auto-import.
From the command line do:
ember install ember-auto-import
npm install dayjs
Then you can just import dayjs where you need it.
For example in a component:
//app/components/today.js
import dayjs from 'dayjs';
import Component from '#glimmer/component';
export default class TodayComponent extends Component {
today = dayjs().format();
}

How to use ES6 module in ember.js (with ember cli)?

Standard project set up with ember cli seems to be using ES6 modules when I generate controllers/routes/models etc. with the cli. Sometimes though I want to import/export an additional function/module ie. I may want to write a function that I use in the controller in a separate file.
When I try to import the function in the standard ES6 way ember-cli seems to have a problem with handling it.
Let's say I've created controller with:
ember g route tesit
then I create a function in app/routes/testit/logger.js
const logger = function(msg) {
console.log(msg);
};
export default logger;
and import it in my controller app/routes/testit.js:
import Ember from 'ember';
import logger from './testit/logger.js'
export default Ember.Route.extend({
beforeModel() {
logger('it works');
}
});
then I get the following error:
Error: Could not find module myproject/routes/testit/logger.js imported from myproject/routes/testit
How can I resolve it?
Remove .js extension from import logger from './testit/logger.js'; line.
See Description section from MDN.

Ember-cli addons and helpers

What is the correct way of placing your helper files and also where should they go with respect to the resolver finding them from an addon ember-cli project?
I am running ember-cli 0.2.2.
I generated an helper from an addon project with:
ember g helper display-helper
The generator placed the file in app/helpers which seemed wrong to me, I would have thought that it should have been placed in addon helpers. I moved the file to addon/helpers and it looks like this:
export default Ember.Handlebars.registerBoundHelper('displayHelper', function displayHelper(searchPath) {
return new Ember.Handlebars.SafeString(get(this, searchPath));
});
When I ran ember test I get the following output:
✘ Error: Assertion Failed: A helper named 'displayHelper' could not be
found
The only way I get this helper to be found by the resolver is to add an import that references the helper in a component that is using it like this:
import displayHelper from '../helpers/display-helper';
This does not seem correct, I would have thought the resolver would have found this automatically?
Also even if I have the reference, the following code ends up with the same error message as above:
import Ember from 'ember';
var get = Ember.get;
function displayHelper(context, searchPath) {
return new Ember.Handlebars.SafeString(get(context, searchPath));
}
export default Ember.Handlebars.makeBoundHelper(displayHelper);
So to sum up, I have to have this line in the component whose template uses the helper:
import displayHelper from '../helpers/display-helper';
And I have to use registerBoundHelper and not makeBoundHelper like the docs say or the helper cannot be found.
If you move your helper from app/helpers to addon/helpers, it is not available in your app namespace. To fix this, add the following file:
// app/helpers/display-helper.js
import displayHelper from 'your-addon-name/helpers/display-helper";
export default displayHelper;
(Do not copy your-addon-name literally, use the name of your addon, which is also your addon's namespace.)
This is based on the instructions here:
http://www.ember-cli.com/#addon-components
Just like the example component there, you can put your real helper code in addons/helpers/display-helper, but you need to import and reexport it to your app for your resolver to find it.

Import custom library in ember-cli

I have web app and Ember app in iframe. I want to import custom library from web app to ember app like global variable. Library look like object with function:
var helpers = {
helper1: function() {},
helper2: function() {}
};
Library working with sockets and will the same for both applications.
I wrote:
app.import("./../../../public/scripts/js-helpers.js"); //file located in web app
I can't access variable helpers in project and ember-cli copy folder public into their working folder. Sorry if question is stupid, I can't understand ember-cli import principles.
I'll propose one solution, which I find to be the easiest. You won't have globally scoped variables, but you use then ES6 module approach.
For example purposes, let's say you have a file under app_name/lib/ called helper.js. lib is a directory you create for holding your custom libraries. You don't have to use that name. Use the export default command as such:
export default {
helper1: function() {},
helper2: function() {}
};
Then, lets say you need this in a route. Here could be one such route:
import helper from 'app_name/lib/helper';
export default Ember.Route.extend({
model: function(){
helper.helper1();
}
helper is the name of what you imported, and represents the object that you exported in your helper.js. This method seems to be the style in which Ember-CLI suggests you should use