Monthly Archives: August 2016

Updating your Node.js environment

I have used to use Windows Update and Visual Studio Extensions and Updates feature. Now the problem is that keeping your Node.js environment up-to-date is not possible using those tools.

There are couple package managers available for Windows, but there are no “native” for example PowerShell command that could be executed. I don’t like to use a tool for just single task.

Node.js

You can see Node.js version number when you start Node.Js Command Prompt

UpdateNodeJs_NodeJsVersionNumber

So far the easiest way to update your Node.js to download installer from Node.js web site from https://nodejs.org/en/download/. Note that there are two versions available LTS and Current. LTS stands for Long Term Support. Now I’m currently running the latest version of Node.js so I don’t need to update it.

UpdateNodeJs_DownloadNodeJsLTS

If you select LTS (it’s selected by default), you can see that Current version is v.4.4.7 with npm version 2.15.8.

UpdateNodeJs_DownloadNodeJsCurrent

If you select Current, you can see that Current version number has changed to v.6.3.1 with npm version 3.10.3.

Npm

If I have the latest version of Node.js, it doesn’t mean that I have the latest version of NPM. I found really excellent script that will update NPM for you with couple commands. https://www.npmjs.com/package/npm-windows-upgrade. It will show the current version of the NPM installed to your system. It also installs “any” NPM version you want so you can downgrade if the latest version would turn out to be buggy.

Open PowerShell as Administrator

UpdateNodeJs_StartPowerShell

Set-ExecutionPolicy Unrestricted -Scope CurrentUser -Force

UpdateNodeJs_PSSetExecutionPolicy

npm install --global --production npm-windows-upgrade

UpdateNodeJs_PSInstallNpmWindowsUpgrade

npm-windows-upgrade

UpdateNodeJs_PSNpmWindowsUpgrade

Now we can close PowerShell and start Node.js Command Prompt to verify that installation was successful.

npm version

UpdateNodeJs_CmdNpmVersion

Possible error messages

You can get few error message while executing npm-windows-upgrade.

The first one “Scripts cannot executed on this system.” comes if you haven’t changed execution policy.

UpdateNodeJs_ErrorScripts

The another one “NPM cannot be upgraded without administrative rights. To run PowerShell as Administrator, right-click PowerShell and select ‘Run as Administrator’.” comes if you try to execute npm-windows-upgrade with non-administrative mode.

UpdateNodeJs_ErrorRights

PnP-JS-Core samples

This is the part four of my posts about SharePoint client side development using Node.js.

You can see previous parts from here:

During this post we will extend existing PnP Workbench with different common scripts.

Code Template

I have created following template that can be used to test different codes easily. You just need to write your own code after // write code here comment. I have used this template for all example codes here unless I have told otherwise.

var testbench = testbench || {};
testbench.tests = function() {
    var targetElement = jQuery("#pnp-test-bench");
    targetElement.empty();

    runCode = function(){
        targetElement.append("<h2>Test: Test name</h2>");
        // write code here
    };   
    return {
        runCode: runCode
    }
};

jQuery('document').ready(function(){
    var t = new testbench.tests();
    t.runCode();
});

PnPJsSamples_EmptyCode

Web

Here are scripts related to Web.

Show title of the web

var testbench = testbench || {};

testbench.tests = function() {
    var targetElement = jQuery("#pnp-test-bench");
    targetElement.empty();

    runCode = function(){
        targetElement.append("<h2>Test: getWebTitle</h2>");
        $pnp.sp.web.select("Title").get()
            .then(function(web){
                targetElement.append(web.Title + "<br />");
            })  
            .catch(function(error){ 
                targetElement.append(error + "<br />");
        })
    };   

    return {
        runCode: runCode
    }
};

jQuery('document').ready(function(){
    var t = new testbench.tests();
    t.runCode();
});

PnPJsSamples_WebTitleCode

If everything went fine, you should see the title of the web in test bench area.

PnPJsSamples_WebTitleBrowser

Show all properties from web object

This can be useful when you try to see what is current state of the web object.

var testbench = testbench || {};

testbench.tests = function() {
    var targetElement = jQuery("#pnp-test-bench");
    targetElement.empty();

    runCode = function(){
        targetElement.append("<h2>Test: getWeb</h2>");
        $pnp.sp.web.get()
            .then(function(web){
                for (var key in web) {
                    targetElement.append(key + ": " + web[key] + "<br />");
                }
            })  
            .catch(function(error){ 
                targetElement.append(error + "<br />");
        });
    };   

    return {
        runCode: runCode
    }
};

jQuery('document').ready(function(){
    var t = new testbench.tests();
    t.runCode();
});

PnPJsSamples_GetWebCode

If everything went fine, you should see all properties of the current web in test bench area.

PnPJsSamples_GetWebBrowser

Lists

Enumerate all lists from current web

This enumerates all lists from current web and shows all their properties.

var testbench = testbench || {};

testbench.tests = function() {
    var targetElement = jQuery("#pnp-test-bench");
    targetElement.empty();

    runCode = function(){
        targetElement.append("<h2>Test: enumLists</h2>");
        $pnp.sp.web.lists.select('Id', 'Title').orderBy('Title').get()
            .then(function(listIds) {
                for (var index in listIds) {
                    var l = $pnp.sp.web.lists.getById(listIds[index].Id);
                    l.get()
                        .then(function(list){
                            for (var key in list) {
                                targetElement.append(key + ": " + list[key] + "<br />");
                            }
                            targetElement.append("<hr />");
                        })  
                        .catch(function(error){ 
                            targetElement.append(error + "<br />");
                    });
                }
            })
            .catch(function(error){ 
                targetElement.append(error + "<br />");
        });
    };   

    return {
        runCode: runCode
    }
};

jQuery('document').ready(function(){
    var t = new testbench.tests();
    t.runCode();
});

PnPJsSamples_EnumListsCode

If everything went fine, you should see all lists under current web and all properties of the list in test bench area. This is quite long list, so I have taken just a snapshot of the first list.

PnPJsSamples_EnumListsBrowser

Enumerate List Items

Enumerates all items from the selected list.

var testbench = testbench || {};

testbench.tests = function() {
    var targetElement = jQuery("#pnp-test-bench");
    targetElement.empty();

    runCode = function(){
        targetElement.append("<h2>Test: enumListItems</h2>");
        $pnp.sp.web.lists.getByTitle("Documents").items.get()
            .then(function(items){
                for (var i=0; i < items.length; i++) {
                   for (var key in items[i]) {
                        targetElement.append(key + ": " + items[i][key] + "<br />");
                    }
                    targetElement.append("<hr />");
                }
            })  
            .catch(function(error){ 
                targetElement.append(error + "<br />");
        });
    };   

    return {
        runCode: runCode
    }
};

jQuery('document').ready(function(){
    var t = new testbench.tests();
    t.runCode();
});

PnPJsSamples_EnumListItemsCode

If everything went fine, you should see all lists items from the selected list and all properties of each list item in test bench area. This is quite long list, so I have taken just a snapshot of the first list item.

PnPJsSamples_EnumListItemsBrowser

Search

Search sites

This example uses search to list all site collections from the tenant. It lists only those current user has rights.

var testbench = testbench || {};

testbench.tests = function() {
    var targetElement = jQuery("#pnp-test-bench");
    targetElement.empty();

    runCode = function(){
        targetElement.append("<h2>Test: searchSites</h2>");
        $pnp.sp.search('contentclass:sts_site')
            .then(function(searchResult) {
                targetElement.append("Search took " + searchResult.ElapsedTime + "ms to complete.<br />");
                targetElement.append("Total rows " + searchResult.TotalRows + ".<br />");
                targetElement.append("Total rows including duplicates " + searchResult.TotalRowsIncludingDuplicates + ".<br />");
                targetElement.append("<hr />");

                for (var index in searchResult.PrimarySearchResults) {
                    var resultItem = searchResult.PrimarySearchResults[index];
                    for (var key in resultItem) {
                        targetElement.append(key + ": " +resultItem[key] + "<br />");
                    }
                    targetElement.append("<hr />");
                }
            })
            .catch(function(error){ 
                targetElement.append(error + "<br />");
        });
    };   

    return {
        runCode: runCode
    }
};

jQuery('document').ready(function(){
    var t = new testbench.tests();
    t.runCode();
});

PnPJsSamples_SearchSitesCode

If everything went fine, you should see list of search results and all properties of each search result item in test bench area. This is quite long list, so I have taken just a snapshot of the first item.PnPJsSamples_SearchSitesBrowser

