Using PnP-JS-Core (sp-pnp-js) in Node.js environment

PnP-JS-Core ❤ Node.js

Do you know what is PnP-JS-Core? I hope so. If don’t know about PnP-JS-Core, here is a quick overview:

The Patterns and Practices JavaScript Core Library was created to help developers by simplifying common operations within SharePoint and the SharePoint Framework. Currently it contains a fluent API for working with the full SharePoint REST API as well as utility and helper functions. This takes the guess work out of creating REST requests, letting developers focus on the what and less on the how.

In other words that’s an wrapper over SharePoint REST API as well as other helper functions. PnP-JS-Core can speedup your development by providing a lot of useful functions, utilities, operators and objects to work with SharePoint. For example consider how it’s easy to do some routine operations:

pnp-js-core experience

I really recommend you to take a look at the official github repository here - https://github.com/SharePoint/PnP-JS-Core as well as wiki

The main purpose for PnP-JS-Core is using inside browser. You include sp-pnp-js into your html and you are ready to go. But the library is designed with extensibility and supportability in mind. That means you can run PnP-JS-Core not only in browser, but in Node.js environment too. Hmmm…. why do you need this, you might ask. Nowadays Node.js integrates in your development pipeline more and more. Do you know gulp, webpack, browserify, etc.? All this tools run on Node.js. With Node.js you can build any type of application – web applications, desktop (cross platform!) apps, micro services, Azure functions and many many other things. Sometimes you need to interact with SharePoint from you Node.js application. Ideally you would like to utilize PnP-JS-Core for that task as well. Meet node-pnp-js which will help you.

As you might guess the main issue when working with SharePoint from Node.js is authentication. When using inside browser, current user is already authenticated and you can use the library as is. For Node.js situation is different. There is no authenticated user and you have to implement authentication by your own. node-pnp-js uses my other library node-sp-auth as authentication provider. In the past I’ve created a sample of integration PnP-JS-Core and Node.js and node-pnp-js is just a logical continuation designed as a separate reusable package.

So let’s get started!

In order to install run

npm install node-pnp-js --save

Now a few words about PnP-JS-Core configuration mechanism. There is a special method called pnp.setup allowing you to set some global configuration parameters for PnP-JS-Core library. These parameters also include fetchClientFactory – factory method returning a class responsible for making actual http requests. When using in browser, built-in fetch client uses fetch API. This is something not available out of the box for Node.js, but hopefully there is module node-fetchnode-pnp-js implements  it’s own version of fetchClientFactory with node-fetch and authentication coming from node-sp-auth.

What you need to do next is to set custom fetchClientFactory  supplied from node-pnp-js using pnp.setup:

import * as pnp from 'sp-pnp-js';
import NodeFetchClient from 'node-pnp-js';

pnp.setup({
        fetchClientFactory: () => {
            return new NodeFetchClient(credentials);
        }
    });

That’s it. Now you can use PnP-JS-Core in your Node.js app without problems. node-sp-auth supports many different authentication options, please use wiki to see different options as well as configuration required.

Sample usage:

new pnp.Web('https://your.sharepoint.com/sites/yoursite').get()
    .then(data => {
        console.log(`Your web title: ${data.Title}`);
    })

A few words about setting up SharePoint site urls. There are three ways how you can provide your SharePoint site url.

1. You can use Site or Web constructor:

pnp.setup({
        fetchClientFactory: () => {
            return new NodeFetchClient(credentials);
        }
    });

new pnp.Web(siteUrl).get()
    .then(data => {
        console.log(`Your web title: ${data.Title}`);
    })

2. You can set baseUrl for pnp.setup:

pnp.setup({
        fetchClientFactory: () => {
            return new NodeFetchClient(credentials);
        },
        baseUrl: siteUrl
    });

// now you can access your web using chaining syntax 
// (pnp.sp.web will reference the web with url you provided as baseUrl):
pnp.sp.web.get()
    .then(data => {
        console.log(`Your web title: ${data.Title}`);
    })

3. You can also use siteUrl constructor param for NodeFetchClient:

pnp.setup({
        fetchClientFactory: () => {
            return new NodeFetchClient(credentials, siteUrl);
        }
    });

// now you can access your web using chaining syntax 
// (pnp.sp.web will reference the web with url you provided as siteUrl param):
pnp.sp.web.get()
    .then(data => {
        console.log(`Your web title: ${data.Title}`);
    })

Basically that’s it, you see it’s not so difficult to add PnP-JS-Core to Node.js. New features are coming to node-sp-auth in a future thus you will have more options when developing Node.js applications.