open-index/open-npm huggingface dataset:
npm package: @raideno/convex-analytics
Description: Easily integrate analytics into your convex backend.
Author: raideno
Latest version: 0.0.5

# Convex Analytics

Convex agnostic analytics package. Compatible with posthog, discord webhooks, mail alerts, etc.

```bash
npm install @raideno/convex-analytics
```

`convex/schema.ts`
```ts
import { analyticsTables } from "@raideno/convex-analytics/server";
import { defineSchema } from "convex/server";

export default defineSchema({
  ...analyticsTables,
  /*
   * Your app tables...
   */
});
```

`convex/analytics.ts`
```ts
import { internalConvexAnalytics } from "@raideno/convex-analytics/server";
import { DiscordProcessorFactory } from "@raideno/convex-analytics/processors/discord";
import { PosthogProcessorFactory } from "@raideno/convex-analytics/processors/posthog";

import configuration from "./analytics.config";

export const { store, analytics, process } = internalConvexAnalytics({
    processors: [
        /*
         * Will only capture events named "demo_perform_action".
         */
        DiscordProcessorFactory({
            url: process.env.DISCORD_WEBHOOK_URL!,
            events: ["demo_perform_action"],
        }),
        /*
         * Will capture all events.
         */
        PosthogProcessorFactory({
            key: process.env.POSTHOG_KEY!,
            host: "https://us.i.posthog.com",
            events: ["*"],
        }),
    ],
    processEveryK: 1,
});
```

`convex/actions.ts`
```ts
/*
 * Imports
 */

import { analytics } from "./analytics"

export const perform = action({
  args: {
    value: v.optional(v.string()),
  },
  handler: async (context, args) => {
    /*
     * ...
     */

    await analytics.track(
      context as unknown as GenericActionCtx<AnyDataModel>,
      {
        name: "demo_perform_action",
        distinctId: userId,
        properties: {
          value: args.value || "no_value",
        },
      }
    );

    /*
     * ...
     */
  },
});
```

You can also provide custom processors by implementing the `Processor` interface from `@raideno/convex-analytics/processors`.
```ts
export const { store, analytics, process } = internalConvexAnalytics({
    processors: [
        {
            events: ["*"],
            /*
             * Receives an action context and a batch of events of up to `processEveryK`.
             * Must return the list of processed event IDs.
             */
            handler: async (context, events) => {
                console.log(
                    "[events]:",
                    events.map((e) => e.name)
                );
                return events.map((e) => e._id);
            },
        } as Processor,
    ],
    processEveryK: 1,
});
```

An example app can be found in the [demo package](./packages/demo/README.md).
npm package: @raideno/convex-billing
Description: Easy stripe billing for convex apps.
Author: raideno
Latest version: 0.0.28
Deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.

# Convex Stripe Billing

A demo project is available at [https://convex-billing-demo.vercel.app/](https://convex-billing-demo.vercel.app/).

Stripe subscriptions, limits and features for Convex apps. Implemented according to the best practices listed in [Stripe Recommendations](https://github.com/t3dotgg/stripe-recommendations).

## Install

```bash
npm install @raideno/convex-billing stripe
```

## Documentation

You can find the detailed documentation @ [https://raideno.github.io/convex-billing](https://raideno.github.io/convex-billing).
npm package: @raideno/convex-kv
Description: Use Convex tables as a typed key-value store.
Author: raideno
Latest version: 0.1.0

# Convex KV

Use a Convex table as a key-value store with optional expiration.

```bash
npm install @raideno/convex-kv
```

`convex/schema.ts`
```ts
import { defineSchema } from "convex/server";
import { kvTables } from "@raideno/convex-kv/server";

export default defineSchema({
  ...kvTables,
  /*
   * Your app tables...
   */
});
```

`convex/kv.ts`
```ts
import { internalConvexKv } from "@raideno/convex-kv/server";

export const { store, kv } = internalConvexKv();
```

`convex/actions.ts`
```ts
import { action } from "./_generated/server";
import { v } from "convex/values";

import { kv } from "./kv";

export const save = action({
  args: {
    key: v.string(),
    value: v.any(),
    ttlMs: v.optional(v.number()),
  },
  handler: async (context, args) => {
    await kv.setWithExpiration(context, {
      key: args.key,
      value: args.value,
      expiresInMs: args.ttlMs,
    });
  },
});

export const load = action({
  args: {
    key: v.string(),
  },
  handler: async (context, args) => {
    return await kv.getOrDefault(context, {
      key: args.key,
      defaultValue: "not_found",
    });
  },
});
```

## API

- `kv.set(context, { key, value })`
- `kv.setWithExpiration(context, { key, value, expiresInMs? | expiresAt? })`
- `kv.get(context, { key })`
- `kv.getOrDefault(context, { key, defaultValue })`
- `kv.has(context, { key })`
- `kv.delete(context, { key })`

Expired keys are treated as missing and cleaned up lazily on reads.