简体   繁体   中英

How to use alternative implementation for npm packages to use Atlaskit without accepting Atlassian Design Guidelines License

Most of the Atlaskit editor is licensed with MIT or Apache 2.0 License. I'm trying to figure out how Atlaskit is supposed to be used without accepting non-free (as in freedom) Atlassian Design Guidelines License (ADG License) which is used for packages @atlaskit/icon , @atlaskit/icon-file-type and @atlaskit/icon-object which are part of deeply nested dependencies for the Atlaskit editor.

I'm fully aware that I need to re-create alternative icons and themes and I'm fine with that. However, when I create package.json and run npm install I get the above mentioned ADG licensed packages when I include following dependencies:

...
"dependencies": {
    "@atlaskit/editor-core": "^120",
    "@atlaskit/media-core": "^31",
    "@atlaskit/smart-card": "^13",
    ...

How can I pass my own implementation to be used eg instead of ADG licensed default @atlaskit/icon from npmjs.com?

Forking the whole Atlaskit package tree just to modify dependencies to override these 3 packages is obviously possible but is there a better way? It seems that npm-force-resolutions can do something like this but as far as I know, it only allows replacing the dependency version number so I could simply select which official implementation of eg @atlaskit/icon I would like to use but that doesn't allow changing to totally different implementation. All versions of @atlaskit/icon have identical license and I'm trying to do this because I don't like ADG license and I'm willing to reimplement the required parts.

I would prefer something that I can save in main level package.json (or in a file next to it) where I require other atlaskit dependencies. I'm using node v12 in case it makes a difference. I don't need to support any lesser version but I'd like to be compatible with v14, too.

Update : given above dependencies, npm list "@atlaskit/icon" will emit

my-atlaskit-editor@0.0.1 /local/path/to/my/editor
├─┬ @atlaskit/editor-core@120.1.2
│ ├─┬ @atlaskit/calendar@9.2.10
│ │ └── @atlaskit/icon@20.1.2  deduped
│ ├─┬ @atlaskit/checkbox@10.1.14
│ │ └── @atlaskit/icon@20.1.2  deduped
│ ├─┬ @atlaskit/datetime-picker@9.4.7
│ │ ├─┬ @atlaskit/field-base@14.0.5
│ │ │ └── @atlaskit/icon@20.1.2  deduped
│ │ └── @atlaskit/icon@20.1.2  deduped
│ ├─┬ @atlaskit/droplist@10.0.8
│ │ └── @atlaskit/icon@20.1.2  deduped
│ ├─┬ @atlaskit/editor-common@44.1.0
│ │ ├── @atlaskit/icon@20.1.2  deduped
│ │ ├─┬ @atlaskit/media-picker@54.2.3
│ │ │ ├─┬ @atlaskit/flag@12.4.5
│ │ │ │ └── @atlaskit/icon@20.1.2  deduped
│ │ │ ├── @atlaskit/icon@20.1.2  deduped
│ │ │ └─┬ @atlaskit/media-card@68.0.2
│ │ │   └── @atlaskit/icon@20.1.2  deduped
│ │ └─┬ @atlaskit/profilecard@12.4.4
│ │   ├─┬ @atlaskit/avatar@18.0.2
│ │   │ └── @atlaskit/icon@20.1.2  deduped
│ │   └── @atlaskit/icon@20.1.2  deduped
│ ├─┬ @atlaskit/editor-markdown-transformer@3.1.25
│ │ └─┬ @atlaskit/editor-common@46.1.1
│ │   ├── @atlaskit/icon@20.1.2  deduped
│ │   ├─┬ @atlaskit/media-card@68.0.2
│ │   │ └── @atlaskit/icon@20.1.2  deduped
│ │   └─┬ @atlaskit/media-picker@54.2.3
│ │     ├─┬ @atlaskit/flag@12.4.5
│ │     │ └── @atlaskit/icon@20.1.2  deduped
│ │     └── @atlaskit/icon@20.1.2  deduped
│ ├─┬ @atlaskit/emoji@62.8.4
│ │ └── @atlaskit/icon@20.1.2  deduped
│ ├─┬ @atlaskit/form@7.4.1
│ │ └── @atlaskit/icon@20.1.2  deduped
│ ├── @atlaskit/icon@20.1.2 
│ ├─┬ @atlaskit/media-card@67.2.3
│ │ ├── @atlaskit/icon@20.1.2  deduped
│ │ └─┬ @atlaskit/media-viewer@44.4.4
│ │   └── @atlaskit/icon@20.1.2  deduped
│ ├─┬ @atlaskit/media-editor@37.0.12
│ │ ├── @atlaskit/icon@20.1.2  deduped
│ │ └─┬ @atlaskit/media-card@68.0.2
│ │   └── @atlaskit/icon@20.1.2  deduped
│ ├─┬ @atlaskit/media-filmstrip@38.0.4
│ │ ├── @atlaskit/icon@20.1.2  deduped
│ │ └─┬ @atlaskit/media-card@68.0.2
│ │   └── @atlaskit/icon@20.1.2  deduped
│ ├─┬ @atlaskit/media-picker@54.2.3
│ │ ├─┬ @atlaskit/flag@12.4.5
│ │ │ └── @atlaskit/icon@20.1.2  deduped
│ │ ├── @atlaskit/icon@20.1.2  deduped
│ │ └─┬ @atlaskit/media-card@68.0.2
│ │   └── @atlaskit/icon@20.1.2  deduped
│ ├─┬ @atlaskit/mention@18.18.3
│ │ ├─┬ @atlaskit/avatar@18.0.2
│ │ │ └── @atlaskit/icon@20.1.2  deduped
│ │ └── @atlaskit/icon@20.1.2  deduped
│ ├─┬ @atlaskit/modal-dialog@10.6.4
│ │ └── @atlaskit/icon@20.1.2  deduped
│ ├─┬ @atlaskit/radio@3.2.3
│ │ └── @atlaskit/icon@20.1.2  deduped
│ ├─┬ @atlaskit/select@11.0.14
│ │ └── @atlaskit/icon@20.1.2  deduped
│ ├─┬ @atlaskit/status@0.9.25
│ │ └── @atlaskit/icon@20.1.2  deduped
│ └─┬ @atlaskit/task-decision@16.1.2
│   └── @atlaskit/icon@20.1.2  deduped
├─┬ @atlaskit/media-picker@54.2.3
│ ├─┬ @atlaskit/dropdown-menu@9.0.6
│ │ └── @atlaskit/icon@20.1.2  deduped
│ ├─┬ @atlaskit/flag@12.4.5
│ │ └── @atlaskit/icon@20.1.2  deduped
│ ├── @atlaskit/icon@20.1.2  deduped
│ ├─┬ @atlaskit/media-card@68.0.2
│ │ └── @atlaskit/icon@20.1.2  deduped
│ └─┬ @atlaskit/media-ui@12.5.1
│   ├─┬ @atlaskit/avatar@18.0.2
│   │ └── @atlaskit/icon@20.1.2  deduped
│   └── @atlaskit/icon@20.1.2  deduped
└─┬ @atlaskit/smart-card@13.5.1
  └── @atlaskit/icon@20.1.2  deduped

Is it possible to replace just package @atlaskit/icon without replacing all the packages in the tree between my-atlaskit-editor and @atlaskit/icon . In this example it would be following list:

@atlaskit/avatar
@atlaskit/calendar
@atlaskit/checkbox
@atlaskit/datetime-picker
@atlaskit/dropdown-menu
@atlaskit/droplist
@atlaskit/editor-common
@atlaskit/editor-core
@atlaskit/editor-markdown-transformer
@atlaskit/emoji
@atlaskit/field-base
@atlaskit/flag
@atlaskit/form
@atlaskit/media-card
@atlaskit/media-editor
@atlaskit/media-filmstrip
@atlaskit/media-picker
@atlaskit/media-ui
@atlaskit/media-viewer
@atlaskit/mention
@atlaskit/modal-dialog
@atlaskit/profilecard
@atlaskit/radio
@atlaskit/select
@atlaskit/smart-card
@atlaskit/status
@atlaskit/task-decision

That's lots of packages to override just to change the dependencies in nested packages. In practice, I would need to fork all those packages and change dependencies of each nested package to refer to my forked version which again has only modified dependencies pointing to yet another package forked by me. At the leaf of this whole replaced tree would be a package.json that points to free variants of @atlaskit/icon , @atlaskit/icon-file-type and @atlaskit/icon-object .

Is there really no way to fix this mess without forking and modifying dependencies in the whole tree?

NPM natively supports package aliases since version 6.9.0

So in your case you could take the following approach:

  "dependencies": {
    "@atlaskit/editor-core": "npm:another-editor-core@^1.0",
    "@atlaskit/media-core": "npm:another-media-core@^1.0",
    "@atlaskit/smart-card": "npm:another-smart-card@^1.0"
  }

This will have the effect of installing another-editor-core@^1.0 instead of @atlaskit/editor-core . Then when your code attempt to require @atlaskit/editor-core , another-editor-core will be required instead:

const editor = require("@atlaskit/editor-core") // this is actually another-editor-core

An easy way to manage that would be to create an org in npm so that you can have scoped packages like @my-org-name/editor-core

Edit:

As pointed in the comments, the solution above won't support transitive dependencies, but only direct dependencies.

It seems that this is currently not supported by npm even using npm-force-resolutions . After a bit of research I couldn't find any other tool that would make that work with npm.

However this is supported by yarn using selective dependency resolutions :

  "resolutions": {
    "@atlaskit/editor-core": "npm:another-editor-core@^1.0",
    "@atlaskit/media-core": "npm:another-media-core@^1.0",
    "@atlaskit/smart-card": "npm:another-smart-card@^1.0"
  }

So I see 3 options for you moving forward:

  1. Migrate to yarn (if your project allow this)
  2. Write a script that parse package-lock.json to override the resolved packages. That should not actually be that hard. The script could be run as a preinstall step, exactly like npm-force-resolutions
  3. Request this feature on npm-force-resolutions repo , possibly contributing to the repo yourself if familiar with clojure and time permit.

Good luck!

An alternative would be to create a private NPM package using the @atlaskit package as a base, then replacing the dependencies that with your own packages. See https://docs.npmjs.com/files/package.json for details on creating a package description andhttps://docs.npmjs.com/creating-and-publishing-private-packages for publishing a private package. You may want to consider using a tool to automate the update process to pull the latest @atlaskit package and create and publish your alternative.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM