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

ngx-persistent-repository

v1.0.1

Published

A persistent repository for storing basic key-value pairs to be used in Angular project providing a global and component specific namespaces.

Downloads

14

Readme

NgxPersistentRepository

A persistent repository for storing basic key-value pairs to be used in Angular project providing a global and component specific namespaces.

In many cases there is no need for a database as the persistent data is stored in a browser cookie. However, if the compressed repository exceeds maximal cookie size of 4KB, the persistent data must be held in a database.

The API allows to initialize the repository with values from a database and provides hooks for synchronizing the repository with the database.

Installation

npm install ngx-persistent-repository

Dependencies

The packages below must be manually installed in order to use the persistent repository:

"@angular/common": ">=6.0.0",
"@angular/core": ">=6.0.0",
"tslib": ">1.9.0",
"ngx-cookie-service": "^2.4.0 || ^3.0.0",
"lodash": "^4.0.0",
"lzutf8": "^0.5.5",
"stream": "^0.0.2"

Global Repository Usage

In your module.ts file:

import { PersistentRepositoryService } from 'ngx-persistent-repository';

@NgModule({
   ...
   providers: [..., PersistentRepositoryService, ...],
   ...
);

To use the repository, simply inject PersistentRepositoryService into your class.

Component Repository Usage

If you want use a separate namespace in the repository for one of you components, let the component inherit from PersistentRepositoryComponent:

import { PersistentRepositoryComponent } from 'ngx-persistent-repository';

export class YourComponent extends PersistentRepositoryComponent implements ... {
    constructor() {
        super();
        ...
    }
    ...
}

You component will inherit all repository methods properly namespaced. To access the global repository use the protected property persistentRepository or the public accessor getPersistentRepository().

Example/Demo

A simple example can be found under src/app directory of the repository. Use ng serve to start the demo.

API Documentation

You can find the typedoc documentation in the /projects/ngx-persistent-repository/docs folder of this repository.

Tips and Tricks

Cookies and Persistence

To actually enable the repository you must call the method enableCookies() or use the enableCookies option in your call to setOptions(). The reason for this lies in the fact that you should normally ask the user's permission before you use cookies. So the usage pattern is to use status of your cookie-consent package to control cookie activation.

If you don't use a cookie-consent package you still need to call enableCookies(true) or use the respective option.

The default setup uses a cookie named 'ngx-persistent-repository' to store the repository data. The cookie will expire after 365 days. Use the cookieConfig option for full control over the cookie parameters.

External Persistence Database

When using an external database to store the repository you need to provide a hook for reading data from the database (setFetchPersistentDataHook()) and another hook for writing data to the database (setWritePersistentDataHook()).

Note that these hooks will only be used when you set a database handle via setDatabaseHandle(). The database handle can be something like a user specific hash or user id. It will be passed to the hooks as reference to the correct dataset.

As soon as you clear the database handle, the repository persistence will revert to use the cookie.

While changes to the repository are immediately visible and access to persistence data stored in cookies is instantaneous - access to external databases is not. It is therefore essential use the provides Promise return values if you need to be certain the data has been synchronized with the persistence database.

You can use the updatePersistentDataImmediate() to make sure the current repository data gets synchronized with the persistence database like this:

this.updatePersistentDataImmediate().then(() => {
    // now the repository and the external database are synchronous
}).catch((error) => {
    // what ever you want to do in this case...
});

A typical read hook looks like this:

this.preferences.setFetchPersistentDataHook((databaseHandle: string) => {
    return new Promise<PRGenericValues>((resolve, reject) => {
        const params = new HttpParams({
            fromObject: {
                hash: databaseHandle
            }
        });

        this.http.get("/user", {params: params}).toPromise().then((result: HttpReply) => {
            let prefs: PRGenericValues = {};
            if (result.success && result.user) {
                try {
                    prefs = JSON.parse(atob(result.user.preferences)) || {};
                    this.user = result.user;
                } catch (e) {
                    // ignore errors
                }
                resolve(prefs);
            } else {
                resolve(prefs);
            }
        }).catch((error) => {
            console.error("error reading preferences", error);
        });
    });
});

A matching write hook would look like this:

this.repository.setWritePersistentDataHook((databaseHandle: string, data: PRGenericValues) => {
    return new Promise<void>((resolve) => {
        const userPreferences: PRGenericValues = _.clone(data);

        const envelope: ClientSideUserModel = {
            hash: databaseHandle,
            preferences: btoa(JSON.stringify(userPreferences))
        };

        this.http.put("/user", envelope).toPromise().then((result: HttpReply) => {
            if (!result.success) {
                console.warning("unable to write preferences", result);
            }
            resolve();
        }).catch((error) => {
            console.error("error writing preferences", error);
        });
    });