Is it possible to load an aliased module? - module

I have a module "default/foo/bar" and a module "agency/foo/bar". I setup an alias to load the agency module instead of the default module. Yet I still want "agency/foo/bar" to load "default/foo/bar" but that's not possible because of the alias. Is there a way to accomplish this?
Here's actual snippets:
aliases: [
["gis/ol/config", "agency/ol/config"],
["aliased/gis/config", "gis/ol/config"]
],
Try to load the original module but it doesn't work..config is an Object:
define(["aliased/gis/config"], function (config) { // config is an object });

I find that using map instead of aliases is much clearer and easier to understand:
map: {
'*': {
'gis/ol/config': 'agency/ol/config'
},
'agency/ol/config': {
'gis/ol/config': 'gis/ol/config'
}
}
This configuration causes all modules to load 'agency/ol/config' in place of 'gis/ol/config', except for 'agency/ol/config' which will load 'gis/ol/config' as 'gis/ol/config'.

Related

Translations Service

I'm looking for a solution/idea to dynamically change the translation value of each key in Sparatcus translations files outside the code. I don't want only to create a file and override the I18nModule config, I'm looking for some kind of service/API like Lokalize API to be able to change the translation values outside the code.
Thanks in advance!
The internationalisation features are prepared for this. Although we do not have a service at hand for the localised labels, Spartacus is prepared for this. You can read more about this at https://sap.github.io/spartacus-docs/i18n/#lazy-loading. You can configure loadPath to an API endpoint, including the variable language (lng) and namespace (ns).
imports: [
B2cStorefrontModule.withConfig({
i18n: {
backend: {
loadPath: 'assets/i18n-assets/{{lng}}/{{ns}}.json'
// crossOrigin: true (use this option when i18n assets come from a different domain)
},
chunks: translationChunksConfig
}
})
];

Aurelia library js file in Bundle but is resolved as static file

My project structure is as follows:
src
..lib
....someLibrary.js
bundles.js:
"bundles": {
"dist/app-build": {
"includes": [
"[**/*.js]",
"**/*.html!text",
"**/*.css!text"
],
"options": {
"sourceMaps": 'inline'
"inject": true,
"minify": true,
"depCache": true,
"rev": true
}
},
The project builds fine, but when I check app-build.js I don't find a definition for lib/someLibrary.js. I am using typescript for my own project so I assume this has something to do with that, how can I mix regular js files and output from my transpiled TS files into the same app-build bundle?
Update
So I tried to split the 'build-system' gulp task into two tasks: 'build-typescript' which is the same as 'build-system' was before, then I created 'build-libs' which looks like so:
gulp.task('build-libs', function() {
return gulp.src(paths.root + '**/*.js')
.pipe(plumber({errorHandler: notify.onError('Error: <%= error.message %>')}))
.pipe(changed(paths.output, {extension: '.js'}))
.pipe(sourcemaps.write('.', { includeContent: false, sourceRoot: '/src' }).on('error', gutil.log))
.pipe(gulp.dest(paths.output));
});
I then added to my dist/app-build bundle config: "lib/someLibrary.min.js"
And now my app-build.js does have the library defined, however when I try to use the library in one of my views using:
<require from="lib/someLibrary.min.js">
I get an error:
Failed to load resource: the server responded with a status of 404 (Static File '/dist/lib/someLibrary.min.html' not found)
What?!?? Why is it looking for html when nowhere is html ever involved in this whole scenario? Why is something that should be easy this hard?
Update2
So apparently 'require' does not work with javascript files. I changed to use the 'script' tag, however it seems these get stripped out when rendered by Aurelia. I am at a loss as to how to get Aurelia to do what I want it to.
Ok so after much frustration and disbelief at how hard something so simple could be, in addition to the changes to the build tasks mentioned above (which includes the javascript library file that has no npm/jspm package into the app-bundle) I created a modified version of this solution which looks as follows:
import { bindable, bindingMode, customElement, noView } from 'aurelia-framework';
#noView()
#customElement('scriptinjector')
export class ScriptInjector {
#bindable public url;
#bindable public isLocal;
#bindable public isAsync;
#bindable({ defaultBindingMode: bindingMode.oneWay }) protected scripttag;
public attached() {
if (this.url) {
this.scripttag = document.createElement('script');
if (this.isAsync) {
this.scripttag.async = true;
}
if (this.isLocal) {
const code = 'System.import(\'' + this.url + '\').then(null, console.error.bind(console));';
this.scripttag.text = code;
} else {
this.scripttag.setAttribute('src', this.url);
}
document.body.appendChild(this.scripttag);
}
}
public detached() {
if (this.scripttag) {
this.scripttag.remove();
}
}
}
To use it, simply add the following tag to the view where you want the script library to be used as follows:
<scriptinjector url="lib/bootstrap-toc.js" is-local.bind='true'></scriptinjector>
This will keep the original scriptinjector functionality which allows you to add remote 3rd party libraries to your Aurelia app but it will also allow you to load any local 3rd party libraries that you have bundled with your app.
Hope this helps someone.

TypeScript 2 TSX preserve and noimplicitany error TS2602: the global type 'JSX.Element' does not exist

I'm using TypeScript 2 and TSX with the preserve (not React) setting and with "noImplicitAny" enabled:
"noImplicitAny": true,
"jsx": "preserve"
The problem is, I keep getting this error when trying to build a simple TSX file:
error TS2602: JSX element implicitly has type 'any' because the global type 'JSX.Element' does not exist.
Here's an example of my TSX file:
'use strict';
import m from './m';
export default {
view() {
return (
<h1>Hello Mithril!</h1>
);
}
};
I'm trying to get TSX working with a non-React stack (Mithril). Thanks in advance!
Answer to original question: (how to solve the TS2602 error)
This is quite simple, as explained here:
As the errors say: "because the global type 'JSX.Element' does not exist"
you can define those types:
declare namespace JSX {
interface Element { }
interface IntrinsicElements { div: any; }
}
I recommend getting the react-jsx.d.ts file from DefinitelyTyped
You can use this file as a source for more complete typings (you'll need definitions for every sub-element in IntrinsicElements, i.e. div, p, a, etc.)
Getting farther with TSX and Mithril:
Once you've solved the typing issues, you'll find that you're not quite there. If you use the "jsx": "preserve" setting, the HTML code will be written directly in the generated js file, without any translation. This of course can't be loaded by a web browser (because it's a javascript file, not an html file).
I think there are two ways to make it work:
First solution that comes to mind is to use "jsx":"react" and write a small wrapper that will forward the calls to mithril, like this:
class React {
public static createElement(selector: string, attributes: object, ...children: Mithril.Child[]): Mithril.Child {
return m(selector, attributes, children);
}
}
This is the solution I'm currently using because it doesn't involve additional tools.
The other solution is to keep "jsx":"preserve" and use Babel, as described in mithril documentation, to translate the jsx file (which is generated by typescript from the tsx file) to a valid js file.
In the end, I've managed to make it work, but I found the process quite messy, with typescript/npm module system getting in the way to have JSX types extend Mithril types (so that your functions can return mithril-compatible types), etc. I had to modify the mithril typings (and drop npm #types/mithril), and add a few modules of my own.
I'm interested to know if someone solved this problem in an elegant and simple way!
Due to the lack of reputation it won't let me comment on youen's answer above so I'll include this in an answer of my own.
First of all, you can include this gist at the top of your project and name it something like mithril-jsx.d.ts so that typescript will see it as a type definition and won't compile it. The linked gist simply declares JSX.element as m.Vnode<any, any> and lists every HTML element under JSX.IntrinsicElements as any. Not a huge deal but a time saver.
Second, and the reason I'm even posting this: You do not need gulp or any other tool to compile .tsx files to mithril-using .js ones. All you have to do is specify these in your tsconfig.json
{
"compilerOptions": {
//...your other stuff here
"jsx": "react",
"jsxFactory": "m"
}
}
More information about the compiler options here: http://www.typescriptlang.org/docs/handbook/compiler-options.html
I am also developing with Mithril(2.0.3) and TypeScript(3.5.3).
TS7026: JSX element implicitly has type 'any' because no interface 'JSX.IntrinsicElements' exists.
This error message can be resolved by installing #types/react.
npm install --save-dev #types/react
tsconfig.json has the following settings.
{
"compilerOptions": {
"jsx": "react",
"jsxFactory": "m"
}
}

intern.js How to test legacy non modular code

I'm using intern.js as a test framework to test dojo modules and it works well.
Now I have to test some non modular legacy code but I can't.
This is an example of a simple file to test:
var Component = function() {
this.itWorks = function() {
return true;
}
};
And this is the test
define([
'intern!object',
'intern/chai!assert',
'intern/order!controls/component',
], function (registerSuite, assert) {
registerSuite({
name: 'test legacy code',
'simple test': function () {
console.log(Component);
}
});
});
The test fails sayng that "Component is not defined".
I've notice that it works only if I write
window.Component = Component
At the bottom of file to test.
I can't modify all the file to test, is it possible to test the file in a different way?
This should work fine. One possible issue is where you're loading component from. The 'controls/component' dependency in 'intern/order!controls/component' is, barring any special loader config, relative to the file doing the loading. That means that if the project is setup like this:
project/
controls/
component.js
tests/
intern.js
componentTest.js
and component is being loaded from componentTest.js, then the dependency should be 'intern/order!../controls/component.js'. (It will actually work without the '../' in this case since controls is a top level directory in the project.)
Another potential issue is that a non-AMD identifier should use the .js suffix. This tells the loader that the thing being loaded is a generic script rather than an AMD module.
Also note that the order plugin is only needed to load multiple legacy files in a specific order. If order doesn't matter, or you're just loading one script, you can just use the script itself '../controls/component.js' as the dependency.
<"/"https://stackoverflow.com/tags" term="legacy" /">
<"/!-- begin snippet: js hide: false console: true babel: false --"/">
"var Component" = function() {
"this.itWorks" = function() {
return=true;
}
};
<"/"!-- end snippet --"/">

Dojo amd loading cross-domain modules at runtime

I want to load Dojo1.9 amd modules from an ad-hoc server on the www, but I won't know from where until runtime (with url params).
In essence, I want to do the equivalent of this:
require(['http://www.foo.com/SomeRandomModule'], function( SomeRandomModule ) {
// use SomeRandomModule
});
Quick and dirty way
Might have some unexpected quirks when it comes to the module system and relative paths, I haven't used it enough to say:
require([ "//host/myext/mod1/mod2.js" ],function(mod2){
// If current webpage is http:// or https:// or file://
// it tries to use the same protocol
});
Better way
Configure require() to treat all modules that start with a certain package name (e.g. foo) as coming from a particular URL. From your starter page, something like:
<script src="dojo/dojo.js"
data-dojo-config="packages:[{name:'myext',location:'//host/js/myext'}], async: 1, >
</script>
This lets you vastly improve your first example to:
require([ "myext/mod1/mod2" ],function(mod2){
});
If you are using a Dojo Bootstrap installation instead, you can avoid touching your data-dojo-config and instead put it inside the run.js startup file:
require({
baseUrl: '',
packages: [
'dojo',
'dijit',
'dojox',
'myapp',
{ name: 'myext', location: '//host/js/myext', map: {} }
]
}, [ 'myapp' ]);