Have ideas to improve npm?Join in the discussion! »

    spfx-base-data-services
    TypeScript icon, indicating that this package has built-in type declarations

    1.2.13 • Public • Published

    npm npm GitHub package.json version (branch) Total alerts Language grade: JavaScript

    spfx-base-data-services

    Contents

    Description

    spfx-base-dataservice is a set of base classes and tools aimed to create a data service able to interract with main SharePoint / O365 data sources in SPFX web parts. It contains base implementation for the following services:

    • SharePoint List including main data types (text, boolean, lookup, Taxonomy...).
    • Document Library.
    • SharePoint Users.
    • Taxonomy Term set stored in a global group or in the site collection group.

    The main feature provided by implementing this library is:

    • Easy models and service design.
    • Automatic link management for linked fields (Taxonomy, Lookups, Users).
    • Cache management: all service can store data in cache using an age in minutes.
    • Online/Offline management for Progressive Web Apps: calls to service automatically switch to local storage in case the app is offline. All features are available.
    • Version conflicts check (version management must be activated on list). In case the destination item is newer, an error is thrown and the destination item is returned.
    • Automatic data synchronization. All actions made by services offline are stored in a transactions table. A synchronization process runs api calls for all transactions and guarantees data consistency between SharePoint and local database.

    Installation

    To use the package, it must be installed via npm and saved as project dependency using the command:

    npm i spfx-base-data-service --save

    Project integration

    The service needs a few configuration to work in a SPFX webpart project.

    Initialization

    In webparts code file override init method as following :

    public  onInit(): Promise<void> {
        return  super.onInit().then(_  => {
            ServicesConfiguration.Init({
                lastConnectionCheckResult:  false,
                dbName:  "sp-db",
                dbVersion:  1,
                checkOnline:  true, // true for pwa, else false
                context:  this.context,
                currentUserId: -1, // if used in queries, must be initialized after
                serviceFactory:  new  ServiceFactory(), // service factory implementation
                tableNames:  ["list", "termset"], // 1 table per service
                translations: { // translations used for synchronization
                    AddLabel:  strings.AddLabel,
                    DeleteLabel:  strings.DeleteLabel,
                    IndexedDBNotDefined:  strings.IndexedDBNotDefined,
                    SynchronisationErrorFormat:  strings.SynchronisationErrorFormat,
                    UpdateLabel:  strings.UpdateLabel,
                    UploadLabel:  strings.UploadLabel,
                    versionHigherErrorMessage:  strings.versionHigherErrorMessage,
                    typeTranslations: { // One per model, key is class name
                        SPFile:  strings.SPFileLabel
                    }
                }
            });
        });
    }

    Packaging the solution

    As services use Class names to generate model and service instances, the following function must be added in file gulpfile.js:

    ...
    const  TerserPlugin = require('terser-webpack-plugin');
    const  glob = require('glob');
    
    build.configureWebpack.setConfig({
        additionalConfiguration: (config) => {
            // only prod buid
            if (build.getConfig().production) {
                // get excluded names for uglify
                const reserved = glob.sync('./src/{services,models}/**/*.ts').map((filePath) => {
                    return filePath.replace(/.*\/(\w+)\.ts/g, "$1");
                }).concat("SPFile", "TaxonomyTerm", "TaxonomyHiddenListService", "TaxonomyHidden", "UserService", "User");
                config.optimization.minimizer =
                [
                    new TerserPlugin
                    (
                        {
                            extractComments: false,
                            sourceMap: false,
                            cache: false,
                            parallel: false,
                            terserOptions:
                            {
                                output: { comments: false },
                                compress: { warnings: false },
                                mangle: {
                                    reserved: reserved
                                }
                            }
                        }
                    )
                ];
            }
            return config;
        }
    });

    where ./src/{services,models}/**/*.ts is the path in solution where services and models are stored

    Implementation

    Service Factory

    To be able to instanciate models ans services, a service factory based on type BaseServiceFactory. The service factory exposes 2 methods :

    • create for service instanciation
    • getItemTypeByName for model instanciation

    Each method is based on model type name, implementation of service factory should be as following:

    // import model types and service types
    import { BaseServiceFactory, BaseDataService, IBaseItem, TaxonomyHidden, User, TaxonomyHiddenListService, UserService} from "spfx-base-data-services";
    export class ServiceFactory extends BaseServiceFactory {
        /**
        * Instanciate a data service given associated model name
        * @param  modelName - Model associated with the service type to instanciate
        */
        public create(modelName: string): BaseDataService<IBaseItem> {
            let result = null;
            switch (modelName) {
                /* Base */
                case TaxonomyHidden["name"]:
                    result = new TaxonomyHiddenListService();
                    break;
                case User["name"]:
                    result = new UserService();
                    break;
                /*
                   Add cases for all model names
                */
                default:
                    throw Error(strings.errorUnknownItemTypeName);
            }
            return result;
        }
    
        /**
        * Retrieve model constructor given its name
        * @param modelName - Model type name
        */
        public getItemTypeByName(modelName: string): (new (item?: any) => IBaseItem) {
            let result = super.getItemTypeByName(typeName);
            if(!result) {
                switch (typeName) {
                    /* Base */
                    case TaxonomyHidden["name"]:
                        result = TaxonomyHidden;
                        break;
                    case User["name"]:
                        result = User;
                        break;
                    /*
                        Add cases for all model names
                    */
                    default:
                        throw Error(strings.errorUnknownItemTypeName);
                }
            }
            return result;
        }
    }

    SharePoint List

    List item model

    A list item model is a class that inherits from base class SPItem. To link properties to list fields, use decorator function spField with appropriate parameters according to field name, type and the way you want to retrieve value. By default, ID and Title field are retrieved in id and title properties. In case of linked fields in model declaration, associated models and services must exist and must be declared in ServiceFactory implementation.

    Sample:

    import { SPItem, FieldType, Decorators } from "spfx-base-data-services";
    // import lookup types
    const spField = Decorators.spField;
    
    export class Model extends SPItem {
        //////////////////
        // Simple types //
        //////////////////
        // Text, boolean --> no type needed
        @spField({fieldName: "TextField", defaultValue: ""})
        public text: string;
        @spField({fieldName: "BooleanField", defaultValue: false})
        public bool: boolean;
        // Other simple types
        @spField({fieldName: "DateField", fieldType:FieldType.Date, defaultValue: null})
        public date: Date;
        @spField({fieldName: "JsonField", fieldType:FieldType.Json, defaultValue: null})
        public json: any;
    
        //////////////
        // Taxonomy //
        //////////////
        @spField({fieldName: "TaxonomyField", fieldType:FieldType.Taxonomy, modelName: "TaxoModelName", defaultValue: null})
        public taxonomyField: TaxoModelName;
        @spField({fieldName: "TaxonomyFieldMulti", fieldType:FieldType.TaxonomyMulti, modelName: "TaxoModelName", defaultValue: []})
        public taxonomyField: Array<TaxoModelName>;
        // On Taxonomy fields, if model is omitted, retrieve wssid only
        @spField({fieldName: "TaxonomyField", fieldType:FieldType.Taxonomy, defaultValue: -1})
        public taxonomyFieldWssId: number;
    
        ////////////
        // Lookup //
        ////////////
        @spField({fieldName: "LookupField", fieldType:FieldType.Lookup, modelName: "LookupModelName", defaultValue: null})
        public lookup: LookupModelName;
        @spField({fieldName: "LookupFieldMulti", fieldType:FieldType.LookupMulti, modelName: "LookupModelName", defaultValue: []})
        public lookupMulti: Array<LookupModelName>;
        // On Lookup fields, if model is omitted, retrieve id only
        @spField({fieldName: "LookupField", fieldType:FieldType.Lookup, defaultValue: -1})
        public lookupId: number;
    
        //////////
        // User //
        //////////
        @spField({fieldName: "UserField", fieldType:FieldType.User, modelName: "User", defaultValue: null})
        public user: User;
        @spField({fieldName: "UserFieldMulti", fieldType:FieldType.UserMulti, modelName: "User", defaultValue: []})
        public userMulti: Array<User>;
        // On User fields, if model is omitted, retrieve id only
        @spField({fieldName: "UserField", fieldType:FieldType.User, defaultValue: -1})
        public userId: number;
    }

    List service

    A SharePoint List service inherits from base class BaseListItemService. Links to SharePoint list and local db are set by overriding constructor. There is no other method to declare if the solution only needs to access list via already available operations:

    • Add or update
    • Delete
    • Get all elements
    • Get by query
    • Get by id(s)

    Sample:

    // Add import to Model
    import { BaseListItemService } from "spfx-base-data-services";
    
    export class ListService extends BaseListItemService<Model> {
        constructor() {
            // find items in list with web relative url /lists/listurl, store cache in table ListTableName and cache results for 10 minutes
            super(Model, "/lists/listurl", "ListTableName", 10);
        }
    }

    Taxonomy Term set

    Taxonomy term model

    A taxonomy term model is a class that inherits from base class TaxonomyTerm. By default, this object exposes the following properties :

    • Term id
    • Label
    • Term path
    • Custom properties
    • Custom sort order
    • Deprecated

    Sample:

    import { TaxonomyTerm } from  'spfx-base-data-services';
    
    export  class  ModelName extends  TaxonomyTerm {
    }

    Term set service

    A taxonomy term set service inherits from base class BaseTermsetService. Links to SharePoint term set and local db are set by overriding constructor. Service can search global term set or for local term set (stored in site collection group), link can be made on term set id or by name. There is no other method to declare if the solution only needs to access term set via already available operations:

    • Get all elements
    • Get by id(s)

    Sample:

    import { BaseTermsetService } from 'spfx-base-data-services';
    // import ModelName
    
    export class TermSetService extends BaseTermsetService<ModelName> {
        constructor() {
            super(NameOrId, TableName, false /* store in site collection group */, 1440 /* cache duration in minutes */);
        }
    }

    Library

    Library service

    File model

    Extending Services

    Overriding default services methods

    Creating a custom service

    Synchronization events

    Using a service

    Classes and interfaces description

    Install

    npm i spfx-base-data-services

    DownloadsWeekly Downloads

    165

    Version

    1.2.13

    License

    MIT

    Unpacked Size

    1.18 MB

    Total Files

    303

    Last publish

    Collaborators

    • avatar
    • avatar