Code Monkey home page Code Monkey logo

packemon's Introduction

Packemon

Build Status npm version

Gotta pack 'em all!

Are you a library maintainer? Confused on how to build packages for consumers? Unsure of what tooling and plugins to use? What about CommonJS vs ECMAScript? TypeScript, JavaScript, or FlowType? Forget that headache and let Packemon do the heavy lifting for you. No need to fiddle with Babel or Rollup configurations!

Packemon is a "batteries included" CLI that will prepare each package for distribution by building with the proper tooling and plugins, provide sane defaults and configurations, verify package requirements, and much more! By default Packemon will generate ECMAScript modules, but can be configured to support all formats.

Features

  • Scaffold TypeScript packages, in either a monorepo or polyrepo project setup.
  • Configure packages for Node.js, Web browsers, or React Native, with multiple output formats like CommonJS and ECMAScript (default).
  • Build packages with Rollup to create self-contained and tree-shaken bundles. Provide the smallest file sizes possible!
  • Support a single index import, multiple imports, deep imports, or any kind of entry point.
  • Transform packages with Babel's preset-env and the configured platform targets. Only ship and polyfill what's truly necessary!
  • Generate and combine TypeScript declarations into a single public-only API representation.
  • Generate compact source maps for platform + format based builds.

Requirements

  • Linux, OSX, Windows
  • Node 18.12+

Documentation

https://packemon.dev

packemon's People

Contributors

azu avatar dependabot[bot] avatar milesj avatar wespickett avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

packemon's Issues

ENOENT: no such file or directory, open /apps/web/package.json'

Packemon used with moonrepo. When I build it on package of browser_pckg, It works. But, when I ran build it via moonrepo on whole of projects it doesn't work regarding that other react projects work well but the Packemon doesn't work in the browser_pckg package.

_placement of browser_pckg is shared->front->web>pckgs->browser_pckg

I thinks something is wrong on tsconfig files for giving right address as far as address of browser_pckg path.

tsconfig.json in browser_pckg

{
    "extends": "../../../tsconfig.options.json",
    "compilerOptions": {
        "outDir": "../../../.moon/cache/types/shared/pckgs/browser_pckg",
        "verbatimModuleSyntax": false
    },
    "include": [
        "src/**/*",
        "tests/**/*"
    ],
    "references": [
        {
            "path": "./tsconfig.esm.json"
        },
        {
            "path": "./tsconfig.lib.json"
        }
    ]
}

tsconfig.lib.json in browser_pckg

{
  "extends": "../../../tsconfig.options.json",
  "compilerOptions": {
    "outDir": "lib",
    "rootDir": "src"
  },
  "include": [
    "src/**/*"
  ],
  "references": []
}

tsconfig.options.json of main project

// https://www.npmjs.com/package/tsconfig-moon
{
  "extends": "tsconfig-moon/tsconfig.json",
  "compilerOptions": {
    "allowJs": true,
    "lib": ["esnext", "dom"],
    "moduleResolution": "nodenext",
    "target": "es2022",
    "composite": true,
    "declaration": true,
    "declarationMap": true,
    "emitDeclarationOnly": true,
    "incremental": true,
    "noEmit": false,
    "noEmitOnError": true,
    "skipLibCheck": true,
    "verbatimModuleSyntax": false
  }
}
> packemon build --addEngines

@monorepo/browserpckg**
  β—Ό lib (206 B) β—Ό esm (188 B) 595ms
u2204oneuser@u2204onehost:/mnt/workspa
pnpm run build

