Using Connect javascript API with npm/typescript

The Connect docs demonstrate how you can run the API using a script tag

<script src="https://connect-cdn.atl-paas.net/all.js"></script>

I went looking for the library in npm and found atlassian-connect-js - npm but it appears to have a different API. My attempt to get it working was

import AP from "atlassian-connect-js";

AP.context.getToken().then((token: any) => {
  console.log({token});
});

but context is undefined. How should I go about retrieving the token?

Because of security and “get you the latest version” reasons - you have to load all.js from connect-cdn.atl-pass.net. Loading locally could be done (not encouraged) - but you’d have to download it from connect-cd.atl-paas.net every once in a while.

/Daniel

Hey @danielwester, thanks for the pointer. Do you have any advice how to incorporate it into a typescript project? I’m a little confused because there’s @types/atlassian-connect-js - npm which has types matching the all.js API but I don’t see how they would be applied to the global AP.

It turns out the issue was having both atlassian-connect-js and @types/atlassian-connect-js installed at the same time. Once I removed the atlassian-connect-js dependency the following started working with the globally defined AP from the all.js script.

import { AP } from "atlassian-connect-js";

AP.context.getToken().then((token: any) => {
  console.log({token});
});
2 Likes

I don’t think the atlassian-connect-js package is meant to be used client-side. This is the server-side implementation running in the host product. Not sure why they chose to publish it on NPM :thinking:

Keep in mind that the @types/atlassian-connect-js are community maintained, these are not official types. If you have questions about the typing, it’s best to contact @tobitheo.

1 Like

Hey @remie yes that does appear to be the source of the confusion here. @types/atlassian-connect-js is the types for all.js but the atlassian-connect-js package is, as you mention, intended for the backend so it has an entirely different API.

My instructions above turned out to be incomplete as they fixed the compile errors but resulted in a runtime error. To get it working I added

src/@types/global.d.ts

import AtlassianConnect from "atlassian-connect-js";

declare global {
  const AP: typeof AtlassianConnect.AP;
}

This makes the AP namespace globally available so you can just refer to it in typescript without an import. This assumes that you’ve made the AP global available by importing all.js using a script tag.

3 Likes

What we tend to do is import the @types/atlassian-connect-js package in our tsconfig.json:

{
  "compilerOptions": {
    "types": [
      "react",
      "jest",
      "atlassian-connect-js"
    ],
    ...
  },
  ...
}

This way, typescript will will pick up the globally defined types in the package without having to have atlassian-connect-js installed.

Also, @joshp actually started the package I believe, so he’s also a good person to talk to.

Hey @tobitheo, I gave this a go but typescript isn’t able to resolve the global without the additional global declaration I had above. Looking at DefinitelyTyped/index.d.ts at master · DefinitelyTyped/DefinitelyTyped · GitHub I don’t see it added to the global namespace so I’m not entirely surprised. I’ve never used a package that uses namespaces before though so I’m unfamiliar with the options around them. Maybe there’s a tsconfig option that adds namespaces to the global namespace automatically?

We use this to make sure the namespace is globally available:

export {};

declare global {

  namespace AP {
  ...
  }
}

The reason for this is that the file is not included as a module unless it exports something, so it is just being ignored.

Also, it should not be required to add it to types in your tsconfig. From the TS documentation:

By default all visible ”@types” packages are included in your compilation. Packages in node_modules/@types of any enclosing folder are considered visible. For example, that means packages within ./node_modules/@types/, ../node_modules/@types/, ../../node_modules/@types/, and so on.

If types is specified, only packages listed will be included in the global scope.

@opsb Thank you, this helped me a lot!

1 Like

Interesting. I wonder why this is working for us… :sweat_smile:

I think it is working because you have populated the types config parameter with the packages of which you expect global typings. However, this also means that when you add new @types packages with global scope, you will have to adjust your tsconfig file, whereas that would not be required if you did not specify the types config parameter.

It is even more interesting that you can actually achieve a combination of both by removing types and adding include. For instance, we use @types typings, but we also have our own private global typings in our private packages. In our tsconfig we do not specify types, but we do have:

  "include": [
    "./src/**/*.ts",
    "./typings/*.d.ts",
    "./typings/**/*.d.ts",
    "../node_modules/@collabsoft-net/**/*.d.ts"
  ],

which will make these typings available to us in our projects, including the global ones.

Thanks for tagging me @tobitheo!

@opsb you’re totally correct that it’s confusing that the type definitions don’t exactly match the existing atlassian-connect-js package on NPM. When adding types to DefinitelyTyped, you are required to name the types with the name of an existing npm package, and I came to the same conclusion as @remie that the atlassian-connect-js was the implementation inside Atlassian infrastructure, and that it was the most appropriate name for these type definitions.

I’ve just put together a sample repository which uses the global AP in a react project with needing to explicitly reference @types/atlassian-connect-js in case it’s useful to anyone:

2 Likes