Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/muhammad-salem/esmpack
esmpack, transform javascript files to es module that can be imported by browser.
https://github.com/muhammad-salem/esmpack
esm esmodules esmpack js nodejs ts
Last synced: about 2 months ago
JSON representation
esmpack, transform javascript files to es module that can be imported by browser.
- Host: GitHub
- URL: https://github.com/muhammad-salem/esmpack
- Owner: muhammad-salem
- License: mit
- Created: 2020-09-24T06:00:39.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2023-12-21T22:15:10.000Z (about 1 year ago)
- Last Synced: 2024-11-09T21:11:17.808Z (about 2 months ago)
- Topics: esm, esmodules, esmpack, js, nodejs, ts
- Language: TypeScript
- Homepage:
- Size: 118 KB
- Stars: 1
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# esmpack
[![NPM Version][npm-image]][npm-url]
[![NPM Downloads][downloads-image]][downloads-url]
[![LICENSE][license-img]][license-url]
![npm-dependencies][npm-dep-url]
![GitHub contributors][contributors][npm-image]: https://img.shields.io/npm/v/@ibyar/esmpack.svg
[npm-url]: https://npmjs.org/package/@ibyar/esmpack
[downloads-image]: https://img.shields.io/npm/dt/@ibyar/esmpack
[downloads-url]: https://npmjs.org/package/@ibyar/esmpack
[license-img]: https://img.shields.io/github/license/ibyar/esmpack
[license-url]: https://github.com/ibyar/esmpack/blob/master/LICENSE
[npm-dep-url]: https://img.shields.io/david/ibyar/esmpack.svg?maxAge=2592000
[contributors]: https://img.shields.io/github/contributors/ibyar/esmpackesmpack, transform javascript files to es module that can be imported by browser.
## `Install`
- As Global
``` bash
npm i -g @ibyar/esmpack
yarn global add @ibyar/esmpack
```
- As Developer Dependencies``` bash
npm i --save-dev @ibyar/esmpack
yarn add --dev @ibyar/esmpack
```# How to use
can load config from js file (es module), or json file, if not
```
Version 0.1.9
Usage: esmpack [config path] [options]if no config file in the commend will try to search for file names
'esmpack.js', 'esmpack.mjs' and 'esmpack.json'.Examples:
esmpack
esmpack esmpack.js
esmpack esmpack.json -w -d
esmpack -v
esmpack --helpOptions:
--prod build for production, minify modules, css, etc...
-d --debug output debug messages on internal operations
-s --silent don't print any thing
-w --watch watch files for change
-h --help print help message
-v --version output the version number
```### Javascript Config file
js config file, proved a way to connect `esmpack` with any plugin, the built-in plugins can be called by its name `css, html, json, text, image, audio`.
- The built in plugin, will try to fetch the resource with `fetch` request.
- The Built-in plugin provide 3 different information about the resource file:
- 1- `value` : content itself, its type controlled by the plugin, import `.json` file will return json object, import `.txt`, `.css` and `.html` will return a string object.
- 2- `url` : a url for the resources.
- 3- `promise`: the promise to listen, to be notified with the fetch result.```ts
declare module '*.html' {
export default value;
export const value: string;
export const url: string;
export const promise: Promise;
}import htmlFile, {url as appUrl, promise as appPromise} from './app-root.html';
// will be transformed tolet htmlFile;
const appUrl;
const appPromise;
```if didn't provide a config path to the cli, will search for config file in the `process.cwd()` for file name `esmpack.config.js` if not found, then search for `esmpack.config.mjs`, then `esmpack.config.json`, if non of them found, will exits with error code.
Could be a js module file with default export as `JSConfig Interface` object. in that case make sure the `package.json` is marked as module package, `{"type": "module"}`. this options is useful for nodejs when (importing a non `.mjs`) OR ( import `.js`) file.
```js
let pdfHandler = (importSyntax, relativeFilePath) => {
/**
* write plugin for pdf files
* convert the pdf file to js module with default export as content of the pdf as `string`.
*/
return {action: 'module'};
};const config = {
moduleResolution: 'relative',
outDir: 'build/web_modules/',
pathMap: { 'src': 'dist' },
src: {
files: [],
include: ['./dist/**/*.js'],
exclude: []
},
resources: {
files: [],
include: ['./src/**/*.*'],
exclude: ['./src/**/*.{js,ts,tsx}']
},
plugins: [
'css',
'html',
'image',
'json',
'txt',
{ text: /\.pdf$/g, handler: pdfHandler },
{ test: /\.xml$/g, moduleType: 'text'},
]
};
export default config;
```# JSON Config file
- for now the built-in plugin the oly pne supported.
```json
{
"moduleResolution": "relative",
"outDir": "public/web_modules/",
"pathMap": {
"src": "dist"
},
"src": {
"files": [],
"include": [
"./dist/**/*.js"
],
"exclude": []
},
"resources": {
"files": [],
"include": [
"./src/**/*.*"
],
"exclude": [
"./src/**/*.{js,ts,tsx}"
]
},
"plugins": [
"css",
"html",
"json",
"text",
"image"
]
}
```# API ESMConfig Interface
```ts
export interface ESMConfig {/**
* build dir
*/
outDir: string;/**
* location of input files
*/
src: SourceInput;/**
* resource dir to copy to and look/resolve other import
* module '.css', '.html' '.map' files.
*/
resources: SourceInput;pathMap: { [key: string]: string };
/**
* preferred extension for build files '.js'.
*
* for web use ".js" if your server can't handle ".mjs"
* as MIME type "text/javascript" and Content-Type: text/javascript.
*
* for nodejs support ".mjs" out of box starting with version .
* or As of Node 13, you can use ext: ".js"
* and can trigger support by setting "type": "module", in package.json
*/
extension: ModuleExtension;/**
* `relative`: convert import statement to be relative path to its dir
* ```
* npm_modules/@models/people/model/person.js
* export class Person {....}
*
* npm_modules/@models/people/index.js
* export { Person } from './model/person';
*
* dist/views/person-component.js
* import { Person } from '@models/people';
* ```
* will be
*
* ```
* {outDir}/@models/people/model/person.js
* export class Person {....}
*
* {outDir}/@models/people/index.js
* export { Person } from './model/person.js';
*
* {outDir}/dist/views/person-component.js
* import { Person } from '../../@models/people/index.js';
* ```
*
* `static`: resolve import to be static path, 'baseUrl' should be used
* the new path will ``` 'baseUrl' / 'pkg_name' / 'file path inside outDir'```
* assume baseUrl = '/js/esm'
* the full url if http://localhost/js/esm
*
* ```
* {outDir}/@models/people/model/person.js
* export class Person {....}
*
* {outDir}/@models/people/index.js
* export { Person } from '/js/esm/@models/model/person.js';
*
* {outDir}/{project_pkg_name}/views/person-component.js
* import { Person } from '/js/esm/@models/people/index.js';
* ```
*
* `flat`: all modules will be in 'outDir' folder,
* files name will be combination from package name and module path, joined by '.'
*
* ```
* {outDir}/@models.people.model.person.js
* export class Person {....}
*
* {outDir}/@models.people.index.js
* export { Person } from './@models.people.model.person.js';
*
* {outDir}/{project_pkg_name}.views.person-component.js
* import { Person } from './@models.people.index.js';
* ```
*
*/
moduleResolution: 'relative' | 'static' | 'flat';/**
* Base directory to resolve 'static' module names.
*/
baseUrl: string;/**
* the output of this transformation shall
* scan 'all' js files in 'files' and 'include' and 'npm_modules' package.
*
* or just 'follow' import statements in js module files for this workspace.
*
* default to 'all'
*/
workspaceResolution: 'all' | 'follow';/**
* list of plugins to handle non-js supported files,
*
* built-in plugin is ['html', 'css', 'txt' ,'json', 'image files, png, jpg, ico,...']
*/
plugins: PluginHandler[];/**
* build for production
*/
prod: boolean,
}
```## ClI JSConfig Interface
```ts
type ConfigPlugin = string| { text: /\.pdf$/g, handler: (importSyntax: ImportSyntax, relativeFilePath: string): PluginAction };
export interface JSConfig {
outDir: string;
src?: SourceInput;
resources?: SourceInput;
pathMap?: { [key: string]: string };
extension?: ".js" | ".mjs";
moduleResolution?: 'relative' | 'static' | 'flat';
baseUrl?: string;
workspaceResolution?: 'all' | 'follow';
plugins?: ConfigPlugin[];
}
```## How to build A Plugin
- for now all built-in plugin intercepting only `import` statement, `export` statement not implemented yet.
```ts
class PluginAction { action: 'replace' | 'fetch' | 'module', inline?: string }
let pdfHandler = (importSyntax: ImportSyntax, relativeFilePath: string): PluginAction => {
// write plugin for pdf files
return {action: 'module'};
};// provide a new plugin with the help of built-in plugin behavior.
let mdPluginHandler = new Plugin('text');
let pngImage = new Plugin('objectURL');let config = {
...
plugins: [
'json',
{ test: /\.pdf$/g, handler: pdfHandler },
{ test: /\.xml$/g, moduleType: 'text' },
{ test: /\.md$/g, handler: mdPluginHandler },
{ test: /\.png$/g, handler: pngImage }
]
}
````replace:` replace import statement with code.
`fetch`: replace the import statement with a fetch request code, from the inline.
`module`: convert the resource file to a js module, and import its default.
`inline`: hold code to be replaced with the import statement.
`moduleType` value could be: `text`, `json`, `blob`, `arrayBuffer`, `file`, `uint8`, `objectURL`, `base64` and `dataBase64`.## Example
`app/file.html`
```html
Hello from HTML
````app/main-module.js`
```ts
import htmlContent, {url, promise, value} from './file1.html';console.log(htmlContent); // print undefined
console.log(value); // print undefined
console.log(url); // print 'http://site-url/{outDir}/app/file1.html'promise.then(content => {
console.log(htmlContent); // print 'Hello from HTML
'
console.log(value); // print 'Hello from HTML
'
console.log(content); // print 'Hello from HTML
'console.log(content == htmlContent); // print true
console.log(content == html); // print true, the same object
})
.catch(reason => console.error('failed loading html file'));```
`@aurora/esmpack` support operator `as` for renaming the default exported names in the wildcard
```ts
import json, {promise as jsonPromise} from './file.json';
import text, {promise as textPromise} from './file.txt';import {url as imageUrl} from './image.jpg';
file1Promise.then(content => {
....
});textPromise.then(content => {
....
});```
`@aurora/esmpack` support operator `export` from a non-js file.
```ts
///export * from './file.json';
export * from './file.txt';
/**will throw error at runtime,
* keep aware of renaming wildcard binding names, so not conflict with each other.
* Consider explicitly re-exporting to resolve the ambiguity
*/export {url as imageUrl, jpg as imageObject} from './image.jpg';
export * as image from './image.jpg';
```## TO:DO
- set extension of module file to '.js' or '.mjs', currently, doesn't override filename.
- moduleResolution `static` and `flat`: currently `relative` is supported