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 🙏

© 2026 – Pkg Stats / Ryan Hefner

kalapa-consent-web-sdk

v1.0.3-0.1

Published

Kalapa CMP SDK

Readme

Kalapa Consent Web SDK

Package: kalapa-consent-web-sdk

Version: 1.0.30.1

A consent management library for web apps. It provides consent UI, server sync, and local persistence so tracked features (ads, analytics, personalization) only run after valid user consent.


Contents


Requirements

| Item | Minimum | | --- | --- | | Browser | Modern browsers with ES module support (or use UMD build) | | Network | Internet access to CMP backend | | Optional | TypeScript for type definitions |


Installation

Use package manager (recommended), CDN, or Kalapa-hosted script.

Package manager (npm / Yarn / pnpm)

npm install kalapa-consent-web-sdk
yarn add kalapa-consent-web-sdk
pnpm add kalapa-consent-web-sdk

CDN (jsDelivr)

Replace 1.0.30.1 with your target version.

ESM:

https://cdn.jsdelivr.net/npm/[email protected]/dist/kalapa-consent-web-sdk.js

UMD:

https://cdn.jsdelivr.net/npm/[email protected]/dist/kalapa-consent-web-sdk.umd.js

Quick Start

Version 1.0.30.1 uses a two-phase initialization model. Creating the SDK instance and loading project / user data are separate steps:

  1. Construct — provide immutable connection credentials (and optional UI options).
  2. Setup — provide project code and optional user ID; makes network calls to load config and existing consent.

Recommended: Builder pattern

import KalapaCMPSDK from "kalapa-consent-web-sdk";

const sdk = await KalapaCMPSDK.builder({
  baseUrl: "https://cmp-api-dev.kalapa.vn",
  orgApiKey: "your-org-api-key",
})
  .withLanguage("vi")          // optional
  .withForceConsent(true)      // optional
  .create({
    projectCode: "my-project",
    userId: "logged-in-user-id", // optional
  });

// sdk is fully ready — setup() has already been called

Alternative: Constructor + explicit setup()

import KalapaCMPSDK from "kalapa-consent-web-sdk";

const sdk = new KalapaCMPSDK({
  baseUrl: "https://cmp-api-dev.kalapa.vn",
  orgApiKey: "your-org-api-key",
});

await sdk.setup({
  projectCode: "my-project",
  userId: "logged-in-user-id", // optional
});

UMD (CDN) usage

<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/kalapa-consent-web-sdk.umd.js"></script>
<script>
  var sdk = new window.KalapaCMPSDK({
    baseUrl: "https://cmp-api-dev.kalapa.vn",
    orgApiKey: "your-org-api-key",
  });

  // Pass autoShow: false so setup() does not show the modal on its own.
  // ensureConsent() will show it exactly once and resolve when the user grants consent.
  sdk.setup({ projectCode: "my-project", autoShow: false }).then(function () {
    return sdk.ensureConsent();
  }).then(function (granted) {
    if (granted) {
      loadAds();       // replace with your own tracked features
      loadAnalytics();
    }
  });
</script>

Parameter reference

| Parameter | Type | Where | Description | | --- | --- | --- | --- | | baseUrl | string | SDKCoreParams | Dev: https://cmp-api-dev.kalapa.vn · Prod: https://api.cmp.kalapa.vn | | orgApiKey | string | SDKCoreParams | Organisation API key provided by Kalapa | | projectCode | string | SDKSetupParams | Project identifier configured in the Kalapa CMP console | | userId | string? | SDKSetupParams | Logged-in user ID. If omitted, SDK uses an anonymous device identity | | autoShow | boolean? | SDKSetupParams | Controls the auto-show during setup. Defaults to true (show if consent is missing or need_reconsent). Pass false to suppress the "no consent yet" show while still auto-showing when the server signals need_reconsent |


Core Concepts

Two-phase initialization

The SDK separates concerns cleanly:

  • Constructor / builder — validates credentials, pre-loads UI assets. No network calls.
  • setup() — loads project config and the subject's existing consent from the backend; initialises the consent UI; and auto-shows the consent modal if consent is missing or re-consent is required. Must resolve before calling any other public method.