β–ͺβ–ͺβ–ͺβ–ͺ browser_pckg:build
packemon pack --addEngines --addExports (in ./shared/pckgs/browser_pckg)
  browser_pckg:build | @monorepo/browserpckg**
  browser_pckg:build |   β—Ό lib (206 B) β—Ό esm (188 B) 564ms
  browser_pckg:build | 
  browser_pckg:build |  ERROR 
  browser_pckg:build | 
  browser_pckg:build |  ENOENT: no such file or directory, open
  browser_pckg:build |  '/mnt/workspace1/dir_git/dir_my_repo/nft-music/apps/web/package.json'
  browser_pckg:build | 
  browser_pckg:build |  STACK TRACE 
  browser_pckg:build | 
  browser_pckg:build |     at Object.openSync (node:fs:601:3)
  browser_pckg:build |     at Object.readFileSync (node:fs:469:35)
  browser_pckg:build |     at Object.load (/mnt/workspace1/dir_git/dir_my_repo/nft-music/node_modules/.
  browser_pckg:build | pnpm/@[email protected][email protected]/node_modules/@boost/common/cjs/seriali
  browser_pckg:build | zers/json.cjs:20:36)
  browser_pckg:build |     at /mnt/workspace1/dir_git/dir_my_repo/nft-music/node_modules/.pnpm/@boost+c
  browser_pckg:build | [email protected][email protected]/node_modules/@boost/common/cjs/Project.cjs:118:23
  browser_pckg:build |     at Array.map (<anonymous>)
  browser_pckg:build |     at Project.getWorkspacePackages 
  browser_pckg:build | (/mnt/workspace1/dir_git/dir_my_repo/nft-music/node_modules/.pnpm/@boost+common@
  browser_pckg:build | [email protected]/node_modules/@boost/common/cjs/Project.cjs:114:8)
  browser_pckg:build |     at Project.memoizer 
  browser_pckg:build | (/mnt/workspace1/dir_git/dir_my_repo/nft-music/node_modules/.pnpm/@boost+decorat
  browser_pckg:build | [email protected]/node_modules/@boost/decorators/cjs/Memoize.cjs:39:26)
  browser_pckg:build |     at PackageValidator.getWorkspacePackageNames 
  browser_pckg:build | (/mnt/workspace1/dir_git/dir_my_repo/nft-music/node_modules/.pnpm/[email protected]
  browser_pckg:build | [email protected]/node_modules/packemon/cjs/PackageValidator.cjs:319:59)
  browser_pckg:build |     at PackageValidator.checkDependencies 
  browser_pckg:build | (/mnt/workspace1/dir_git/dir_my_repo/nft-music/node_modules/.pnpm/[email protected]
  browser_pckg:build | [email protected]/node_modules/packemon/cjs/PackageValidator.cjs:62:48)
  browser_pckg:build |     at PackageValidator.validate 
  browser_pckg:build | (/mnt/workspace1/dir_git/dir_my_repo/nft-music/node_modules/.pnpm/[email protected]
  browser_pckg:build | [email protected]/node_modules/packemon/cjs/PackageValidator.cjs:36:12)
  browser_pckg:build |     at Packemon.validate 
  browser_pckg:build | (/mnt/workspace1/dir_git/dir_my_repo/nft-music/node_modules/.pnpm/[email protected]
  browser_pckg:build | [email protected]/node_modules/packemon/cjs/Packemon.cjs:44:55)
  browser_pckg:build |     at PackCommand.pack 
  browser_pckg:build | (/mnt/workspace1/dir_git/dir_my_repo/nft-music/node_modules/.pnpm/[email protected]
  browser_pckg:build | [email protected]/node_modules/packemon/cjs/commands/Build.cjs:74:43)
  browser_pckg:build |     at async PackCommand.run 
  browser_pckg:build | (/mnt/workspace1/dir_git/dir_my_repo/nft-music/node_modules/.pnpm/[email protected]
  browser_pckg:build | [email protected]/node_modules/packemon/cjs/commands/Pack.cjs:11:5)
  browser_pckg:build |     at async Program.runAndRender (/mnt/workspace1/dir_git/dir_my_repo/nft-music
  browser_pckg:build | /node_modules/.pnpm/@[email protected][email protected][email protected][email protected]/nod
  browser_pckg:build | e_modules/@boost/cli/cjs/Program.cjs:474:24)
  browser_pckg:build |     at async Program.run (/mnt/workspace1/dir_git/dir_my_repo/nft-music/node_mod
  browser_pckg:build | ules/.pnpm/@[email protected][email protected][email protected][email protected]/node_modules
  browser_pckg:build | /@boost/cli/cjs/Program.cjs:298:18)
  browser_pckg:build |     at async Program.runAndExit (/mnt/workspace1/dir_git/dir_my_repo/nft-music/n
  browser_pckg:build | ode_modules/.pnpm/@[email protected][email protected][email protected][email protected]/node_
  browser_pckg:build | modules/@boost/cli/cjs/Program.cjs:317:22)
  browser_pckg:build |     at async run (/mnt/workspace1/dir_git/dir_my_repo/nft-music/node_modules/.pn
  browser_pckg:build | pm/[email protected][email protected]/node_modules/packemon/cjs/bin.cjs:44:3)
  browser_pckg:build | 

Bug: `native` platform exports are pointing to the incorrect files when also building `node`

version: 3.x

Test Repo: https://github.com/j3tan/packemon-native-web-package

native exports look like:

{
  "exports": {
    "./mobile": {
      "react-native": {
        "types": "./lib/native/mobile/index.d.ts", <==== This is incorrect
        "default": "./lib/native/mobile.js" <==== This is incorrect
      },
      "default": "./lib/native/mobile.js" <==== This is incorrect
    },
  }
 }

but the file structure looks like:

lib/
β”œβ”€β”€ mobile/
β”‚   β”œβ”€β”€ mobile.js
β”‚   β”œβ”€β”€ mobile.js.map
β”œβ”€β”€ native/
β”‚   β”œβ”€β”€ index.d.ts
β”‚   β”œβ”€β”€ index.d.ts.map
{
  "packemon": [
    { <== Removing this target fixes the issue
      "bundle": true,
      "format": "lib",
      "platform": "node"
    },
    {
      "bundle": true,
      "format": "esm",
      "platform": "browser",
      "inputs": {
        "web": "src/web/index.ts"
      }
    },
    {
      "bundle": true,
      "format": "lib",
      "platform": "native",
      "inputs": {
        "mobile": "src/mobile/index.ts"
      }
    }
  ]
 }

My guess is a conflict when building 2 format lib targets?

.css.ts imports not inlined in output

I am guessing this is related to #229.

When I import File.css.ts it no longer throws an error, but also it does not inline the import into the index.js output file. So in the eventual build I'm missing all of the css files and they are not inlined.

So my build output will succeed, but esm/index.js will contain stuff like:

import { link } from './Link.css';
import { card } from './Card.css';

But packemon won't output those Link.css.ts and Card.css.ts files.

I haven't been able to dive too far into packemon, but I assume there's some other place where something is assuming that these are real .css files and not .css.ts files.

`const __dirname` throw "Property id of VariableDeclarator expected node to be of a type ["LVal"] but instead got "CallExpression""

packemon throw an error when transpile following code.

Property id of VariableDeclarator expected node to be of a type ["LVal"] but instead got "CallExpression"

const __dirname = 1;

This this a parts of following snippet.

import * as path from "path";
import * as url from "url";

const __filename__ = url.fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename__);
console.log(__dirname);

I know that babel-plugin-cjs-esm-interop transpile __dirname.
But, This error is unexpected.