Creating a PnP-JS-Core Workbench

This is the third part of my posts about SharePoint client side development using Node.js.

You can see previous parts from here:

During this post we will load Office PnP client side scripts and create simple workbench to test our applications in SharePoint.

Setting up project

Create project

The first this is to create a new project. It’s called PnPTestBench. I have covered these steps more detailed in part 2 so I will just show commands and end result here.

Open Node.js Command Prompt

cd \Source
md PnPTestBench
cd PnPTestBench
npm init

name: pnptestbench
version: (Accept default value)
description: PnP-JS-Core Test Bench
entry point: (Accept default value)
test command:
git repository:
keywords:
author: (Enter your name)
license: (Accept default value)

npm install --save-dev gulp

WebStack_GulpLocalInstall

npm install --save-dev gulp-serve

PnPTestBench_GulpServeInstall

Copy files from existing project

We have already created working gulpfile in our previous project so we can reuse those in this also.

PnPTestBench_CopyFilesSource

PnPTestBench_CopyFilesTarget

Copy gulpfile.js, dev_sharepoint_local.crt and dev_sharepoint_local.key from MyFirstProject folder to PnPTestBench folder.

Add required scripts

Office PnP scripts can be loaded as npm package manager. If you are not familiar with Office PnP, you can go to see more information from their GitHub project page. https://github.com/OfficeDev/PnP-JS-Core

jQuery

npm install jquery --save-dev

PnPTestBench_JQueryInstall

Typings

npm install typings --save-dev

PnPTestBench_TypingsInstall

Sp-pnp-js

npm install sp-pnp-js –save-dev

PnPTestBench_SpPnPInstallSuccess

If you will get following error message “’typings’ is not recognized as an internal or external command and “Failed at the sp-pnp-js@x.x.x postinstall script ‘typings install’.”, you didn’t install typings package before installing sp-pnp-js package.

PnPTestBench_SpPnPInstallFails

Building test bench

Creating folders

Now we have installed required packages to get our project working.

We need to create a new folder called app and couple sub folders for it. This is because gulpfile.js contains reference to it.

md app
md app\scripts
md app\styles

PnPTestBench_CreateAppFolders

Open Visual Studio code

PnPTestBench_OpenVSCode

Creating files

Now we can create one html, style sheet and JavaScript file with following content.

app.css

(This is empty file)

app.js

var testbench = testbench || {};
testbench.tests = function() {
   var targetElement = jQuery("#pnp-test-bench");
   targetElement.empty();

   writeGreeting = function(name) {
      targetElement.append("<h2>Test: writeGreeting</h2>");
      targetElement.append("Hello " + name + "<br />");
   };
   return {
      writeGreeting: writeGreeting
   }
};

jQuery('document').ready(function(){
   var t = new testbench.tests();
   t.writeGreeting("Jani");
});

PnPTestBench_AppJs

index.html

<html>
<head>
<title>SharePoint PnP test bench</title>
<style>
body {
   font-family: Verdana, Geneva, sans-serif;
}
.example {
   margin: 10px;
}
.example .code {
   border: 1px solid lightgray;
   padding: 10px;
   font-family: "Lucida Console", Monaco, monospace;
}
</style>
</head>

<body>
<h1>SharePoint PnP test bench</h1>
<div class="example">
<p>Copy following code to your SharePoint site:</p>
<p class="code">
&lt;script type="text/javascript" src="https://dev.sharepoint.local/scripts/jquery.min.js"&gt;&lt;/script&gt;<br />
&lt;script type="text/javascript" src="https://dev.sharepoint.local/scripts/pnp.min.js"&gt;&lt;/script&gt;<br />
&lt;script type="text/javascript" src="https://dev.sharepoint.local/scripts/app.js"&gt;&lt;/script&gt;<br />
&lt;link rel="stylesheet" type="text/css" href="https://dev.sharepoint.local/styles/app.css" /&gt;<br />
&lt;div id="pnp-test-bench"&gt;&lt;/div&gt;<br />
</p>
</div>
</body>
</html>

PnPTestBench_IndexHtml

Copying library files

But wait… What about pnp javascript file. It’s located in node_modules\sp-pnp-js\dist sub folder, but we are not serving that folder. It doesn’t make sense to serve content from every single library folder. It makes the testing of the application much harder.

