@sudobility/consumables_service 0.0.5 → 0.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CLAUDE.md +56 -34
- package/dist/helpers/ConsumablesHelper.d.ts +55 -7
- package/dist/helpers/ConsumablesHelper.d.ts.map +1 -1
- package/dist/helpers/ConsumablesHelper.js +55 -7
- package/dist/helpers/ConsumablesHelper.js.map +1 -1
- package/dist/helpers/WebhookHelper.d.ts +15 -3
- package/dist/helpers/WebhookHelper.d.ts.map +1 -1
- package/dist/helpers/WebhookHelper.js +15 -3
- package/dist/helpers/WebhookHelper.js.map +1 -1
- package/dist/schema/index.d.ts +8 -1
- package/dist/schema/index.d.ts.map +1 -1
- package/dist/schema/index.js +8 -1
- package/dist/schema/index.js.map +1 -1
- package/dist/types/index.d.ts +9 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +4 -1
- package/dist/types/index.js.map +1 -1
- package/package.json +3 -3
package/CLAUDE.md
CHANGED
|
@@ -3,69 +3,88 @@
|
|
|
3
3
|
Shared backend library for consumable credits management with Drizzle ORM.
|
|
4
4
|
|
|
5
5
|
**npm**: `@sudobility/consumables_service` (public)
|
|
6
|
+
**Version**: 0.0.5
|
|
7
|
+
**License**: BUSL-1.1
|
|
6
8
|
|
|
7
9
|
## Tech Stack
|
|
8
10
|
|
|
9
|
-
- **Language**: TypeScript (strict mode)
|
|
11
|
+
- **Language**: TypeScript 5.9.x (strict mode)
|
|
10
12
|
- **Runtime**: Bun
|
|
11
|
-
- **Package Manager**: Bun (
|
|
12
|
-
- **Build**: TypeScript compiler (ESM)
|
|
13
|
-
- **Test**:
|
|
13
|
+
- **Package Manager**: Bun (never npm/yarn/pnpm)
|
|
14
|
+
- **Build**: TypeScript compiler via `tsconfig.esm.json` (ESM only)
|
|
15
|
+
- **Test**: Vitest 4.x
|
|
16
|
+
- **ORM**: Drizzle ORM >=0.44.0 (peer dependency)
|
|
14
17
|
|
|
15
18
|
## Project Structure
|
|
16
19
|
|
|
17
20
|
```
|
|
18
21
|
src/
|
|
19
|
-
├── index.ts # Main exports
|
|
22
|
+
├── index.ts # Main barrel exports (types, schema, helpers)
|
|
20
23
|
├── types/
|
|
21
|
-
│ └── index.ts #
|
|
24
|
+
│ └── index.ts # ConsumableBalance, ConsumablePurchase, ConsumableUsage, RevenueCatWebhookEvent, ConsumablesConfig
|
|
22
25
|
├── schema/
|
|
23
|
-
│ └── index.ts # Drizzle
|
|
26
|
+
│ └── index.ts # createConsumablesSchema(pgSchema) -- Drizzle table definitions
|
|
24
27
|
└── helpers/
|
|
25
|
-
├── index.ts #
|
|
26
|
-
├── ConsumablesHelper.ts # Core business logic
|
|
27
|
-
└── WebhookHelper.ts
|
|
28
|
+
├── index.ts # Re-exports ConsumablesHelper, validateWebhookSignature, parseConsumablePurchaseEvent
|
|
29
|
+
├── ConsumablesHelper.ts # Core business logic class (balance CRUD, purchase/usage recording)
|
|
30
|
+
└── WebhookHelper.ts # RevenueCat webhook HMAC validation + event parsing
|
|
28
31
|
tests/
|
|
29
|
-
├── ConsumablesHelper.test.ts
|
|
30
|
-
└── WebhookHelper.test.ts
|
|
32
|
+
├── ConsumablesHelper.test.ts # Business logic tests with mock DB
|
|
33
|
+
└── WebhookHelper.test.ts # HMAC validation + event parsing tests
|
|
31
34
|
```
|
|
32
35
|
|
|
33
36
|
## Commands
|
|
34
37
|
|
|
35
38
|
```bash
|
|
36
|
-
bun run build # Build ESM
|
|
39
|
+
bun run build # Build ESM via tsc -p tsconfig.esm.json
|
|
37
40
|
bun run clean # Remove dist/
|
|
38
|
-
bun run dev # Watch mode
|
|
39
|
-
bun test # Run tests
|
|
40
|
-
bun run
|
|
41
|
-
bun run
|
|
42
|
-
bun run
|
|
41
|
+
bun run dev # Watch mode (tsc --watch)
|
|
42
|
+
bun test # Run tests (vitest run)
|
|
43
|
+
bun run test:watch # Watch tests
|
|
44
|
+
bun run lint # ESLint (eslint src/)
|
|
45
|
+
bun run lint:fix # ESLint with auto-fix
|
|
46
|
+
bun run typecheck # TypeScript check (tsc --noEmit)
|
|
47
|
+
bun run format # Prettier format
|
|
48
|
+
bun run format:check # Prettier check (CI-friendly)
|
|
49
|
+
bun run verify # All checks + build (typecheck && lint && test && build) -- use before commit
|
|
43
50
|
```
|
|
44
51
|
|
|
52
|
+
## Dependencies
|
|
53
|
+
|
|
54
|
+
### Peer Dependencies
|
|
55
|
+
- `@sudobility/types` ^1.9.53 -- shared type definitions (ConsumableBalanceResponse, ConsumablePurchaseRequest, ConsumableSource, ConsumableUseResponse)
|
|
56
|
+
- `drizzle-orm` >=0.44.0 -- ORM for database operations
|
|
57
|
+
|
|
58
|
+
### Dev Dependencies
|
|
59
|
+
- TypeScript ^5.9.0, Vitest ^4.0.4, drizzle-orm ^0.45.1, ESLint ^9.x, Prettier ^3.x
|
|
60
|
+
|
|
61
|
+
## Build Configuration
|
|
62
|
+
|
|
63
|
+
- **tsconfig.json**: Used for type checking (`noEmit: true`), strict mode, `isolatedModules: true`
|
|
64
|
+
- **tsconfig.esm.json**: Extends tsconfig.json, sets `noEmit: false`, `module: ESNext`, `outDir: ./dist`, `declarationMap: true`, `sourceMap: true`
|
|
65
|
+
|
|
45
66
|
## Key Concepts
|
|
46
67
|
|
|
47
68
|
### Schema Creator
|
|
48
|
-
|
|
49
69
|
`createConsumablesSchema(pgSchema)` creates three tables within a given Drizzle PgSchema:
|
|
50
|
-
- `consumable_balances`
|
|
51
|
-
- `consumable_purchases`
|
|
52
|
-
- `consumable_usages`
|
|
70
|
+
- `consumable_balances` -- user balance (user_id PK, balance, initial_credits, timestamps)
|
|
71
|
+
- `consumable_purchases` -- purchase audit trail (serial id, user_id, credits, source, transaction_ref_id, product_id, price_cents, currency, timestamp)
|
|
72
|
+
- `consumable_usages` -- usage audit trail (serial id, user_id, filename, timestamp)
|
|
53
73
|
|
|
54
|
-
The consuming API passes its own schema so migrations stay in one place.
|
|
74
|
+
The `schema` parameter is typed as `any` intentionally to avoid drizzle-orm version coupling. The consuming API passes its own schema so migrations stay in one place.
|
|
55
75
|
|
|
56
76
|
### ConsumablesHelper
|
|
57
|
-
|
|
58
77
|
Core business logic class. Constructed with `(db, tables, config)`:
|
|
59
|
-
- `getBalance(userId)`
|
|
60
|
-
- `recordPurchase(userId, request)`
|
|
61
|
-
- `recordUsage(userId, filename?)`
|
|
62
|
-
- `getPurchaseHistory
|
|
63
|
-
- `
|
|
78
|
+
- `getBalance(userId)` -- get-or-create; auto-grants `config.initialFreeCredits` on first access and records a "free" purchase audit entry
|
|
79
|
+
- `recordPurchase(userId, request)` -- insert purchase record + atomic balance increment via `SET balance = balance + N`
|
|
80
|
+
- `recordUsage(userId, filename?)` -- atomic decrement with `WHERE balance > 0` guard; returns `{ success: false }` if insufficient
|
|
81
|
+
- `getPurchaseHistory(userId, limit?, offset?)` -- paginated, most-recent-first
|
|
82
|
+
- `getUsageHistory(userId, limit?, offset?)` -- paginated, most-recent-first
|
|
83
|
+
- `recordPurchaseFromWebhook(userId, transactionId, credits, source, productId, priceCents, currency)` -- idempotent; deduplicates by `transaction_ref_id`
|
|
64
84
|
|
|
65
85
|
### WebhookHelper
|
|
66
|
-
|
|
67
|
-
- `
|
|
68
|
-
- `parseConsumablePurchaseEvent(event)` — extract purchase data from RevenueCat webhook
|
|
86
|
+
- `validateWebhookSignature(rawBody, signature, secret)` -- HMAC-SHA256 validation using Node.js `crypto`
|
|
87
|
+
- `parseConsumablePurchaseEvent(event)` -- extracts purchase data from RevenueCat webhook; only processes `NON_RENEWING_PURCHASE` and `INITIAL_PURCHASE` event types; maps store names to source (STRIPE->web, APP_STORE->apple, PLAY_STORE->google)
|
|
69
88
|
|
|
70
89
|
## Usage
|
|
71
90
|
|
|
@@ -93,8 +112,8 @@ APIs using this library:
|
|
|
93
112
|
|
|
94
113
|
## Related Projects
|
|
95
114
|
|
|
96
|
-
- **svgr_api**
|
|
97
|
-
- **consumables_client** (`@sudobility/consumables_client`)
|
|
115
|
+
- **svgr_api** -- The primary consuming API. It uses `createConsumablesSchema` and `ConsumablesHelper` for its credits system. Changes here directly affect svgr_api.
|
|
116
|
+
- **consumables_client** (`@sudobility/consumables_client`) -- Frontend counterpart that calls this service's API endpoints over HTTP. The client and service must agree on API contracts (response shapes, error codes).
|
|
98
117
|
|
|
99
118
|
Dependency direction: `svgr_api` --> `consumables_service` (library dep); `consumables_client` --> `consumables_service` (HTTP at runtime)
|
|
100
119
|
|
|
@@ -104,6 +123,7 @@ Dependency direction: `svgr_api` --> `consumables_service` (library dep); `consu
|
|
|
104
123
|
- **Atomic balance operations**: Balance increments (purchases) and decrements (usage) use atomic SQL operations (e.g., `SET credits = credits + N`). Never read-then-write; always use atomic updates to avoid race conditions.
|
|
105
124
|
- **Idempotent webhook processing**: `recordPurchaseFromWebhook()` uses the transaction reference as a deduplication key. Replaying the same webhook is safe and produces no duplicate records.
|
|
106
125
|
- **Get-or-create pattern for balances**: `getBalance(userId)` creates a balance row with `initialFreeCredits` if none exists. This avoids separate "create user" flows.
|
|
126
|
+
- **Drizzle query building**: Uses `eq()`, `desc()`, `sql` template literals from `drizzle-orm` for type-safe query construction.
|
|
107
127
|
|
|
108
128
|
## Gotchas
|
|
109
129
|
|
|
@@ -112,6 +132,8 @@ Dependency direction: `svgr_api` --> `consumables_service` (library dep); `consu
|
|
|
112
132
|
- **Balance decrements guard against going negative**: `recordUsage()` uses a `WHERE credits > 0` guard in the atomic update. If the balance is zero, the operation fails gracefully rather than going negative. Do not remove this guard.
|
|
113
133
|
- **Consumer owns migrations**: Even though this package defines the schema, the consuming API (e.g., svgr_api) generates and runs migrations. Never add migration files to this package.
|
|
114
134
|
- **Free credits are granted once**: `getBalance()` only grants `initialFreeCredits` on first access (row creation). Subsequent calls return the existing balance. Do not change this to grant free credits on every call.
|
|
135
|
+
- **`db` is typed as `any`**: The ConsumablesHelper constructor accepts `db: any` to avoid version coupling with drizzle-orm. This sacrifices type safety for flexibility.
|
|
136
|
+
- **`recordPurchase` calls `getBalance` first**: This ensures the balance row exists before incrementing. The extra query is intentional for the get-or-create pattern.
|
|
115
137
|
|
|
116
138
|
## Testing
|
|
117
139
|
|
|
@@ -1,24 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Core business logic for consumable credit management.
|
|
3
|
+
* Provides balance CRUD, purchase recording, usage recording, and
|
|
4
|
+
* idempotent webhook processing with atomic database operations.
|
|
5
|
+
*/
|
|
1
6
|
import type { ConsumablesSchemaResult } from "../schema";
|
|
2
7
|
import type { ConsumableBalanceResponse, ConsumablePurchaseRequest, ConsumableSource, ConsumableUseResponse } from "@sudobility/types";
|
|
3
8
|
import type { ConsumablePurchase, ConsumableUsage, ConsumablesConfig } from "../types";
|
|
9
|
+
/**
|
|
10
|
+
* Core helper class for managing consumable credits.
|
|
11
|
+
* Handles balance get-or-create, purchase recording with atomic increments,
|
|
12
|
+
* usage recording with atomic decrements, and idempotent webhook processing.
|
|
13
|
+
*/
|
|
4
14
|
export declare class ConsumablesHelper {
|
|
5
15
|
private db;
|
|
6
16
|
private tables;
|
|
7
17
|
private config;
|
|
8
18
|
constructor(db: any, tables: ConsumablesSchemaResult, config: ConsumablesConfig);
|
|
9
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Gets or creates a balance record for the given user.
|
|
21
|
+
* On first access, grants initialFreeCredits and records a "free" purchase audit entry.
|
|
22
|
+
* @param userId - The user's unique identifier.
|
|
23
|
+
* @returns The user's balance and initial credits.
|
|
24
|
+
*/
|
|
10
25
|
getBalance(userId: string): Promise<ConsumableBalanceResponse>;
|
|
11
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* Records a purchase and atomically increments the user's credit balance.
|
|
28
|
+
* Ensures the balance row exists via getBalance() before updating.
|
|
29
|
+
* @param userId - The user's unique identifier.
|
|
30
|
+
* @param request - Purchase details including credits, source, and optional metadata.
|
|
31
|
+
* @returns The updated balance after the purchase.
|
|
32
|
+
*/
|
|
12
33
|
recordPurchase(userId: string, request: ConsumablePurchaseRequest): Promise<ConsumableBalanceResponse>;
|
|
13
|
-
/**
|
|
34
|
+
/**
|
|
35
|
+
* Records a credit usage and atomically decrements the balance by 1.
|
|
36
|
+
* Uses a WHERE balance > 0 guard to prevent negative balances.
|
|
37
|
+
* @param userId - The user's unique identifier.
|
|
38
|
+
* @param filename - Optional filename associated with this usage.
|
|
39
|
+
* @returns The updated balance and whether the deduction was successful.
|
|
40
|
+
*/
|
|
14
41
|
recordUsage(userId: string, filename?: string): Promise<ConsumableUseResponse>;
|
|
15
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* Fetches paginated purchase history for a user, ordered most recent first.
|
|
44
|
+
* @param userId - The user's unique identifier.
|
|
45
|
+
* @param limit - Maximum number of records to return. Defaults to 50.
|
|
46
|
+
* @param offset - Number of records to skip. Defaults to 0.
|
|
47
|
+
* @returns Array of purchase records.
|
|
48
|
+
*/
|
|
16
49
|
getPurchaseHistory(userId: string, limit?: number, offset?: number): Promise<ConsumablePurchase[]>;
|
|
17
|
-
/**
|
|
50
|
+
/**
|
|
51
|
+
* Fetches paginated usage history for a user, ordered most recent first.
|
|
52
|
+
* @param userId - The user's unique identifier.
|
|
53
|
+
* @param limit - Maximum number of records to return. Defaults to 50.
|
|
54
|
+
* @param offset - Number of records to skip. Defaults to 0.
|
|
55
|
+
* @returns Array of usage records.
|
|
56
|
+
*/
|
|
18
57
|
getUsageHistory(userId: string, limit?: number, offset?: number): Promise<ConsumableUsage[]>;
|
|
19
58
|
/**
|
|
20
|
-
*
|
|
21
|
-
* Checks if transaction_ref_id already exists to prevent
|
|
59
|
+
* Records a purchase from a webhook event, with idempotency.
|
|
60
|
+
* Checks if the transaction_ref_id already exists to prevent duplicate processing.
|
|
61
|
+
* Safe to call multiple times with the same transactionId.
|
|
62
|
+
* @param userId - The user's unique identifier.
|
|
63
|
+
* @param transactionId - The unique transaction reference from RevenueCat.
|
|
64
|
+
* @param credits - Number of credits to grant.
|
|
65
|
+
* @param source - Purchase source ("web", "apple", or "google").
|
|
66
|
+
* @param productId - The RevenueCat product identifier.
|
|
67
|
+
* @param priceCents - The purchase price in cents.
|
|
68
|
+
* @param currency - The ISO currency code.
|
|
69
|
+
* @returns Whether the webhook was already processed and the current balance.
|
|
22
70
|
*/
|
|
23
71
|
recordPurchaseFromWebhook(userId: string, transactionId: string, credits: number, source: ConsumableSource, productId: string, priceCents: number, currency: string): Promise<{
|
|
24
72
|
alreadyProcessed: boolean;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConsumablesHelper.d.ts","sourceRoot":"","sources":["../../src/helpers/ConsumablesHelper.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ConsumablesHelper.d.ts","sourceRoot":"","sources":["../../src/helpers/ConsumablesHelper.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,KAAK,EACV,yBAAyB,EACzB,yBAAyB,EACzB,gBAAgB,EAChB,qBAAqB,EACtB,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EACV,kBAAkB,EAClB,eAAe,EACf,iBAAiB,EAClB,MAAM,UAAU,CAAC;AAElB;;;;GAIG;AACH,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,EAAE,CAAM;IAChB,OAAO,CAAC,MAAM,CAA0B;IACxC,OAAO,CAAC,MAAM,CAAoB;gBAGhC,EAAE,EAAE,GAAG,EACP,MAAM,EAAE,uBAAuB,EAC/B,MAAM,EAAE,iBAAiB;IAO3B;;;;;OAKG;IACG,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,yBAAyB,CAAC;IAkCpE;;;;;;OAMG;IACG,cAAc,CAClB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,yBAAyB,GACjC,OAAO,CAAC,yBAAyB,CAAC;IAsCrC;;;;;;OAMG;IACG,WAAW,CACf,MAAM,EAAE,MAAM,EACd,QAAQ,CAAC,EAAE,MAAM,GAChB,OAAO,CAAC,qBAAqB,CAAC;IA8BjC;;;;;;OAMG;IACG,kBAAkB,CACtB,MAAM,EAAE,MAAM,EACd,KAAK,SAAK,EACV,MAAM,SAAI,GACT,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAWhC;;;;;;OAMG;IACG,eAAe,CACnB,MAAM,EAAE,MAAM,EACd,KAAK,SAAK,EACV,MAAM,SAAI,GACT,OAAO,CAAC,eAAe,EAAE,CAAC;IAW7B;;;;;;;;;;;;OAYG;IACG,yBAAyB,CAC7B,MAAM,EAAE,MAAM,EACd,aAAa,EAAE,MAAM,EACrB,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,gBAAgB,EACxB,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC;QAAE,gBAAgB,EAAE,OAAO,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,CAAC;CAyB3D"}
|
|
@@ -1,11 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Core business logic for consumable credit management.
|
|
3
|
+
* Provides balance CRUD, purchase recording, usage recording, and
|
|
4
|
+
* idempotent webhook processing with atomic database operations.
|
|
5
|
+
*/
|
|
1
6
|
import { eq, desc, sql } from "drizzle-orm";
|
|
7
|
+
/**
|
|
8
|
+
* Core helper class for managing consumable credits.
|
|
9
|
+
* Handles balance get-or-create, purchase recording with atomic increments,
|
|
10
|
+
* usage recording with atomic decrements, and idempotent webhook processing.
|
|
11
|
+
*/
|
|
2
12
|
export class ConsumablesHelper {
|
|
3
13
|
constructor(db, tables, config) {
|
|
4
14
|
this.db = db;
|
|
5
15
|
this.tables = tables;
|
|
6
16
|
this.config = config;
|
|
7
17
|
}
|
|
8
|
-
/**
|
|
18
|
+
/**
|
|
19
|
+
* Gets or creates a balance record for the given user.
|
|
20
|
+
* On first access, grants initialFreeCredits and records a "free" purchase audit entry.
|
|
21
|
+
* @param userId - The user's unique identifier.
|
|
22
|
+
* @returns The user's balance and initial credits.
|
|
23
|
+
*/
|
|
9
24
|
async getBalance(userId) {
|
|
10
25
|
const { consumableBalances } = this.tables;
|
|
11
26
|
const existing = await this.db
|
|
@@ -35,7 +50,13 @@ export class ConsumablesHelper {
|
|
|
35
50
|
}
|
|
36
51
|
return { balance: freeCredits, initial_credits: freeCredits };
|
|
37
52
|
}
|
|
38
|
-
/**
|
|
53
|
+
/**
|
|
54
|
+
* Records a purchase and atomically increments the user's credit balance.
|
|
55
|
+
* Ensures the balance row exists via getBalance() before updating.
|
|
56
|
+
* @param userId - The user's unique identifier.
|
|
57
|
+
* @param request - Purchase details including credits, source, and optional metadata.
|
|
58
|
+
* @returns The updated balance after the purchase.
|
|
59
|
+
*/
|
|
39
60
|
async recordPurchase(userId, request) {
|
|
40
61
|
const { consumableBalances, consumablePurchases } = this.tables;
|
|
41
62
|
// Ensure balance record exists (idempotent)
|
|
@@ -68,7 +89,13 @@ export class ConsumablesHelper {
|
|
|
68
89
|
initial_credits: updated[0].initial_credits,
|
|
69
90
|
};
|
|
70
91
|
}
|
|
71
|
-
/**
|
|
92
|
+
/**
|
|
93
|
+
* Records a credit usage and atomically decrements the balance by 1.
|
|
94
|
+
* Uses a WHERE balance > 0 guard to prevent negative balances.
|
|
95
|
+
* @param userId - The user's unique identifier.
|
|
96
|
+
* @param filename - Optional filename associated with this usage.
|
|
97
|
+
* @returns The updated balance and whether the deduction was successful.
|
|
98
|
+
*/
|
|
72
99
|
async recordUsage(userId, filename) {
|
|
73
100
|
const { consumableBalances, consumableUsages } = this.tables;
|
|
74
101
|
// Atomically decrement (with guard against going negative)
|
|
@@ -92,7 +119,13 @@ export class ConsumablesHelper {
|
|
|
92
119
|
});
|
|
93
120
|
return { balance: result[0].balance, success: true };
|
|
94
121
|
}
|
|
95
|
-
/**
|
|
122
|
+
/**
|
|
123
|
+
* Fetches paginated purchase history for a user, ordered most recent first.
|
|
124
|
+
* @param userId - The user's unique identifier.
|
|
125
|
+
* @param limit - Maximum number of records to return. Defaults to 50.
|
|
126
|
+
* @param offset - Number of records to skip. Defaults to 0.
|
|
127
|
+
* @returns Array of purchase records.
|
|
128
|
+
*/
|
|
96
129
|
async getPurchaseHistory(userId, limit = 50, offset = 0) {
|
|
97
130
|
const { consumablePurchases } = this.tables;
|
|
98
131
|
return this.db
|
|
@@ -103,7 +136,13 @@ export class ConsumablesHelper {
|
|
|
103
136
|
.limit(limit)
|
|
104
137
|
.offset(offset);
|
|
105
138
|
}
|
|
106
|
-
/**
|
|
139
|
+
/**
|
|
140
|
+
* Fetches paginated usage history for a user, ordered most recent first.
|
|
141
|
+
* @param userId - The user's unique identifier.
|
|
142
|
+
* @param limit - Maximum number of records to return. Defaults to 50.
|
|
143
|
+
* @param offset - Number of records to skip. Defaults to 0.
|
|
144
|
+
* @returns Array of usage records.
|
|
145
|
+
*/
|
|
107
146
|
async getUsageHistory(userId, limit = 50, offset = 0) {
|
|
108
147
|
const { consumableUsages } = this.tables;
|
|
109
148
|
return this.db
|
|
@@ -115,8 +154,17 @@ export class ConsumablesHelper {
|
|
|
115
154
|
.offset(offset);
|
|
116
155
|
}
|
|
117
156
|
/**
|
|
118
|
-
*
|
|
119
|
-
* Checks if transaction_ref_id already exists to prevent
|
|
157
|
+
* Records a purchase from a webhook event, with idempotency.
|
|
158
|
+
* Checks if the transaction_ref_id already exists to prevent duplicate processing.
|
|
159
|
+
* Safe to call multiple times with the same transactionId.
|
|
160
|
+
* @param userId - The user's unique identifier.
|
|
161
|
+
* @param transactionId - The unique transaction reference from RevenueCat.
|
|
162
|
+
* @param credits - Number of credits to grant.
|
|
163
|
+
* @param source - Purchase source ("web", "apple", or "google").
|
|
164
|
+
* @param productId - The RevenueCat product identifier.
|
|
165
|
+
* @param priceCents - The purchase price in cents.
|
|
166
|
+
* @param currency - The ISO currency code.
|
|
167
|
+
* @returns Whether the webhook was already processed and the current balance.
|
|
120
168
|
*/
|
|
121
169
|
async recordPurchaseFromWebhook(userId, transactionId, credits, source, productId, priceCents, currency) {
|
|
122
170
|
// Check for duplicate
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ConsumablesHelper.js","sourceRoot":"","sources":["../../src/helpers/ConsumablesHelper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAc5C,MAAM,OAAO,iBAAiB;IAK5B,YACE,EAAO,EACP,MAA+B,EAC/B,MAAyB;QAEzB,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED
|
|
1
|
+
{"version":3,"file":"ConsumablesHelper.js","sourceRoot":"","sources":["../../src/helpers/ConsumablesHelper.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,11 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Webhook validation and parsing utilities for RevenueCat events.
|
|
3
|
+
* Handles HMAC-SHA256 signature verification and extraction of purchase data
|
|
4
|
+
* from webhook payloads.
|
|
5
|
+
*/
|
|
1
6
|
import type { RevenueCatWebhookEvent } from "../types";
|
|
2
7
|
/**
|
|
3
|
-
* Validates RevenueCat webhook HMAC signature.
|
|
8
|
+
* Validates a RevenueCat webhook HMAC-SHA256 signature.
|
|
9
|
+
* @param rawBody - The raw request body string.
|
|
10
|
+
* @param signature - The signature from the webhook header.
|
|
11
|
+
* @param secret - The shared webhook secret.
|
|
12
|
+
* @returns True if the signature is valid, false otherwise.
|
|
4
13
|
*/
|
|
5
14
|
export declare function validateWebhookSignature(rawBody: string, signature: string, secret: string): boolean;
|
|
6
15
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
16
|
+
* Parses a RevenueCat webhook event and extracts purchase data.
|
|
17
|
+
* Only processes NON_RENEWING_PURCHASE and INITIAL_PURCHASE event types.
|
|
18
|
+
* Maps store names to sources (STRIPE -> web, APP_STORE -> apple, PLAY_STORE -> google).
|
|
19
|
+
* @param event - The RevenueCat webhook event payload.
|
|
20
|
+
* @returns Extracted purchase data, or null if the event type is not a consumable purchase.
|
|
9
21
|
*/
|
|
10
22
|
export declare function parseConsumablePurchaseEvent(event: RevenueCatWebhookEvent): {
|
|
11
23
|
userId: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebhookHelper.d.ts","sourceRoot":"","sources":["../../src/helpers/WebhookHelper.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"WebhookHelper.d.ts","sourceRoot":"","sources":["../../src/helpers/WebhookHelper.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAGH,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,UAAU,CAAC;AAEvD;;;;;;GAMG;AACH,wBAAgB,wBAAwB,CACtC,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GACb,OAAO,CAKT;AAQD;;;;;;GAMG;AACH,wBAAgB,4BAA4B,CAC1C,KAAK,EAAE,sBAAsB,GAC5B;IACD,MAAM,EAAE,MAAM,CAAC;IACf,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;CACf,GAAG,IAAI,CAeP"}
|
|
@@ -1,6 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Webhook validation and parsing utilities for RevenueCat events.
|
|
3
|
+
* Handles HMAC-SHA256 signature verification and extraction of purchase data
|
|
4
|
+
* from webhook payloads.
|
|
5
|
+
*/
|
|
1
6
|
import { createHmac } from "crypto";
|
|
2
7
|
/**
|
|
3
|
-
* Validates RevenueCat webhook HMAC signature.
|
|
8
|
+
* Validates a RevenueCat webhook HMAC-SHA256 signature.
|
|
9
|
+
* @param rawBody - The raw request body string.
|
|
10
|
+
* @param signature - The signature from the webhook header.
|
|
11
|
+
* @param secret - The shared webhook secret.
|
|
12
|
+
* @returns True if the signature is valid, false otherwise.
|
|
4
13
|
*/
|
|
5
14
|
export function validateWebhookSignature(rawBody, signature, secret) {
|
|
6
15
|
const hmac = createHmac("sha256", secret);
|
|
@@ -14,8 +23,11 @@ const STORE_TO_SOURCE = {
|
|
|
14
23
|
PLAY_STORE: "google",
|
|
15
24
|
};
|
|
16
25
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
26
|
+
* Parses a RevenueCat webhook event and extracts purchase data.
|
|
27
|
+
* Only processes NON_RENEWING_PURCHASE and INITIAL_PURCHASE event types.
|
|
28
|
+
* Maps store names to sources (STRIPE -> web, APP_STORE -> apple, PLAY_STORE -> google).
|
|
29
|
+
* @param event - The RevenueCat webhook event payload.
|
|
30
|
+
* @returns Extracted purchase data, or null if the event type is not a consumable purchase.
|
|
19
31
|
*/
|
|
20
32
|
export function parseConsumablePurchaseEvent(event) {
|
|
21
33
|
const validTypes = ["NON_RENEWING_PURCHASE", "INITIAL_PURCHASE"];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WebhookHelper.js","sourceRoot":"","sources":["../../src/helpers/WebhookHelper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGpC
|
|
1
|
+
{"version":3,"file":"WebhookHelper.js","sourceRoot":"","sources":["../../src/helpers/WebhookHelper.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGpC;;;;;;GAMG;AACH,MAAM,UAAU,wBAAwB,CACtC,OAAe,EACf,SAAiB,EACjB,MAAc;IAEd,MAAM,IAAI,GAAG,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IAC1C,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IACrB,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;IACpC,OAAO,SAAS,KAAK,QAAQ,CAAC;AAChC,CAAC;AAED,MAAM,eAAe,GAA2B;IAC9C,MAAM,EAAE,KAAK;IACb,SAAS,EAAE,OAAO;IAClB,UAAU,EAAE,QAAQ;CACrB,CAAC;AAEF;;;;;;GAMG;AACH,MAAM,UAAU,4BAA4B,CAC1C,KAA6B;IAS7B,MAAM,UAAU,GAAG,CAAC,uBAAuB,EAAE,kBAAkB,CAAC,CAAC;IAEjE,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC;QAC3C,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO;QACL,MAAM,EAAE,KAAK,CAAC,KAAK,CAAC,WAAW;QAC/B,aAAa,EAAE,KAAK,CAAC,KAAK,CAAC,cAAc;QACzC,SAAS,EAAE,KAAK,CAAC,KAAK,CAAC,UAAU;QACjC,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,2BAA2B,GAAG,GAAG,CAAC;QACrE,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,QAAQ;QAC9B,KAAK,EAAE,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,KAAK;KAC/D,CAAC;AACJ,CAAC"}
|
package/dist/schema/index.d.ts
CHANGED
|
@@ -1,9 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* @fileoverview Drizzle ORM schema factory for consumable credit tables.
|
|
3
|
+
* Creates balance, purchase, and usage tables within a consumer-provided PgSchema.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Creates consumable credit tables within a given Drizzle PgSchema.
|
|
3
7
|
* The consuming API passes its own schema so migrations stay in one place.
|
|
4
8
|
*
|
|
5
9
|
* Uses `any` for schema param to avoid drizzle-orm version coupling
|
|
6
10
|
* between this library and the consuming API.
|
|
11
|
+
*
|
|
12
|
+
* @param schema - A Drizzle PgSchema instance from the consuming API.
|
|
13
|
+
* @returns An object containing the three table definitions: consumableBalances, consumablePurchases, consumableUsages.
|
|
7
14
|
*/
|
|
8
15
|
export declare function createConsumablesSchema(schema: any): {
|
|
9
16
|
consumableBalances: any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AASH;;;;;;;;;GASG;AACH,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,GAAG;;;;EA6BlD;AAED,MAAM,MAAM,uBAAuB,GAAG,UAAU,CAAC,OAAO,uBAAuB,CAAC,CAAC"}
|
package/dist/schema/index.js
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Drizzle ORM schema factory for consumable credit tables.
|
|
3
|
+
* Creates balance, purchase, and usage tables within a consumer-provided PgSchema.
|
|
4
|
+
*/
|
|
1
5
|
import { varchar, timestamp, serial, integer, } from "drizzle-orm/pg-core";
|
|
2
6
|
/**
|
|
3
|
-
*
|
|
7
|
+
* Creates consumable credit tables within a given Drizzle PgSchema.
|
|
4
8
|
* The consuming API passes its own schema so migrations stay in one place.
|
|
5
9
|
*
|
|
6
10
|
* Uses `any` for schema param to avoid drizzle-orm version coupling
|
|
7
11
|
* between this library and the consuming API.
|
|
12
|
+
*
|
|
13
|
+
* @param schema - A Drizzle PgSchema instance from the consuming API.
|
|
14
|
+
* @returns An object containing the three table definitions: consumableBalances, consumablePurchases, consumableUsages.
|
|
8
15
|
*/
|
|
9
16
|
export function createConsumablesSchema(schema) {
|
|
10
17
|
const consumableBalances = schema.table("consumable_balances", {
|
package/dist/schema/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,SAAS,EACT,MAAM,EACN,OAAO,GACR,MAAM,qBAAqB,CAAC;AAE7B
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schema/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,OAAO,EACP,SAAS,EACT,MAAM,EACN,OAAO,GACR,MAAM,qBAAqB,CAAC;AAE7B;;;;;;;;;GASG;AACH,MAAM,UAAU,uBAAuB,CAAC,MAAW;IACjD,MAAM,kBAAkB,GAAG,MAAM,CAAC,KAAK,CAAC,qBAAqB,EAAE;QAC7D,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,UAAU,EAAE;QACzD,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QAChD,eAAe,EAAE,OAAO,CAAC,iBAAiB,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;QAChE,UAAU,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE;QAC1D,UAAU,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE;KAC3D,CAAC,CAAC;IAEH,MAAM,mBAAmB,GAAG,MAAM,CAAC,KAAK,CAAC,sBAAsB,EAAE;QAC/D,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE;QAC7B,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,EAAE;QACtD,OAAO,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE;QACrC,MAAM,EAAE,OAAO,CAAC,QAAQ,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE;QACnD,kBAAkB,EAAE,OAAO,CAAC,oBAAoB,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;QAClE,UAAU,EAAE,OAAO,CAAC,YAAY,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;QAClD,WAAW,EAAE,OAAO,CAAC,aAAa,CAAC;QACnC,QAAQ,EAAE,OAAO,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QAC7C,UAAU,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE;KAC3D,CAAC,CAAC;IAEH,MAAM,gBAAgB,GAAG,MAAM,CAAC,KAAK,CAAC,mBAAmB,EAAE;QACzD,EAAE,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE;QAC7B,OAAO,EAAE,OAAO,CAAC,SAAS,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,EAAE;QACtD,QAAQ,EAAE,OAAO,CAAC,UAAU,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC;QAC9C,UAAU,EAAE,SAAS,CAAC,YAAY,CAAC,CAAC,UAAU,EAAE,CAAC,OAAO,EAAE;KAC3D,CAAC,CAAC;IAEH,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,CAAC;AACvE,CAAC"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Service-only type definitions for the consumables backend library.
|
|
3
|
+
* Defines database row types, RevenueCat webhook event structure, and service configuration.
|
|
4
|
+
*/
|
|
5
|
+
/** Database row type for a user's consumable credit balance. */
|
|
1
6
|
export interface ConsumableBalance {
|
|
2
7
|
user_id: string;
|
|
3
8
|
balance: number;
|
|
@@ -5,6 +10,7 @@ export interface ConsumableBalance {
|
|
|
5
10
|
created_at: Date;
|
|
6
11
|
updated_at: Date;
|
|
7
12
|
}
|
|
13
|
+
/** Database row type for a consumable credit purchase record. */
|
|
8
14
|
export interface ConsumablePurchase {
|
|
9
15
|
id: number;
|
|
10
16
|
user_id: string;
|
|
@@ -16,12 +22,14 @@ export interface ConsumablePurchase {
|
|
|
16
22
|
currency: string | null;
|
|
17
23
|
created_at: Date;
|
|
18
24
|
}
|
|
25
|
+
/** Database row type for a consumable credit usage record. */
|
|
19
26
|
export interface ConsumableUsage {
|
|
20
27
|
id: number;
|
|
21
28
|
user_id: string;
|
|
22
29
|
filename: string | null;
|
|
23
30
|
created_at: Date;
|
|
24
31
|
}
|
|
32
|
+
/** Structure of a RevenueCat webhook event payload. */
|
|
25
33
|
export interface RevenueCatWebhookEvent {
|
|
26
34
|
api_version: string;
|
|
27
35
|
event: {
|
|
@@ -35,6 +43,7 @@ export interface RevenueCatWebhookEvent {
|
|
|
35
43
|
purchased_at_ms: number;
|
|
36
44
|
};
|
|
37
45
|
}
|
|
46
|
+
/** Configuration for the ConsumablesHelper service. */
|
|
38
47
|
export interface ConsumablesConfig {
|
|
39
48
|
initialFreeCredits: number;
|
|
40
49
|
revenueCatWebhookSecret?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAIH,gEAAgE;AAChE,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,IAAI,CAAC;IACjB,UAAU,EAAE,IAAI,CAAC;CAClB;AAED,iEAAiE;AACjE,MAAM,WAAW,kBAAkB;IACjC,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,IAAI,CAAC;CAClB;AAED,8DAA8D;AAC9D,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,MAAM,CAAC;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,UAAU,EAAE,IAAI,CAAC;CAClB;AAID,uDAAuD;AACvD,MAAM,WAAW,sBAAsB;IACrC,WAAW,EAAE,MAAM,CAAC;IACpB,KAAK,EAAE;QACL,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,MAAM,CAAC;QACpB,UAAU,EAAE,MAAM,CAAC;QACnB,2BAA2B,EAAE,MAAM,CAAC;QACpC,QAAQ,EAAE,MAAM,CAAC;QACjB,KAAK,EAAE,MAAM,CAAC;QACd,cAAc,EAAE,MAAM,CAAC;QACvB,eAAe,EAAE,MAAM,CAAC;KACzB,CAAC;CACH;AAID,uDAAuD;AACvD,MAAM,WAAW,iBAAiB;IAChC,kBAAkB,EAAE,MAAM,CAAC;IAC3B,uBAAuB,CAAC,EAAE,MAAM,CAAC;CAClC"}
|
package/dist/types/index.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Service-only type definitions for the consumables backend library.
|
|
3
|
+
* Defines database row types, RevenueCat webhook event structure, and service configuration.
|
|
4
|
+
*/
|
|
2
5
|
export {};
|
|
3
6
|
//# sourceMappingURL=index.js.map
|
package/dist/types/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;;GAGG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sudobility/consumables_service",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.6",
|
|
4
4
|
"description": "Shared backend library for consumable credits management with Drizzle ORM",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -39,11 +39,11 @@
|
|
|
39
39
|
"author": "Sudobility",
|
|
40
40
|
"license": "BUSL-1.1",
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"@sudobility/types": "^1.9.
|
|
42
|
+
"@sudobility/types": "^1.9.54",
|
|
43
43
|
"drizzle-orm": ">=0.44.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@sudobility/types": "^1.9.
|
|
46
|
+
"@sudobility/types": "^1.9.54",
|
|
47
47
|
"drizzle-orm": "^0.45.1",
|
|
48
48
|
"vitest": "^4.0.4",
|
|
49
49
|
"@types/bun": "latest",
|