Expected

No Error

Actual

Error:

Property id of VariableDeclarator expected node to be of a type ["LVal"] but instead got "CallExpression""

Workaround

Avoid to define __dirname variable.

import * as path from "path";
import * as url from "url";

const x = url.fileURLToPath(import.meta.url);
const y = path.dirname(x);
console.log(y);

Reproduce Repository

https://github.com/azu/packemon-mjs-__dirname-error

Unable to use `PackageValidator` for non-packemon packages

Version: 3.x

The requirement for a Package to have a packemon configuration object inhibits the ability to use the validation utilities for non-packemon projects.

Previously, we would run all of the package.json files in a repository through the PackageValidate#validate method. Given that we only have some packages that are packemon enabled, this fails with the error:

Error: Invalid `packemon` configuration for <some-non-packemon-package>, must be an object or array of objects. 

Appreciate any workarounds here for constructing the required Package object so that we can continue to leverage the validation utilities would be helpful.

clean command is not working

When executing the clean command, artifacts are not cleaned up properly.
The reason for this bug is that the Package's artifacts property is an empty array when the clean command is executed.
To correct this bug, the generateArtifacts function should be executed before executing the clean function of Package to generate the artifacts in advance.

package.main incorrectly set to cjs/index.js

Running packemon build sets the main field on package.json to ./cjs/index.cjs but ./cjs/index.cjs does not exist. I think it should be set to the value under exports["."].node value which in this case points to an actual file: ./cjs/node.cjs.

It also adds "src/**/*.{ts,tsx,json}" to the files field. Is there a reason for this? Is there a way to make it not touch package.json

any way to add rollup plugins?

hey!
What would be the preferred way to add rollup plugins to the default config? Also if I missed this in documentation can you point me to the link?

How to disable addFiles?

I was trying to disable addFiles in my project as I need other main entry.

"build": "packemon build --addEngines --declaration=standard --addFiles=false",
"pack": "cross-env NODE_ENV=production packemon pack --addEngines --declaration=standard --addFiles=false",

Fails with following error

 Flags and short option groups may not use inline values. [ARG:VALUE_NO_INLINE]

 $ packemon build --addEngines --declaration=standard --addFiles=false

"helpers" feature not removing babelHelpers

Hey @milesj - following on from the discussion on #207

  • I've tried all the options for the features.helpers field and I'm still seeing the babelHelpers bundled inline.
  • I tested invalid values to make sure the config was picking this up, but it wouldn't start without one of the 4 valid options.

I noticed you mentioned in the previous issue:

But I can't seem to get the snapshots to reflect the helper changes, and I can't figure out why...

From looking at the snapshots in your PR to implement the helper option, I would expect Scenario 2 not to have the babel helpers above the example function because it's set to be external here? This is the same output I'm seeing when setting the config locally and build too:

image

--project flag with project references

Howdy!

I ran across an issue with the --project flag on being attached to my pack script in a project using project references.

Looks like you've already addressed that issue with this commit.

What is your typical cadence for releasing hotfixes such as these?

Bug: subpaths for `lib` format are not generated properly

I noticed that in one of our packages, subpaths were not being built properly for lib format. ESM seems to work fine. This is highlighted by the fact that the generated exports file paths do not exist in the lib/ folder.

Package JSON example

{
 ...
  "packemon": [
    {
      "format": "esm",
      "platform": "browser",
      "inputs": {
        "index": "src/index.ts",
        "helpers": "src/helpers/index.ts",
        "utils": "src/utils/index.ts"
      }
    },
    {
      "format": "lib",
      "platform": "node",
      "inputs": {
        "index": "src/index.ts",
        "helpers": "src/helpers/index.ts",
        "utils": "src/utils/index.ts"
      }
    }
  ],
  "packageManager": "[email protected]",
  "types": "./lib/index.d.ts",
  "module": "./esm/index.js",
  "exports": {
    "./package.json": "./package.json",
    ".": {
      "browser": {
        "types": "./esm/index.d.ts",
        "module": "./esm/index.js",
        "import": "./esm/index.js"
      },
      "node": {
        "types": "./lib/index.d.ts",
        "default": "./lib/index.js"
      },
      "default": "./lib/index.js"
    },
    "./helpers": {
      "browser": {
        "types": "./esm/helpers.d.ts",
        "module": "./esm/helpers.js",
        "import": "./esm/helpers.js"
      },
      "node": {
        "types": "./lib/helpers.d.ts", <------ These do not exist
        "default": "./lib/helpers.js" <------ These do not exist 
      },
      "default": "./lib/helpers.js"
    },
    "./utils": {
      "browser": {
        "types": "./esm/utils.d.ts",
        "module": "./esm/utils.js",
        "import": "./esm/utils.js"
      },
      "node": {
        "types": "./lib/utils.d.ts", <------ These do not exist
        "default": "./lib/utils.js" <------ These do not exist
      },
      "default": "./lib/utils.js"
    }
  }
}

Example Repo:
https://github.com/j3tan/packemon-test/tree/main

Let me know if I'm missing a configuration or some important detail

Bug: types not added to export map for tsx input files

https://github.com/wespickett/packemon-test2

Steps:
npm install
cd packages/example1
npm run build

cd ../..
npm run fix

Repeat steps 2-3

