Skip to content

Repository files navigation

ngx-local-vault

Reactive, encrypted browser storage for Angular — built on Signals, under 2KB gzipped, zero runtime dependencies.

Also available for: React (npm · demo) · Vue (npm · demo)

Most storage wrappers give you a getter/setter pair and leave persistence, encryption, and expiry as an exercise for the consumer. ngx-local-vault collapses all three into a single WritableSignal: read it like any other signal, write it like any other signal, and the library takes care of encrypting the payload, syncing it to localStorage or sessionStorage, expiring it on a TTL, and staying inert during SSR.

  • Signals-native — watchSignal() returns a real WritableSignal<T>, no wrapper API to learn
  • Encrypted at rest — payloads are obfuscated before they ever touch the browser's storage
  • TTL built in — pass expiresIn: '1m' and the entry self-destructs, in-tab, without a reload
  • SSR-safe — guarded by PLATFORM_ID, becomes a no-op persistence layer on the server
  • Zero dependencies — @angular/core and @angular/common as peers, nothing else

Install

npm i ngx-local-vault

Supports Angular 17, 18, 19, and 20.

Configure

import { ApplicationConfig } from '@angular/core';
import { provideVault } from 'ngx-local-vault';

export const appConfig: ApplicationConfig = {
  providers: [
    provideVault({ prefix: 'app_', encryptionKey: 'change-me', driver: 'local' })
  ]
};

Use

import { inject } from '@angular/core';
import { VaultService } from 'ngx-local-vault';

const vault = inject(VaultService);

const theme = vault.watchSignal<'light' | 'dark'>('theme', 'light');
theme.set('dark');
theme();

const session = vault.watchSignal<string | null>('session-token', null, { expiresIn: '15m' });
session.set('jwt-goes-here');

expiresIn accepts ms, s, m, h, or d suffixes — '500ms', '30s', '15m', '2h', '1d'.

Demo

Live: https://ysndmr.github.io/ngx-local-vault/

projects/demo-app is a live showcase: a theme switcher backed by watchSignal(), and a TTL demo that saves a mock profile, shows the encrypted ciphertext sitting in localStorage next to the decrypted reactive value, and lets you watch it auto-delete after 60 seconds.

npm install
npm run build:lib
npm start

npm start serves demo-app; the library must be built first since the app imports ngx-local-vault from its built output (dist/ngx-local-vault), not the source directly — standard Angular library-workspace convention.

Security model

The encryption here is obfuscation, not a security boundary. The key lives in your app's bundle (or wherever you configure encryptionKey), so anyone with access to the running page — devtools, a browser extension, an XSS payload — can recover it just like they could any other client-side secret. This library does not, and cannot, protect data from an attacker who already controls the browser session.

What it does protect against is casual, incidental exposure: data no longer sits in localStorage as plain, human-readable JSON for a screen share, a saved HAR file, or a storage-reading browser extension to pick up at a glance. It raises the bar from "trivial to read" to "requires deliberate effort," nothing more.

Don't use this to store data you wouldn't be OK with the end user (or anything running in their browser) eventually reading — API secrets, other users' data, anything that needs real confidentiality. For that, encryption has to happen server-side, with a key the client never sees.

Publishing (maintainer)

  1. Log in to npm once, locally:

    npm login
  2. Build the library — this also strips tslib from the published dependencies (ng-packagr adds it back on every build; scripts/patch-lib-package.mjs removes it) so the zero-dependency badge stays honest:

    npm run build:lib
  3. Dry-run the publish before it's live:

    cd dist/ngx-local-vault
    npm publish --dry-run
  4. If the file list and package.json look right, publish for real:

    npm publish --access public

CI (.github/workflows/publish.yml) does this automatically on every push to main: it builds the library and the demo app, deploys the demo to GitHub Pages, and publishes to npm if an NPM_TOKEN secret is configured on the repository (Settings → Secrets and variables → Actions). No token, no publish step — the Pages deploy still runs.

License

MIT

ngx-local-vault

About

No description, website, or topics provided.

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages