unjs / mkdist Goto Github PK
View Code? Open in Web Editor NEWLightweight file-to-file transpiler.
License: MIT License
Lightweight file-to-file transpiler.
License: MIT License
mkdist 1.1.2 on Node.js 16.14.2, v18.14.0.
.mts
and .cts
files in your src
directory.mkdist -d --ext js
// farewells.cts
export function sayGoodbye(name: string) {
console.log(`Goodbye, ${name}!`)
}
// greetings.ts
export function sayHello(name: string) {
console.log(`Hello, ${name}!`)
}
// index.mts
import { sayHello } from './greetings.js'
import { sayGoodbye } from './farewells.cjs'
sayHello('World')
sayGoodbye('World')
StackBlitz example: https://stackblitz.com/edit/node-erv3qh?file=package.json&view=editor (use pnpm build:tsc
to build with TypeScript and pnpm build:mkdist
to build with mkdist
, start
to run ./dist/index.mjs
with Node).
mkdist
ignores .cts
and .mts
files and copies them as is instead of compiling them to .cjs
(+.d.cts
) and .mjs
(+.d.mts
) respectfully.
I could've tried to explain the importance of these file extensions on my own but Bing did a nicer job than me π’
The
.mjs
and.cjs
extensions are used to specify the module type of a JavaScript file in Node.js 16+. The.mjs
extension indicates that the file is an ECMAScript module (ESM), which is a standard format for modular JavaScript code. The.cjs
extension indicates that the file is a CommonJS module, which is a legacy format that was widely used before ESM was introduced12.The
.mts
and.cts
extensions are used to specify the module type of a TypeScript file. TypeScript is a superset of JavaScript that adds static types and other features. The.mts
extension indicates that the file is an ESM TypeScript file, which will be emitted as an.mjs
file when compiled to JavaScript. The.cts
extension indicates that the file is a CommonJS TypeScript file, which will be emitted as a.cjs
file when compiled to JavaScript1.These extensions help Node.js to determine how to load and execute different types of modules without relying on ambiguous heuristics or configuration options3. They also help developers to write clear and consistent code across different environments.
While this is a nice explanation, it fails to mention a few other important things:
If your file has a .ts
extension, TypeScript always assumes the resulting file will have .js
extension. So if any of the files in your project imports the other file that has .ts
extension, and you use Node16
(NodeNext
) module resolution (which you very much should btw), TypeScript forces you to write import with .js
extension, which is incompatible with mkdist
, unless you force it in .js
extension mode (--ext js
), which you cannot do in environments like nuxt-module-builder
without patching it (which is exactly what I'm struggling with and what I am doing).
The other important thing is that .ts
, .cts
, .mts
on the declaration files imply the existence of the file with the same basename: that is, index.d.ts
says βthe declaration file is for index.js
β, a.d.cts
is βfor a.cjs
β, and b.d.mts
is βfor b.mjs
β. That becomes super important for libraries that ship with wildcard exports
in package.json
, as well helps you as developer to avoid writing types
condition which may or may not lead to a correct declaration file (without types
export condition TypeScript looks for [basename].d.[ts/cts/mts]
).
{
"exports": {
"./locale-data/*": { "import": "./dist/locale-data/*" }
}
}
No response
mkdist uses a post-build transform to add explicit extensions (src) but this is not always working (eg with multi line imports) unjs/unbuild#83.
We shall migrate to mlly.parseStaticImports.
Tag 1.3.0 has a vulnerable version of esbuild 1.18.4:
https://github.com/unjs/mkdist/blob/v1.3.0/package.json#L34
The main branch has the up to date secure version of esbuild already:
https://github.com/unjs/mkdist/blob/main/package.json#L34
I have several code security scanners all flagging this issue in the package.json. Relevant nist report: https://nvd.nist.gov/vuln/detail/CVE-2023-39323
The latest current tag 1.3.0 has a vulnerable version of esbuild in it. The main branch has the patched version of esbuild in it. Can you push up a minor version update of like 1.3.1 which would include the main branch with the latest patched version of esbuild which is at 0.19.5.
Tag 1.3.0 has a vulnerable version of esbuild 1.18.4:
https://github.com/unjs/mkdist/blob/v1.3.0/package.json#L34
The main branch has the up to date secure version of 0.19.5 already:
https://github.com/unjs/mkdist/blob/main/package.json#L34
Thanks!
Relevent https://nvd.nist.gov/vuln/detail/CVE-2023-39323
No response
If a sass file uses a relative @import
from another file, it won't be inlines
Reproduction: https://stackblitz.com/edit/node-hutoco?file=src%2Fstyle.sass
(run npm test
)
Context: #27 > nuxt/module-builder#87
In <script setup lang="ts">
, SFC compiler uses TS definition as the hint for generating runtime props. example
Currently, mkdist will always remove the TS annotation make the information lost. I think we should introduce an option to disable the behaviour and probably bypass <script setup lang="ts">
smartly by default.
Hello, I was looking to integrate unbuild in a component library where I ship both a compiled version of all components and the uncompiled vue files.
For the last step (ship uncompiled, individual component files), I would use mkdist, but I noticed that there is no way to filter the type of input files. In my case, I have in the same folder tests, Storybook stories, .vue
files, and some shared .ts
files.
It would be great to have the option to customize the **
glob that is used by default with an array of glob patterns.
a reproduction or simple code @pi0
https://github.com/gaoletian/mkdist-issues-192
// src/Foo.ts
export enum Type {
Foo,
Bar
}
export default class Action {}
// dist/Foo.js
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
module.exports = exports.Type = void 0;
var Type = exports.Type = /* @__PURE__ */(Type2 => {
Type2[Type2["Foo"] = 0] = "Foo";
Type2[Type2["Bar"] = 1] = "Bar";
return Type2;
})(Type || {});
class Action {}
module.exports = Action;
// test.js
const foo = require('./dist/Foo');
console.log(foo);
console.log(foo.Type);
$ node test.js
foo = [class Action]
foo.Type = undefined
Hi! π
Firstly, thanks for your work on this project! π
Today I used patch-package to patch [email protected]
for the project I'm working on.
Here is the diff that solved my problem:
diff --git a/node_modules/mkdist/dist/index.mjs b/node_modules/mkdist/dist/index.mjs
index 1403db8..7b1582a 100644
--- a/node_modules/mkdist/dist/index.mjs
+++ b/node_modules/mkdist/dist/index.mjs
@@ -59,7 +59,9 @@ const jsLoader = async (input, { options }) => {
}
const isCjs = options.format === "cjs";
if (isCjs) {
- contents = jiti("").transform({ source: contents, retainLines: false }).replace(/^exports.default = /gm, "module.exports = ").replace(/^var _default = exports.default = /gm, "module.exports = ").replace("module.exports = void 0;", "");
+ contents = jiti("")
+ .transform({ source: contents, retainLines: false })
+ .replace("module.exports = void 0;", "");
}
let extension = isCjs ? ".js" : ".mjs";
if (options.ext) {
This issue body was partially generated by patch-package.
Thank you for your work on this project. It is (nearly) perfect for my use case. I'm authoring a pure ESM library in typescript, so the addition of file extensions to imports is very very nice.
However, I've seemed to find a bug... If import statements are over multiple lines, the file extensions does not seem to be resolved in the output (making the ESM dist incompatible with Node and the browser).
// src/index.ts
import { a } from './a';
import {
b
} from './b';
export { a, b }
$ mkdist
// dist/index.mjs
import { a } from './a.mjs';
import {
b
} from './b'; // <- .mjs missing, breaks ESM
export { a, b }
This is the commit where I changed imports and things started working correctly: manzt/zarrita.js@bd6706a
(#29)
I have a directory:
project
βββ src
βββ map.vue
map.vue:
<template>
<div @click="onClick">{{count}}</div>
</template>
<script lang="ts">
export default {
data() {
return { count: 0 };
},
method: {
onClick() {
this.count += 1;
}
}
}
</script>
<style lang="less" scoped>
div {
color: red;
}
</style>
Then:
cd project
mkdist --format=esm --ext=vue -d
Then it get:
project
βββ dist
β βββ map.vue
βββ src
βββ map.vue
What I really want to get is:
project
βββ dist
β βββ map.js
βββ src
βββ map.vue
This issue lists Renovate updates and detected dependencies. Read the Dependency Dashboard docs to learn more.
These updates are awaiting their schedule. Click on a checkbox to get an update now.
@types/node
, @vitest/coverage-v8
, @volar/typescript
, @vue/language-core
, cssnano
, esbuild
, eslint-config-unjs
, mlly
, pkg-types
, pnpm
, sass
, semver
, vitest
, vue
, vue-tsc
)These updates have all been created already. Click a checkbox below to force a retry/rebase of any.
These are blocked by an existing closed PR and will not be recreated unless you click a checkbox below.
.github/workflows/autofix.yml
actions/checkout v4
actions/setup-node v4
autofix-ci/action ea32e3a12414e6d3183163c3424a7d7a8631ad84
.github/workflows/ci.yml
actions/checkout v4
actions/setup-node v4
codecov/codecov-action v4
package.json
autoprefixer ^10.4.19
citty ^0.1.6
cssnano ^7.0.0
defu ^6.1.4
esbuild ^0.20.2
fs-extra ^11.2.0
globby ^14.0.1
jiti ^1.21.0
mlly ^1.6.1
mri ^1.2.0
pathe ^1.1.2
pkg-types ^1.1.0
postcss ^8.4.38
postcss-nested ^6.0.1
semver ^7.6.0
@types/fs-extra ^11.0.4
@types/mri ^1.2.0
@types/node ^20.12.7
@types/semver ^7.5.8
@vitest/coverage-v8 ^1.5.2
@volar/typescript ^2.2.0-alpha.10
@vue/language-core ^2.0.14
changelogen ^0.5.5
eslint ^8.57.0
eslint-config-unjs ^0.2.1
modern-normalize ^2.0.0
prettier ^3.2.5
sass ^1.75.0
typescript ^5.4.5
unbuild ^2.0.0
vitest ^1.5.2
vue ^3.4.25
vue-tsc ^2.0.14
vue-tsc1 ^1.8.27
sass ^1.75.0
typescript >=5.4.5
vue-tsc ^1.8.27 || ^2.0.14
pnpm 9.0.6
when passing in { format: 'cjs' }
I get the following error:
ERROR The "path" argument must be of type string. Received undefined 12:19:22
at validateString (internal/validators.js:124:11)
at dirname (path.js:1128:5)
at t.transform.Object.assign.legacy (node_modules/jiti/dist/jiti.js:1:40213)
at Function.f [as transform] (node_modules/jiti/dist/jiti.js:1:40499)
at jsLoader (node_modules/mkdist/dist/index.js:35:44)
at processTicksAndRejections (internal/process/task_queues.js:93:5)
at async loadFile (node_modules/mkdist/dist/index.js:83:23)
at async vueLoader (node_modules/mkdist/dist/index.js:57:24)
at async loadFile (node_modules/mkdist/dist/index.js:83:23)
at async Object.mkdist (node_modules/mkdist/dist/index.js:115:21)
Using disabledLoaders
users can use defaults but disable specific loaders only.
Line 6 in 1543502
When I build a vue component, PropType<string | number | null>
will lose null
type.
These are experimental at the moment and without widespread support.
https://www.typescriptlang.org/docs/handbook/esm-node.html#new-file-extensions
follow up on #26
Define CLI
by citty
I want to use unbuild mkdist to process a batch of svg file, converted to react component, i can't find a way to do that
see example in here: https://stackblitz.com/edit/node-xpfcjp
Hey! First of all, thank you so much for this awesome package! I've started using it with unbuild
and it has been a life-saver.
I'd like to point out that I've experienced a massive speed loss when generating CJS. I suspect it's due to the fact that the esm
generated by esbuild
gets passed to jiti
(which uses babel instead of esbuild).
Could you give the option to use esbuild
exclusively as a CJS transformer instead, or pass the esbuild transform to jiti?
just as we have done with #134, we should add extensions to relative imports within the JS output of runtime directories, or these will not be valid in a module context
see nuxt/nuxt#19689
Node 18.15.0.
mkdist: latest
No reproduction
As per the documentation in https://github.com/nuxt/module-builder, it's mentioned that only js, ts and vue files would be transformed.
runtime/*: Individually transformed files using [unjs/mkdist](https://github.com/unjs/mkdist)
Javascript and .ts files will be transformed to .mjs with extracted types on .d.ts file with same name
.vue files will be transformed with extracted .d.ts file
-> Other files will be copied as is
I have an issue where sass files are transformed to empty css but I would like the scss file to be copied as is. I see from the tests that scss files are compiled:
Line 86 in a0d637d
Is there a way to opt-out of this and to just copy the file as is?
No response
No response
Maintaining mkdist seperated from unbuild only makes sense if mkdist is commonly used separated or it increases testability or maintainability.
I think for next steps, it makes sense to merge mkdist into unbuild and maintain single version.
Name | Version |
---|---|
mkdist --version |
1.5.0 |
node --version |
v22.0.0 |
npm --version |
10.5.1 |
lsb_release -ds |
Arch Linux |
uname -mr |
6.8.7-arch1-1 x86_64 |
create fresh
# create a tmp dir and navigate to
cd $(mktemp -d)
# initialize empty package.json
npm init -y
# set package "type" to "module
# add "start" to package scripts
npm pkg set type="module" scripts.start="node src/index.js"
# create src/
mkdir src
# write some dummy console
echo 'console.log("xyzzy");' > src/index.js
# build for esm
npx mkdist --dist=dist --format=esm --ext=mjs
# build for cjs
npx mkdist --dist=dist --format=cjs --ext=cjs
# check dist/ files
tree dist
dist
βββ index.cjs
1 directory, 1 file
every build is cleaning the dist/
every build is cleaning the dist/
I'm aware the cleanDist
option was added f613c17 but no cli arg was ever added
cd $(mktemp -d); npm init -y; npm pkg set type="module" scripts.start="node src/index.js"
mkdir src; echo 'console.log("xyzzy");' > src/index.js
npx mkdist --dist=dist --format=esm --ext=mjs
npx mkdist --dist=dist --format=cjs --ext=cjs
tree dist
dist
βββ index.cjs
1 directory, 1 file
I've just made a PR for this issue, will link here shortly
UPDATE: #217
No response
for use with siroc
etc.
edit: exists
In a directory where there is both components.d.ts
and components.mjs
both output files (may) have the contents of components.mjs
.
Example: https://unpkg.com/browse/@nuxt/[email protected]/dist/runtime/components.tmpl.d.ts
cc: @pi0
Currently import foo from '../bar'
is not resolved. Context #7
Currently, <script setup lang="ts">
is being completely bypassed, as of #15. However, bypassing should only be needed when using type-only macros, e.g. defineProps<{ foo: number }>()
(not defineProps({ foo: Number })
).
So, to improve this:
defineProps<{ foo: number }>()
to defineProps({ foo: number })
. This may be complex to implement, and may even require help from the Vue team. The reverse of https://github.com/sapphi-red/vue-convert-to-script-setup-from-composition-api may work.I will implement the "quick and acceptable solution" soon.
Warn if CommonJS syntax detected to use ext: js
or format: cjs
require
__filename
/ __dirname
module.*
exports.*
TODO: Upgrade syntax when possible
It will be nice to support tsconfig
paths, or at least allow for aliasing, so it can be done manually.
For valid .mjs
/ type: module
output, we need to resolve imports with explicit extension and also handle index
files. This way a relative import is a valid URL.
Hello, I want to use unbuild with mkdist builder to bundle my vue component library and publish them to npm. When using it in my vite project, it seems like vite will not do transform code inside node_modules and, however, my code are required to run in a web browser with chormium 70 and some syntaxs like optional chain may not be supported. I found that using unbuild with rollup builder supports custom rollupOptions and thus can specify custom esbuild options while mkdist does not support custom esbuild options. Maybe mkdist can provide options to define custom esbuild options? Thanks a lot!
Inside: https://github.com/unjs/mkdist/blob/main/src/loaders/js.ts#L33
Hi, i use your package through (unbuild)[https://github.com/unjs/unbuild].
And after a lot of test to translate ts component to js. I'm fail with component who use scrip setup
.
The component is only copy without transformation. with ts or js component it's ok and the type file is generate.
Maybe i miss something =)
Have a nice day
A declarative, efficient, and flexible JavaScript library for building user interfaces.
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. πππ
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google β€οΈ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.