npm package: @smart-dev-agency/smart-grow-logs
Description: Smart Grow Logs - Secure logging SDK for web applications.
Author: Smart Dev Agency S.A.S
Latest version: 2.0.0

# Smart Grow Logs - Web SDK

Smart Grow Logs for the web sends encrypted logs from browser apps and can automatically capture uncaught browser errors.

## What This SDK Is For

Use this SDK if you want to:

- send logs from React, Vue, Vite or plain browser apps
- attach metadata such as user, session or domain context
- capture uncaught browser errors automatically
- capture unhandled promise rejections automatically

## Before You Start

You need:

1. A Smart Grow Logs project.
2. An API key.
3. Your ingestion URL.

## Installation

```bash
npm install @smart-dev-agency/smart-grow-logs
```

Or with your preferred package manager:

```bash
yarn add @smart-dev-agency/smart-grow-logs
pnpm add @smart-dev-agency/smart-grow-logs
```

## Quick Start

```typescript
import { LogLevel, SmartGrowLogs } from '@smart-dev-agency/smart-grow-logs';

await SmartGrowLogs.initialize({
  apiKey: 'sgl_your_api_key',
  baseUrl: 'https://logs-api.smart-grow.app/',
  debug: true,
  autoCaptureEnabled: true,
});

await SmartGrowLogs.info('Application started');

await SmartGrowLogs.sendLog({
  level: LogLevel.Error,
  message: 'Checkout failed',
  stackTrace: new Error().stack,
  metadata: {
    orderId: 'ORD-123',
    step: 'payment',
  },
  userIdentifier: 'user@example.com',
  sessionId: 'session-abc-123',
});
```

## Common Use Cases

### 1. Log a User Action

```typescript
await SmartGrowLogs.info('User opened billing page');
```

### 2. Log a Caught Error

```typescript
try {
  await api.checkout();
} catch (error) {
  const err = error as Error;

  await SmartGrowLogs.error(err.message, {
    stackTrace: err.stack,
    metadata: {
      feature: 'checkout',
    },
  });
}
```

### 3. Log With Business Metadata

```typescript
await SmartGrowLogs.warn('Payment retry scheduled', {
  metadata: {
    orderId: 'ORD-123',
    retry: 2,
    provider: 'stripe',
  },
  userIdentifier: 'user@example.com',
});
```

## Auto-Capture

With `autoCaptureEnabled: true`, the SDK registers:

- `window.error`
- `unhandledrejection`

### What Is Captured Today

All auto-captured errors are sent at `fatal` level.

- uncaught browser errors
- unhandled promise rejections

### What Is Not Captured Automatically

- framework boundaries that catch the error before it reaches the browser globals
- errors you swallow manually in your own `try/catch`

If your framework catches the error first, forward it manually.

## Framework Examples

### React

Initialize once during startup:

```typescript
import { SmartGrowLogs } from '@smart-dev-agency/smart-grow-logs';

export async function initLogger() {
  await SmartGrowLogs.initialize({
    apiKey: import.meta.env.VITE_SMARTGROW_API_KEY,
    baseUrl: import.meta.env.VITE_SMARTGROW_URL,
    debug: import.meta.env.DEV,
  });
}
```

Forward boundary errors manually:

```typescript
componentDidCatch(error: Error, info: React.ErrorInfo) {
  void SmartGrowLogs.error(error.message, {
    stackTrace: error.stack,
    metadata: {
      source: 'react-error-boundary',
      componentStack: info.componentStack,
    },
  });
}
```

### Vue

```typescript
import { SmartGrowLogs } from '@smart-dev-agency/smart-grow-logs';

await SmartGrowLogs.initialize({
  apiKey: import.meta.env.VITE_SMARTGROW_API_KEY,
  baseUrl: import.meta.env.VITE_SMARTGROW_URL,
});

app.config.errorHandler = (error, instance, info) => {
  void SmartGrowLogs.error(String(error), {
    metadata: {
      source: 'vue-error-handler',
      info,
    },
  });
};
```

## API Essentials

Main entry points:

