SPFx solution using PnPjs for Project Online REST API

SPFx Project SharePoint

If you know me or follow me on Twitter/LinkedIn, you must have realized by now how much I like the PnPjs library. Enough to venture myself to speak about it on 3 SharePoint Saturday events last year. The library has packages for SharePoint and Graph endpoints and can be easily used on SPFx solutions. But if you need an SPFx solution that consumes Project Online API, what options do you have?
Kudos to Paweł Hawrylak who started creating the Project module for PnPjs and currently already offers support for a wide range of endpoints. The module is currently in a dev branch and requires additional work and testing, but it’s already a phenomenal effort.

This blog post will cover the required steps to generate a local PnPjs Project package to consume Project Online REST APIs and create a SPFx web part that uses it.

Published npm packaged

2019-12-31 update
If you only want to give the current version a try, there is now a packaged published to npm that you can simply install. Don’t forget to also install the required dependencies of @pnp/common, @pnp/odata, @pnp/logging and you are ready to rock!

npm i pnpjs-project-online-package @pnp/common@1.3.7 @pnp/logging@1.3.7 @pnp/odata@1.3.7 --save-exact

Get the code from GitHub

2019-11-14 update: I now have a repository forked from the main PnPjs project where I added the code for the project module. The good news is that this is using the latest PnPjs version (1.3.7 at the time)

https://github.com/joelfmrodrigues/pnpjs/tree/feature/project-online-api

From here, you can download, clone or fork it, what ever makes sense for what you plan to do with it. Just be aware that if you plan to fork it to contribute, and you have also previously forked the original PnPjs repository, you may need to delete the last and fork after that.
You can find the original code under Paweł’s GitHub fork of the main PnPjs project on GitHub.

Build PnPjs packages

Since we have the PnPjs source code, we need to build and generate local packages. You can get additional information of the PnPjs gulp commands on the official documentation.

Run the following commands in the order specified:

  1. npm install – to install the npm packages required by PnPjs
  2. gulp build – to ensure that the solution can build successfully
  3. gulp package – to generate all the different library packages, including the new Project package

Peer dependencies

We are going to install the local Project package that we have just build in our SPFx solution. Unfortunately, the peer dependencies don’t seem to work as expected when you do so and you get errors when trying to use the packages on your web part.
If you inspect the package.json file for the Project package created (dist/packages/project), you can find the following required peerDependencies which are not resolved by default

  "peerDependencies": {
        "@pnp/common": "1.3.7",
        "@pnp/logging": "1.3.7",
        "@pnp/odata": "1.3.7"
    },

Not the ideal solution for sure, but a simple way to get around this problem is to simply install the packages yourself.
Remember that we are only testing the new Project package and all the others are kept untouched, so seems sensible to me to install them directly from npm.
Ensure that your command prompt is on the
dist/packages/project directory and run the following command

npm install @pnp/common@1.3.7 @pnp/logging@1.3.7 @pnp/odata@1.3.7

The Project package is now ready to be consumed by our solution.

Create new SPFx solution

I’m not going to provide any specific instructions here as the official documentation is excellent and give you all the information you need. If you are new to SharePoint Framework development, please check it out and learn how to get started.

Add PnPjs packages to SPFx solution

Again, remember that Project is the only package that is not published to npm, so is the only one that we need to install from a local path.
Start by installing all the common PnPjs packages that you usually install. In this case I’m using the 1.2.5 version as it’s the version that matches the local version.

npm install @pnp/common@1.3.7 @pnp/logging@1.3.7 @pnp/odata@1.3.7 --save-exact

Next, install the local Project package by providing a relative path to the package folder. In my example:

npm install ../PnPjs/dist/packages/project

Establish Context

Following the official guidance, we also need to establish the context when using the library in SPFx. Simply add the following block of code into your web part main file as provided on the documentation:

import { project } from "pnpjs-project-online-package"; // or import from your local package for development

// ...

public onInit(): Promise<void> {

  return super.onInit().then(_ => {

    // other init code may be present

    project.setup({
      spfxContext: this.context,
      project: {
        baseUrl: 'https://XXXXXXXXXX.sharepoint.com/sites/pwa'
      }
    });
  });
}

// ...

Please note that we are setting the baseUrl property to be the PWA site. This is to allow the solution to work from any SharePoint sites, not only Project Online.

Use it!

It’s all done and you can now use the fluent library to interact with project online!
All you need to do is to import the Project package when you need it

import { project } from "@pnp/project";

Some usage examples:

// get all projects
const projects = await project.projects.get();

// get projects, filtering by name, returning only the Id and Name properties, and limiting the results count to 1
const projectInfo = await project.projects.filter(`Name eq '${projectName}'`).select('Id,Name').top(1).get();

// create timesheet
const createResult = await project.timeSheetPeriods.getById('XXXXXXXXXXXXXXXX').createTimeSheet();