mirror of
https://github.com/zoriya/drizzle-otel.git
synced 2025-12-06 00:46:09 +00:00
autumn telemetry sdk
This commit is contained in:
5
packages/otel-autumn/.npmignore
Normal file
5
packages/otel-autumn/.npmignore
Normal file
@@ -0,0 +1,5 @@
|
||||
src/
|
||||
tsconfig.json
|
||||
*.test.ts
|
||||
.gitignore
|
||||
node_modules/
|
||||
13
packages/otel-autumn/CHANGELOG.md
Normal file
13
packages/otel-autumn/CHANGELOG.md
Normal file
@@ -0,0 +1,13 @@
|
||||
# @kubiks/otel-autumn
|
||||
|
||||
## 1.0.0
|
||||
|
||||
### Major Changes
|
||||
|
||||
- Initial release of OpenTelemetry instrumentation for Autumn billing SDK
|
||||
- Instrument core billing operations: check, track, checkout, attach, cancel
|
||||
- Comprehensive span attributes for billing observability
|
||||
- Support for feature access control monitoring
|
||||
- Usage tracking instrumentation
|
||||
- Checkout flow tracing with Stripe integration details
|
||||
- Product lifecycle management (attach/cancel) tracing
|
||||
21
packages/otel-autumn/LICENSE
Normal file
21
packages/otel-autumn/LICENSE
Normal file
@@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2025 Kubiks
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
220
packages/otel-autumn/README.md
Normal file
220
packages/otel-autumn/README.md
Normal file
@@ -0,0 +1,220 @@
|
||||
# @kubiks/otel-autumn
|
||||
|
||||
OpenTelemetry instrumentation for the [Autumn](https://useautumn.com) billing SDK.
|
||||
Capture spans for every billing operation including feature checks, usage tracking, checkout flows, product attachments, and cancellations with detailed metadata.
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
npm install @kubiks/otel-autumn
|
||||
# or
|
||||
pnpm add @kubiks/otel-autumn
|
||||
```
|
||||
|
||||
**Peer Dependencies:** `@opentelemetry/api` >= 1.9.0, `autumn-js` >= 0.1.0
|
||||
|
||||
## Quick Start
|
||||
|
||||
```ts
|
||||
import { Autumn } from "autumn-js";
|
||||
import { instrumentAutumn } from "@kubiks/otel-autumn";
|
||||
|
||||
const autumn = instrumentAutumn(
|
||||
new Autumn({
|
||||
secretKey: process.env.AUTUMN_SECRET_KEY!,
|
||||
})
|
||||
);
|
||||
|
||||
// All operations are now automatically traced
|
||||
const checkResult = await autumn.check({
|
||||
customer_id: "user_123",
|
||||
feature_id: "messages",
|
||||
});
|
||||
|
||||
await autumn.track({
|
||||
customer_id: "user_123",
|
||||
feature_id: "messages",
|
||||
value: 1,
|
||||
});
|
||||
```
|
||||
|
||||
`instrumentAutumn` wraps your Autumn client instance — no configuration changes needed. Every SDK call creates a client span with detailed billing attributes.
|
||||
|
||||
## What Gets Traced
|
||||
|
||||
This instrumentation wraps the core Autumn billing methods:
|
||||
|
||||
- **`check`** - Feature access and product status checks
|
||||
- **`track`** - Usage event tracking
|
||||
- **`checkout`** - Checkout session creation
|
||||
- **`attach`** - Product attachment to customers
|
||||
- **`cancel`** - Product cancellation
|
||||
|
||||
Each operation creates a dedicated span with operation-specific attributes.
|
||||
|
||||
## Span Attributes
|
||||
|
||||
### Common Attributes (All Operations)
|
||||
|
||||
| Attribute | Description | Example |
|
||||
| ----------------------- | ----------------------------------- | ------------------ |
|
||||
| `billing.system` | Constant value `autumn` | `autumn` |
|
||||
| `billing.operation` | Operation type | `check`, `track` |
|
||||
| `autumn.resource` | Resource being accessed | `features`, `products` |
|
||||
| `autumn.target` | Full operation target | `features.check` |
|
||||
| `autumn.customer_id` | Customer ID | `user_123` |
|
||||
| `autumn.entity_id` | Entity ID (if applicable) | `org_456` |
|
||||
|
||||
### Check Operation
|
||||
|
||||
| Attribute | Description | Example |
|
||||
| ------------------------- | --------------------------------- | ------------ |
|
||||
| `autumn.feature_id` | Feature being checked | `messages` |
|
||||
| `autumn.product_id` | Product being checked | `pro` |
|
||||
| `autumn.allowed` | Whether access is allowed | `true` |
|
||||
| `autumn.balance` | Current balance/remaining uses | `42` |
|
||||
| `autumn.usage` | Current usage | `8` |
|
||||
| `autumn.included_usage` | Included usage in plan | `50` |
|
||||
| `autumn.unlimited` | Whether usage is unlimited | `false` |
|
||||
| `autumn.required_balance` | Required balance for operation | `1` |
|
||||
|
||||
### Track Operation
|
||||
|
||||
| Attribute | Description | Example |
|
||||
| -------------------------- | ------------------------------ | ----------------- |
|
||||
| `autumn.feature_id` | Feature being tracked | `messages` |
|
||||
| `autumn.event_name` | Custom event name | `message_sent` |
|
||||
| `autumn.value` | Usage value tracked | `1` |
|
||||
| `autumn.event_id` | Generated event ID | `evt_123` |
|
||||
| `autumn.idempotency_key` | Idempotency key for dedup | `msg_456` |
|
||||
|
||||
### Checkout Operation
|
||||
|
||||
| Attribute | Description | Example |
|
||||
| --------------------------- | ---------------------------------- | ------------------------- |
|
||||
| `autumn.product_id` | Product being purchased | `pro` |
|
||||
| `autumn.product_ids` | Multiple products (comma-separated)| `pro, addon_analytics` |
|
||||
| `autumn.checkout_url` | Stripe checkout URL | `https://checkout.stripe.com/...` |
|
||||
| `autumn.has_prorations` | Whether prorations apply | `true` |
|
||||
| `autumn.total_amount` | Total checkout amount | `2000` (cents) |
|
||||
| `autumn.currency` | Currency code | `usd` |
|
||||
| `autumn.force_checkout` | Whether to force Stripe checkout | `false` |
|
||||
| `autumn.invoice` | Whether to create invoice | `true` |
|
||||
|
||||
### Attach Operation
|
||||
|
||||
| Attribute | Description | Example |
|
||||
| ------------------------ | ------------------------------- | -------------------------------- |
|
||||
| `autumn.product_id` | Product being attached | `pro` |
|
||||
| `autumn.success` | Whether attachment succeeded | `true` |
|
||||
| `autumn.checkout_url` | Checkout URL if payment needed | `https://checkout.stripe.com/...`|
|
||||
|
||||
### Cancel Operation
|
||||
|
||||
| Attribute | Description | Example |
|
||||
| ---------------------- | -------------------------------- | ---------- |
|
||||
| `autumn.product_id` | Product being cancelled | `pro` |
|
||||
| `autumn.success` | Whether cancellation succeeded | `true` |
|
||||
|
||||
## Configuration
|
||||
|
||||
You can optionally configure the instrumentation:
|
||||
|
||||
```ts
|
||||
import { instrumentAutumn } from "@kubiks/otel-autumn";
|
||||
|
||||
const autumn = instrumentAutumn(client, {
|
||||
// Capture customer data in spans (default: false)
|
||||
captureCustomerData: true,
|
||||
|
||||
// Capture product options/configuration (default: false)
|
||||
captureOptions: true,
|
||||
});
|
||||
```
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Feature Access Control
|
||||
|
||||
```ts
|
||||
const autumn = instrumentAutumn(new Autumn({ secretKey: process.env.AUTUMN_SECRET_KEY! }));
|
||||
|
||||
// Check if user can access a feature
|
||||
const result = await autumn.check({
|
||||
customer_id: "user_123",
|
||||
feature_id: "messages",
|
||||
required_balance: 1,
|
||||
});
|
||||
|
||||
if (result.data?.allowed) {
|
||||
// User has access
|
||||
console.log(`Remaining: ${result.data.balance}`);
|
||||
}
|
||||
```
|
||||
|
||||
### Usage Tracking
|
||||
|
||||
```ts
|
||||
// Track feature usage
|
||||
await autumn.track({
|
||||
customer_id: "user_123",
|
||||
feature_id: "messages",
|
||||
value: 1,
|
||||
idempotency_key: `msg_${messageId}`, // Prevent double-counting
|
||||
});
|
||||
```
|
||||
|
||||
### Checkout Flow
|
||||
|
||||
```ts
|
||||
// Create a checkout session for a product
|
||||
const result = await autumn.checkout({
|
||||
customer_id: "user_123",
|
||||
product_id: "pro",
|
||||
force_checkout: false, // Use billing portal if payment method exists
|
||||
});
|
||||
|
||||
if (result.data?.url) {
|
||||
// Redirect to Stripe checkout
|
||||
console.log(`Checkout URL: ${result.data.url}`);
|
||||
}
|
||||
```
|
||||
|
||||
### Product Management
|
||||
|
||||
```ts
|
||||
// Attach a free product
|
||||
const attachResult = await autumn.attach({
|
||||
customer_id: "user_123",
|
||||
product_id: "free",
|
||||
});
|
||||
|
||||
// Cancel a subscription
|
||||
const cancelResult = await autumn.cancel({
|
||||
customer_id: "user_123",
|
||||
product_id: "pro",
|
||||
});
|
||||
```
|
||||
|
||||
## Observability Benefits
|
||||
|
||||
This instrumentation helps you:
|
||||
|
||||
- **Monitor billing operations** - Track success rates, latencies, and errors for all billing calls
|
||||
- **Debug checkout issues** - See complete checkout flows including prorations and payment failures
|
||||
- **Analyze feature usage** - Understand which features are being checked and tracked most
|
||||
- **Track customer journey** - Follow customers through check → track → checkout flows
|
||||
- **Identify bottlenecks** - Find slow billing operations impacting user experience
|
||||
- **Audit billing events** - Complete trace of all billing-related operations
|
||||
|
||||
## Best Practices
|
||||
|
||||
1. **Always track server-side** - Use `check` and `track` on the backend for security
|
||||
2. **Use idempotency keys** - Prevent duplicate tracking with `idempotency_key`
|
||||
3. **Monitor check failures** - Alert on high rates of `allowed: false` checks
|
||||
4. **Track checkout abandonment** - Monitor spans where checkout URLs are generated but not completed
|
||||
5. **Correlate with business metrics** - Link billing spans to revenue and conversion metrics
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
53
packages/otel-autumn/package.json
Normal file
53
packages/otel-autumn/package.json
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"name": "@kubiks/otel-autumn",
|
||||
"version": "1.0.0",
|
||||
"private": false,
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
},
|
||||
"description": "OpenTelemetry instrumentation for the Autumn billing SDK",
|
||||
"author": "Kubiks",
|
||||
"license": "MIT",
|
||||
"repository": "kubiks-inc/otel",
|
||||
"sideEffects": false,
|
||||
"type": "module",
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./dist/types/index.d.ts",
|
||||
"import": "./dist/index.js",
|
||||
"default": "./dist/index.js"
|
||||
}
|
||||
},
|
||||
"main": "./dist/index.js",
|
||||
"types": "./dist/types/index.d.ts",
|
||||
"files": [
|
||||
"dist",
|
||||
"LICENSE",
|
||||
"README.md"
|
||||
],
|
||||
"engines": {
|
||||
"node": "^18.19.0 || >=20.6.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "pnpm clean && tsc",
|
||||
"clean": "rimraf dist",
|
||||
"prepublishOnly": "pnpm build",
|
||||
"type-check": "tsc --noEmit",
|
||||
"unit-test": "vitest --run",
|
||||
"unit-test-watch": "vitest"
|
||||
},
|
||||
"dependencies": {},
|
||||
"devDependencies": {
|
||||
"@opentelemetry/api": "^1.9.0",
|
||||
"@opentelemetry/sdk-trace-base": "^2.1.0",
|
||||
"@types/node": "18.15.11",
|
||||
"autumn-js": "^0.1.40",
|
||||
"rimraf": "3.0.2",
|
||||
"typescript": "^5",
|
||||
"vitest": "0.33.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@opentelemetry/api": ">=1.9.0 <2.0.0",
|
||||
"autumn-js": ">=0.1.0"
|
||||
}
|
||||
}
|
||||
204
packages/otel-autumn/src/index.test.ts
Normal file
204
packages/otel-autumn/src/index.test.ts
Normal file
@@ -0,0 +1,204 @@
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
import { trace, type Tracer, type Span } from "@opentelemetry/api";
|
||||
import { instrumentAutumn } from "./index";
|
||||
import type { Autumn } from "autumn-js";
|
||||
|
||||
describe("instrumentAutumn", () => {
|
||||
let mockClient: Autumn;
|
||||
let mockTracer: Tracer;
|
||||
let mockSpan: Span;
|
||||
|
||||
beforeEach(() => {
|
||||
// Mock span
|
||||
mockSpan = {
|
||||
setAttributes: vi.fn(),
|
||||
setAttribute: vi.fn(),
|
||||
setStatus: vi.fn(),
|
||||
end: vi.fn(),
|
||||
recordException: vi.fn(),
|
||||
} as any;
|
||||
|
||||
// Mock tracer
|
||||
mockTracer = {
|
||||
startSpan: vi.fn().mockReturnValue(mockSpan),
|
||||
} as any;
|
||||
|
||||
// Mock trace.getTracer
|
||||
vi.spyOn(trace, "getTracer").mockReturnValue(mockTracer);
|
||||
|
||||
// Mock Autumn client
|
||||
mockClient = {
|
||||
check: vi.fn().mockResolvedValue({ data: { allowed: true, balance: 5 } }),
|
||||
track: vi.fn().mockResolvedValue({ data: { id: "evt_123" } }),
|
||||
checkout: vi.fn().mockResolvedValue({ data: { url: "https://checkout.stripe.com" } }),
|
||||
attach: vi.fn().mockResolvedValue({ data: { success: true } }),
|
||||
cancel: vi.fn().mockResolvedValue({ data: { success: true } }),
|
||||
} as any;
|
||||
});
|
||||
|
||||
it("should not instrument the same client twice", () => {
|
||||
const instrumented1 = instrumentAutumn(mockClient);
|
||||
const instrumented2 = instrumentAutumn(instrumented1);
|
||||
|
||||
expect(instrumented1).toBe(instrumented2);
|
||||
});
|
||||
|
||||
describe("check method", () => {
|
||||
it("should create a span for check operations", async () => {
|
||||
const instrumented = instrumentAutumn(mockClient);
|
||||
|
||||
await instrumented.check({
|
||||
customer_id: "user_123",
|
||||
feature_id: "messages",
|
||||
});
|
||||
|
||||
expect(mockTracer.startSpan).toHaveBeenCalledWith(
|
||||
"autumn.check",
|
||||
expect.objectContaining({ kind: expect.any(Number) })
|
||||
);
|
||||
});
|
||||
|
||||
it("should set span attributes for check", async () => {
|
||||
const instrumented = instrumentAutumn(mockClient);
|
||||
|
||||
await instrumented.check({
|
||||
customer_id: "user_123",
|
||||
feature_id: "messages",
|
||||
required_balance: 1,
|
||||
});
|
||||
|
||||
expect(mockSpan.setAttribute).toHaveBeenCalledWith("autumn.customer_id", "user_123");
|
||||
expect(mockSpan.setAttribute).toHaveBeenCalledWith("autumn.feature_id", "messages");
|
||||
expect(mockSpan.setAttribute).toHaveBeenCalledWith("autumn.required_balance", 1);
|
||||
});
|
||||
|
||||
it("should handle check errors", async () => {
|
||||
mockClient.check = vi.fn().mockRejectedValue(new Error("API Error"));
|
||||
const instrumented = instrumentAutumn(mockClient);
|
||||
|
||||
await expect(
|
||||
instrumented.check({ customer_id: "user_123", feature_id: "messages" })
|
||||
).rejects.toThrow("API Error");
|
||||
|
||||
expect(mockSpan.recordException).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
|
||||
describe("track method", () => {
|
||||
it("should create a span for track operations", async () => {
|
||||
const instrumented = instrumentAutumn(mockClient);
|
||||
|
||||
await instrumented.track({
|
||||
customer_id: "user_123",
|
||||
feature_id: "messages",
|
||||
value: 1,
|
||||
});
|
||||
|
||||
expect(mockTracer.startSpan).toHaveBeenCalledWith(
|
||||
"autumn.track",
|
||||
expect.objectContaining({ kind: expect.any(Number) })
|
||||
);
|
||||
});
|
||||
|
||||
it("should set span attributes for track", async () => {
|
||||
const instrumented = instrumentAutumn(mockClient);
|
||||
|
||||
await instrumented.track({
|
||||
customer_id: "user_123",
|
||||
feature_id: "messages",
|
||||
value: 1,
|
||||
idempotency_key: "msg_456",
|
||||
});
|
||||
|
||||
expect(mockSpan.setAttribute).toHaveBeenCalledWith("autumn.customer_id", "user_123");
|
||||
expect(mockSpan.setAttribute).toHaveBeenCalledWith("autumn.feature_id", "messages");
|
||||
expect(mockSpan.setAttribute).toHaveBeenCalledWith("autumn.value", 1);
|
||||
expect(mockSpan.setAttribute).toHaveBeenCalledWith("autumn.idempotency_key", "msg_456");
|
||||
});
|
||||
});
|
||||
|
||||
describe("checkout method", () => {
|
||||
it("should create a span for checkout operations", async () => {
|
||||
const instrumented = instrumentAutumn(mockClient);
|
||||
|
||||
await instrumented.checkout({
|
||||
customer_id: "user_123",
|
||||
product_id: "pro",
|
||||
});
|
||||
|
||||
expect(mockTracer.startSpan).toHaveBeenCalledWith(
|
||||
"autumn.checkout",
|
||||
expect.objectContaining({ kind: expect.any(Number) })
|
||||
);
|
||||
});
|
||||
|
||||
it("should set span attributes for checkout", async () => {
|
||||
const instrumented = instrumentAutumn(mockClient);
|
||||
|
||||
await instrumented.checkout({
|
||||
customer_id: "user_123",
|
||||
product_id: "pro",
|
||||
force_checkout: true,
|
||||
});
|
||||
|
||||
expect(mockSpan.setAttribute).toHaveBeenCalledWith("autumn.customer_id", "user_123");
|
||||
expect(mockSpan.setAttribute).toHaveBeenCalledWith("autumn.product_id", "pro");
|
||||
expect(mockSpan.setAttribute).toHaveBeenCalledWith("autumn.force_checkout", true);
|
||||
});
|
||||
|
||||
it("should handle multiple product IDs", async () => {
|
||||
const instrumented = instrumentAutumn(mockClient);
|
||||
|
||||
await instrumented.checkout({
|
||||
customer_id: "user_123",
|
||||
product_ids: ["pro", "addon_analytics"],
|
||||
});
|
||||
|
||||
expect(mockSpan.setAttribute).toHaveBeenCalledWith("autumn.product_ids", "pro, addon_analytics");
|
||||
});
|
||||
});
|
||||
|
||||
describe("attach method", () => {
|
||||
it("should create a span for attach operations", async () => {
|
||||
const instrumented = instrumentAutumn(mockClient);
|
||||
|
||||
await instrumented.attach({
|
||||
customer_id: "user_123",
|
||||
product_id: "free",
|
||||
});
|
||||
|
||||
expect(mockTracer.startSpan).toHaveBeenCalledWith(
|
||||
"autumn.attach",
|
||||
expect.objectContaining({ kind: expect.any(Number) })
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe("cancel method", () => {
|
||||
it("should create a span for cancel operations", async () => {
|
||||
const instrumented = instrumentAutumn(mockClient);
|
||||
|
||||
await instrumented.cancel({
|
||||
customer_id: "user_123",
|
||||
product_id: "pro",
|
||||
});
|
||||
|
||||
expect(mockTracer.startSpan).toHaveBeenCalledWith(
|
||||
"autumn.cancel",
|
||||
expect.objectContaining({ kind: expect.any(Number) })
|
||||
);
|
||||
});
|
||||
|
||||
it("should set span attributes for cancel", async () => {
|
||||
const instrumented = instrumentAutumn(mockClient);
|
||||
|
||||
await instrumented.cancel({
|
||||
customer_id: "user_123",
|
||||
product_id: "pro",
|
||||
});
|
||||
|
||||
expect(mockSpan.setAttribute).toHaveBeenCalledWith("autumn.customer_id", "user_123");
|
||||
expect(mockSpan.setAttribute).toHaveBeenCalledWith("autumn.product_id", "pro");
|
||||
});
|
||||
});
|
||||
});
|
||||
529
packages/otel-autumn/src/index.ts
Normal file
529
packages/otel-autumn/src/index.ts
Normal file
@@ -0,0 +1,529 @@
|
||||
import {
|
||||
context,
|
||||
SpanKind,
|
||||
SpanStatusCode,
|
||||
trace,
|
||||
type Span,
|
||||
} from "@opentelemetry/api";
|
||||
import type { Autumn } from "autumn-js";
|
||||
|
||||
const DEFAULT_TRACER_NAME = "@kubiks/otel-autumn";
|
||||
const INSTRUMENTED_FLAG = Symbol("kubiksOtelAutumnInstrumented");
|
||||
|
||||
// Semantic attribute constants
|
||||
export const SEMATTRS_BILLING_SYSTEM = "billing.system" as const;
|
||||
export const SEMATTRS_BILLING_OPERATION = "billing.operation" as const;
|
||||
export const SEMATTRS_AUTUMN_RESOURCE = "autumn.resource" as const;
|
||||
export const SEMATTRS_AUTUMN_TARGET = "autumn.target" as const;
|
||||
|
||||
// Customer attributes
|
||||
export const SEMATTRS_AUTUMN_CUSTOMER_ID = "autumn.customer_id" as const;
|
||||
export const SEMATTRS_AUTUMN_ENTITY_ID = "autumn.entity_id" as const;
|
||||
|
||||
// Product attributes
|
||||
export const SEMATTRS_AUTUMN_PRODUCT_ID = "autumn.product_id" as const;
|
||||
export const SEMATTRS_AUTUMN_PRODUCT_IDS = "autumn.product_ids" as const;
|
||||
export const SEMATTRS_AUTUMN_PRODUCT_NAME = "autumn.product_name" as const;
|
||||
export const SEMATTRS_AUTUMN_PRODUCT_SCENARIO = "autumn.product_scenario" as const;
|
||||
|
||||
// Feature attributes
|
||||
export const SEMATTRS_AUTUMN_FEATURE_ID = "autumn.feature_id" as const;
|
||||
export const SEMATTRS_AUTUMN_FEATURE_NAME = "autumn.feature_name" as const;
|
||||
export const SEMATTRS_AUTUMN_ALLOWED = "autumn.allowed" as const;
|
||||
export const SEMATTRS_AUTUMN_BALANCE = "autumn.balance" as const;
|
||||
export const SEMATTRS_AUTUMN_USAGE = "autumn.usage" as const;
|
||||
export const SEMATTRS_AUTUMN_INCLUDED_USAGE = "autumn.included_usage" as const;
|
||||
export const SEMATTRS_AUTUMN_UNLIMITED = "autumn.unlimited" as const;
|
||||
export const SEMATTRS_AUTUMN_REQUIRED_BALANCE = "autumn.required_balance" as const;
|
||||
|
||||
// Checkout attributes
|
||||
export const SEMATTRS_AUTUMN_CHECKOUT_URL = "autumn.checkout_url" as const;
|
||||
export const SEMATTRS_AUTUMN_HAS_PRORATIONS = "autumn.has_prorations" as const;
|
||||
export const SEMATTRS_AUTUMN_TOTAL_AMOUNT = "autumn.total_amount" as const;
|
||||
export const SEMATTRS_AUTUMN_CURRENCY = "autumn.currency" as const;
|
||||
export const SEMATTRS_AUTUMN_FORCE_CHECKOUT = "autumn.force_checkout" as const;
|
||||
export const SEMATTRS_AUTUMN_INVOICE = "autumn.invoice" as const;
|
||||
|
||||
// Track attributes
|
||||
export const SEMATTRS_AUTUMN_EVENT_NAME = "autumn.event_name" as const;
|
||||
export const SEMATTRS_AUTUMN_VALUE = "autumn.value" as const;
|
||||
export const SEMATTRS_AUTUMN_EVENT_ID = "autumn.event_id" as const;
|
||||
export const SEMATTRS_AUTUMN_IDEMPOTENCY_KEY = "autumn.idempotency_key" as const;
|
||||
|
||||
// Attach/Cancel attributes
|
||||
export const SEMATTRS_AUTUMN_SUCCESS = "autumn.success" as const;
|
||||
|
||||
export interface InstrumentationConfig {
|
||||
/**
|
||||
* Whether to capture customer data in spans.
|
||||
* @default false
|
||||
*/
|
||||
captureCustomerData?: boolean;
|
||||
|
||||
/**
|
||||
* Whether to capture product options/configuration in spans.
|
||||
* @default false
|
||||
*/
|
||||
captureOptions?: boolean;
|
||||
}
|
||||
|
||||
interface InstrumentedAutumn extends Autumn {
|
||||
[INSTRUMENTED_FLAG]?: true;
|
||||
}
|
||||
|
||||
function finalizeSpan(span: Span, error?: unknown): void {
|
||||
if (error) {
|
||||
if (error instanceof Error) {
|
||||
span.recordException(error);
|
||||
} else {
|
||||
span.recordException(new Error(String(error)));
|
||||
}
|
||||
span.setStatus({ code: SpanStatusCode.ERROR });
|
||||
} else {
|
||||
span.setStatus({ code: SpanStatusCode.OK });
|
||||
}
|
||||
span.end();
|
||||
}
|
||||
|
||||
function annotateCheckSpan(
|
||||
span: Span,
|
||||
params: {
|
||||
customer_id: string;
|
||||
feature_id?: string;
|
||||
product_id?: string;
|
||||
entity_id?: string;
|
||||
required_balance?: number;
|
||||
},
|
||||
): void {
|
||||
span.setAttributes({
|
||||
[SEMATTRS_BILLING_SYSTEM]: "autumn",
|
||||
[SEMATTRS_BILLING_OPERATION]: "check",
|
||||
[SEMATTRS_AUTUMN_RESOURCE]: params.feature_id ? "features" : "products",
|
||||
[SEMATTRS_AUTUMN_TARGET]: params.feature_id
|
||||
? "features.check"
|
||||
: "products.check",
|
||||
});
|
||||
|
||||
span.setAttribute(SEMATTRS_AUTUMN_CUSTOMER_ID, params.customer_id);
|
||||
|
||||
if (params.feature_id) {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_FEATURE_ID, params.feature_id);
|
||||
}
|
||||
|
||||
if (params.product_id) {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_PRODUCT_ID, params.product_id);
|
||||
}
|
||||
|
||||
if (params.entity_id) {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_ENTITY_ID, params.entity_id);
|
||||
}
|
||||
|
||||
if (typeof params.required_balance === "number") {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_REQUIRED_BALANCE, params.required_balance);
|
||||
}
|
||||
}
|
||||
|
||||
function annotateCheckResponse(span: Span, response: Record<string, unknown>): void {
|
||||
if (typeof response.allowed === "boolean") {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_ALLOWED, response.allowed);
|
||||
}
|
||||
|
||||
if (typeof response.balance === "number") {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_BALANCE, response.balance);
|
||||
}
|
||||
|
||||
if (typeof response.usage === "number") {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_USAGE, response.usage);
|
||||
}
|
||||
|
||||
if (typeof response.included_usage === "number") {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_INCLUDED_USAGE, response.included_usage);
|
||||
}
|
||||
|
||||
if (typeof response.unlimited === "boolean") {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_UNLIMITED, response.unlimited);
|
||||
}
|
||||
|
||||
if (typeof response.status === "string") {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_PRODUCT_SCENARIO, response.status);
|
||||
}
|
||||
}
|
||||
|
||||
function annotateTrackSpan(
|
||||
span: Span,
|
||||
params: {
|
||||
customer_id: string;
|
||||
feature_id?: string;
|
||||
event_name?: string;
|
||||
value?: number;
|
||||
entity_id?: string;
|
||||
idempotency_key?: string;
|
||||
},
|
||||
): void {
|
||||
span.setAttributes({
|
||||
[SEMATTRS_BILLING_SYSTEM]: "autumn",
|
||||
[SEMATTRS_BILLING_OPERATION]: "track",
|
||||
[SEMATTRS_AUTUMN_RESOURCE]: "events",
|
||||
[SEMATTRS_AUTUMN_TARGET]: "events.track",
|
||||
});
|
||||
|
||||
span.setAttribute(SEMATTRS_AUTUMN_CUSTOMER_ID, params.customer_id);
|
||||
|
||||
if (params.feature_id) {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_FEATURE_ID, params.feature_id);
|
||||
}
|
||||
|
||||
if (params.event_name) {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_EVENT_NAME, params.event_name);
|
||||
}
|
||||
|
||||
if (typeof params.value === "number") {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_VALUE, params.value);
|
||||
}
|
||||
|
||||
if (params.entity_id) {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_ENTITY_ID, params.entity_id);
|
||||
}
|
||||
|
||||
if (params.idempotency_key) {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_IDEMPOTENCY_KEY, params.idempotency_key);
|
||||
}
|
||||
}
|
||||
|
||||
function annotateTrackResponse(span: Span, response: { id?: string }): void {
|
||||
if (response.id) {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_EVENT_ID, response.id);
|
||||
}
|
||||
}
|
||||
|
||||
function annotateCheckoutSpan(
|
||||
span: Span,
|
||||
params: {
|
||||
customer_id: string;
|
||||
product_id?: string;
|
||||
product_ids?: string[];
|
||||
entity_id?: string;
|
||||
force_checkout?: boolean;
|
||||
invoice?: boolean;
|
||||
},
|
||||
config?: InstrumentationConfig,
|
||||
): void {
|
||||
span.setAttributes({
|
||||
[SEMATTRS_BILLING_SYSTEM]: "autumn",
|
||||
[SEMATTRS_BILLING_OPERATION]: "checkout",
|
||||
[SEMATTRS_AUTUMN_RESOURCE]: "checkout",
|
||||
[SEMATTRS_AUTUMN_TARGET]: "checkout.create",
|
||||
});
|
||||
|
||||
span.setAttribute(SEMATTRS_AUTUMN_CUSTOMER_ID, params.customer_id);
|
||||
|
||||
if (params.product_id) {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_PRODUCT_ID, params.product_id);
|
||||
}
|
||||
|
||||
if (params.product_ids && params.product_ids.length > 0) {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_PRODUCT_IDS, params.product_ids.join(", "));
|
||||
}
|
||||
|
||||
if (params.entity_id) {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_ENTITY_ID, params.entity_id);
|
||||
}
|
||||
|
||||
if (typeof params.force_checkout === "boolean") {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_FORCE_CHECKOUT, params.force_checkout);
|
||||
}
|
||||
|
||||
if (typeof params.invoice === "boolean") {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_INVOICE, params.invoice);
|
||||
}
|
||||
}
|
||||
|
||||
function annotateCheckoutResponse(
|
||||
span: Span,
|
||||
response: {
|
||||
url?: string;
|
||||
has_prorations?: boolean;
|
||||
total?: number;
|
||||
currency?: string;
|
||||
},
|
||||
): void {
|
||||
if (response.url) {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_CHECKOUT_URL, response.url);
|
||||
}
|
||||
|
||||
if (typeof response.has_prorations === "boolean") {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_HAS_PRORATIONS, response.has_prorations);
|
||||
}
|
||||
|
||||
if (typeof response.total === "number") {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_TOTAL_AMOUNT, response.total);
|
||||
}
|
||||
|
||||
if (response.currency) {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_CURRENCY, response.currency);
|
||||
}
|
||||
}
|
||||
|
||||
function annotateAttachSpan(
|
||||
span: Span,
|
||||
params: {
|
||||
customer_id: string;
|
||||
product_id: string;
|
||||
entity_id?: string;
|
||||
},
|
||||
): void {
|
||||
span.setAttributes({
|
||||
[SEMATTRS_BILLING_SYSTEM]: "autumn",
|
||||
[SEMATTRS_BILLING_OPERATION]: "attach",
|
||||
[SEMATTRS_AUTUMN_RESOURCE]: "products",
|
||||
[SEMATTRS_AUTUMN_TARGET]: "products.attach",
|
||||
});
|
||||
|
||||
span.setAttribute(SEMATTRS_AUTUMN_CUSTOMER_ID, params.customer_id);
|
||||
span.setAttribute(SEMATTRS_AUTUMN_PRODUCT_ID, params.product_id);
|
||||
|
||||
if (params.entity_id) {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_ENTITY_ID, params.entity_id);
|
||||
}
|
||||
}
|
||||
|
||||
function annotateAttachResponse(
|
||||
span: Span,
|
||||
response: {
|
||||
success?: boolean;
|
||||
checkout_url?: string;
|
||||
},
|
||||
): void {
|
||||
if (typeof response.success === "boolean") {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_SUCCESS, response.success);
|
||||
}
|
||||
|
||||
if (response.checkout_url) {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_CHECKOUT_URL, response.checkout_url);
|
||||
}
|
||||
}
|
||||
|
||||
function annotateCancelSpan(
|
||||
span: Span,
|
||||
params: {
|
||||
customer_id: string;
|
||||
product_id: string;
|
||||
},
|
||||
): void {
|
||||
span.setAttributes({
|
||||
[SEMATTRS_BILLING_SYSTEM]: "autumn",
|
||||
[SEMATTRS_BILLING_OPERATION]: "cancel",
|
||||
[SEMATTRS_AUTUMN_RESOURCE]: "products",
|
||||
[SEMATTRS_AUTUMN_TARGET]: "products.cancel",
|
||||
});
|
||||
|
||||
span.setAttribute(SEMATTRS_AUTUMN_CUSTOMER_ID, params.customer_id);
|
||||
span.setAttribute(SEMATTRS_AUTUMN_PRODUCT_ID, params.product_id);
|
||||
}
|
||||
|
||||
function annotateCancelResponse(span: Span, response: { success?: boolean }): void {
|
||||
if (typeof response.success === "boolean") {
|
||||
span.setAttribute(SEMATTRS_AUTUMN_SUCCESS, response.success);
|
||||
}
|
||||
}
|
||||
|
||||
export function instrumentAutumn(
|
||||
client: Autumn,
|
||||
config?: InstrumentationConfig,
|
||||
): Autumn {
|
||||
// Check if already instrumented
|
||||
if ((client as InstrumentedAutumn)[INSTRUMENTED_FLAG]) {
|
||||
return client;
|
||||
}
|
||||
|
||||
const tracer = trace.getTracer(DEFAULT_TRACER_NAME);
|
||||
|
||||
// Instrument check method
|
||||
const originalCheck = client.check.bind(client);
|
||||
const instrumentedCheck = async function instrumentedCheck(
|
||||
params: Parameters<typeof originalCheck>[0],
|
||||
): Promise<ReturnType<typeof originalCheck>> {
|
||||
const span = tracer.startSpan("autumn.check", {
|
||||
kind: SpanKind.CLIENT,
|
||||
});
|
||||
|
||||
annotateCheckSpan(span, params as {
|
||||
customer_id: string;
|
||||
feature_id?: string;
|
||||
product_id?: string;
|
||||
entity_id?: string;
|
||||
required_balance?: number;
|
||||
});
|
||||
|
||||
const activeContext = trace.setSpan(context.active(), span);
|
||||
|
||||
try {
|
||||
const result = await context.with(activeContext, () =>
|
||||
originalCheck(params),
|
||||
);
|
||||
|
||||
if (result.data) {
|
||||
annotateCheckResponse(span, result.data as Record<string, unknown>);
|
||||
}
|
||||
|
||||
finalizeSpan(span);
|
||||
return result;
|
||||
} catch (error) {
|
||||
finalizeSpan(span, error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Instrument track method
|
||||
const originalTrack = client.track.bind(client);
|
||||
const instrumentedTrack = async function instrumentedTrack(
|
||||
params: Parameters<typeof originalTrack>[0],
|
||||
): Promise<ReturnType<typeof originalTrack>> {
|
||||
const span = tracer.startSpan("autumn.track", {
|
||||
kind: SpanKind.CLIENT,
|
||||
});
|
||||
|
||||
annotateTrackSpan(span, params as {
|
||||
customer_id: string;
|
||||
feature_id?: string;
|
||||
event_name?: string;
|
||||
value?: number;
|
||||
entity_id?: string;
|
||||
idempotency_key?: string;
|
||||
});
|
||||
|
||||
const activeContext = trace.setSpan(context.active(), span);
|
||||
|
||||
try {
|
||||
const result = await context.with(activeContext, () =>
|
||||
originalTrack(params),
|
||||
);
|
||||
|
||||
if (result.data) {
|
||||
annotateTrackResponse(span, result.data);
|
||||
}
|
||||
|
||||
finalizeSpan(span);
|
||||
return result;
|
||||
} catch (error) {
|
||||
finalizeSpan(span, error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Instrument checkout method
|
||||
const originalCheckout = client.checkout.bind(client);
|
||||
const instrumentedCheckout = async function instrumentedCheckout(
|
||||
params: Parameters<typeof originalCheckout>[0],
|
||||
): Promise<ReturnType<typeof originalCheckout>> {
|
||||
const span = tracer.startSpan("autumn.checkout", {
|
||||
kind: SpanKind.CLIENT,
|
||||
});
|
||||
|
||||
annotateCheckoutSpan(span, params as {
|
||||
customer_id: string;
|
||||
product_id?: string;
|
||||
product_ids?: string[];
|
||||
entity_id?: string;
|
||||
force_checkout?: boolean;
|
||||
invoice?: boolean;
|
||||
}, config);
|
||||
|
||||
const activeContext = trace.setSpan(context.active(), span);
|
||||
|
||||
try {
|
||||
const result = await context.with(activeContext, () =>
|
||||
originalCheckout(params),
|
||||
);
|
||||
|
||||
if (result.data) {
|
||||
annotateCheckoutResponse(span, result.data);
|
||||
}
|
||||
|
||||
finalizeSpan(span);
|
||||
return result;
|
||||
} catch (error) {
|
||||
finalizeSpan(span, error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Instrument attach method
|
||||
const originalAttach = client.attach.bind(client);
|
||||
const instrumentedAttach = async function instrumentedAttach(
|
||||
params: Parameters<typeof originalAttach>[0],
|
||||
): Promise<ReturnType<typeof originalAttach>> {
|
||||
const span = tracer.startSpan("autumn.attach", {
|
||||
kind: SpanKind.CLIENT,
|
||||
});
|
||||
|
||||
annotateAttachSpan(span, params as {
|
||||
customer_id: string;
|
||||
product_id: string;
|
||||
entity_id?: string;
|
||||
});
|
||||
|
||||
const activeContext = trace.setSpan(context.active(), span);
|
||||
|
||||
try {
|
||||
const result = await context.with(activeContext, () =>
|
||||
originalAttach(params),
|
||||
);
|
||||
|
||||
if (result.data) {
|
||||
annotateAttachResponse(span, result.data);
|
||||
}
|
||||
|
||||
finalizeSpan(span);
|
||||
return result;
|
||||
} catch (error) {
|
||||
finalizeSpan(span, error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Instrument cancel method
|
||||
const originalCancel = client.cancel.bind(client);
|
||||
const instrumentedCancel = async function instrumentedCancel(
|
||||
params: Parameters<typeof originalCancel>[0],
|
||||
): Promise<ReturnType<typeof originalCancel>> {
|
||||
const span = tracer.startSpan("autumn.cancel", {
|
||||
kind: SpanKind.CLIENT,
|
||||
});
|
||||
|
||||
annotateCancelSpan(span, params as {
|
||||
customer_id: string;
|
||||
product_id: string;
|
||||
});
|
||||
|
||||
const activeContext = trace.setSpan(context.active(), span);
|
||||
|
||||
try {
|
||||
const result = await context.with(activeContext, () =>
|
||||
originalCancel(params),
|
||||
);
|
||||
|
||||
if (result.data) {
|
||||
annotateCancelResponse(span, result.data);
|
||||
}
|
||||
|
||||
finalizeSpan(span);
|
||||
return result;
|
||||
} catch (error) {
|
||||
finalizeSpan(span, error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
// Replace methods with instrumented versions
|
||||
client.check = instrumentedCheck;
|
||||
client.track = instrumentedTrack;
|
||||
client.checkout = instrumentedCheckout;
|
||||
client.attach = instrumentedAttach;
|
||||
client.cancel = instrumentedCancel;
|
||||
|
||||
// Mark as instrumented
|
||||
(client as InstrumentedAutumn)[INSTRUMENTED_FLAG] = true;
|
||||
|
||||
return client;
|
||||
}
|
||||
21
packages/otel-autumn/tsconfig.json
Normal file
21
packages/otel-autumn/tsconfig.json
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES2020",
|
||||
"module": "ESNext",
|
||||
"moduleResolution": "bundler",
|
||||
"lib": ["ES2020", "DOM"],
|
||||
"outDir": "dist",
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true,
|
||||
"strict": false,
|
||||
"esModuleInterop": true,
|
||||
"skipLibCheck": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"resolveJsonModule": true,
|
||||
"declarationDir": "dist/types",
|
||||
"stripInternal": true
|
||||
},
|
||||
"include": ["src/**/*"],
|
||||
"exclude": ["node_modules", "dist", "**/*.test.ts"]
|
||||
}
|
||||
397
pnpm-lock.yaml
generated
397
pnpm-lock.yaml
generated
@@ -21,6 +21,30 @@ importers:
|
||||
specifier: ^1.11.3
|
||||
version: 1.11.3
|
||||
|
||||
packages/otel-autumn:
|
||||
devDependencies:
|
||||
'@opentelemetry/api':
|
||||
specifier: ^1.9.0
|
||||
version: 1.9.0
|
||||
'@opentelemetry/sdk-trace-base':
|
||||
specifier: ^2.1.0
|
||||
version: 2.1.0(@opentelemetry/api@1.9.0)
|
||||
'@types/node':
|
||||
specifier: 18.15.11
|
||||
version: 18.15.11
|
||||
autumn-js:
|
||||
specifier: ^0.1.40
|
||||
version: 0.1.40(better-auth@1.3.25(react@18.2.0))(better-call@1.0.19)(convex@1.27.4(react@18.2.0))(react@18.2.0)
|
||||
rimraf:
|
||||
specifier: 3.0.2
|
||||
version: 3.0.2
|
||||
typescript:
|
||||
specifier: ^5
|
||||
version: 5.3.3
|
||||
vitest:
|
||||
specifier: 0.33.0
|
||||
version: 0.33.0(less@4.2.0)(sass@1.69.7)(stylus@0.59.0)
|
||||
|
||||
packages/otel-better-auth:
|
||||
devDependencies:
|
||||
'@opentelemetry/api':
|
||||
@@ -37,7 +61,7 @@ importers:
|
||||
version: 18.15.11
|
||||
better-auth:
|
||||
specifier: ^1.0.0
|
||||
version: 1.3.25
|
||||
version: 1.3.25(react@18.2.0)
|
||||
rimraf:
|
||||
specifier: 3.0.2
|
||||
version: 3.0.2
|
||||
@@ -217,138 +241,288 @@ packages:
|
||||
'@changesets/write@0.3.0':
|
||||
resolution: {integrity: sha512-slGLb21fxZVUYbyea+94uFiD6ntQW0M2hIKNznFizDhZPDgn2c/fv1UzzlW43RVzh1BEDuIqW6hzlJ1OflNmcw==}
|
||||
|
||||
'@esbuild/aix-ppc64@0.25.4':
|
||||
resolution: {integrity: sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [aix]
|
||||
|
||||
'@esbuild/android-arm64@0.18.20':
|
||||
resolution: {integrity: sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm64@0.25.4':
|
||||
resolution: {integrity: sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm@0.18.20':
|
||||
resolution: {integrity: sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-arm@0.25.4':
|
||||
resolution: {integrity: sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-x64@0.18.20':
|
||||
resolution: {integrity: sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/android-x64@0.25.4':
|
||||
resolution: {integrity: sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [android]
|
||||
|
||||
'@esbuild/darwin-arm64@0.18.20':
|
||||
resolution: {integrity: sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-arm64@0.25.4':
|
||||
resolution: {integrity: sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-x64@0.18.20':
|
||||
resolution: {integrity: sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/darwin-x64@0.25.4':
|
||||
resolution: {integrity: sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@esbuild/freebsd-arm64@0.18.20':
|
||||
resolution: {integrity: sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-arm64@0.25.4':
|
||||
resolution: {integrity: sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-x64@0.18.20':
|
||||
resolution: {integrity: sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/freebsd-x64@0.25.4':
|
||||
resolution: {integrity: sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@esbuild/linux-arm64@0.18.20':
|
||||
resolution: {integrity: sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm64@0.25.4':
|
||||
resolution: {integrity: sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm@0.18.20':
|
||||
resolution: {integrity: sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-arm@0.25.4':
|
||||
resolution: {integrity: sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ia32@0.18.20':
|
||||
resolution: {integrity: sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ia32@0.25.4':
|
||||
resolution: {integrity: sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-loong64@0.18.20':
|
||||
resolution: {integrity: sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-loong64@0.25.4':
|
||||
resolution: {integrity: sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-mips64el@0.18.20':
|
||||
resolution: {integrity: sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-mips64el@0.25.4':
|
||||
resolution: {integrity: sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [mips64el]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ppc64@0.18.20':
|
||||
resolution: {integrity: sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-ppc64@0.25.4':
|
||||
resolution: {integrity: sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-riscv64@0.18.20':
|
||||
resolution: {integrity: sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-riscv64@0.25.4':
|
||||
resolution: {integrity: sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-s390x@0.18.20':
|
||||
resolution: {integrity: sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-s390x@0.25.4':
|
||||
resolution: {integrity: sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-x64@0.18.20':
|
||||
resolution: {integrity: sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/linux-x64@0.25.4':
|
||||
resolution: {integrity: sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@esbuild/netbsd-arm64@0.25.4':
|
||||
resolution: {integrity: sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-x64@0.18.20':
|
||||
resolution: {integrity: sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/netbsd-x64@0.25.4':
|
||||
resolution: {integrity: sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [netbsd]
|
||||
|
||||
'@esbuild/openbsd-arm64@0.25.4':
|
||||
resolution: {integrity: sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-x64@0.18.20':
|
||||
resolution: {integrity: sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/openbsd-x64@0.25.4':
|
||||
resolution: {integrity: sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [openbsd]
|
||||
|
||||
'@esbuild/sunos-x64@0.18.20':
|
||||
resolution: {integrity: sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
|
||||
'@esbuild/sunos-x64@0.25.4':
|
||||
resolution: {integrity: sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [sunos]
|
||||
|
||||
'@esbuild/win32-arm64@0.18.20':
|
||||
resolution: {integrity: sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-arm64@0.25.4':
|
||||
resolution: {integrity: sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-ia32@0.18.20':
|
||||
resolution: {integrity: sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-ia32@0.25.4':
|
||||
resolution: {integrity: sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-x64@0.18.20':
|
||||
resolution: {integrity: sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==}
|
||||
engines: {node: '>=12'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@esbuild/win32-x64@0.25.4':
|
||||
resolution: {integrity: sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==}
|
||||
engines: {node: '>=18'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@hexagon/base64@1.1.28':
|
||||
resolution: {integrity: sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==}
|
||||
|
||||
@@ -652,6 +826,21 @@ packages:
|
||||
assertion-error@1.1.0:
|
||||
resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==}
|
||||
|
||||
autumn-js@0.1.40:
|
||||
resolution: {integrity: sha512-nAmyFJLOQqKosb8MHv09rB2pma8LyOHWsuYtrjXND+2LM51vToco1mweLIYIs/aX33iLAVUxfpXEEt8P3UYoxw==}
|
||||
peerDependencies:
|
||||
better-auth: ^1.3.17
|
||||
better-call: ^1.0.12
|
||||
convex: ^1.25.4
|
||||
react: '*'
|
||||
peerDependenciesMeta:
|
||||
better-auth:
|
||||
optional: true
|
||||
better-call:
|
||||
optional: true
|
||||
react:
|
||||
optional: true
|
||||
|
||||
available-typed-arrays@1.0.5:
|
||||
resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==}
|
||||
engines: {node: '>= 0.4'}
|
||||
@@ -787,6 +976,22 @@ packages:
|
||||
config-chain@1.1.13:
|
||||
resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==}
|
||||
|
||||
convex@1.27.4:
|
||||
resolution: {integrity: sha512-aPP3uxOF5v+K4uftXxRh8GAYepsjsFgU+S9IpAyLVNaFU3Z72WB1rIhaSzPAo4Q0TJWsOKANFGU903IU92QDTA==}
|
||||
engines: {node: '>=18.0.0', npm: '>=7.0.0'}
|
||||
hasBin: true
|
||||
peerDependencies:
|
||||
'@auth0/auth0-react': ^2.0.1
|
||||
'@clerk/clerk-react': ^4.12.8 || ^5.0.0
|
||||
react: ^18.0.0 || ^19.0.0-0 || ^19.0.0
|
||||
peerDependenciesMeta:
|
||||
'@auth0/auth0-react':
|
||||
optional: true
|
||||
'@clerk/clerk-react':
|
||||
optional: true
|
||||
react:
|
||||
optional: true
|
||||
|
||||
copy-anything@2.0.6:
|
||||
resolution: {integrity: sha512-1j20GZTsvKNkc4BY3NpMOM8tt///wY3FpIzozTOFO2ffuZcV61nojHXVKIy3WM+7ADCy5FVhdZYHYDdgTU0yJw==}
|
||||
|
||||
@@ -836,6 +1041,10 @@ packages:
|
||||
resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
|
||||
decode-uri-component@0.4.1:
|
||||
resolution: {integrity: sha512-+8VxcR21HhTy8nOt6jf20w0c9CADrw1O8d+VZ/YzzCt4bJ3uBjw+D1q2osAB8RnpwwaeYBxy0HyKQxD5JBMuuQ==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
deep-eql@4.1.3:
|
||||
resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -858,6 +1067,10 @@ packages:
|
||||
defu@6.1.4:
|
||||
resolution: {integrity: sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==}
|
||||
|
||||
dequal@2.0.3:
|
||||
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
|
||||
engines: {node: '>=6'}
|
||||
|
||||
detect-indent@6.1.0:
|
||||
resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -1028,6 +1241,11 @@ packages:
|
||||
engines: {node: '>=12'}
|
||||
hasBin: true
|
||||
|
||||
esbuild@0.25.4:
|
||||
resolution: {integrity: sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==}
|
||||
engines: {node: '>=18'}
|
||||
hasBin: true
|
||||
|
||||
escalade@3.1.1:
|
||||
resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -1062,6 +1280,10 @@ packages:
|
||||
resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
filter-obj@5.1.0:
|
||||
resolution: {integrity: sha512-qWeTREPoT7I0bifpPUXtxkZJ1XJzxWtfoWWkdVGqa+eCr3SHW/Ocp89o8vLvbUuQnadybJpjOKu4V+RwO6sGng==}
|
||||
engines: {node: '>=14.16'}
|
||||
|
||||
find-up@4.1.0:
|
||||
resolution: {integrity: sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -1713,6 +1935,10 @@ packages:
|
||||
resolution: {integrity: sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ==}
|
||||
engines: {node: '>=6.0.0'}
|
||||
|
||||
query-string@9.3.1:
|
||||
resolution: {integrity: sha512-5fBfMOcDi5SA9qj5jZhWAcTtDfKF5WFdd2uD9nVNlbxVv1baq65aALy6qofpNEGELHvisjjasxQp7BlM9gvMzw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
queue-microtask@1.2.3:
|
||||
resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==}
|
||||
|
||||
@@ -1801,6 +2027,9 @@ packages:
|
||||
rou3@0.5.1:
|
||||
resolution: {integrity: sha512-OXMmJ3zRk2xeXFGfA3K+EOPHC5u7RDFG7lIOx0X1pdnhUkI8MdVrbV+sNsD80ElpUZ+MRHdyxPnFthq9VHs8uQ==}
|
||||
|
||||
rou3@0.6.3:
|
||||
resolution: {integrity: sha512-1HSG1ENTj7Kkm5muMnXuzzfdDOf7CFnbSYFA+H3Fp/rB9lOCxCPgy1jlZxTKyFoC5jJay8Mmc+VbPLYRjzYLrA==}
|
||||
|
||||
run-parallel@1.2.0:
|
||||
resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==}
|
||||
|
||||
@@ -1919,6 +2148,10 @@ packages:
|
||||
spdx-license-ids@3.0.16:
|
||||
resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==}
|
||||
|
||||
split-on-first@3.0.0:
|
||||
resolution: {integrity: sha512-qxQJTx2ryR0Dw0ITYyekNQWpz6f8dGd7vffGNflQQ3Iqj9NJ6qiZ7ELpZsJ/QBhIVAiDfXdag3+Gp8RvWa62AA==}
|
||||
engines: {node: '>=12'}
|
||||
|
||||
sprintf-js@1.0.3:
|
||||
resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==}
|
||||
|
||||
@@ -1984,6 +2217,11 @@ packages:
|
||||
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
|
||||
engines: {node: '>= 0.4'}
|
||||
|
||||
swr@2.3.6:
|
||||
resolution: {integrity: sha512-wfHRmHWk/isGNMwlLGlZX5Gzz/uTgo0o2IRuTMcf4CPuPFJZlq0rDaKUx+ozB5nBOReNV1kiOyzMfj+MBMikLw==}
|
||||
peerDependencies:
|
||||
react: ^16.11.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
|
||||
term-size@2.2.1:
|
||||
resolution: {integrity: sha512-wK0Ri4fOGjv/XPy8SBHZChl8CM7uMc5VML7SqiQ0zG7+J5Vr+RMQDoHa2CNT6KHUnTGIXH34UDMkPzAUyapBZg==}
|
||||
engines: {node: '>=8'}
|
||||
@@ -2112,6 +2350,11 @@ packages:
|
||||
resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
|
||||
engines: {node: '>= 4.0.0'}
|
||||
|
||||
use-sync-external-store@1.6.0:
|
||||
resolution: {integrity: sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==}
|
||||
peerDependencies:
|
||||
react: ^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0
|
||||
|
||||
validate-npm-package-license@3.0.4:
|
||||
resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==}
|
||||
|
||||
@@ -2471,72 +2714,147 @@ snapshots:
|
||||
human-id: 1.0.2
|
||||
prettier: 2.8.8
|
||||
|
||||
'@esbuild/aix-ppc64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-arm@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-x64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/android-x64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-arm64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-arm64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-x64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/darwin-x64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-arm64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-arm64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-x64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/freebsd-x64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-arm@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ia32@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ia32@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-loong64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-loong64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-mips64el@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-mips64el@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ppc64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-ppc64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-riscv64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-riscv64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-s390x@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-s390x@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/linux-x64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-arm64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-x64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/netbsd-x64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-arm64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/openbsd-x64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/sunos-x64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/sunos-x64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-arm64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-arm64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-ia32@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-ia32@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-x64@0.18.20':
|
||||
optional: true
|
||||
|
||||
'@esbuild/win32-x64@0.25.4':
|
||||
optional: true
|
||||
|
||||
'@hexagon/base64@1.1.28': {}
|
||||
|
||||
'@isaacs/cliui@8.0.2':
|
||||
@@ -2920,11 +3238,23 @@ snapshots:
|
||||
|
||||
assertion-error@1.1.0: {}
|
||||
|
||||
autumn-js@0.1.40(better-auth@1.3.25(react@18.2.0))(better-call@1.0.19)(convex@1.27.4(react@18.2.0))(react@18.2.0):
|
||||
dependencies:
|
||||
convex: 1.27.4(react@18.2.0)
|
||||
query-string: 9.3.1
|
||||
rou3: 0.6.3
|
||||
swr: 2.3.6(react@18.2.0)
|
||||
zod: 4.1.11
|
||||
optionalDependencies:
|
||||
better-auth: 1.3.25(react@18.2.0)
|
||||
better-call: 1.0.19
|
||||
react: 18.2.0
|
||||
|
||||
available-typed-arrays@1.0.5: {}
|
||||
|
||||
balanced-match@1.0.2: {}
|
||||
|
||||
better-auth@1.3.25:
|
||||
better-auth@1.3.25(react@18.2.0):
|
||||
dependencies:
|
||||
'@better-auth/core': 1.3.25
|
||||
'@better-auth/utils': 0.3.0
|
||||
@@ -2939,6 +3269,8 @@ snapshots:
|
||||
kysely: 0.28.7
|
||||
nanostores: 1.0.1
|
||||
zod: 4.1.11
|
||||
optionalDependencies:
|
||||
react: 18.2.0
|
||||
|
||||
better-call@1.0.19:
|
||||
dependencies:
|
||||
@@ -3065,6 +3397,13 @@ snapshots:
|
||||
ini: 1.3.8
|
||||
proto-list: 1.2.4
|
||||
|
||||
convex@1.27.4(react@18.2.0):
|
||||
dependencies:
|
||||
esbuild: 0.25.4
|
||||
prettier: 3.1.1
|
||||
optionalDependencies:
|
||||
react: 18.2.0
|
||||
|
||||
copy-anything@2.0.6:
|
||||
dependencies:
|
||||
is-what: 3.14.1
|
||||
@@ -3113,6 +3452,8 @@ snapshots:
|
||||
|
||||
decamelize@1.2.0: {}
|
||||
|
||||
decode-uri-component@0.4.1: {}
|
||||
|
||||
deep-eql@4.1.3:
|
||||
dependencies:
|
||||
type-detect: 4.0.8
|
||||
@@ -3137,6 +3478,8 @@ snapshots:
|
||||
|
||||
defu@6.1.4: {}
|
||||
|
||||
dequal@2.0.3: {}
|
||||
|
||||
detect-indent@6.1.0: {}
|
||||
|
||||
diff-sequences@29.6.3: {}
|
||||
@@ -3286,6 +3629,34 @@ snapshots:
|
||||
'@esbuild/win32-ia32': 0.18.20
|
||||
'@esbuild/win32-x64': 0.18.20
|
||||
|
||||
esbuild@0.25.4:
|
||||
optionalDependencies:
|
||||
'@esbuild/aix-ppc64': 0.25.4
|
||||
'@esbuild/android-arm': 0.25.4
|
||||
'@esbuild/android-arm64': 0.25.4
|
||||
'@esbuild/android-x64': 0.25.4
|
||||
'@esbuild/darwin-arm64': 0.25.4
|
||||
'@esbuild/darwin-x64': 0.25.4
|
||||
'@esbuild/freebsd-arm64': 0.25.4
|
||||
'@esbuild/freebsd-x64': 0.25.4
|
||||
'@esbuild/linux-arm': 0.25.4
|
||||
'@esbuild/linux-arm64': 0.25.4
|
||||
'@esbuild/linux-ia32': 0.25.4
|
||||
'@esbuild/linux-loong64': 0.25.4
|
||||
'@esbuild/linux-mips64el': 0.25.4
|
||||
'@esbuild/linux-ppc64': 0.25.4
|
||||
'@esbuild/linux-riscv64': 0.25.4
|
||||
'@esbuild/linux-s390x': 0.25.4
|
||||
'@esbuild/linux-x64': 0.25.4
|
||||
'@esbuild/netbsd-arm64': 0.25.4
|
||||
'@esbuild/netbsd-x64': 0.25.4
|
||||
'@esbuild/openbsd-arm64': 0.25.4
|
||||
'@esbuild/openbsd-x64': 0.25.4
|
||||
'@esbuild/sunos-x64': 0.25.4
|
||||
'@esbuild/win32-arm64': 0.25.4
|
||||
'@esbuild/win32-ia32': 0.25.4
|
||||
'@esbuild/win32-x64': 0.25.4
|
||||
|
||||
escalade@3.1.1: {}
|
||||
|
||||
escape-string-regexp@1.0.5: {}
|
||||
@@ -3318,6 +3689,8 @@ snapshots:
|
||||
dependencies:
|
||||
to-regex-range: 5.0.1
|
||||
|
||||
filter-obj@5.1.0: {}
|
||||
|
||||
find-up@4.1.0:
|
||||
dependencies:
|
||||
locate-path: 5.0.0
|
||||
@@ -3954,6 +4327,12 @@ snapshots:
|
||||
|
||||
pvutils@1.1.3: {}
|
||||
|
||||
query-string@9.3.1:
|
||||
dependencies:
|
||||
decode-uri-component: 0.4.1
|
||||
filter-obj: 5.1.0
|
||||
split-on-first: 3.0.0
|
||||
|
||||
queue-microtask@1.2.3: {}
|
||||
|
||||
quick-lru@4.0.1: {}
|
||||
@@ -4045,6 +4424,8 @@ snapshots:
|
||||
|
||||
rou3@0.5.1: {}
|
||||
|
||||
rou3@0.6.3: {}
|
||||
|
||||
run-parallel@1.2.0:
|
||||
dependencies:
|
||||
queue-microtask: 1.2.3
|
||||
@@ -4170,6 +4551,8 @@ snapshots:
|
||||
|
||||
spdx-license-ids@3.0.16: {}
|
||||
|
||||
split-on-first@3.0.0: {}
|
||||
|
||||
sprintf-js@1.0.3: {}
|
||||
|
||||
stackback@0.0.2: {}
|
||||
@@ -4249,6 +4632,12 @@ snapshots:
|
||||
|
||||
supports-preserve-symlinks-flag@1.0.0: {}
|
||||
|
||||
swr@2.3.6(react@18.2.0):
|
||||
dependencies:
|
||||
dequal: 2.0.3
|
||||
react: 18.2.0
|
||||
use-sync-external-store: 1.6.0(react@18.2.0)
|
||||
|
||||
term-size@2.2.1: {}
|
||||
|
||||
tinybench@2.5.1: {}
|
||||
@@ -4364,6 +4753,10 @@ snapshots:
|
||||
|
||||
universalify@0.1.2: {}
|
||||
|
||||
use-sync-external-store@1.6.0(react@18.2.0):
|
||||
dependencies:
|
||||
react: 18.2.0
|
||||
|
||||
validate-npm-package-license@3.0.4:
|
||||
dependencies:
|
||||
spdx-correct: 3.2.0
|
||||
|
||||
Reference in New Issue
Block a user