Expected:

 "exports": {
    "./package.json": "./package.json",
    "./otherweb": {
      "node": {
        "types": "./lib/node/web.d.ts",
        "default": "./lib/node/node/web.js"
      },
      "default": "./lib/node/node/web.js"
    },
    "./web": {
      "browser": {
        "types": "./esm/browser/index.d.ts",
        "module": "./esm/web.js",
        "import": "./esm/web.js"
      }
    },
    ".": {
      "react-native": {
        "types": "./lib/node/index.d.ts",
        "default": "./lib/native/index.js"
      },
      "default": "./lib/native/index.js"
    }
  }

Actual:

"exports": {
    "./package.json": "./package.json",
    "./otherweb": {
      "node": "./lib/node/node/web.js",
      "default": "./lib/node/node/web.js"
    },
    "./web": {
      "browser": {
        "module": "./esm/web.js",
        "import": "./esm/web.js"
      }
    },
    ".": {
      "react-native": {
        "types": "./lib/native/node/index.d.ts",
        "default": "./lib/native/index.js"
      },
      "default": "./lib/native/index.js"
    }
  }

Possible fix: https://github.com/wespickett/packemon-test2/blob/main/fix.patch

Question/Feature Request: How to replace the build step?

Hi there!

I want to replace the compilation step and do something similar to what tshy so I can rely on running tsc and have more control of the compilation.

Since tshy does some of the work that packemon does, I was thinking of simply having a script to build each dialect. The script is simple and does the following:

  • creates a tempory package.json in src with appropriate module
  • symilnks the package root to src/node_modules/[PKG] to support imports
  • compiles tsconfig.DIALECT.json
  • deletes package.json and src/node_modules

How hard would it be to customize packemon to call a script or a function I'm exporting to do that?

regeneratorRuntime is not defined in build output

Attempting packemon for a project. Its building the project fast without errors. But the output contains references to regeneratorRuntime which is not in scope. Checking this SO question it says the @babel/plugin-transform-runtime plugin should be used.. but I am not sure how to add that as packemon uses its internal babel configuration? Is there a way to extend it / add a plugin for it?

You can reproduce it by cloning the fix-web-api-issues branch here. Running node lib/bin.js should not throw.

Thanks 😁

Bug: browser condition block in exports is missing default

version 3.x

Builds in the Artifact are isolated per config:
https://github.com/milesj/packemon/blob/master/packages/packemon/src/Package.ts#L179-L202

So the findEntryPoint for lib here will always be null while an esm build is being processed: https://github.com/milesj/packemon/blob/master/packages/packemon/src/Artifact.ts#L324

So the default for browser (and maybe others?) needs to be added in at another point:

Possible fix:
missingDefaults.patch

ES module issues after a clean scaffold of `polyrepo-package`

Hi,

I'm setting up a new project using npx packemon scaffold --template polyrepo-package ./packemon-test. This successfully scaffolds all files and installs dependencies. I am able to build and pack my project. However when I try to run the test command or lint command I get errors relating to ES module.

$ jest
ReferenceError: module is not defined in ES module scope
This file is being treated as an ES module because it has a '.js' file extension and '/packemon-test/package.json' contains "type": "module". To treat it as a CommonJS script, rename it to use the '.cjs' file extension.
$ eslint --cache --fix ./src ./tests

