How to conditional exports from package.json - javascript

I have section exports in my package.json:
"exports": {
"import": "./dist/a.es.js",
"require": "./dist/b.umd.js"
},
But for development, I would like to have different path:
"exports": {
"DEV": {
"import": "./src/a.es.js", // <---------- SRC
"require": "./src/b.umd.js" , // <---------- SRC
},
"PROD": {
"import": "./dist/a.es.js",
"require": "./dist/b.umd.js"
}
},
Is there any way how to use some env variable?

I was able to solve this using this setup
In the package that my program imports:
{
"name": "my-special-node-package",
"version": "1.0.0",
"license": "MIT",
"exports": {
".": {
"production": {
"require": "./prod/index.cjs.js",
"import": "./prod/index.esm.js"
},
"default": {
"require": "./index.cjs.js",
"import": "./index.esm.js"
}
},
}
}
And then in my program:
// index.js
const myPkg = require('my-special-node-package')
On production I use node --conditions=production index.js to execute the node program. Otherwise I use node index.js in dev mode.
Also, since I'm using TypeScript and since TypeScript is only really used during development time, I was able to change the default require/import values to point to a index.ts file.
{
// ....
"exports": {
".": {
"production": {
"require": "./dist/index.cjs.js",
"import": "./dist/index.esm.js"
},
"default": "./index.ts"
},
}
}
This setup allows for my local development to always TS files directly and not rely on each package to be built whenever it changes.

Related

I can't access/find my exports when using my npm package

I am currently working on a web app using next js and I want to import an npm package I wrote a few months ago but the import does not work because my imports are undefined. The package only contains an bundle.js and I wonder if this could be the cause.
This package is written in Typescript and transpiled into Javascript using Webpack and ts-loader.
All my exports are like export default foo or export foo. I have 2 objects exported in this package Patient and Doctor.
Here is how I have been trying to import them
import SkopAPI from "skop-api"
I get this error when I try to use the package after this import.
screenshot of the error
or
import {Patient} from "skop-api"
or again
import Patient from "skop-api"
The error is different in this case Screenshot of the 2nd error
This is my index.js file
import Doctor from './Doctor';
import Patient from './Patient';
export {Doctor, Patient};
Here is the npm package webpack configuration
module.exports = {
entry: './src/index.ts',
mode: 'development',
target: "web",
resolve: {
extensions: ['.ts','.js'],
},
module: {
rules: [{
test: /\.ts$/,
use: [
'ts-loader',
]
}],
},
output: {
filename: 'SkopAPI.js',
path: path.resolve(__dirname, 'dist'),
path: path.resolve(__dirname, 'demo'),
library:{
name: 'SkopAPI',
type: 'umd',
},
globalObject: 'this',
},
};
Package.json
{
"name": "skop-api",
"version": "1.1.8",
"description": "API for the Skop",
"main": "dist/SkopAPI.js",
"files": [
"dist"
],
"license": "CC BY-NC-ND 4.0",
"keywords": [
"api",
"skop",
"health api",
"health",
"WeMed"
],
"author": "Ben Gregory",
"repository": {
"type": "git",
"url": "https://github.com/BenGregory23/SKOP-API-documentation.git"
},
"homepage": "https://github.com/BenGregory23/SKOP-API-documentation#readme",
"scripts": {
"build": "webpack"
},
"dependencies": {
"#opentok/client": "^2.22.1",
"#tensorflow-models/blazeface": "^0.0.7",
"#tensorflow/tfjs-backend-webgl": "^3.18.0",
"#tensorflow/tfjs-core": "^3.18.0",
"axios": "^0.27.2",
"base64url": "^3.0.1",
"sweetalert2": "^11.4.10"
},
"devDependencies": {
"ts-loader": "^9.3.0",
"typescript": "^4.7.3",
"webpack": "^5.72.0",
"webpack-cli": "^4.9.2",
"concurrently": "^6.2.1"
}
}
I tried to add to my package the code in javascript and not only the bundle named SkopAPI.js but Patient and Doctor objects were still undefined.
Code to reproduce
import {Patient} from "skop-api"
export default foo(){
const key = "key123";
const room = 995;
Patient.init(key, room);
}
As I understand your problem, you have 2 differents projects (=2 package.json) :
your skop-api project, exporting items
your "client project", importing functions you describe in skop-api
How are you importing skop-api in your client ?
you should have something like this in your client's package.json
"dependencies":{
"skop-api": "file:../path/to/skop-api/bundle.js"
...
}