We can use Gulp to copy library file from its original location to app\scripts folder.

Open gulpfile.js and add following content to it.

gulp.task('copy-files', function() {
   gulp.src('./node_modules/jquery/dist/jquery.min.js').pipe(gulp.dest('./app/scripts'));
   gulp.src('./node_modules/sp-pnp-js/dist/pnp.min.js').pipe(gulp.dest('./app/scripts'));
});

PnPTestBench_GulpFileJs

Because we don’t modify these files that often, we can copy library files to scripts folder when we add new library files. This is done by executing following command in Node.js Command Prompt.

gulp copy-files

PnPTestBench_GulpCopyFiles

Now we can start our test bench

gulp serve-https

PnPTestBench_GulpServeHttps

Then we need to copy html from the example code block to SharePoint test page. If you are unsure how to do this, check instructions from Getting ready for SharePoint development using node.js: http://salomaa.info/sharepoint/getting-ready-for-sharepoint-development-using-node-js/ posting.

PnPTestBench_Browser

Our test bench works fine. Now we can continue working with it. I have created few test cases that use Office PnP JavaScript Core. I will

Getting ready for SharePoint development using node.js

There has been lot of discussion about new SharePoint Framework to be released soon. Here are instructions how you will get your development environment ready for new SharePoint programming model. You can also use these instructions to start working with OfficePnP JavaScript libraries.

Install required / recommended software

Visual Studio Code

