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

@makemind/sdk

v0.1.0

Published

MAKEMIND Platform SDK for Web Applications

Readme

@makemind/sdk

MAKEMIND Platform SDK for Web Applications (React, Vue, Angular, etc.)

Installation

npm install @makemind/sdk

The SDK talks to the MAKEMIND API gateway over HTTPS. Installing it pulls in nothing else: you only need an API key and your application ID.

firebase is an optional peer. Two features load it on demand and only when you use them — web push (messaging.registerDevice, messaging.onPushMessage) and App Check tokens. Everything else, including every gateway call, works with firebase absent.

Quick Start

import { initializeMAKEMIND, getMAKEMIND } from '@makemind/sdk';

// Initialize MAKEMIND SDK
initializeMAKEMIND({
  apiKey: 'your-api-key',
  applicationId: 'plm', // Your application ID
  environment: 'development',
  // Optional: override the gateway base URL (defaults to https://api.makemind.app).
  // Point this at a locally running gateway during development.
  baseUrl: 'http://127.0.0.1:5001/<project-id>/us-central1/apiGateway',
});

// Use the SDK
const makemind = getMAKEMIND();

initializeMAKEMIND accepts { apiKey, applicationId, environment?, baseUrl?, apiVersion?, getAppCheckToken? }. All service calls are issued against ${baseUrl}/api/${apiVersion} (apiVersion defaults to v1).

App Check (first-party apps only)

Pass getAppCheckToken — an async provider returning a Firebase App Check token — to have the SDK attach it as X-Firebase-AppCheck on every gateway call. This lets browser/mobile apps pass App Check enforcement on the pre-login endpoints (signin/signup/password-reset/oauth). Backward-compatible: omit it for M2M / API-key integrations (exempt from App Check server-side), and a provider returning null simply omits the header.

import { getToken } from 'firebase/app-check';
initializeMAKEMIND({
  apiKey, applicationId,
  getAppCheckToken: async () => (await getToken(appCheck, false)).token,
});

Authentication

const makemind = getMAKEMIND();

// Sign in with email + password
const user = await makemind.auth.signInWithEmail(email, password);

// Sign up a new user
const newUser = await makemind.auth.signUp(email, password, {
  displayName: 'Jane Doe',
});

// Listen to auth state changes
const unsubscribe = makemind.auth.onAuthStateChanged((user) => {
  if (user) {
    console.log('User signed in:', user.uid);
    console.log('Tenant:', user.tenantId);
    console.log('Roles:', user.roles);
  }
});

// Sign out
await makemind.auth.signOut();

// Get user memberships (tenants user belongs to)
const memberships = await makemind.auth.getUserMemberships();

// Switch tenant
await makemind.auth.switchTenant('new-tenant-id');

Data Operations

const makemind = getMAKEMIND();

// Query with tenant isolation
const { data: products } = await makemind.data.query({
  collection: 'plm_products',
  where: [
    { field: 'tenant_id', op: '==', value: makemind.tenantId },
    { field: 'status', op: '==', value: 'active' },
  ],
  orderBy: [{ field: 'created_at', direction: 'desc' }],
  limit: 20,
});

// Get single document
const product = await makemind.data.get({
  collection: 'plm_products',
  documentId: 'product-id',
});

// Create document (tenant_id auto-added)
const result = await makemind.data.create({
  collection: 'plm_products',
  data: {
    product_code: 'PRD-001',
    product_name: 'Sample Product',
    status: 'development',
  },
});

// Update document
await makemind.data.update({
  collection: 'plm_products',
  documentId: 'product-id',
  data: { status: 'active' },
});

// Real-time subscription
const unsubscribe = makemind.data.onCollectionSnapshot(
  {
    collection: 'plm_products',
    where: [{ field: 'tenant_id', op: '==', value: makemind.tenantId }],
  },
  (products) => {
    console.log('Products updated:', products);
  }
);

// Cleanup
unsubscribe();

Logic / Workflows

const makemind = getMAKEMIND();

// ECO workflow transition
await makemind.logic.ecoTransition('eco-id', 'submit');
await makemind.logic.ecoTransition('eco-id', 'approve', {
  comments: 'Approved for implementation',
});