Oops! Something went wrong! :(

ESLint: 8.9.0

Error [ERR_REQUIRE_ESM]: require() of ES Module /packemon-test/.eslintrc.js from /packemon-test/node_modules/@eslint/eslintrc/dist/eslintrc.cjs not supported.
.eslintrc.js is treated as an ES module file as it is a .js file whose nearest parent package.json contains "type": "module" which declares all .js files in that package scope as ES modules.
Instead rename .eslintrc.js to end in .cjs, change the requiring code to use dynamic import() which is available in all CommonJS modules, or change "type": "module" to "type": "commonjs" in /packemon-test/package.json to treat all .js files as CommonJS (using .mjs for all ES modules instead).

Is there anything more I need to configure before running these commands?

TypeScript library with `"type": "module"` generating `cjs` declarations with `.d.ts` suffix

I have a TypeScript library with "type": "module" , I want to build both ESM and CommonJS output.

package.json:

  "packemon": {
    "format": [
      "esm",
      "cjs"
    ],
    "platform": [
      "node",
      "browser"
    ],
    "api": "public"
  },

Generated esm output looks fine but the cjs output also has declarations with .d.ts suffixes instead of .d.cts.
image

This will cause problems in CommonJS project importing the library.
See:
microsoft/TypeScript#50466 (comment)
microsoft/TypeScript#50466 (comment)

Bug: `transform-react-jsx currently only accepts useBuiltIns or useSpread but not both`

Hitting this issue while trying to upgrade to Packemon 3. Looks like it was part of the breaking changes in PR #160 but seems to impact packages using react JSX

Running `packemon build --addExports --no-addFiles --declaration --quiet --loadConfigs` in ./packages/some-package 

**ERROR** 
[BABEL] path/to/some/file.ts: transform-react-jsx currently only accepts useBuiltIns or useSpread but not both (While processing: "/src/web/node_modules/@babel/preset-react/lib/index.js$0")

STACK TRACE 
    at /src/web/node_modules/@babel/plugin-transform-react-jsx/lib/create-plugin.js:63:17
    ...

if (features.react) {
presets.push([
resolve('@babel/preset-react'),
{
// development: __DEV__,
runtime: features.react,
throwIfNamespace: true,
useBuiltIns: true,
useSpread: true,
},
]);
}

Related:
https://github.com/babel/babel/blob/34136c53f82976ee93eb72885beeacf9782d2e6a/packages/babel-plugin-transform-react-jsx/src/create-plugin.ts#L129-L136

https://github.com/babel/babel/blob/05deb6040523c0af4847c5c8f6d1589a0d8d3e89/packages/babel-helper-builder-react-jsx/src/index.ts#L266-L271

Version 1.0

After the last few PRs, Packemon feels rather stable and feature complete enough for a v1. I will leave this issue open for a while to test a bit more and receive any feedback.

With that being said, I plan on making the following changes for the v1 release since they are breaking:

Controversial? Force modules by default?

Now that Node v12.18+ supports ES modules, we're dropping Node v10, and everyone pretty much writes their code nowadays with import/export, perhaps we force ES as the default? This would make mjs the default for node and esm the default for browser. lib would still exist, just opt-in.

"default" is imported from external module "react" but never used in "src/file.tsx"

I have a file that looks like this:

// Avatar.tsx
import {forwardRef} from 'react';
import {avatar, wrapper} from './Avatar.css';
import {createView} from './createView';

interface AvatarProps {
 …
}

function sanitizeString(str = '') {
  …
}

export const Avatar = forwardRef<HTMLSpanElement, AvatarProps>(
  ({avatar, size, variant, badge, ...props}, fwdedRef) => {
    return (
      <StyledAvatarWrapper badge={badge} size={size}>
        <StyledAvatar {...props} ref={fwdedRef} variant={variant}>
          {av}
        </StyledAvatar>
      </StyledAvatarWrapper>
    );
  },
);

I have typescript in the root config set with:

"jsx": "react-jsx"

I can build this without packemon without getting the warning in the title (via rollup or vite or something), but am having trouble finding whichever setting is causing this to happen in packemon.

My invocation in my moon.yml file is more or less lifted from the example repo:

tasks:
  # https://moonrepo.dev/docs/guides/examples/packemon
  build:
    command:
      - 'packemon'
      - 'pack'
      - '--addEngines'
      - '--addExports'
      - '--declaration'
    inputs:
      - '@globs(sources)'
      - 'package.json'
      - 'tsconfig.*.json'

the errors log out twice, presumably once for tsconfig.esm.json and once for tsconfig.lib.json.

I believe it's happening on every file that has a destructured react import like import {useRef} from 'react';

Running latest version of packemon.

I appreciate the help, just a pointer in a direction works for me if that's all you have time for πŸ™ .

`packemon build` doc is outdated?

packemon v2 removed multiple formats option.
https://packemon.dev/docs/migrate/2.0#removed-multiple-format-support-when-configuring-a-package
#119

However, packemon build docs has referred multiple formats option.

"formats": ["lib", "esm", "umd"],
https://packemon.dev/docs/build#how-it-works

Actually, This example configuration looks like invalid.

❯ npm run build

> [email protected] build
> packemon build


 ERROR

 The following validations have failed for `packemon-build-formats`:
   - Unknown fields: formats.

[4.0] Packemon ignores tsconfig `outDir`

Since there's only one format in v4, I kinda expected it to follow tsconfig outDir. It's fine if it doesn't, but how do I configure packemon's output to lib instead of mjs?

Add configuration options as parameters to `scaffold`

Hi there! Thanks for the awesome tool :)

I'm automating the creation of packages inside my company and would like to pass author, project-name, and repositoryUrl to the scaffold command.

Also, I'd like to suggest that inside monorepos that are already git repositories the repository URL could be automatically detected ;)

Flag to build only one endpoint

Would it possible to add a cli flag to only build one package. Having a case where I have just adjusted one of the entry points and want to test it out now so no need to build out the other packages.

e.g.

packemon build --only bin

Thanks :)

Question: React component library

Howdy Miles,

I am building a design system and using packemon for my bundler. I have a package that contains all of my react components, and I'm wondering about the recommended setup for optimal tree-shaking for such a package. By default, packemon supports tree-shaking by utilizing pure annotations, which gets me most of the way there.

One goal I would like to accomplish is individual component imports:

import Component from '@package/react/Component`;

After reading through the documentation the two solutions I've identified are:

  1. Create an input for each component.
  2. Override the default Rollup config to add inputs for each component.

I just want to make sure I'm going down the right path and there isn't something glaringly obvious I'm missing.

Thanks in advance!

Bug: Assets are not being bundled properly when using esm bundle format

Version: [email protected]

The esm format with bundling tries to copy an invalid asset into an assets folder.

Running `packemon build --addExports --no-addFiles --declaration --quiet --loadConfigs` in ./my-app 

ERROR
ENOENT: no such file or directory, copyfile '/path/to/my-app/app.css' -> '/path/to/my-app/assets/app-92722f3f.css'

My hunch is that the asset import path in the generated index.js file is incorrectly set. That means when we are doing the pass to generate hashed assets for files, it fails because the file path doesn't exist. It should point to the appropriate file (in [email protected] it looks like it uses ../assets/style-somehash.css)

my-app/
β”œβ”€ assets/
β”‚  β”‚  β”œβ”€ app-somehash.css (generated)
β”œβ”€ src/
β”‚  β”œβ”€ app/
β”‚  β”‚  β”œβ”€ app.css
β”‚  β”‚  β”œβ”€ index.ts
β”‚  β”œβ”€ index.js (generated)
β”‚  β”œβ”€ index.ts

// src/index.js (generated file)
// Bundled with Packemon: https://packemon.dev
// Platform: browser, Support: stable, Format: esm

import 'app.css'; <=== This should probably be `../assets/app~somehash.css` or `./app/app.css`
function app() {
  console.log('app started');
}
export { app };
//# sourceMappingURL=index.js.map

Example repo: https://github.com/j3tan/packemon-asset-test

UNLICENSED package cannot pass license validation