Subject identity

  • userId in setup() (or setUser()) identifies the consent subject.
  • If omitted, the SDK generates an anonymous device-scoped identity.
  • Consent is scoped per subject. To switch users at runtime, call setUser() — do not create a new SDK instance.

Re-consent

If the backend returns need_reconsent: true (e.g. the project's consent policy changed), the SDK automatically presents the modal again.

Local snapshot vs. server state

| Method | Network call | Typical use | | --- | --- | --- | | isConsentGranted() | No | Fast gate check before loading a tracked feature | | lastGrantedConsent() | No | Read local category-level consent | | checkUserConsent() | Yes | Sync latest valid consent from server | | ensureConsent() | Yes | Full consent flow (shows UI when required) | | withdrawConsent() | Yes | Withdraw consent and reset local / UI state |

GUI options & remote defaults

SDKOptions (passed via builder or constructor) are merged with remote options fetched from the backend during setup(). Remote settings act as the base; anything you pass locally overrides the corresponding field.


API Reference

KalapaCMPSDK.builder(coreParams)

Returns a fluent KalapaCMPSDKBuilder for constructing the SDK.

KalapaCMPSDK.builder(coreParams: SDKCoreParams): KalapaCMPSDKBuilder

Builder methods

| Method | Type | Description | | --- | --- | --- | | .withLanguage(lang) | "vi" \| "en" | UI language | | .withDarkMode(enabled) | boolean | Enable dark mode | | .withForceConsent(enabled) | boolean | Prevent the page from being used without consent | | .withGuiOptions(options) | SDKGuiOptions | Layout, position, and color overrides (see below) | | .build() | KalapaCMPSDK | Returns SDK instance; setup() not yet called | | .create(setupParams) | Promise<KalapaCMPSDK> | Returns ready SDK instance; calls setup() internally |

new KalapaCMPSDK(coreParams, options?)

Direct constructor. Prefer the builder for readability.

new KalapaCMPSDK(
  coreParams: { baseUrl: string; orgApiKey: string },
  options?: SDKOptions
)

sdk.setup(params): Promise<void>

Initialises (or re-initialises) the SDK for a project and user. Fetches project config and existing consent from the backend, then auto-shows the consent modal if needed. Must be called before any other public method. Safe to call again to switch project or user — tears down previous state first.

sdk.setup({
  projectCode: string;
  userId?: string;
  autoShow?: boolean; // default: true
}): Promise<void>

When autoShow: false, setup still fetches remote consent (to detect policy changes), but suppresses the modal unless the server signals need_reconsent (e.g. consent was revoked or the policy changed). In that case the modal is always shown regardless of this flag. This removes the double-show flicker when ensureConsent() is called immediately after.

| Error code | Cause | | --- | --- | | 1202 SETUP_IN_PROGRESS | Called while a previous setup() is still running | | 1203 INVALID_AUTO_SHOW | autoShow is not a boolean |

sdk.setUser(userId?): Promise<void>

Switches the active user without changing the project. Equivalent to calling setup({ projectCode: <current>, userId }). Throws if setup() has never been called.

await sdk.setUser("new-user-id");
// or clear to anonymous:
await sdk.setUser();

sdk.ensureConsent(callback?): Promise<boolean>

Ensures a valid consent exists for the current subject. Shows the modal when needed, and resolves true once the user grants consent.

await sdk.ensureConsent((granted, consent) => {
  if (granted) {
    console.log("Granted:", consent);
  }
});

sdk.isConsentGranted(): boolean

Local-only quick check. No network call.

sdk.lastGrantedConsent(): ConsentSnapshot | null

Returns the local consent snapshot. No network call.

type ConsentSnapshot = {
  version?: string;
  consents: Record<string, boolean>;
};

sdk.checkUserConsent(): Promise<Consent | null>

Fetches the latest valid consent from the server. Returns null if consent is missing or re-consent is required.

const consent = await sdk.checkUserConsent();
console.log(consent); // e.g. { analytics: true, ads: false }

sdk.withdrawConsent(): Promise<boolean>

Withdraws consent on the server, clears local snapshot and UI state, and shows the consent modal again.

await sdk.withdrawConsent();

sdk.getSubjectKey(): string

Returns the effective subject key currently used for consent sync (userId-derived or anonymous device ID).

SDKOptions

interface SDKOptions {
  language?: "vi" | "en";
  forceConsent?: boolean;
  darkMode?: boolean;
  guiOptions?: SDKGuiOptions;
}

SDKGuiOptions

interface SDKGuiOptions {
  consentModal?: {
    layout?: "box" | "box wide" | "box inline" | "cloud" | "cloud inline" | "bar" | "bar inline";
    position?: "top" | "bottom" | "middle" | "top left" | "top center" | "top right"
             | "middle left" | "middle center" | "middle right"
             | "bottom left" | "bottom center" | "bottom right";
  };
  preferencesModal?: {
    layout?: "box" | "bar" | "bar wide";
    position?: "left" | "right";
  };
  ui?: {
    themeMode?: "light" | "dark" | "system";
    color?: {
      light?: SDKUiPalette;
      dark?: SDKUiPalette;
    };
    radius?: {
      sm?: number | string;
      md?: number | string;
      lg?: number | string;
    };
  };
}

interface SDKUiPalette {
  primary?: string;
  on_primary?: string;
  secondary?: string;
  on_secondary?: string;
  text?: string;
  background?: string;
  border?: string;
  overlay?: string;
  section?: string;
}

Common Patterns

Gate tracked features with consent

Pass autoShow: false to setup() so the modal is only shown once by ensureConsent().

await sdk.setup({ projectCode: "my-project", autoShow: false });
await sdk.ensureConsent();
if (sdk.isConsentGranted()) {
  loadAds();
  loadAnalytics();
}

Full builder setup with UI customization

const sdk = await KalapaCMPSDK.builder({
  baseUrl: "https://cmp-api-dev.kalapa.vn",
  orgApiKey: "your-org-api-key",
})
  .withLanguage("vi")
  .withDarkMode(false)
  .withForceConsent(true)
  .withGuiOptions({
    consentModal: { layout: "box", position: "bottom right" },
    preferencesModal: { layout: "box", position: "right" },
    ui: {
      themeMode: "system",
      color: {
        light: { primary: "#0d5c63", on_primary: "#ffffff" },
        dark:  { primary: "#0d5c63", on_primary: "#ffffff" },
      },
    },
  })
  .create({ projectCode: "my-project", userId: "user-id" });

await sdk.ensureConsent();

Switch user after login

await sdk.setUser("logged-in-user-id");
await sdk.ensureConsent();

Clear user after logout (back to anonymous)

await sdk.setUser(); // no userId → anonymous
await sdk.ensureConsent();

Switch project

await sdk.setup({ projectCode: "another-project", userId: currentUserId });
await sdk.ensureConsent();

Withdraw consent

const ok = await sdk.withdrawConsent();
if (ok) {
  stopAllTrackedFeatures();
}

Error Handling

  • Do not assume consent is granted if a network call fails.
  • Treat isConsentGranted() === false as "not safe to track yet".
  • For checkUserConsent(), handle null and keep tracking disabled until consent is confirmed.
const consent = await sdk.checkUserConsent();
if (consent == null && !sdk.isConsentGranted()) {
  disableTracking();
}

SDK error codes

| Code | Key | Cause | | --- | --- | --- | | 1002 | INVALID_URL | baseUrl is missing or not a valid http(s):// URL | | 1003 | INVALID_API_KEY | orgApiKey is missing or fewer than 10 characters | | 1101 | INVALID_OPTIONS | guiOptions is present but not an object | | 1102 | INVALID_CONSENT_MODAL_LAYOUT | consentModal.layout is not a recognised value | | 1103 | INVALID_CONSENT_MODAL_POSITION | consentModal.position is not a recognised value | | 1104 | INVALID_PREFERENCES_MODAL_LAYOUT | preferencesModal.layout is not a recognised value | | 1105 | INVALID_PREFERENCES_MODAL_POSITION | preferencesModal.position is not a recognised value | | 1106 | INVALID_LANGUAGE | language is not a string | | 1107 | INVALID_LANGUAGE | language is not "vi" or "en" | | 1108 | INVALID_FORCE_CONSENT | forceConsent is not a boolean | | 1109 | INVALID_DARK_MODE_OPTION | darkMode is not a boolean | | 1110 | INVALID_THEME_MODE | ui.themeMode is not "light", "dark", or "system" | | 1111 | INVALID_UI_COLOR | A color palette value is not a string | | 1112 | INVALID_UI_RADIUS | A radius value is not a number or string | | 1200 | INVALID_PROJECT_CODE | projectCode is empty | | 1201 | SETUP_NOT_CALLED | Public method called before setup() | | 1202 | SETUP_IN_PROGRESS | setup() called while a previous call is still running | | 1203 | INVALID_AUTO_SHOW | autoShow is not a boolean |


Troubleshooting

Consent modal does not appear

  • Verify baseUrl and orgApiKey.
  • Confirm setup() has resolved before calling ensureConsent().
  • Check network access / CORS for the CMP backend.
  • Check the browser console and Network tab.

isConsentGranted() stays false after accepting

  • Ensure you are checking with the same SDK subject identity (same projectCode + userId).
  • If the user changed, call setUser() then ensureConsent().
  • Verify the /consents endpoint returns success and a tracking ID.

User switched but old consent is still used

  • Call setUser(newUserId) whenever the subject changes at runtime — do not construct a new SDK instance.
  • Call ensureConsent() again after setUser() resolves.

Build / bundler issues

  • Ensure the package entry for kalapa-consent-web-sdk resolves to dist/kalapa-consent-web-sdk.js.
  • If using a local package link, rebuild the SDK so dist/ is up to date.

Migration from 1.0.29.x

| Old (1.0.29.x) | New (1.0.30.x) | | --- | --- | | new KalapaCMPSDK({ credentials: { url, key, userId? } }) | new KalapaCMPSDK({ baseUrl, orgApiKey }) + sdk.setup({ projectCode, userId? }) | | credentials.url | baseUrl | | credentials.key | orgApiKey | | credentials.userId | setup({ userId }) or setUser(userId) | | No projectCode concept | Required in setup() | | updateCredentials() | setUser(userId?) | | Recreate SDK instance to switch user | sdk.setUser(userId?) | | N/A | KalapaCMPSDK.builder() fluent API | | N/A | SDKOptions: language, forceConsent, darkMode, guiOptions | | ConsentSnapshot.version: number \| null \| undefined | ConsentSnapshot.version?: string | | CDN: *.min.js / *.umd.min.js | CDN: *.js / *.umd.js |


Changelog

1.0.30

  • Breaking: Two-phase initialization — constructor sets credentials; setup({ projectCode, userId? }) loads config and consent.
  • Breaking: Credential fields renamed: credentials.urlbaseUrl, credentials.keyorgApiKey.
  • Breaking: userId moved from constructor credentials to setup() / setUser().
  • New fluent builder: KalapaCMPSDK.builder(coreParams).withXxx().create(setupParams).
  • New setUser(userId?) for switching subjects at runtime without recreating the SDK instance.
  • New getSubjectKey() returns the effective subject key.
  • New SDKOptions for local overrides: language, forceConsent, darkMode, guiOptions (layout, position, colors, border-radius, theme mode).
  • Remote GUI options fetched from backend and merged with local overrides.
  • Structured SDKError with error codes for validation failures and setup guard violations.

1.0.29

  • Bug fixes.
  • Public API ensureConsent with callback.

1.0.28

  • UI/UX improvements.
  • Bug fixes.

1.0.27

  • Subject-scoped consent key and improved identity switching behaviour.
  • Public API: ensureConsent(), withdrawConsent().

Earlier

  • Initial Web SDK release with consent UI, server sync, and local snapshot.

For environment URLs, API keys, and backend integration details, contact Kalapa support.