Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
281 changes: 281 additions & 0 deletions examples/minimal-sdk/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,281 @@
# Minimal SDK Example

This example demonstrates how to build a complete SDK using `@lytics/sdk-kit`.

## Features Demonstrated

### ✅ Plugin System
- **Logger Plugin** - Console logging with levels
- **Analytics Plugin** - Event tracking with batching
- **Monitor Plugin** - Cross-plugin event monitoring

### ✅ Core Capabilities
- **Configuration** - Hierarchical config with defaults
- **Events** - Pub/sub event system with wildcards
- **Lifecycle** - Init/destroy with proper cleanup
- **API Exposure** - Public methods from plugins
- **Plugin Communication** - Inter-plugin events

## Project Structure

```
examples/minimal-sdk/
├── src/
│ ├── index.ts # Main SDK and demo
│ └── plugins/
│ ├── logger.ts # Logging plugin
│ ├── analytics.ts # Analytics plugin
│ └── monitor.ts # Monitoring plugin
├── package.json
├── tsconfig.json
└── README.md
```

## Running the Example

### Install Dependencies

From the repository root:

```bash
pnpm install
```

### Build the Example

```bash
cd examples/minimal-sdk
pnpm build
```

### Run the Demo

```bash
pnpm start
```

## Code Walkthrough

### 1. Logger Plugin

**File:** `src/plugins/logger.ts`

Demonstrates:
- Setting a namespace (`plugin.ns('logger')`)
- Providing config defaults
- Exposing public methods (`debug`, `info`, `warn`, `error`)
- Listening to SDK lifecycle events
- Emitting custom events

```typescript
export const loggerPlugin: PluginFunction = (plugin, instance, config) => {
plugin.ns('logger');

plugin.defaults({
logger: {
enabled: true,
level: 'info',
},
});

plugin.expose({
debug(message: string) { /* ... */ },
info(message: string) { /* ... */ },
// ...
});

instance.on('sdk:ready', () => {
console.log('SDK ready!');
});
};
```

### 2. Analytics Plugin

**File:** `src/plugins/analytics.ts`

Demonstrates:
- Event batching and auto-flush
- Timer management in lifecycle
- Emitting events for other plugins
- Async operations

```typescript
export const analyticsPlugin: PluginFunction = (plugin, instance, config) => {
plugin.ns('analytics');

plugin.expose({
track(eventName: string, properties?: any) {
eventQueue.push({ eventName, properties });
plugin.emit('analytics:tracked', { eventName });
},
flush: async () => { /* send to server */ }
});

instance.on('sdk:ready', () => {
startFlushTimer();
});
};
```

### 3. Monitor Plugin

**File:** `src/plugins/monitor.ts`

Demonstrates:
- Wildcard event subscriptions (`analytics:*`)
- Plugin-to-plugin communication
- Reading config from other plugins
- Statistics collection

```typescript
export const monitorPlugin: PluginFunction = (plugin, instance, config) => {
plugin.ns('monitor');

// Listen to all analytics events
instance.on('analytics:*', (data) => {
console.log('Analytics event:', data);
});

// Listen to specific events
instance.on('analytics:tracked', () => {
stats.trackedEvents++;
});
};
```

### 4. Main SDK

**File:** `src/index.ts`

Shows how to:
- Create SDK instance
- Register multiple plugins
- Configure plugins
- Use exposed APIs
- Subscribe to events
- Handle lifecycle

```typescript
const sdk = createMySDK({
logger: { level: 'debug' },
analytics: { batchSize: 3 },
});

sdk.on('sdk:ready', () => console.log('Ready!'));

await sdk.init();

// Use plugin methods
sdk.info('Hello world');
sdk.track('button_clicked', { button: 'sign_up' });
sdk.identify('user-123', { name: 'John' });

// Check stats from monitor
const stats = sdk.getStats();

await sdk.destroy();
```

## Expected Output

When you run the demo, you should see:

```
============================================================
SDK Kit - Minimal Example
============================================================

[Monitor] Analytics event: { ... }
2024-01-01T12:00:00.000Z [MySDK] [INFO] SDK initialized successfully

✅ SDK is ready!

2024-01-01T12:00:00.001Z [MySDK] [DEBUG] Debug information
📊 Event tracked: button_clicked
📊 Event tracked: form_submitted

⏱️ Waiting for auto-flush...

[Analytics] Flushing 3 events to https://my-analytics.example.com/events
[Analytics] Events: [...]

📈 Monitoring Stats:
{ trackedEvents: 3, identifyCalls: 1, pageViews: 1, ... }

📝 All Logs:
2024-01-01T12:00:00.000Z [MySDK] [INFO] SDK initialized
...

⚙️ Configuration:
Analytics endpoint: https://my-analytics.example.com/events
Logger level: debug

🧹 Destroying SDK...
2024-01-01T12:00:01.000Z [MySDK] [INFO] SDK destroyed

✅ Demo complete!
============================================================
```

## Key Takeaways

### Plugin Architecture
- Plugins are **pure functions** that receive capabilities
- Each plugin sets a **unique namespace**
- Plugins can **expose methods** that become part of the SDK API
- Plugins **communicate via events** (decoupled)

### Configuration
- Hierarchical config with **dot-notation** access
- **Defaults are underwritten** (user config wins)
- Config is **accessible** to all plugins
- Can be **updated at runtime**

### Events
- **Pub/sub pattern** for loose coupling
- **Wildcard subscriptions** (e.g., `analytics:*`)
- **Lifecycle events** (`sdk:init`, `sdk:ready`, `sdk:destroy`)
- **Custom events** for plugin communication

### Lifecycle
- **`init()`** - Start the SDK, emit events
- **`destroy()`** - Clean up resources, flush data
- Plugins can **hook into lifecycle** via events
- Proper **cleanup** prevents memory leaks

## Extending This Example

You can easily add more plugins:

```typescript
// Create a new plugin
export const myPlugin: PluginFunction = (plugin, instance, config) => {
plugin.ns('my.plugin');

plugin.defaults({
my: { plugin: { setting: 'value' } }
});

plugin.expose({
myMethod() {
plugin.emit('my:event', { data: 'value' });
}
});
};

// Register it
sdk.use(myPlugin);
```

## Next Steps

- Check out the [Core Package README](../../packages/core/README.md) for full API documentation
- See the [Architecture Notes](../../notes/architecture.md) for design details
- Build your own plugins following these patterns
- Create a production-ready SDK with error handling, retries, etc.

## Questions?

See the main [README](../../README.md) or check the [specs](../../specs) for more information.

20 changes: 20 additions & 0 deletions examples/minimal-sdk/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"name": "minimal-sdk-example",
"version": "1.0.0",
"description": "Minimal example SDK built with @lytics/sdk-kit",
"type": "module",
"main": "dist/index.js",
"types": "dist/index.d.ts",
"scripts": {
"build": "tsc",
"dev": "tsc --watch",
"start": "node dist/index.js"
},
"dependencies": {
"@lytics/sdk-kit": "workspace:*"
},
"devDependencies": {
"typescript": "^5.9.3"
}
}

Loading