// NCR workflow
await makemind.logic.ncrTransition('issue-id', 'assignContainment', {
  assignedTo: 'user-id',
  containmentAction: 'Quarantine affected parts',
});

// Marketplace bid
await makemind.logic.bidTransition('request-id', 'bid-id', 'submit');

// Gate approval
await makemind.logic.gateApproval('product-id', 'production', 'approve');

// Generic flow execution
const result = await makemind.logic.executeFlow('flow-id', {
  input: 'data',
});

Tenant Management

const makemind = getMAKEMIND();

// Get current tenant
const tenant = await makemind.tenant.getCurrent();

// Update tenant settings
await makemind.tenant.updateTenant({
  settings: { industryType: 'electronics' },
});

// List members
const members = await makemind.tenant.listMembers();

// Invite member
await makemind.tenant.inviteMember({
  email: '[email protected]',
  role: 'manager',
});

// Workspaces
const workspaces = await makemind.tenant.listWorkspaces();
await makemind.tenant.createWorkspace({
  name: 'Development Team',
  description: 'R&D workspace',
});

Messaging / Notifications

const makemind = getMAKEMIND();

// Send notification
await makemind.messaging.send({
  template: 'ecoReviewRequest',
  recipients: ['user-1', 'user-2'],
  data: {
    ecoNumber: 'ECO-2024-001',
    title: 'Design Change Request',
  },
  channels: ['push', 'email'],
});

// Listen to notifications
const unsubscribe = makemind.messaging.onNotifications(
  (notifications) => {
    console.log('Notifications:', notifications);
  },
  { unreadOnly: true }
);

// Mark as read
await makemind.messaging.markAsRead('notification-id');

Settlement / Billing

const makemind = getMAKEMIND();

// Record usage event
await makemind.settlement.recordProductCreation('product-id');
await makemind.settlement.recordDocumentUpload('doc-id', 2.5); // 2.5 MB

// Get usage stats
const stats = await makemind.settlement.getUsageStats('currentMonth');

// Get billing summary
const billing = await makemind.settlement.getBillingSummary();

// Check quotas
const quotas = await makemind.settlement.getQuotaStatus();

// List invoices
const invoices = await makemind.settlement.listInvoices({ status: 'pending' });

Storage

const makemind = getMAKEMIND();

// Upload a file
const uploaded = await makemind.storage.upload({
  path: 'products/product-id/documents/spec.pdf',
  file: fileFromInput, // File | Blob
  metadata: { documentType: 'spec' },
  onProgress: (progress) => console.log(`${progress.toFixed(0)}%`),
});

// Get a download URL / download directly
const url = await makemind.storage.getDownloadUrl('products/product-id/documents/spec.pdf');
const blob = await makemind.storage.download('products/product-id/documents/spec.pdf');

// List, copy, move, delete
const { files } = await makemind.storage.listFiles({ prefix: 'products/product-id/documents/' });
await makemind.storage.copy('a.pdf', 'b.pdf');
await makemind.storage.move('a.pdf', 'archive/a.pdf');
await makemind.storage.delete('a.pdf');

// PLM-specific helpers
await makemind.storage.uploadProductDocument('product-id', file, { documentType: 'drawing' });
await makemind.storage.uploadEcoAttachment('eco-id', file);
await makemind.storage.uploadQualityAttachment('issue-id', file);
const productDocs = await makemind.storage.getProductDocuments('product-id');

// Bucket management
const buckets = await makemind.storage.listBuckets();
await makemind.storage.createBucket({ name: 'reports', publicAccess: false });
const stats = await makemind.storage.getUsageStats();

AI

const makemind = getMAKEMIND();

// Chat completion
const { message, usage } = await makemind.ai.chat([
  { role: 'user', content: 'Summarize this ECO for a release note.' },
]);

// Streaming (polling-based; delivers content deltas as they arrive)
await makemind.ai.chatStream(
  [{ role: 'user', content: 'Draft a quality report.' }],
  (chunk) => process.stdout.write(chunk),
  { onDone: (response) => console.log('done', response.usage) }
);