- `SmartGrowLogs.initialize(options)`
- `SmartGrowLogs.sendLog(options)`
- `SmartGrowLogs.debug(...)`
- `SmartGrowLogs.info(...)`
- `SmartGrowLogs.warn(...)`
- `SmartGrowLogs.error(...)`
- `SmartGrowLogs.fatal(...)`

Important option fields:

- `apiKey`
- `baseUrl`
- `debug`
- `autoCaptureEnabled`

Important log fields:

- `level`
- `message`
- `stackTrace`
- `metadata`
- `userIdentifier`
- `sessionId`

## Auto-Detected Fields

The SDK sends browser and device context automatically, including:

- `device_type`
- `os_name`
- `os_version`
- `app_version`
- `browser_name`
- `browser_version`
- `screen_width`
- `screen_height`
- `language`
- `timezone`

## App Version Detection

The SDK tries these sources, in this order:

1. `<meta name="version" content="1.0.0">`
2. `<meta name="app-version" content="1.0.0">`
3. `window.APP_VERSION`
4. `window.__APP_VERSION__`

Example:

```html
<meta name="version" content="1.2.3" />
```

## Server-Side Rendering (SSR)

When using frameworks like **Next.js** or **Nuxt 3**, code runs on both server and client. The SDK is browser-only — initialize it only on the client side.

### Next.js App Router

```typescript
// app/providers.tsx
'use client';
import { useEffect } from 'react';
import { SmartGrowLogs } from '@smart-dev-agency/smart-grow-logs';

export function LoggerProvider({ children }: { children: React.ReactNode }) {
  useEffect(() => {
    SmartGrowLogs.initialize({
      apiKey: process.env.NEXT_PUBLIC_SMARTGROW_API_KEY!,
      baseUrl: process.env.NEXT_PUBLIC_SMARTGROW_URL!,
    });
  }, []);
  return <>{children}</>;
}
```

### Nuxt 3

```typescript
// plugins/smart-grow-logs.client.ts  ← the .client suffix ensures browser-only
import { SmartGrowLogs } from '@smart-dev-agency/smart-grow-logs';

export default defineNuxtPlugin(async () => {
  await SmartGrowLogs.initialize({
    apiKey: useRuntimeConfig().public.smartgrowApiKey,
    baseUrl: useRuntimeConfig().public.smartgrowUrl,
  });
});
```

## SDK Lifecycle

For SPAs that need to re-initialize (e.g. after authentication changes), call `destroy()` before re-initializing to prevent duplicate event listeners:

```typescript
SmartGrowLogs.destroy();
await SmartGrowLogs.initialize({ apiKey: '...', baseUrl: '...' });
```

## Known Limitations

The following error sources are **not captured automatically** by the SDK:

| Source | Captured? | Workaround |
|--------|-----------|------------|
| Web Workers | No | Forward errors manually via `postMessage` or listen to `worker.onerror` |
| Cross-origin iframes | No | Same-origin policy prevents parent from seeing iframe errors |
| Third-party scripts (CORS) | Partial | Stack trace may be sanitized; only `"Script error."` is visible |
| `Promise.reject()` with circular object | Yes (stringified with `String()`) | No action needed |
| React / Vue component errors | No (framework catches first) | Use `componentDidCatch` or `app.config.errorHandler` — see Framework Examples |

### Web Worker errors

To capture errors from a Worker, forward them to the main thread:

```typescript
// In your worker file
self.onerror = (event) => {
  self.postMessage({ type: 'worker-error', message: event.message, stack: '' });
};

// In main thread
worker.addEventListener('message', (e) => {
  if (e.data.type === 'worker-error') {
    void SmartGrowLogs.error(e.data.message, { stackTrace: e.data.stack });
  }
});
```

## Troubleshooting

### Browser errors are captured, but React or Vue component errors are not

That is expected if your framework catches them first. Forward them manually from your framework boundary or handler.

### I want full manual control over global errors

Disable automatic capture:

```typescript
await SmartGrowLogs.initialize({
  apiKey: 'sgl_your_api_key',
  baseUrl: 'https://logs-api.smart-grow.app/',
  autoCaptureEnabled: false,
});
```

## Browser Support

- Chrome 87+
- Firefox 78+
- Safari 14+
- Edge 88+

Requires WebAssembly support.

## License

MIT