npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

@sp-entity/entity

v1.2.0

Published

Entity class for SharePoint list

Downloads

11

Readme

sp-entity

Generate strongly-typed models from SharePoint lists in TypeScript.

Table of Contents

Prerequisites

  • Node 6.9.0+
  • NPM 3+

Supported SharePoint Versions

  • SharePoint Online
  • SharePoint 2016
  • SharePoint 2013

Installation

Install sp-entity cli globally

npm install -g @sp-entity/cli

Add sp-entity as a dependency in project

npm install @sp-entity/entity --save

Getting Started

CLI

# login to sharepoint site
spe login

# generate dataContext folder with default sp-entity config
cd {project folder}/src
spe init

# generate entity classes
spe ./dataContext/spe.config.json

Code

import { DataContext } from './dataContext/dataContext'; // generated by sp-entity
import { EmployeeItem } from './dataContext/employee'; // generated by sp-entity

// initialize dataContext with default params (webUrl: _spPageContextInfo.webAbsoluteUrl)
const dataContext: DataContext = new DataContext();
dataContext.employee.get(1).then((employee: EmployeeItem) => {
    console.log(`${employee.firstName} ${employee.lastName}`); // Steve Rogers
});

Usage

The following usage examples are based on sample generated code below.

Get

dataContext.employee.get(1).then((employee: EmployeeItem) => {
    console.log(employee);
});

/* Output
{
    id: 1,
    title: 'Mr',
    firstName: 'Steve',
    lastName: 'Rogers',
    officeId: 1,
    active: false,
    skills: ['TypeScript', 'SharePoint'],
    created: '2018-01-01T00:00:00Z',
    createdById: 6
    ...
} */

Create

dataContext.employee.create({
    active: true,
    title: 'Mr',
    firstName: 'Steve',
    lastName: 'Rogers',
    officeId: 1
});

Update

const employee: EmployeeItem = await dataContext.employee.get(1);
employee.officeId = 5; // update office lookup
employee.skills = ['TypeScript', 'SharePoint']; // update skills
dataContext.employee.update(employee); // commit changes

// or

dataContext.employee.update({
    id: 1, // id property is required for updates
    officeId: 5,
    skills: ['TypeScript', 'SharePoint']
});

Delete

dataContext.employee.delete(1);

Query

dataContext.employee.query().then((employees: Array<EmployeeItem>) => {
    // ...
});

Query with params

// entity.fields property holds a map to list fields' internal names
// using es6's object destructuring to get a reference to fields used in code
const { id, firstName, lastName, active, created } = dataContext.employee.fields;

const employees: Array<EmployeeItem> = await dataContext.employee.query({
    $select: [id, firstName, lastName],
    $filter: `${active} eq 1`,
    $orderby: { orderBy: created, ascending: false }
});

Query with $expand

// office is a property mapped from a lookup field
const { id, firstName, lastName, office } = dataContext.employee.fields;

const employees: Array<EmployeeItem> = await dataContext.employee.query({
    // $select: ['Id','First_x0020_Name','Last_x0020_Name','Office/City','Office/Country']
    $select: [id, firstName, lastName, office.city, office.country],
    // $expand: ['Office']
    $expand: [office.$name] // $name property holds a lookup's internal name
});

Query with paging

import { SpEntityPaged } from '@sp-entity/entity';
import { DataContext } from './dataContext/dataContext';
import { EmployeeFields, EmployeeItem } from './dataContext/employee';

const dataContext: DataContext = new DataContext();
    
const { active } = dataContext.employee.fields;
let employeesPaged: SpEntityPaged<EmployeeFields, EmployeeItem>;

employeesPaged = await dataContext.employee.queryPaged({ $filter: `${active} eq 1`, $top: 5 /* page size */ });
console.log(employeesPaged.page); // 0

employeesPaged = await employeesPaged.getNext();
console.log(employeesPaged.page); // 1

employeesPaged = await employeesPaged.getNext();
console.log(employeesPaged.page); // 2

employeesPaged = await employeesPaged.getPrev();
console.log(employeesPaged.page); // 1

employeesPaged = await employeesPaged.getPrev();
console.log(employeesPaged.page); // 0

const employees: Array<EmployeeItem> = employeesPaged.items;
...

SPFx Web Part

import { DataContext } from './dataContext/dataContext'; // generated by sp-entity
import { EmployeeItem } from './dataContext/employee'; // generated by sp-entity

export default class SpEntitySampleWebPart extends BaseClientSideWebPart<ISpEntitySampleWebPartProps> {

  private employees: Array<EmployeeItem>;

  public async onInit(): Promise<void> {

    // initialize dataContext with spfx context web url
    const dataContext: DataContext = new DataContext(this.context.pageContext.web.absoluteUrl);
    this.employees = await dataContext.employee.query();
  }

  private renderEmployees(): string {
    return this.employees
      .map((employee: EmployeeItem) => `<div>${employee.firstName} ${employee.lastName} works at ${employee.office.city}, ${employee.office.country} office</div>`)
      .join('')
  }

  ...
}

Config

spe init command generates an spe.config.json file with all visible SharePoint lists in currently logged in site. Update config file to only include lists required in project and update their entityName if necessary, e.g.

{
    "entities": [
        {
            "entityName": "Employee",
            "listName": "Employees"
        },
        {
            "entityName": "Office",
            "listName": "Offices"
        }
}

An odataVerbose flag is automatically added to generated config and set to true for all sp2013 environments. You may remove this flag if your 2013 environment is updated to SP1 and supports JSON light. Read this post for more information.

Code Generation

Running spe command generates a folder for each entity in the config.

The sample config above generates the following folder structure:

  • dataContext
    • employee
      • employeeFields.interface.ts
      • employeeFields.ts
      • employeeItem.ts
    • office
      • officeFields.interface.ts
      • officeFields.ts
      • officeItem.ts
    • dataContext.ts
    • spe.config.json

Sample Generated Code

employeeFields.ts (auto-generated)

An {entityName}Fields.ts file is generated with mappings for default fields in the list returned by SharePoint's rest API. You may modify the file by adding/removing field mappings, updating property names and adding/removing expand fields for lookups (e.g. office.city and office.country).

Make sure to run spe tool after modifying this file to automatically update related interfaces.

import { EmployeeFields } from './employeeFields.interface';

export const employeeFields: EmployeeFields = {

    active: 'Active',
    created: 'Created',
    // each lookup field in the list is mapped to two properties:
    // an expand property with id and title mappings by default
    createdBy: { $name: 'Author', id: 'Id', title: 'Title' },
    // and an id property
    createdById: 'AuthorId',
    firstName: 'First_x0020_Name',
    id: 'Id',
    lastName: 'Last_x0020_Name',
    // city and country mappings have been added manually here
    office: { $name: 'Office', id: 'Id', title: 'Title', city: 'City', country: 'Country' },
    officeId: 'OfficeId',
    picture: 'Picture',
    permissions: 'EffectiveBasePermissions',
    skills: 'Skills',
    title: 'Title'
};

employeeItem.ts (auto-generated)

import { iso8601Date, SpBasePermissions, SpUrlValue } from '@sp-entity/entity';

export interface EmployeeItem {

    active: boolean;
    readonly created: iso8601Date;
    readonly createdBy: { id: number, title: string };
    readonly createdById: number;
    firstName: string;
    readonly id: number;
    lastName: string;
    readonly office: { city: string, country: string, id: number, title: string };
    officeId: number;
    readonly permissions: SpBasePermissions;
    picture: SpUrlValue;
    skills: Array<string>;
    title: string;
}

dataContext.ts (auto-generated)

import { SpEntity } from '@sp-entity/entity';
import { EmployeeFields, employeeFields, EmployeeItem, employeeListName } from './employee';
import { OfficeFields, officeFields, OfficeItem, officeListName } from './office';

export class DataContext {

    public readonly employee: SpEntity<EmployeeFields, EmployeeItem>;
    public readonly office: SpEntity<OfficeFields, OfficeItem>;

    public constructor(webUrl?: string) {

        this.employee = new SpEntity(employeeListName, employeeFields, webUrl);
        this.office = new SpEntity(officeListName, officeFields, webUrl);
    }
}

Authentication

spe login and spe logout commands can be used to store/delete encrypted credentials for context sharepoint site. Using spe cli without logging in first will prompt for credentials every time.

Login wizard is provided by the following awesome libraries:

Node Environment

In order to use sp-entity in a node environment, a fetch client factory must be provided using setup method

Install pnp-auth dependency

npm install pnp-auth --save

Setup sp-entity's fetchClientFactory

import { setup } from '@sp-entity/entity';
import { IAuthOptions } from 'node-sp-auth';
import NodeFetchClient from 'pnp-auth/lib/NodeFetchClient';

const siteUrl: string = 'https://contoso.sharepoint.com/sites/example';

const authOptions: IAuthOptions = {
    username: '[email protected]',
    password: 'password'
};

setup({
    fetchClientFactory: () => {
        return new NodeFetchClient(authOptions, siteUrl) as GlobalFetch;
    }
});

const dataContext: DataContext = new DataContext();
...

IE10 Support

Following polyfills are required for using sp-entity in IE10

This is not required for SPFx projects as they include above polyfills by default

License

MIT