// Or consume as an async generator
for await (const delta of makemind.ai.streamChat([{ role: 'user', content: 'Hi' }])) {
  console.log(delta);
}

// Embeddings
const { embeddings } = await makemind.ai.createEmbedding(['spec text', 'another doc']);

// Vector search over a tenant knowledge collection
const hits = await makemind.ai.vectorSearch('specs', 'torque tolerance', { limit: 5 });

// Vision
await makemind.ai.analyzeImage('https://example.com/part.png', 'Describe this part.');
await makemind.ai.analyzeImageBase64(base64Data, 'image/png', 'Describe this part.');

// Tool calling
const { toolCalls } = await makemind.ai.chatWithTools(
  [{ role: 'user', content: 'Look up product PRD-001.' }],
  [{ name: 'getProduct', description: 'Fetch a product by code', parameters: { type: 'object' } }]
);

// Convenience helpers
const { text } = await makemind.ai.generate('Write a one-line changelog entry.');
const { summary } = await makemind.ai.summarize(longText, { style: 'bullet', maxLength: 100 });
const { translation } = await makemind.ai.translate('Hello world', 'ko');

Search

const makemind = getMAKEMIND();

// Simple query
const results = await makemind.search.query({ q: 'bracket', collections: ['plm_products'], perPage: 20 });

// Advanced query with facets/filters/highlighting
const advanced = await makemind.search.advanced({
  query: 'bracket',
  collection: 'plm_products',
  facets: ['status', 'category'],
  filters: { status: 'active' },
  highlightFields: ['product_name'],
});

// Autocomplete suggestions
const suggestions = await makemind.search.suggestions({ prefix: 'brac', collection: 'plm_products' });

// Analytics and reindexing
const analytics = await makemind.search.getAnalytics({ startDate: '2026-01-01' });
const { jobId } = await makemind.search.bulkReindex({ collection: 'plm_products' });
const status = await makemind.search.getBulkReindexStatus({ jobId });

Apps (App Builder)

const makemind = getMAKEMIND();

// Create and manage apps
const { appId } = await makemind.apps.createApp({ name: 'field-service', displayName: 'Field Service' });
const app = await makemind.apps.getApp(appId);
const { apps } = await makemind.apps.listApps({ status: 'draft' });
await makemind.apps.updateApp(appId, { settings: { theme: { mode: 'dark' } } });

// Pages
const { pageId } = await makemind.apps.createPage(appId, { name: 'Home', path: '/', isHomePage: true });
await makemind.apps.updatePage(appId, pageId, { title: 'Home' });
const pages = await makemind.apps.listPages(appId);

// Publishing & versioning
await makemind.apps.publish(appId, 'Initial release');
const versions = await makemind.apps.getVersions(appId);
await makemind.apps.rollback(appId, versions[0].version);

// Domains
await makemind.apps.addSubdomain(appId, 'field-service');
const { verificationToken, dnsRecords } = await makemind.apps.addCustomDomain(appId, 'app.example.com');

// AI-assisted UI generation
const { components } = await makemind.apps.generateUI('A form to log a quality issue');

// Live-edit collaboration
const { sessionToken, wsEndpoint } = await makemind.apps.startSession(appId, pageId);

Marketplace

const makemind = getMAKEMIND();

// Discovery
const results = await makemind.marketplace.search({ query: 'inventory', category: 'operations' });
const listing = await makemind.marketplace.getDetail('listing-id');
const featured = await makemind.marketplace.getFeatured();

// Installation
const { bindingId } = await makemind.marketplace.install('listing-id');
const installed = await makemind.marketplace.listInstalled();
await makemind.marketplace.uninstall('listing-id');

// App runtime (proxy calls through the installed binding)
const config = await makemind.marketplace.getConfig(bindingId);
await makemind.marketplace.proxy(bindingId, { method: 'GET', path: 'items' });

// Reviews
await makemind.marketplace.createReview({ listingId: 'listing-id', rating: 5, body: 'Great app' });
const reviews = await makemind.marketplace.listReviews('listing-id');