You can download lightweight Visual Studio for free from Microsoft (https://code.visualstudio.com/).WebStack_VSCodeDownload

Installation of the VSCode is really simple. I have noticed that if you select “Open with Code” actions will help you working with VSCode better. So during “Select Additional Tasks” step, remember to select both Add “Open with Code”… checkboxes as shown on below.

WebStack_VSCodeInstallPath

Node.js

Next thing is to install Node.js to host your new development environment. You can download it from Node.js web site (https://nodejs.org/en/download/). Installation is Next – Next installation that won’t require any configurations.

Gulp

The first thing is to install gulp. Gulp needs to be installed globally so that every project can use it.

Open Node.js command prompt and type

npm install --global gulp-cli

It will install Gulp for you. This won’t take long.

WebStack_GulpGlobalInstall

After we have installed Gulp, we will create a folder for the project.

Create Project

Create project folders

C:\Users\janis>cd \
C:\>md Source
C:\>cd Source
C:\Source>md MyFirstProject
C:\Source>cd MyFirstProject
C:\Source\MyFirstProject>

WebStack_ProjectCreateFolders

Execute init command to setup project. Project initialization asks several questions about your project. This is almost identical for Visual Studio project window. At this time we don’t connect project to any Source code repository. Note that you need to use lowercase characters in project name.

Configure project

Install gulp to project. It will add required configurations and packages for Gulp to work.

init npm

WebStack_NpmInit

name: myfirstproject (Note that you need to use lower case characters here so you can’t accept default value.)
version: (Accept default value)
description: My First node.js project
entry point: (Accept default value)
test command: (Leave empty)
git repository: (Leave empty)
keywords: (Leave empty)
author: (Enter your name)
license: (Accept default value)

WebStack_NpmInitDetails

After accepting license, init will create package.json file for you like this. You need to confirm it.

WebStack_NpmInitFile

After you have initialized project, you can install gulp to your project.

install --save-dev gulp

WebStack_GulpLocalInstall

Open Windows Explorer and go to C:\Source.

Select MyFirstProject and select Open with code from Context menu.WebStack_OpenVSCode

Create a new file called gulpfile.js and copy following code there.

var gulp = require('gulp');

gulp.task('default', function() {
  // place code for your default task here
});

WebStack_VSCodeGulpFile

Then you can execute gulp. If you get error message that says “No gulpfile found”, you can have created gulpfile.js to wrong folder or made a mistake in its name.

WebStack_GulpExecuteDefault

Adding web server to project

Before you can start developing application, you need to enable web server to your project. This will be done by adding gulp-serve package to your project.

npm i --save-dev gulp-serve

WebStack_CmdInstallGulpServe

After we have added gulp-serve package to our project, we need to edit gulpfile.js to enable web server functionality. This will be done with following lines of code.

var serve = require('gulp-serve');

gulp.task('serve', serve(['app']));

WebStack_VSCodeGulpFileServe

Now you can execute following command in Node.js Command Prompt. System tells us that it will be serving files in localhost port 3000.

gulp serve

WebStack_VSCodeGulpFileServing

Open web browser and type to address bar http://localhost:3000. As you can see from the result, there is nothing to serve for the clients.

WebStack_BrowserNoContent

Creating content

Create a new folder called app and subfolders for it called scripts and styles.

Create also files called app.js, app.css, and index.html with following contents.

function greet() {
    alert("Hello");
}

WebStack_VSCodeAppJs

body {
    background-color: lightgray;
}

WebStack_VSCodeAppCss

<html>
    <head>
        <title>Hello world</title>
        <script type="text/javascript" src="scripts/app.js"></script>
        <link rel="stylesheet" type="text/css" href="styles/app.css" />
    </head>
    <body>
        <h1>Hello world!</h1>
        <button onclick="greet();">Greet</button>
    </body>
</html>

WebStack_VSCodeIndexHtml

Refresh your browser page. Now you can check that you can actually see our test page in your browser. If you click greet button, you will see greeting.

WebStack_BrowserTestContent

Connecting to SharePoint

Creating test site

Now we have created a working test bench and it is time to connect our code to SharePoint. The first thing is to create a test site for us. Log into you tenant and go to Site Contents page.

Select New | Subsite

WebStack_O365SiteContents

Enter site title, description and url.

Select Team Site as site template.

WebStack_O365NewSite

Editing page

Edit page and add Script Editor Web Part to the page.

WebStack_O365AddScriptWebPart

Edit Script Editor Web Part and click EDIT SNIPPLET link.

WebStack_O365EditScriptWebPart

Add following lines to Script Editor.

<script type="text/javascript" src="http://localhost:3000/scripts/app.js"></script>

<link rel="stylesheet" type="text/css" href=" http://localhost:3000/styles/app.css" />

<button onclick="greet();">Greet</button>

Accept changes. Now you can try to click Greet button. As you can see it won’t work. The problem is that our SharePoint site is using encrypted HTTPS connection and our added scripts are using normal HTTP connection. If you try this with Edge as I did in, you may notice that there is no way of getting our button work.

WebStack_O365GreetButtonNotWorking

If you open same page in Internet Explorer, you will see following notification. If you click the Show all content button, you will notice that background changes to light gray and you can click the button.

WebStack_IEShowAllContentNotification

Setting up HTTPS

We don’t always want to confirm that we actually want to see our development work. This requires that we will set up HTTPS service to our development environment.

Creating certificates

Before you will enable HTTPS service, you need to create certificates for you. I have created another post to cover this. http://salomaa.info/sharepoint/setting-up-https-certificates/

Configuring project

We need to copy our certificates to project folder.

Go to C:\Source\DevCertificate folder.

Select dev_sharepoint_local.crt and dev_sharepoint_local.key files and copy files to C:\Source\MyFirstProject folder.

Webstack_ExplorerCopySource

Webstack_ExplorerTargetSource

Open gulpfile.js in Visual Studio Code and add following lines to it.

gulp.task('serve-https', serve({
  root: ['app'],
  port: 443,
  https: {
    key: 'dev_sharepoint_local.key',
    cert: 'dev_sharepoint_local.crt'
  }
}));

WebStack_VSCodeGulpFileHttps

Open Nodejs Command Prompt.

Go to project folder and start gulp with https

gulp serve-https

WebStack_GulpServeHttps

Testing connection

Open your browser and verify that connection to https://dev.sharepoint.local is actually working and you won’t get any certification errors.

webstack_browserhttps

Modifying SharePoint

Now we can modify our scripts from SharePoint.

Go back to your SharePoint test page and replace existing code with this.

<script type="text/javascript" src="https://dev.sharepoint.local/scripts/app.js"></script>
<link rel="stylesheet" type="text/css" href="https://dev.sharepoint.local/styles/app.css" />
<button onclick="greet();">Greet</button>

Click Insert, accept changes and save page.

WebStack_O365EditScriptWebPartHttps

Now you can see that background has been changed to light gray, button works and you don’t get any warnings about the page.

WebStack_O365WorkingScript

Now we have finalized the first part of the SharePoint development with Node.js.

 

Setting up HTTPS certificates

If we want to make proper node.js development for our SharePoint applications, we need to enable HTTPS for our project.

Add host name

Before we can create certificates for our development environment, we need to define host name for development site.

Click Search icon and type note too list Notepad.

Select “Run as administrator” from context menu.

SSL_OpenNotepad

Open C:\Windows\System32\drivers\etc folder.

Change File type to All Files.

Select hosts file and click open.

SSL_OpenHostsFile

Add new entry to hosts file with following information: 127.0.0.1 dev.sharepoint.local

SSL_EditHostsFile

Save file and close Notepad.

Creating certificates

I have used OpenSSL toolkit (https://www.openssl.org/) to generate certificates that I use for HTTPS. OpenSSL is open source toolkit, but they only provide source code.

Install OpenSSL client

You can install OpenSSL client from this location. http://slproweb.com/products/Win32OpenSSL.html.

I have used default settings for it so my application is installed to C:\OpenSSL-Win32. If you have installed it do different location, you need to check paths of next commands.

I have used this excellent post from Dieter Stevens as a base of this part of the post. https://blog.didierstevens.com/2015/03/30/howto-make-your-own-cert-with-openssl-on-windows/ He has shown step by step installation of the client so I won’t cover that in this document.

Note that default length for country name is 2 letters.
If your country has three letter country code, you need to change countryName_max value from openssl.cfg file before going forward.

Creating Certificates

When you have installed the client, you need to create a folder for certificates.

Open Command Prompt.

Go to Source folder.

Create DevCertificate folder and go there.

set RANDFILE= C:\Source\DevCertificate\.rnd
set OPENSSL_CONF=C:\OpenSSL-Win32\bin\openssl.cfg

SSL_CreateFolders

Start OpenSSL client

C:\OpenSSL-Win32\bin\openssl

SSL_OpenSSLExecute

genrsa -out ca.key 4096

SSL_OpenSSLCAGenRsa

req -new -x509 -days 1826 -key ca.key -out ca.crt

Country Name: (Enter 2 letter country code for your country).
State: (Enter your state)
Locality Name: (Enter your city)
Organizational Name: (Enter your company). I have added Development after company name, so that nobody actually thinks that this is real certificate.
Organizational Unit Name: (Enter your OU)
Common Name: sharepoint.local
Email address: (Enter your email address)

SSL_OpenSSLCAReq

genrsa -out dev_sharepoint_local.key 4096

SSL_OpenSSLDevGenRsa

req -new -key dev_sharepoint_local.key -out dev_sharepoint_local.csr

Country Name: (Enter 2 letter country code for your country).
State: (Enter your state)
Locality Name: (Enter your city)
Organizational Name: (Enter your company). I have added Development after company name, so that nobody actually thinks that this is real certificate.
Organizational Unit Name: (Enter your OU)
Common Name: dev.sharepoint.local
Email address: (Enter your email address)
Challenge password: (Enter proper password or leave empty)
Optional company name: (Leave empty)

SSL_OpenSSLDevReq

x509 -req -days 730 -in dev_sharepoint_local.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out dev_sharepoint_local.crt

SSL_OpenSSLx509

pkcs12 -export -out dev_sharepoint_local.p12 -inkey dev_sharepoint_local.key -in dev_sharepoint_local.crt -chain -CAfile ca.crt

SSL_OpenSSLPkcs12

Installing certificates

Before you can use certificates you need to install those to local machine.

Go to C:\Source\DevCertificate.

Install Root certificate

Select ca.crt file and select Install Certificate from context menu.

SSL_ExplorerCA

Select Current User and click next.

SSL_StoreLocationCA

Select Place all certificates in the following location and click Browse…

Select Trusted Root Certification Authorities and click OK.

Click Next

SSL_CertStoreCA

 

Click Yes to security warning.

SSL_SecurityWarningCA

Click OK to close final dialog.

Install development certificate

Select dev_sharepoint_local.crt file and select Install Certificate from context menu.

SSL_ExplorerDev

Select Automatically select the certificate store based on the type of the certificate.

Click Next

Click Finish

Click OK to close final dialog.

SSL_CertStoreDev

Now you have successfully created one root certificate and one certificate for development server.