How to run mocha in the same file with the JS script

Is it possible to have the JS code and the mocha tests in the same file? The purpose will be to have both the implementation and the tests in the same file when you just want to play with something, learn JS, prepare for an interview, etc.
The file will be executed in VSCode using Debug (F5).
function increment(n) {
return n + 1;
}
mocha.setup("bdd");
const { assert } = chai;
describe('Array', function () {
describe('#indexOf()', function () {
it('should increment', function () {
assert.equal(increment(1), 2);
});
});
});
mocha.run();
Trying to run this example which is how you run mocha tests in browser, I get an error "mocha is not defined"
I ran "npm install --save-dev mocha" and "npm install --save-dev chai".
The file is test1.js.
In app.js I have "require("./test1")".
The launch configuration is:
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Launch Program",
"program": "${workspaceFolder}/app.js",
"request": "launch",
"skipFiles": [
"<node_internals>/**"
],
"type": "pwa-node"
}
]
}
After more googling I found the solution, your Debug launch.json file have to have the below configuration. Basically the program you need to launch is "${workspaceFolder}/node_modules/mocha/bin/_mocha".
You do not need any mocha commands in your JS file: mocha.setup("bdd"); mocha.run();
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Mocha Tests",
"type": "pwa-node",
"request": "launch",
"program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
"args": [
"-u",
"bdd",
"--timeout",
"999999",
"--colors",
"${workspaceFolder}/thon-ly-40-questions"
],
"skipFiles": [
"<node_internals>/**"
],
},
]
}

TypeScript cannot find namespace

I am trying to create a web game using webGL, TypeScript and node.
I have a file structure that currently looks like this
> node_modules
> src
engine.ts
webgl.ts
index.ts
index.html
package.json
engine.ts looks like this:
namespace EngineSpace {
export class Engine {
// ....
}
}
and webgl.js:
namespace EngineSpace {
export class WebGLUtil {
// ....
}
}
and index.js
window.onload = function() {
let engine = new EngineSpace.Engine();
engine.start();
}
However when I run npm start, I get that src/index.ts:5:22 - error TS2304: Cannot find name 'EngineSpace'..
I am not sure why it cannot resolve this namespace. Given that I am trying to create a game, how should I have this set up / what would be best practices?
below is the package.json: file
{
"name": "typescript-engine",
"version": "1.0.0",
"description": "",
"main": "app.js",
"scripts": {
"start": "npm run build:live",
"build": "tsc -p .",
"build:live": "nodemon --watch 'src/**/*.ts' --exec 'ts-node' src/index.ts"
},
"repository": {
"type": "git",
"url": ""
},
"keywords": [],
"author": "",
"license": "ISC",
"bugs": {
"url": ""
},
"homepage": "",
"devDependencies": {
"#types/node": "^12.11.1",
"nodemon": "^1.19.4",
"ts-node": "^8.4.1",
"typescript": "^3.6.4"
}
}
here is the tsconfig:
{
"compilerOptions": {
"target": "es5",
"module": "commonjs",
"lib": ["es6","dom"],
"outDir": "lib",
"rootDir": "src",
"strict": false,
"esModuleInterop": true,
"resolveJsonModule": true
}
}
If you want to use namespace in nodejs side you need to export it also to use it in another module. Becuase namespace will be converted like this
engine.ts
namespace EngineSpace {
export class Engine {
public start() {
console.log('hello');
}
}
}
enigne.js
var EngineSpace;
(function (EngineSpace) {
class Engine {
start() {
console.log('hello');
}
}
EngineSpace.Engine = Engine;
})(EngineSpace || (EngineSpace = {}));
And if you want to use some property of another module in nodejs you need to export it and need to require it in another module.
Refer this for nodejs namespace
For the browser setup with typescript please refer this
Hope it helps you

