How to import a token from another extension?

I am building two extensions. One of the extensions depends on the other extension. When I import the token from one extension in order to include it in the requires list of the JupyterFrontEndPlugin object, TypeScript gives the following error:

Type 'Token<IAWSAPIGatewayHandler>' is not assignable to type 'Token<any>'.
  Types have separate declarations of a private property '_tokenStructuralPropertyT'.

Does anyone have any guidance on how to address this issue?

I was able to prevent this error from arising by copying just the lib folder and package.json file into the respective directory in the node_modules directory - but I think I’m doing it wrong, as the extension isn’t able to load the service.

If the two packages are being built in the same repo, I highly recommend lerna (used on lab core and widgets). Such a repo will usually look like:

package.json       # will have `lerna`
lerna.json         # usually <7 lines
tsconfigbase.json  # all those compilerOptions
    tsconfig.json  # extends ../../tsconfigbase.json
    package.json   # with a `dependency` on `@ns/token-producer`
    tsconfig.json  # with a `reference` to `../token-producer` and extends

A slightly more advanced pattern is to have a metapackage, as then you can just lerna run build @ns/metapackage and it will do a nice job.

There aren’t pithy examples of doing this, unfortunately, as one generally doesn’t need all this complexity… until you do. One i’m presently working on is ipydrawio which has a half-dozen extensions, shipped in two python packages, and uses the metapackage pattern.

I’m sorry for the confusion. These are two separate packages in two separate repos. I was able to prevent the error from arising, but I am pretty sure I am still doing something wrong, as the consumer cannot find the provider when JupyterLab runs.

This is the repo for the provider: GitHub - educational-technology-collective/etc-jupyterlab-aws-api-s3-handler

Do you see anything that doesn’t look right?

Ok, so again, a good look at core/widgets is going to help. Really, having the branch you’re planning to work against, e.g. 3.0.x checked out in a legit TypeScript editor experience makes this kind of sleuthing much more reasonable.

Anyhow, the pattern there is often something like:

  src/                      # doesn't have the `jupyter` key
    tokens.ts               # has the Token
    index.ts                # exports * from tokens
  package.json              # has the jupyter key, including sharedPackages
                            # "@ns/useful-feature": {"bundled": true, "singleton": true}
  plugin.ts                 # has the plugin that _provides_ the Token, commands, etc
  package.json              # whatever
  package.json              #  "@ns/useful-feature": {"bundled": false, "singleton": true}

Thank you for the explanation. Actually, what I was missing was the “bundled”: true. I just couldn’t get my head wrapped around what you were referring to by “@ns/useful-feature”, but I got it now. Thanks again for trying to communicate that to me.

1 Like