JS npm package, Cannot use import statement outside a module - javascript

I wanted to use this npm package https://github.com/nefe/number-precision, follow the steps but not working.
npm install number-precision --save--dep
import NP from 'number-precision' orrequire() on my JS file first-line , the error message will like this :
Cannot define require && export or
Cannot use import statement outside a module.
<script src="node_modules/number-precision/build/index.iife.js">import NP from 'number-precision </script>
It won't show any error message but in my js file, NP method still doesn't work.
<script src="/workout.js"></script> and put on my js file first-lineimport NP from 'number-
precision'
I got this:
refused to execute script from 'http://0.0.0.0:2000/node_modules/number-
precision/' because its MIME type ('text/html') is not executable, and strict MIME type
checking is enabled.
How do I correctly execute this npm package in my js file?

To use imports in the browser, the file that does the imports needs to
a) be included with type="module":
<script src="./workout.js" type="module"></script>
b) it only works for scripts that are remote (that is, have a src attribute), it does not work for inline scripts.
Also note that you cannot shorthand reference files from node_modules in the browser, that only works when run with Node.
So, inside your workout.js, start like this:
import 'https://github.com/nefe/number-precision/blob/master/build/index.iife.js';
Unfortunately, that library author does not seem to supply a true ES6 module version (I've just opened an issue on that), so you cannot proceed like the page suggests and import the script into a variable NP.
Executing the script like the import shown above should work for you, though, and expose the library in the global namespace.

If you want to use the standalone <script> tag, look at the content of the iife.js:
https://github.com/nefe/number-precision/blob/master/build/index.iife.js
var NP = (function (exports) {
'use strict';
// ...
return exports;
}({}));
It creates a global NP variable, so no importing is necessary, just put this first:
<script src="./index.iife.js"></script>
(change the src if needed, to the right path to your index.iife.js, however you want to structure it)
If you want to use this with Webpack, it works fine for me. After installing the package, import it in your entry point:
// src/index.js
import NP from 'number-precision'
console.log(NP.round(5, 5));
and then run Webpack to bundle the code:
npx webpack
and a working bundle will be produced in dist/main.js (or somewhere similar). Then link that bundle on your site.

Related

How to include a global file type declaration in a TypeScript (Node.js) package

I'm working on a package that I am planning to publish publicly on npmjs. Let's call it the "text package".
I would like that by default when installing that package, you can import .txt files directly and get the correct type (out of the box), like this:
import text from './file.txt'
The text variable would be of type string because the package would have defined its type, using something like this (in a global.d.ts):
declare module '*.txt' {
export const text: string;
export default text;
}
If I include that global.d.ts in my package, and that I import something from this package, then I will automatically get the correct type when importing a .txt file.
But the problem is sometimes I would just need to import a .txt file without importing anything from the "text package", which is why I was wondering if there is some sort of way, as you install a package to install a global type that does not require to import anything else for the type to apply.
In other words, as soon as you install my "txt package" the declare module '*.txt' would apply to my entire project out of the box.
Is there even a way to do this, or whoever installs my package would have to declare their own global type (e.g., declarations.d.ts) to be able to import .txt files globally?
I know that even if the import type works, it will still require Webpack or another bundler to really work but this question is just about the type.
The short answer is:
TypeScript does not support Global types without importing the file referring to the type.
More details:
One example that I found doing this was Next.js - when creating a TypeScript app using npx create-next-app#latest --typescript you can start importing *.css files (for example) and get the correct type.
Where I got confused is that I originally thought that the type was coming from the next-env.d.ts but even when I deleted the file, *.css import was still working in Visual Studio code. But the reason it was, is because a file in the pages directory were importing Next.js' index.d.ts file.
Basically, in Visual Studio Code, as soon as your import a type somewhere in your project, if it's global, it will be accessible everywhere.
Workaround
So what can be done with the current TypeScript capabilities? To support new file types, you will need a file loader such as Webpack. The logical thing to do would be to add a reference to the file type declaration in the file loader itself. This way, as soon as you configure your file loader to be able to import the file, you will inherit the type:
create a txt.d.ts in our package's source directory (e.g. src) - you can use any name for the file, it's not important
if you are using eslint, add an entry to ignore the type file (e.g. 'src/*.d.ts' in your ignorePatterns option
Since you are adding a d.ts file in your source that is not managed by tsc, you need to add a script that will perform the following actions:
Copy txt.d.ts in the target directory of the compiled files for your package
Add this line at the top of your package's file loader (e.g. loader/index.d.ts: /// <reference types="../txt" />\r\n - this will link the declaration file back into your package. Note that you can add this reference to any file of your package.
This workaround will only work once you import the file referencing back to the declaration - this is the only way TypeScript can be made aware that this type exists (see https://github.com/microsoft/TypeScript/issues/49124).
Another alternative could also be to add manual steps (in a readme file) to add a global type declaration file.
to bundle global types, do the following. form typescript
specify default typings directory at typeRoots. .e.g "typeRoots": ["./src/types"].
create a file /src/types/global.d.ts in the specified directory
declare your types in the file inside declare global {} and make sure to have export {} if you don't already export anything.

How do I import modules with JSX?

I am new to React. I have added it to a project using the information on this site:
https://reactjs.org/docs/add-react-to-a-website.html
Run npm init -y (if it fails, here’s a fix)
Run npm install babel-cli#6 babel-preset-react-app#3
Then,
npx babel --watch src --out-dir . --presets react-app/prod
Whenever I try adding a module it gives me:
Uncaught SyntaxError: Cannot use import statement outside a module.
Here is how I am importing :
import { PostcodeLookup } from "#ideal-postcodes/postcode-lookup"
(I've tried this at the top of my react js file and in a seperate script file called in a componentDidMount() method via:
const script = document.createElement("script");
script.src = "my_script.js";
script.async = true;
document.body.appendChild(script);
Thank you.
Where is the import React from 'react' statement, and how is that js file connected to your html? If you are linking the file containing this code from a <script> tag in your HTML, you need to give that script tag a type="module" attribute.
Notice how in the page you linked there's no reference to imports or exports.
Also how that page says:
Tip
We’re using npm here only to install the JSX preprocessor;
This means it will only process JSX expressions into React.createElement function calls. If you want to use modules, you will either need to use native modules by changing the type of your <script to module
<script type="module" src="./main.js">
or use a bundler.
To use a bundler, check out the next page of the React tutorials:
https://reactjs.org/docs/create-a-new-react-app.html
The steps you mentioned are for jsx setup. Can you paste complete error message ?
Have you installed React in your existing project ?
You perhaps have to install React to make it work.
With export class Arrow... you have to use import {Arrow}... whereas with export default class Arrow... you have to use import Arrow.... In the former case, there might be multiple export... statements in a file and therefore your import statement has to be able to handle importing multiple variables by placing that potential list of variables in braces. With export default... there can be only a single export from that file and therefore the import statement can confidently assert that it is importing a single variable, i.e. import myVariabl

ASP .Net Core 3.1 octokit rest npm package issues

I use npm and a gulpfile.js to essentially export npm packages to a 'lib' folder under 'wwwroot'; this works a treat and whenever I update a specific npm package if it's in my gulpfile.js watch list it'll push the contents to the 'lib' folder.
The issue I have is that I used to use a manually extracted copy of ocktokit-rest in order to query the public api for some repo data. Recently this has stopped working, I assume that GitHub has updated their api which has had some breaking changes for my old version of ocktokit-rest. So with that in mind I installed #Ocktokit/rest version 18.0.9 using the npm package.json. This then creates the following directory:
~/lib/#octokit/rest/
According to the docs I need to refence one of the index.js files inside this. So because Razor doesn't appreciate the use of the # symbol in the path I use the following in my _layout.cshtml
<script src="#Url.Content("~/lib/#octokit/rest/dist-src/index.js")" type="module"></script>
I added the type="module" as I was initially getting some issues with the import statements inside of the index.js file.
Here's the index.js file contents at the above route:
import { Octokit as Core } from "#octokit/core";
import { requestLog } from "#octokit/plugin-request-log";
import { paginateRest } from "#octokit/plugin-paginate-rest";
import { restEndpointMethods } from "#octokit/plugin-rest-endpoint-methods";
import { VERSION } from "./version";
export const Octokit = Core.plugin(requestLog, restEndpointMethods, paginateRest).defaults({
userAgent: `octokit-rest.js/${VERSION}`,
});
This then raises the following error in the chrome debugger:
Uncaught TypeError: Failed to resolve module specifier
"#octokit/core". Relative references must start with either "/", "./",
or "../".
I don't particularly like the idea of adjusting the #octokit/ reference in favour of '../../' because then every time my gulpfile.js npm push task runs I'll have to manually change this file. However for the sake of debugging this I went through and adjusted index.js to look like this:
import { Octokit as Core } from "../../core";
import { requestLog } from "../../plugin-request-log";
import { paginateRest } from "../../plugin-paginate-rest";
import { restEndpointMethods } from "../../plugin-rest-endpoint-methods";
import { VERSION } from "./version";
export const Octokit = Core.plugin(requestLog, restEndpointMethods, paginateRest).defaults({
userAgent: `octokit-rest.js/${VERSION}`,
});
When I did this I got similar error messages for each import that looked something like this:
index.js:4 GET
https://localhost:44364/lib/#octokit/plugin-rest-endpoint-methods
net::ERR_ABORTED 404
Now the above URL is pointed at the directory not a specific file, if I run the above through to a single file I can see it load in the browser and display the file. So If I type:
https://localhost:44364/lib/#octokit/plugin-rest-endpoint-methods/dist-src/endpoints-to-methods.js
I can see the js file displayed in the browser so I know it can be pathed to. Now Ideally I want to be able to use this package in another bit of custom js I wrote that iterates through my repos and creates nice little cards with all the info on, so I'm basically just trying to use it like this:
var octokit = new Octokit({ userAgent: 'agentName' });
But obviously the above is complaining about the existence of Octokit.
So I guess my question is, what the frack? I'm obviously missing something here so if anyone has any ideas in what direction I need to look or research I'd be very grateful.
It's probably nothing to do with the octokit package at all, and much more likely that I just don't understand how to properly import these types of JavaScript libraries into my asp .net core solution
There's a few parts of adding Octokit that you're having difficulties with: handling the # symbol, the scope at which you import it, and the fact that you're trying to use files intended for build tools.
# in a Razor Page
When you're writing JavaScript inline in a <script> tag inside the context of a Razor page, you'll need to escape the # character by using ##. For example, if you were referencing the Octokit path, you would write ##octokit/rest.
Scope
When you're using type=module, your code has module scope, making you unable to reference the Octokit variable outside of the module. In order to break out of module scope, you can attach the Octokit variable to the window object:
window.Octokit = new Octokit({ userAgent: 'agentName' });
Then later on, your code in other script blocks can access Octokit like normal:
const { data } = await Octokit.request("/user");
Building Octokit
The files you're importing are not intended for direct consumption by the browser. It's expecting you to be importing it into JavaScript build tools, not importing it as a module directly from the browser.
The index.js file you're trying to import client side is intended to be used with some JavaScript build tools like Webpack. To get this working the way you want to in gulp, you would need to modify your gulpfile.js to include some kind of a plugin that would import #octocat/rest and output it into a file usable by a browser.
To do this with Webpack, you need to install a Webpack plugin for gulp:
npm install --save-dev webpack-stream gulp-rename
Then, create a file next to your gulpfile.js called index.js that imports the library and does something with it:
import { Octokit } from "#octokit/rest"
window.Octokit = new Octokit({ userAgent: 'agentName' });
Now, modify your gulpfile.js to take index.js and pipe it through the webpack plugin:
const gulp = require('gulp');
const webpack = require('webpack-stream');
const rename = require('gulp-rename');
gulp.task('default', () =>
gulp.src(['index.js'])
.pipe(webpack())
.pipe(rename("index.js"))
.pipe(gulp.dest('lib/octokit/rest/'))
);
After running gulp, you should have an output file that has resolved all of the dependencies necessary for #octokit/rest!
Alternative Solutions
To save the trouble for this specific package, could you instead load Octokit from their CDN? The CDN handles all of the building and package resolution for you. Your code could then be:
<script type="module">
import { Octokit } from "https://cdn.skypack.dev/##octokit/rest";
window.Octokit = new Octokit({ userAgent: 'agentName' });
</script>
(Note that ## will escape the # sign on Razor pages.)
Most packages offer a CDN option for loading their library client side without having to mess around with build tools. Even if they don't officially offer a CDN, sites like jsdelivr or unpkg can still offer a way to import these files.
Sometime in the future, it looks like browsers might support import-maps. Then, you would be able to handle the package resolution through the browser and do something like this on your Razor page:
<script type="importmap">
{
"imports": {
"/##octokit": "/lib/##octokit/"
}
}
</script>
<script type="module">
import { Octokit } from '##octokit/rest';
var octokit = new Octokit({ userAgent: 'agentName' });
</script>
It looks like this might be usable with a polyfill like system-js, where you would add the s.js loader and replace importmap with systemjs-importmap.

Unexpected syntax error unexpected string when referencing JS from HTML?

Alright, I downloaded this off Github trying to run it locally/modify it. https://tympanus.net/Tutorials/InteractiveRepulsionEffect/interactive-repulsive-effect.zip
The main index.html calls the JS in with: <script type="text/javascript" src="app.0ffbaba978f8a0c5e2d0.js"></script> which seems to be a minified version of app.js which I want to modify.
File structure looks like:
I changed the html to: <script type="text/javascript" src="../src/scripts/app.js"></script> which is the correct filepath to the JS that makes the scene, but I then get
Uncaught SyntaxError: Unexpected string
on line 1 of app.js which is:
import 'styles/index.scss';
import Cone from './elements/cone';
import Box from './elements/box';
import Tourus from './elements/tourus';
I tried changing this path, it doesn't matter. It just doesn't "like" the line. What is going on here? How can I reference the editable JS file?
You can't. The JavaScript code you've got isn't ready to be run in a browser.
Those public/app.xxxxxxxxxx.js files are what's ready to run in a browser, and they're likely compiled by Webpack (or something similar). Your repository has some sort of "build" process in place - chances are you can look at the scripts section of package.json to see the available build commands.
Exactly, you have to place yourself in the first-demo folder and modify your app js. Then run
npm install
to install webpack and any missing packages (just once). Then you can run
npm run build
and it will rebuild your public folder with your changes. Better yet, you can just
npm run start
and you will see a hot reload of your changes when you modify app.js in
http://localhost:9000

How do I properly load the lit-html module in Electron

I'm trying to use lit-html to save my self some time, but I'm having trouble getting everything set up correctly.
Electron 4.1.1
Node 11.15
As of 5 minutes before posting this, I've run npm install and electron-rebuild, no luck.
I use require() as one would with any other NPM package
var render = require('lit-html').render
var html = require('lit-html').html
console.log(require("lit-html"))
Unfortunately, I'm greeted with this error
In reference to the three lines of code above.
I don't see any problems with my code.
I've tried reinstalling lit-html through NPM to no avail. I would really love to use this library, but first I have to get over this hurdle. If I'm being honest, I don't know if this error is reproducible, but nothing I do seems to fix it. The problem seems to lie with node and the way that imports are handled.
Am I missing something here? Is this a common issue? If so, what can I do to fix it?
You need to transpile lit-html before you can require it
I tested require('lit-html') and I was greeted with this error:
/home/chbphone55/Workspace/test/node_modules/lit-html/lit-html.js:31
import { defaultTemplateProcessor } from './lib/default-template-processor.js';
It clearly states that the error is coming from lit-html/lit-html.js:31 where the line uses ES Module import syntax.
You can transpile it using tools like Babel or similar ones. However, you may want to try using ES Module syntax so you can import lit-html without transpiling it.
Example:
<!-- HTML File -->
<script type="module" src="index.js"></script>
// index.js
import { html } from 'lit-html';
What if you can't use type="module"
If you are unable to use the type="module" method above, you can also use the ESM package.
ESM is a brilliantly simple, babel-less, bundle-less ECMAScript module loader.
Here are a few examples of how to use it:
Using the node require flag (-r) to load esm before everything else
node -r esm index.js
Loading esm in your main file then loading the rest of your code.
// Set options as a parameter, environment variable, or rc file.
require = require('esm')(module/*, options*/)
module.exports = require('./main.js')

Categories

Resources