Strange Unresolved dependencies to 'vscode' when wrapping monaco-editor and monaco-languageclient as a react component

I need to create a React component that integrates Microsoft's Monaco editor and monaco-languageclient from TypeFox. The goal is for this component to be able to communicate with a language server via the language server protocol.
import React, { useEffect, useRef, useState } from 'react'
import * as monaco from 'monaco-editor/esm/vs/editor/editor.api';
import _ from 'lodash'
import { listen } from 'vscode-ws-jsonrpc';
import {
CloseAction,
createConnection,
ErrorAction,
MonacoLanguageClient,
MonacoServices
} from 'monaco-languageclient';
import normalizeUrl from 'normalize-url';
import ReconnectingWebSocket from 'reconnecting-websocket';
function createLanguageClient(connection) {
return new MonacoLanguageClient({
name: "Sample Language Client",
clientOptions: {
// use a language id as a document selector
documentSelector: [ 'json' ],
// disable the default error handler
errorHandler: {
error: () => ErrorAction.Continue,
closed: () => CloseAction.DoNotRestart
}
},
// create a language client connection from the JSON RPC connection on demand
connectionProvider: {
get: (errorHandler, closeHandler) => {
return Promise.resolve(createConnection(connection, errorHandler, closeHandler))
}
}
});
}
function createUrl(path) {
// const protocol = 'ws';
return normalizeUrl("ws://localhost:3000/sampleServer")
// return normalizeUrl(`${protocol}://${location.host}${location.pathname}${path}`);
}
function createWebSocket(url) {
const socketOptions = {
maxReconnectionDelay: 10000,
minReconnectionDelay: 1000,
reconnectionDelayGrowFactor: 1.3,
connectionTimeout: 10000,
maxRetries: Infinity,
debug: false
};
return new ReconnectingWebSocket(url, undefined, socketOptions);
}
const ReactMonacoEditor = ({ initialText, ...props }) => {
let localRef = useRef(null)
const [ value, setValue ] = useState(initialText)
useEffect(() => {
monaco.languages.register({
id: 'json',
extensions: [ '.json', '.bowerrc', '.jshintrc', '.jscsrc', '.eslintrc', '.babelrc' ],
aliases: [ 'JSON', 'json' ],
mimetypes: [ 'application/json' ],
});
const model = monaco.editor.createModel(value, 'json', monaco.Uri.parse('inmemory://model.json'))
const editor = monaco.editor.create(localRef.current, {
model,
glyphMargin: true,
lightbulb: {
enabled: true
}
});
editor.onDidChangeModelContent(_.debounce(e => {
setValue(editor.getValue())
}, 100))
MonacoServices.install(editor);
// create the web socket
const url = createUrl('/sampleSer ver')
const webSocket = createWebSocket(url);
// listen when the web socket is opened
listen({
webSocket,
onConnection: connection => {
// create and start the language client
const languageClient = createLanguageClient(connection);
const disposable = languageClient.start();
connection.onClose(() => disposable.dispose());
}
});
return () => editor.dispose()
}, [])
return (
<div ref={localRef} style={{ width: 800, height: 600 }}/>
)
}
export default ReactMonacoEditor
package.json
{
"name": "prima-monaco",
"version": "0.1.0",
"author": "sosa corp",
"publisher": "sosacorp",
"private": true,
"engines": {
"vscode": "^1.1.18"
},
"dependencies": {
"lodash": "^4.17.11",
"monaco-editor": "^0.17.0",
"monaco-languageclient": "^0.9.0",
"normalize-url": "^4.3.0",
"react": "^16.8.6",
"react-dom": "^16.8.6",
"react-scripts": "3.0.1",
"reconnecting-websocket": "^4.1.10",
"vscode-ws-jsonrpc": "^0.0.3"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
I am expecting the component to render. Instead I am getting
Failed to compile.
./node_modules/vscode-base-languageclient/lib/workspaceFolders.js
Module not found: Can't resolve 'vscode' in '.../node_modules/vscode-base-languageclient/lib'
Waiting for the debugger to disconnect...
Not sure how to proceed.
I was struggeling with the same problem for hours. Eventually I found the following remark in the changelog of the monaco-languageclient:
vscode-compatibility should be used as an implementation of vscode module at runtime.
To adjust module resolution with webpack:
resolve: {
alias: {
'vscode': require.resolve('monaco-languageclient/lib/vscode-compatibility')
}
}
After adding that alias to my webpack config (in my case quasar.conf), the compilation succeeded.
So in fact the monaco-languageclient is not dependent on the vscode module as the error messages suggest, instead a compatibility-stub inside ot the package itself should be used.
It looks like monaco-languageclient has a dependency issue with vscode-base-languageclient, but it's not clear how to solve it. I set up a project with a similar package.json to yours, the issue is specifically with monaco-languageclient (if you comment out that import it compiles fine) Here's the closest issue I could find: https://github.com/theia-ide/theia/issues/2589#issuecomment-414035697
It looks like you built your project with create-react-app, which doesn't have a tsconfig by default. You may be able to add one, or you could set up a new app with create-react-app your-project --typescript to set up a typescript app. You can try the skipLibCheck option he describes, hope it helps!
Add extra-webpack.config.js with following code
module.exports = {
"resolve": {
"alias": {
'vscode': require.resolve('monaco-languageclient/lib/vscode-compatibility')
}
},
"node": {
"fs": "empty",
"global": true,
"crypto": "empty",
"tls": "empty",
"net": "empty",
"process": true,
"module": false,
"clearImmediate": false,
"setImmediate": true
},
}
Edit package.json
"serve": {
"builder": "#angular-builders/custom-webpack:dev-server",
"options": {
"browserTarget": "angular-monaco-languageclient:build"
},
"configurations": {
"production": {
"browserTarget": "angular-monaco-languageclient:build:production"
}
}
},
it will remove the errors

How to use JSPM overrides in SystemJS config file?

My JSPM version: 0.17.0-beta.5.
My project is using ES6 style import statement using TypeScript.
So...
I installed angular-ui-router like so:
jspm install angular-ui-router
This saves the following lines to my package.json:
"jspm" {
"overrides": {
"github:angular-ui/ui-router#0.2.17": {
"directories": {
"lib": "release"
},
"format": "cjs",
"main": "angular-ui-router",
"registry": "jspm",
"dependencies": {
"angular": "^1.3.2"
},
"meta": {
"angular-ui-router.js": {
"deps": [
"angular"
]
}
}
},
// ... other stuff
Great! So it says the file that should be loaded is located in the release folder.
But in my browser, I load my jspm.conf.js file, which says:
SystemJS.config({
"packages": {
"github:angular-ui/ui-router#0.2.17": {
"map": {
"angular": "github:angular/bower-angular#1.4.9"
}
},
}
// ... little further
"map": {
"angular-ui-router": "github:angular-ui/ui-router#0.2.17"
}
So there is no notion there that SystemJS should look in the release folder as I mentioned above. Therefor, I can't import like
import 'angular-ui-router'
but only like
import angular-ui-router/release/angular-ui-router
How do I use the overrides from package.json in my SystemJS config file jspm.config.js which is loaded in the browser?

Categories

Resources