npm allows for this when the package is set to private. Is there a path for packemon, or do i just need to run clean and build instead of pack?

error  ● Invalid license "UNLICENSED". Must be an official SPDX license type.

Transpile without rolling up to index.js

Hi Miles!

I have a project with the following file structure:

./src
β”œβ”€β”€ index.js
└── theme
    β”œβ”€β”€ KBarAnimator.jsx
    └── KBarCellAccessory.jsx

index.js doesn't import any of the files but I need files to be rendered individually instead of rolled up to a single file. I looked at the docs but wasn't clear how I could do this.

Thanks!

[4.0] Scaffold for polyrepo generates `tsconfig.build.json` but looks for `tsconfig.mjs.json`

To reproduce, scaffold a polyrepo then run packemon pack --declaration

packemon pack --declaration

 ERROR

 Command failed with exit code 1: tsc --declaration --declarationDir mjs --declarationMap --emitDeclarationOnly
 --project tsconfig.mjs.json
 error TS5058: The specified path does not exist: 'tsconfig.mjs.json'.

 STACK TRACE

    at makeError (file:///Users/svallory/Library/pnpm/global/5/.pnpm/[email protected]/node_modules/execa/lib/error.js:60:11)
    at handlePromise (file:///Users/svallory/Library/pnpm/global/5/.pnpm/[email protected]/node_modules/execa/index.js:124:26)
    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)
    at async Promise.all (index 0)
    at async Artifact.buildTypes (file:///Users/svallory/Library/pnpm/global/5/.pnpm/[email protected][email protected]/nod
e_modules/packemon/mjs/Artifact.mjs:134:5)
    at async Promise.all (index 1)
    at async Artifact.build (file:///Users/svallory/Library/pnpm/global/5/.pnpm/[email protected][email protected]/node_mod
ules/packemon/mjs/Artifact.mjs:59:5)
    at async file:///Users/svallory/Library/pnpm/global/5/.pnpm/[email protected][email protected]/node_modules/packemon/mj
s/Package.mjs:48:9
    at async Promise.all (index 1)
    at async Package.build (file:///Users/svallory/Library/pnpm/global/5/.pnpm/[email protected][email protected]/node_modu
les/packemon/mjs/Package.mjs:44:5)
    at async Packemon.build (file:///Users/svallory/Library/pnpm/global/5/.pnpm/[email protected][email protected]/node_mod
ules/packemon/mjs/Packemon.mjs:29:7)
    at async PackCommand.build (file:///Users/svallory/Library/pnpm/global/5/.pnpm/[email protected][email protected]/node_
modules/packemon/mjs/commands/Build.mjs:24:5)
    at async PackCommand.pack (file:///Users/svallory/Library/pnpm/global/5/.pnpm/[email protected][email protected]/node_m
odules/packemon/mjs/commands/Build.mjs:67:5)
    at async PackCommand.run (file:///Users/svallory/Library/pnpm/global/5/.pnpm/[email protected][email protected]/node_mo
dules/packemon/mjs/commands/Pack.mjs:9:5)
    at async Program.runAndRender (file:///Users/svallory/Library/pnpm/global/5/.pnpm/@[email protected][email protected]_react@1
[email protected]/node_modules/@boost/cli/mjs/Program.mjs:464:24)
    at async Program.run (file:///Users/svallory/Library/pnpm/global/5/.pnpm/@[email protected][email protected][email protected]_typ
[email protected]/node_modules/@boost/cli/mjs/Program.mjs:288:18)
    at async Program.runAndExit (file:///Users/svallory/Library/pnpm/global/5/.pnpm/@[email protected][email protected]_react@18.
[email protected]/node_modules/@boost/cli/mjs/Program.mjs:307:22)
    at async run (file:///Users/svallory/Library/pnpm/global/5/.pnpm/[email protected][email protected]/node_modules/packem
on/mjs/bin.mjs:39:3)

[RFC] Version 3.0

My current thoughts on the next major.

Drop Node.js 12

With Node.js v18 going LTS in October, we can drop v12 and shift all version support to the left. v14 will be the new legacy, v16 the new stable, v18 current, and v19? experimental.

Rollup v3

Rollup v3 will be landing shortly: https://twitter.com/lukastaegert/status/1564890445972492288

No more workspaces support

Packemon was initially designed to run from the repo root, and build all packages in the workspace. This has overly complicated the codebase. In v3, Packemon will only build the project with a package.json in the current directory.

If you need workspaces support, use a package manager or build system that builds across many projects.

No more React rendered output

We use Ink (React) to render a very nice looking terminal output. However, this is much slower than simply running in the background, as it's constantly re-rendering the screen. Instead, we will only log to the console when a package is built.

Ship modules

Since Packemon isn't consumed like a standard library, and is purely ran as a binary, we can ship a full ESM package using .mjs files. We should see a slight performance gain with this approach.

Merge code and type artifacts

Our current architecture separates code bundling (rollup) and type declaration generation (typescript) into distinct "artifacts", CodeArtifact and TypesArtifact respectively. While this made sense in the beginning, it has actually resulted in a much more complicated implementation, as they have no context into each other. This is problematic in regards to exports generation and entry point resolution.

In v3, these will be merged into a single layer that produces all the outputs in parallel, while keeping context accurate and in sync.

tsconfig.json automatically inferred

This is the biggest change in v3 that will most likely cause the most disruption. In v2, when generating declarations, Packemon will use the closest tsconfig.json (or a custom config via --declarationConfig). For the most part, this made sense and just worked. However, with TypeScript v4.7 and the introduction of .cts and .mts files, this approach will no longer work, for the following reason:

If a Packemon package is building multiple formats (for example: cjs, esm, lib), a single tsconfig.json is no longer applicable, as TS generates different .d.ts files based on the source file extension. We also now have .d.cts and .d.mts files.

Because of this, Packemon will now require a unique tsconfig for each format being built, and will automatically assume the name based on the format. For example, building an esm package will use tsconfig.esm.json, and a cts package will use tsconfig.cts.json, so on and so forth.

This also means that the dts folder will go away, as the declarations will now live alongside their compiled files. It also means that builds will get slower the more formats you have, as we are doing N tsc compilations instead of just one.

Add electron support

I'd say it's about time to support electron. Babel supports it: https://babeljs.io/docs/en/babel-preset-env#browserslist-integration As does swc: https://swc.rs/docs/configuration/supported-browsers#targets

Add debugging

Add a --debug option that helps debug what's going on.

Disable sourcemaps for Node.js

These aren't really necessary. The new defaults will be:

node - no bundle, no sourcemaps
native - no bundle, sourcemaps
browser - bundle, sourcemaps

Sourcemaps don't seem to be generated correctly

Tested on a file utils.js with utils.js.map

Then used source-map-explorer utils.js utils.js.map (https://www.npmjs.com/package/source-map-explorer)
And I get this error:

source-map-explorer utils.js utils.js.map       

utils.js
  Your source map refers to generated column 9 on line 9, but the source only contains 1 column(s) on that line.
  Check that you are using the correct source map.

Verified the same result using https://www.npmjs.com/package/source-map with script sm.js

It expects line 9 to be the base64encode line, but base64encode is actually on line 7 in the generated code
image

image

Is it possible to disable asset imports?

I am using vanilla extract, which imports .ts files called foo.css.ts

So in application code, it ends up looking like an asset import and triggers that pipeline.

import {vanillaExtractClass} from './file.css';

Then if I run packemon against a library that uses this:

ENOENT: no such file or directory, copyfile
 '/Users/alex/project/packages/@project/ui/src/Badge.css' ->
 '/Users/alex/project/packages/@project/ui/assets/Badge-70d967
 b6.css'

Presumably because there is no .css file. It's referring to a .css.ts file and the normal import behavior is what i'm after.

I don't actually need this feature, so it'd be fine if I could somehow disable it, or minimally disable it for .css files. My guess is there's some way to inject a rollup config override, but I haven't found the exact right magic.

Babel Error: `@babel/plugin-proposal-private-property-in-object ` explicit dependency

Hitting a newly introduced error message in babel version 7.22.5 causes the following error:

--- PLACEHOLDER PACKAGE ---
This @babel/plugin-proposal-private-property-in-object version is not meant to
be imported. Something is importing
@babel/plugi-proposal-private-property-in-object without declaring it in its
dependencies (or devDependencies) in the package.json file.
Add "@babel/plugin-proposal-private-property-in-object" to your devDependencies
to work around this error. This will make this message go away.

Since packemon uses @babel/plugin-proposal-private-property-in-object for babel config, it needs to explicitly declare it as a dependency.

[resolveFromBabel('@babel/plugin-transform-private-property-in-object'), { loose: true }],

Related:
https://github.com/babel/babel-plugin-proposal-private-property-in-object
babel/babel#15687
babel/babel#15694

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined when use cjs/mjs config

@file-cache has used packemon for packaging.

And, packemon config is following.

  "packemon": [
    {
      "inputs": {
        "index": "./src/index.ts"
      },
      "platform": "node",
      "format": "cjs"
    },
    {
      "inputs": {
        "node": "./src/index.ts"
      },
      "platform": "node",
      "format": "mjs",
      "support": "experimental"
    }
  ],

https://github.com/azu/file-cache/blob/26d5a23128bfcb5680c007fedc5607c737a87780/packages/core/package.json#L13-L29

I aim to publish dual package CJS/MJS.
I've published this package, but this package can not be required from CJS.

It means that require("@file-cache/core") throw an error.

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined

Expected

No Error on require("@file-cache/core")

Actual

Can not require("@file-cache/core").
However, import * from "@file-cache/core" is work.

node:internal/modules/cjs/loader:488
      throw e;
      ^

Error [ERR_PACKAGE_PATH_NOT_EXPORTED]: No "exports" main defined in /Users/azu/ghq/github.com/azu/packemon-require-filed-missing/node_modules/@file-cache/core/package.json
    at new NodeError (node:internal/errors:372:5)
    at throwExportsNotFound (node:internal/modules/esm/resolve:472:9)
    at packageExportsResolve (node:internal/modules/esm/resolve:693:7)
    at resolveExports (node:internal/modules/cjs/loader:482:36)
    at Function.Module._findPath (node:internal/modules/cjs/loader:522:31)
    at Function.Module._resolveFilename (node:internal/modules/cjs/loader:919:27)
    at Function.Module._load (node:internal/modules/cjs/loader:778:27)
    at Module.require (node:internal/modules/cjs/loader:1005:19)
    at require (node:internal/modules/cjs/helpers:102:18)
    at Object.<anonymous> (/Users/azu/ghq/github.com/azu/packemon-require-filed-missing/index.js:1:1) {
  code: 'ERR_PACKAGE_PATH_NOT_EXPORTED'
}

Details

Published @file-cache/core/package.json is following:

  "types": "./dts/index.d.ts",
  "main": "./cjs/index.cjs",
  "exports": {
    "./package.json": "./package.json",
    "./*": {
      "types": "./dts/*.d.ts",
      "node": {
        "import": "./mjs/*.mjs"
      }
    },
    ".": {
      "types": "./dts/index.d.ts",
      "node": {
        "import": "./mjs/index.mjs"
      }
    }
  }

I've noticed that that Conditional exports does not define require field like "require": "./cjs/index.cjs".

I mofify node_modules/@file-cache/core/package.json directory and require("@file-cache/core") is work.

  "types": "./dts/index.d.ts",
  "main": "./cjs/index.cjs",
  "exports": {
    "./package.json": "./package.json",
    "./*": {
      "types": "./dts/*.d.ts",
      "node": {
        "import": "./mjs/*.mjs"
      }
    },
    ".": {
      "types": "./dts/index.d.ts",
      "node": {
        "import": "./mjs/index.mjs"
+       "require": "./cjs/index.cjs"
      }
    }
  }

packemon format the exports field automatically. So I can not add require or default property to node.

Reproduce repository

Env

Note

How to disable Dynamic Import transform on CJS?

It looks like that packemon transform import() to require().

index.ts

const main = async () => {
    const pkgDir = await import("pkg-dir");
    console.log(await pkgDir.packageDirectory());
}
main();

to be index.cjs

'use strict';

function _interopNamespace(e) {
  if (e && e.__esModule) return e;
  const n = Object.create(null);

  if (e) {
    for (const k in e) {
      if (k !== 'default') {
        const d = Object.getOwnPropertyDescriptor(e, k);
        Object.defineProperty(n, k, d.get ? d : {
          enumerable: true,
          get: () => e[k]
        });
      }
    }
  }

  n.default = e;
  return Object.freeze(n);
}

const main = async () => {
  const pkgDir = await Promise.resolve().then(() => /*#__PURE__*/_interopNamespace(require('pkg-dir')));
  console.log(await pkgDir.packageDirectory());
};

main();
//# sourceMappingURL=index.cjs.map

I want to use native import() in CJS because it is only way to load ESM from CJS package.

Expected

The output use native import()

Actual

The output use require()

Config

  "scripts": {
    "build": "packemon pack --addEngines --addExports --declaration --declarationConfig tsconfig.json",
    "tsc:build": "tsc"
  },
  "packemon": [
    {
      "inputs": {
        "index": "./src/index.ts"
      },
      "platform": "node",
      "format": "cjs"
    },
    {
      "inputs": {
        "node": "./src/index.ts"
      },
      "platform": "node",
      "format": "mjs"
    }
  ],

https://github.com/azu/packemon-native-dynamic-import/blob/7b3d57b410f3e7d1f2aa8c6549af4c0dff9fdd22/package.json#L7-L26

Reproduce Repository

https://github.com/azu/packemon-native-dynamic-import

This repo use TypeScript and set "module": "NodeNext".
tsc output includes import() expectly.

Workaround

Use new Function

const _importDynamic = new Function("modulePath", "return import(modulePath)");

packemon 4 version is still `0.0.0-internal`

❯ pnpm i -g packemon
 WARN  GET https://registry.npmjs.org/@babel%2Fpreset-flow error (ENOTFOUND). Will retry in 10 seconds. 2 retries left.
 WARN  12 deprecated subdependencies found: @npmcli/[email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected], [email protected]
Packages: +189
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Progress: resolved 2475, reused 2407, downloaded 4, added 16, done
.pnpm/@[email protected]_@[email protected]/node_modules/@swc/core: Running postinstall script, done in 1s

/Users/svallory/Library/pnpm/global/5:
+ packemon 4.0.0

 WARN  Issues with peer dependencies found
.
β”œβ”€β”¬ generator-langium 2.1.0
β”‚ └─┬ yeoman-generator 5.9.0
β”‚   └─┬ mem-fs-editor 9.7.0
β”‚     └── βœ• unmet peer mem-fs@^2.1.0: found 4.0.0
β”œβ”€β”¬ @yeoman/types 1.1.2
β”‚ └── βœ• unmet peer mem-fs@^3.0.0: found 4.0.0
└─┬ skuba 7.3.1
  └─┬ fdir 6.1.1
    └── βœ• unmet peer [email protected]: found 2.3.1

Done in 19.9s

❯ packemon -v
0.0.0-internal

`packemon build` set the wrong `main` field

I have used following config.

  "packemon": [
    {
      "inputs": {
        "index": "src/some.ts"
      },
      "format": "esm",
      "platform": "browser"
    },
    {
      "inputs": {
        "index": "src/some.ts"
      },
      "format": "cjs",
      "platform": "node"
    }
  ],

Then, run packemon build and packemon set the wrong main field

  "main": "./cjs/index.cjs",
  "module": "./esm/index.js",

./cjs/index.cjs is not found.
Actually, packemon build generate ./cjs/some.cjs.

Actual

  "main": "./cjs/index.cjs",

Expected

  "main": "./cjs/some.cjs",

Workaround

Use src/index.ts as inputs

Web builds should polyfill node libraries

Currently building a nodejs project that the path module:

The web output (esm/web.js) currently has this import:

...
// Generated with Packemon: https://packemon.dev
// Platform: browser, Support: current, Format: esm
import { relative, dirname, join, posix, resolve, basename, isAbsolute } from 'path';
...

This first of all breaks parsing as browsers do not like non relative import paths (Uncaught TypeError: Failed to resolve module specifier "path". Relative references must start with either "/", "./", or "../")

It also is not a valid import as the path module library is not available in browsers. It would great if it could "polyfill" / "shim" the path module similar to webpack for web builds

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.