// Publishing (for publisher tenants)
await makemind.marketplace.createPublisherProfile({
  displayName: 'Acme Apps',
  description: 'Field service tools',
  logoUrl: 'https://example.com/logo.png',
  supportEmail: '[email protected]',
});
const newListing = await makemind.marketplace.createListing({ name: 'Inventory Sync' });
await makemind.marketplace.submitForReview((newListing as { listingId: string }).listingId);

Platform Operations (Generic Dispatch)

Every typed service method (data.*, tenant.*, messaging.*, ...) is a thin wrapper around the gateway's RPC dispatch route. When a backend operation does not yet have a typed service method, call it directly with makemind.call():

const makemind = getMAKEMIND();

// call<T>(operation, input) -> POST /api/v<version>/call/:operation
// The `{ data }` response envelope is already unwrapped.
const result = await makemind.call('updateMyProfile', { displayName: 'Jane Doe' });

call(operation, input) invokes a platform Callable operation through the gateway RPC dispatch route. The operation key is the deployed Callable name: namespaced groups use <prefix>-<name> (e.g. settlement-getMRR, marketplace-listPublisherListings); flat exports use the bare name (e.g. createTenant, updateMyProfile). Each operation enforces its own authorization server-side (platform roles / tenant scopes), so calling an operation you are not authorized for still fails with PERMISSION_DENIED — call() does not bypass access control.

This is distinct from logic.call(functionName, input), which executes a tenant-defined logic function (POST /logic/call), not a platform Callable.

Some illustrative operations reachable only through call() (no dedicated typed method yet):

await makemind.call('platformGetAuditLogs', { limit: 50 });
await makemind.call('updateMyProfile', { displayName: 'Jane Doe' });
await makemind.call('endusers-listEndUsers', { limit: 20 });
await makemind.call('knowledge-knowledgeCreateUploadUrl', { fileName: 'spec.pdf' });
await makemind.call('getBillingContact', {});
await makemind.call('updateBillingContact', { email: '[email protected]' });
await makemind.call('getMyLoginHistory', { limit: 10 });
await makemind.call('createBrandingLogoUploadUrl', { fileName: 'logo.png' });
await makemind.call('marketplace-listPublisherListings', {});

React Integration Example

// src/lib/makemind.ts
import { initializeMAKEMIND } from '@makemind/sdk';

export const makemind = initializeMAKEMIND({
  apiKey: import.meta.env.VITE_MAKEMIND_API_KEY,
  applicationId: 'plm',
  environment: import.meta.env.DEV ? 'development' : 'production',
  baseUrl: import.meta.env.VITE_MAKEMIND_BASE_URL, // optional gateway override
});

// src/hooks/useProducts.ts
import { useQuery, useMutation, useQueryClient } from '@tanstack/react-query';
import { getMAKEMIND } from '@makemind/sdk';

export function useProducts() {
  const makemind = getMAKEMIND();

  return useQuery({
    queryKey: ['plm_products', makemind.tenantId],
    queryFn: async () => {
      const result = await makemind.data.query({
        collection: 'plm_products',
        where: [
          { field: 'tenant_id', op: '==', value: makemind.tenantId! },
        ],
        orderBy: [{ field: 'updated_at', direction: 'desc' }],
      });
      return result.data;
    },
    enabled: !!makemind.tenantId,
  });
}

export function useCreateProduct() {
  const queryClient = useQueryClient();
  const makemind = getMAKEMIND();

  return useMutation({
    mutationFn: async (data: CreateProductInput) => {
      const result = await makemind.data.create({
        collection: 'plm_products',
        data,
      });

      // Record usage
      await makemind.settlement.recordProductCreation(result.id);

      return result;
    },
    onSuccess: () => {
      queryClient.invalidateQueries({ queryKey: ['plm_products'] });
    },
  });
}

Error Handling

import { MAKEMINDError, ErrorCodes } from '@makemind/sdk';

try {
  await makemind.data.create({ ... });
} catch (error) {
  if (error instanceof MAKEMINDError) {
    switch (error.code) {
      case ErrorCodes.PERMISSION_DENIED:
        console.error('Access denied');
        break;
      case ErrorCodes.QUOTA_EXCEEDED:
        console.error('Quota exceeded');
        break;
      default:
        console.error('Error:', error.message);
    }
  }
}

License

MIT