@sudobility/subscription_service 1.0.5 → 1.0.7
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 +109 -48
- package/dist/helpers/SubscriptionHelper.d.ts +34 -0
- package/dist/helpers/SubscriptionHelper.d.ts.map +1 -1
- package/dist/helpers/SubscriptionHelper.js +54 -7
- package/dist/helpers/SubscriptionHelper.js.map +1 -1
- package/dist/helpers/index.d.ts +3 -0
- package/dist/helpers/index.d.ts.map +1 -1
- package/dist/helpers/index.js +3 -0
- package/dist/helpers/index.js.map +1 -1
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/types/entitlements.d.ts +6 -0
- package/dist/types/entitlements.d.ts.map +1 -1
- package/dist/types/entitlements.js +6 -0
- package/dist/types/entitlements.js.map +1 -1
- package/dist/types/index.d.ts +3 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js +3 -0
- package/dist/types/index.js.map +1 -1
- package/dist/types/subscription.d.ts +4 -1
- package/dist/types/subscription.d.ts.map +1 -1
- package/dist/types/subscription.js +3 -0
- package/dist/types/subscription.js.map +1 -1
- package/package.json +2 -2
package/CLAUDE.md
CHANGED
|
@@ -1,54 +1,76 @@
|
|
|
1
|
-
# Subscription Service
|
|
1
|
+
# Subscription Service - AI Development Guide
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
## Overview
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Shared backend library for subscription management using RevenueCat. Provides a `SubscriptionHelper` class that calls the RevenueCat REST API v1 to fetch user entitlements and subscription information. Designed for server-side use only (requires a secret API key).
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- **
|
|
10
|
-
- **Runtime**: Bun
|
|
7
|
+
- **Package**: `@sudobility/subscription_service`
|
|
8
|
+
- **Version**: 1.0.5
|
|
9
|
+
- **License**: BUSL-1.1
|
|
11
10
|
- **Package Manager**: Bun (do not use npm/yarn/pnpm for installing dependencies)
|
|
12
|
-
- **
|
|
13
|
-
- **Test**: vitest
|
|
11
|
+
- **Registry**: npm (public, `@sudobility` scope)
|
|
14
12
|
|
|
15
13
|
## Project Structure
|
|
16
14
|
|
|
17
15
|
```
|
|
18
16
|
src/
|
|
19
|
-
├── index.ts # Main exports
|
|
17
|
+
├── index.ts # Main barrel exports
|
|
20
18
|
├── types/
|
|
21
19
|
│ ├── index.ts # Type re-exports
|
|
22
|
-
│ ├── entitlements.ts # RevenueCat API types
|
|
20
|
+
│ ├── entitlements.ts # RevenueCat API response types
|
|
23
21
|
│ └── subscription.ts # SubscriptionInfo type
|
|
24
22
|
└── helpers/
|
|
25
23
|
├── index.ts # Helper re-exports
|
|
26
|
-
└── SubscriptionHelper.ts # RevenueCat API client
|
|
24
|
+
└── SubscriptionHelper.ts # RevenueCat API client class
|
|
27
25
|
tests/
|
|
28
|
-
└──
|
|
26
|
+
└── SubscriptionHelper.test.ts # Vitest tests (mocked fetch)
|
|
29
27
|
```
|
|
30
28
|
|
|
31
|
-
##
|
|
29
|
+
## Key Exports
|
|
30
|
+
|
|
31
|
+
| Export | Type | Description |
|
|
32
|
+
|---|---|---|
|
|
33
|
+
| `SubscriptionHelper` | class | Main API client for RevenueCat entitlements |
|
|
34
|
+
| `SubscriptionHelperConfig` | interface | Config with `revenueCatApiKey` and optional `baseUrl` |
|
|
35
|
+
| `SubscriptionInfo` | interface | Return type with `entitlements` and `subscriptionStartedAt` |
|
|
36
|
+
| `RevenueCatEntitlement` | interface | Raw entitlement from RevenueCat API |
|
|
37
|
+
| `RevenueCatSubscription` | interface | Raw subscription from RevenueCat API |
|
|
38
|
+
| `RevenueCatSubscriberResponse` | interface | Full subscriber response shape |
|
|
39
|
+
|
|
40
|
+
## Development Commands
|
|
32
41
|
|
|
33
42
|
```bash
|
|
34
|
-
bun run build # Build ESM
|
|
43
|
+
bun run build # Build ESM (tsc -p tsconfig.esm.json)
|
|
35
44
|
bun run clean # Remove dist/
|
|
36
|
-
bun run dev # Watch mode
|
|
37
|
-
bun test # Run tests
|
|
38
|
-
bun run
|
|
39
|
-
bun run
|
|
40
|
-
bun run
|
|
45
|
+
bun run dev # Watch mode (tsc --watch)
|
|
46
|
+
bun test # Run tests (vitest run)
|
|
47
|
+
bun run test:watch # Watch mode tests (vitest)
|
|
48
|
+
bun run lint # Run ESLint (eslint src/)
|
|
49
|
+
bun run lint:fix # ESLint auto-fix
|
|
50
|
+
bun run typecheck # TypeScript check (tsc --noEmit)
|
|
51
|
+
bun run format # Prettier format
|
|
52
|
+
bun run format:check # Prettier check
|
|
53
|
+
bun run verify # All checks + build (typecheck -> lint -> test -> build)
|
|
54
|
+
npm publish # Publish to npm (public @sudobility scope)
|
|
41
55
|
```
|
|
42
56
|
|
|
43
57
|
## Key Concepts
|
|
44
58
|
|
|
45
59
|
### SubscriptionHelper
|
|
46
60
|
|
|
47
|
-
Fetches user entitlements from RevenueCat API v1.
|
|
61
|
+
Fetches user entitlements from RevenueCat API v1 (`GET /subscribers/{user_id}`).
|
|
48
62
|
|
|
49
63
|
- Uses RevenueCat secret API key (server-side only)
|
|
50
|
-
- Supports testMode to include/exclude sandbox purchases
|
|
51
|
-
- Returns `["none"]` if user has no active entitlements
|
|
64
|
+
- Supports `testMode` to include/exclude sandbox purchases
|
|
65
|
+
- Returns `["none"]` (the `NONE_ENTITLEMENT` constant from `@sudobility/types`) if user has no active entitlements
|
|
66
|
+
- Tracks the earliest `purchase_date` across all active entitlements as `subscriptionStartedAt`
|
|
67
|
+
|
|
68
|
+
### Methods
|
|
69
|
+
|
|
70
|
+
| Method | Signature | Description |
|
|
71
|
+
|---|---|---|
|
|
72
|
+
| `getEntitlements` | `(userId, testMode?) => Promise<string[]>` | Get active entitlement names |
|
|
73
|
+
| `getSubscriptionInfo` | `(userId, testMode?) => Promise<SubscriptionInfo>` | Get entitlements + subscription start date |
|
|
52
74
|
|
|
53
75
|
### testMode Parameter
|
|
54
76
|
|
|
@@ -60,7 +82,8 @@ The helper checks each subscription's `sandbox` flag and filters accordingly.
|
|
|
60
82
|
## Usage
|
|
61
83
|
|
|
62
84
|
```typescript
|
|
63
|
-
import { SubscriptionHelper
|
|
85
|
+
import { SubscriptionHelper } from "@sudobility/subscription_service";
|
|
86
|
+
import { NONE_ENTITLEMENT } from "@sudobility/types";
|
|
64
87
|
|
|
65
88
|
const helper = new SubscriptionHelper({
|
|
66
89
|
revenueCatApiKey: process.env.REVENUECAT_API_KEY!,
|
|
@@ -71,7 +94,7 @@ const entitlements = await helper.getEntitlements(userId);
|
|
|
71
94
|
// Returns: ["pro"] or ["none"]
|
|
72
95
|
|
|
73
96
|
// Get entitlements (test mode - includes sandbox)
|
|
74
|
-
const
|
|
97
|
+
const testEntitlements = await helper.getEntitlements(userId, true);
|
|
75
98
|
|
|
76
99
|
// Get full subscription info
|
|
77
100
|
const info = await helper.getSubscriptionInfo(userId, testMode);
|
|
@@ -85,12 +108,29 @@ if (!info.entitlements.includes(NONE_ENTITLEMENT)) {
|
|
|
85
108
|
|
|
86
109
|
## Architecture
|
|
87
110
|
|
|
111
|
+
### TypeScript Configuration
|
|
112
|
+
|
|
113
|
+
- Base `tsconfig.json`: strict mode, ES2020 target, bundler module resolution, `noEmit: true`
|
|
114
|
+
- `tsconfig.esm.json`: extends base, adds ESNext module output to `./dist`, declaration + declarationMap + sourceMap
|
|
115
|
+
- `tsconfig.cjs.json`: exists but build script uses ESM config only
|
|
116
|
+
|
|
117
|
+
### Build Output
|
|
118
|
+
|
|
119
|
+
- ESM-only output to `./dist/`
|
|
120
|
+
- Declaration files (`.d.ts`) and declaration maps (`.d.ts.map`) included
|
|
121
|
+
- Source maps enabled
|
|
122
|
+
- Published files: `dist/**/*` and `CLAUDE.md`
|
|
123
|
+
|
|
124
|
+
### Dependency Graph
|
|
125
|
+
|
|
88
126
|
```
|
|
127
|
+
@sudobility/types (peer dependency - provides NONE_ENTITLEMENT)
|
|
128
|
+
|
|
|
89
129
|
subscription_service (this package)
|
|
90
|
-
|
|
130
|
+
^
|
|
91
131
|
ratelimit_service (depends on this)
|
|
92
|
-
|
|
93
|
-
shapeshyft_api, sudojo_api,
|
|
132
|
+
^
|
|
133
|
+
shapeshyft_api, sudojo_api, whisperly_api
|
|
94
134
|
```
|
|
95
135
|
|
|
96
136
|
## Consuming APIs
|
|
@@ -101,35 +141,27 @@ APIs using this library:
|
|
|
101
141
|
- whisperly_api
|
|
102
142
|
- ratelimit_service
|
|
103
143
|
|
|
144
|
+
## Testing
|
|
145
|
+
|
|
146
|
+
- Framework: Vitest (vitest run)
|
|
147
|
+
- Tests located in `tests/` directory (not alongside source)
|
|
148
|
+
- Uses `vi.fn()` and `vi.stubGlobal("fetch", ...)` to mock HTTP calls
|
|
149
|
+
- Tests cover: 404 handling, API errors, active entitlements, expired entitlements, sandbox filtering, test mode, multiple entitlements with earliest date
|
|
150
|
+
|
|
104
151
|
## Publishing
|
|
105
152
|
|
|
106
153
|
```bash
|
|
107
|
-
bun run verify # All checks
|
|
154
|
+
bun run verify # All checks (typecheck -> lint -> test -> build)
|
|
108
155
|
npm publish # Publish to npm
|
|
109
156
|
```
|
|
110
157
|
|
|
111
|
-
## Workspace Context
|
|
112
|
-
|
|
113
|
-
This project is part of the **ShapeShyft** multi-project workspace at the parent directory. See `../CLAUDE.md` for the full architecture, dependency graph, and build order.
|
|
114
|
-
|
|
115
|
-
## Downstream Impact
|
|
116
|
-
|
|
117
|
-
| Downstream Consumer | Relationship |
|
|
118
|
-
|---------------------|-------------|
|
|
119
|
-
| `shapeshyft_api` | Direct dependency - uses SubscriptionHelper for entitlement checks |
|
|
120
|
-
|
|
121
|
-
After making changes:
|
|
122
|
-
1. `bun run verify` in this project (includes tests)
|
|
123
|
-
2. `npm publish`
|
|
124
|
-
3. In `shapeshyft_api`: `bun update @sudobility/subscription_service` then rebuild
|
|
125
|
-
|
|
126
158
|
## Local Dev Workflow
|
|
127
159
|
|
|
128
160
|
```bash
|
|
129
161
|
# In this project:
|
|
130
162
|
bun link
|
|
131
163
|
|
|
132
|
-
# In
|
|
164
|
+
# In consuming API:
|
|
133
165
|
bun link @sudobility/subscription_service
|
|
134
166
|
|
|
135
167
|
# Rebuild after changes:
|
|
@@ -139,6 +171,32 @@ bun run build
|
|
|
139
171
|
bun unlink @sudobility/subscription_service && bun install
|
|
140
172
|
```
|
|
141
173
|
|
|
174
|
+
## Peer / Key Dependencies
|
|
175
|
+
|
|
176
|
+
### Peer Dependencies
|
|
177
|
+
|
|
178
|
+
| Package | Version | Purpose |
|
|
179
|
+
|---|---|---|
|
|
180
|
+
| `@sudobility/types` | `^1.9.53` | Provides `NONE_ENTITLEMENT` constant |
|
|
181
|
+
|
|
182
|
+
### Dev Dependencies
|
|
183
|
+
|
|
184
|
+
| Package | Version | Purpose |
|
|
185
|
+
|---|---|---|
|
|
186
|
+
| `typescript` | ^5.9.0 | Compiler |
|
|
187
|
+
| `vitest` | ^4.0.4 | Test runner |
|
|
188
|
+
| `eslint` | ^9.39.0 | Linter |
|
|
189
|
+
| `prettier` | ^3.7.0 | Formatter |
|
|
190
|
+
| `@typescript-eslint/eslint-plugin` | ^8.50.0 | TS-aware ESLint rules |
|
|
191
|
+
| `@typescript-eslint/parser` | ^8.50.0 | TS ESLint parser |
|
|
192
|
+
| `eslint-plugin-import` | ^2.32.0 | Import order/validation rules |
|
|
193
|
+
| `@types/bun` | latest | Bun runtime types |
|
|
194
|
+
| `@types/node` | ^24.0.0 | Node.js type definitions |
|
|
195
|
+
|
|
196
|
+
## Workspace Context
|
|
197
|
+
|
|
198
|
+
This project is part of the Sudobility multi-project workspace at the parent directory. See `../CLAUDE.md` for the full architecture, dependency graph, and build order.
|
|
199
|
+
|
|
142
200
|
## Pre-Commit Checklist
|
|
143
201
|
|
|
144
202
|
```bash
|
|
@@ -147,8 +205,11 @@ bun run verify # Runs: typecheck -> lint -> test -> build
|
|
|
147
205
|
|
|
148
206
|
## Gotchas
|
|
149
207
|
|
|
150
|
-
- **No
|
|
208
|
+
- **No runtime dependencies** -- Only `@sudobility/types` as a peer dependency (for `NONE_ENTITLEMENT`). All HTTP calls use native `fetch`.
|
|
151
209
|
- **RevenueCat API key is a server-side secret** -- never expose it to the client.
|
|
152
210
|
- **`testMode` controls sandbox filtering** -- in production, always pass `false`. Passing `true` includes sandbox purchases with fake entitlements.
|
|
153
|
-
- **`NONE_ENTITLEMENT` is the string `"none"`** -- it is a constant
|
|
154
|
-
- **ESM-only output** -- no CJS build.
|
|
211
|
+
- **`NONE_ENTITLEMENT` is the string `"none"`** -- it is a constant imported from `@sudobility/types`, not null/undefined. Always compare with `NONE_ENTITLEMENT`.
|
|
212
|
+
- **ESM-only output** -- no CJS build. The `tsconfig.cjs.json` exists but is unused by the build script.
|
|
213
|
+
- **404 from RevenueCat returns `["none"]`** -- Not an error; it means the user has never been seen by RevenueCat.
|
|
214
|
+
- **`baseUrl` defaults to `https://api.revenuecat.com/v1`** -- Override for testing with a mock server.
|
|
215
|
+
- **User ID is URL-encoded** -- `encodeURIComponent(userId)` is applied before constructing the API URL.
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview RevenueCat API client for server-side subscription management.
|
|
3
|
+
*
|
|
4
|
+
* Provides the `SubscriptionHelper` class that calls the RevenueCat REST API v1
|
|
5
|
+
* to fetch user entitlements and subscription information. Handles sandbox
|
|
6
|
+
* filtering via the `testMode` parameter.
|
|
7
|
+
*/
|
|
1
8
|
import type { SubscriptionInfo } from "../types/subscription";
|
|
2
9
|
/**
|
|
3
10
|
* Configuration for SubscriptionHelper.
|
|
@@ -7,21 +14,48 @@ export interface SubscriptionHelperConfig {
|
|
|
7
14
|
revenueCatApiKey: string;
|
|
8
15
|
/** Base URL for RevenueCat API. Defaults to https://api.revenuecat.com/v1 */
|
|
9
16
|
baseUrl?: string;
|
|
17
|
+
/** Request timeout in milliseconds. Defaults to 10000 (10 seconds). */
|
|
18
|
+
timeoutMs?: number;
|
|
10
19
|
}
|
|
11
20
|
/**
|
|
12
21
|
* Helper class for interacting with RevenueCat API to get user entitlements
|
|
13
22
|
* and subscription information.
|
|
23
|
+
*
|
|
24
|
+
* Uses the RevenueCat REST API v1 endpoint `GET /subscribers/{user_id}` to
|
|
25
|
+
* fetch subscriber data, then filters entitlements by expiration and sandbox status.
|
|
14
26
|
*/
|
|
15
27
|
export declare class SubscriptionHelper {
|
|
16
28
|
private readonly apiKey;
|
|
17
29
|
private readonly baseUrl;
|
|
30
|
+
private readonly timeoutMs;
|
|
31
|
+
/**
|
|
32
|
+
* Creates a new SubscriptionHelper instance.
|
|
33
|
+
*
|
|
34
|
+
* @param config - Configuration containing the RevenueCat API key and optional base URL.
|
|
35
|
+
*/
|
|
18
36
|
constructor(config: SubscriptionHelperConfig);
|
|
19
37
|
/**
|
|
20
38
|
* Get active entitlement names for a user.
|
|
39
|
+
*
|
|
40
|
+
* This is a convenience wrapper around `getSubscriptionInfo()` that returns
|
|
41
|
+
* only the entitlements array.
|
|
42
|
+
*
|
|
43
|
+
* @param userId - The RevenueCat user identifier.
|
|
44
|
+
* @param testMode - When true, includes sandbox purchases. Defaults to false.
|
|
45
|
+
* @returns Array of active entitlement names, or `["none"]` if no active entitlements.
|
|
21
46
|
*/
|
|
22
47
|
getEntitlements(userId: string, testMode?: boolean): Promise<string[]>;
|
|
23
48
|
/**
|
|
24
49
|
* Get full subscription info including entitlements and subscription start date.
|
|
50
|
+
*
|
|
51
|
+
* Fetches the subscriber data from RevenueCat, filters out expired entitlements
|
|
52
|
+
* and (optionally) sandbox purchases, and returns the active entitlement names
|
|
53
|
+
* along with the earliest purchase date.
|
|
54
|
+
*
|
|
55
|
+
* @param userId - The RevenueCat user identifier.
|
|
56
|
+
* @param testMode - When true, includes sandbox purchases. Defaults to false.
|
|
57
|
+
* @returns Subscription info with active entitlements and earliest purchase date.
|
|
58
|
+
* @throws Error if the RevenueCat API returns a non-404, non-OK response.
|
|
25
59
|
*/
|
|
26
60
|
getSubscriptionInfo(userId: string, testMode?: boolean): Promise<SubscriptionInfo>;
|
|
27
61
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubscriptionHelper.d.ts","sourceRoot":"","sources":["../../src/helpers/SubscriptionHelper.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SubscriptionHelper.d.ts","sourceRoot":"","sources":["../../src/helpers/SubscriptionHelper.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,sDAAsD;IACtD,gBAAgB,EAAE,MAAM,CAAC;IACzB,6EAA6E;IAC7E,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;GAMG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAS;IACjC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;IAEnC;;;;OAIG;gBACS,MAAM,EAAE,wBAAwB;IAM5C;;;;;;;;;OASG;IACG,eAAe,CACnB,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,OAAe,GACxB,OAAO,CAAC,MAAM,EAAE,CAAC;IASpB;;;;;;;;;;;OAWG;IACG,mBAAmB,CACvB,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,OAAe,GACxB,OAAO,CAAC,gBAAgB,CAAC;CA6E7B"}
|
|
@@ -1,32 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview RevenueCat API client for server-side subscription management.
|
|
3
|
+
*
|
|
4
|
+
* Provides the `SubscriptionHelper` class that calls the RevenueCat REST API v1
|
|
5
|
+
* to fetch user entitlements and subscription information. Handles sandbox
|
|
6
|
+
* filtering via the `testMode` parameter.
|
|
7
|
+
*/
|
|
1
8
|
import { NONE_ENTITLEMENT } from "@sudobility/types";
|
|
2
9
|
/**
|
|
3
10
|
* Helper class for interacting with RevenueCat API to get user entitlements
|
|
4
11
|
* and subscription information.
|
|
12
|
+
*
|
|
13
|
+
* Uses the RevenueCat REST API v1 endpoint `GET /subscribers/{user_id}` to
|
|
14
|
+
* fetch subscriber data, then filters entitlements by expiration and sandbox status.
|
|
5
15
|
*/
|
|
6
16
|
export class SubscriptionHelper {
|
|
17
|
+
/**
|
|
18
|
+
* Creates a new SubscriptionHelper instance.
|
|
19
|
+
*
|
|
20
|
+
* @param config - Configuration containing the RevenueCat API key and optional base URL.
|
|
21
|
+
*/
|
|
7
22
|
constructor(config) {
|
|
8
23
|
this.apiKey = config.revenueCatApiKey;
|
|
9
24
|
this.baseUrl = config.baseUrl ?? "https://api.revenuecat.com/v1";
|
|
25
|
+
this.timeoutMs = config.timeoutMs ?? 10000;
|
|
10
26
|
}
|
|
11
27
|
/**
|
|
12
28
|
* Get active entitlement names for a user.
|
|
29
|
+
*
|
|
30
|
+
* This is a convenience wrapper around `getSubscriptionInfo()` that returns
|
|
31
|
+
* only the entitlements array.
|
|
32
|
+
*
|
|
33
|
+
* @param userId - The RevenueCat user identifier.
|
|
34
|
+
* @param testMode - When true, includes sandbox purchases. Defaults to false.
|
|
35
|
+
* @returns Array of active entitlement names, or `["none"]` if no active entitlements.
|
|
13
36
|
*/
|
|
14
37
|
async getEntitlements(userId, testMode = false) {
|
|
38
|
+
if (!userId || typeof userId !== "string") {
|
|
39
|
+
throw new Error("userId must be a non-empty string");
|
|
40
|
+
}
|
|
15
41
|
const info = await this.getSubscriptionInfo(userId, testMode);
|
|
16
42
|
return info.entitlements;
|
|
17
43
|
}
|
|
18
44
|
/**
|
|
19
45
|
* Get full subscription info including entitlements and subscription start date.
|
|
46
|
+
*
|
|
47
|
+
* Fetches the subscriber data from RevenueCat, filters out expired entitlements
|
|
48
|
+
* and (optionally) sandbox purchases, and returns the active entitlement names
|
|
49
|
+
* along with the earliest purchase date.
|
|
50
|
+
*
|
|
51
|
+
* @param userId - The RevenueCat user identifier.
|
|
52
|
+
* @param testMode - When true, includes sandbox purchases. Defaults to false.
|
|
53
|
+
* @returns Subscription info with active entitlements and earliest purchase date.
|
|
54
|
+
* @throws Error if the RevenueCat API returns a non-404, non-OK response.
|
|
20
55
|
*/
|
|
21
56
|
async getSubscriptionInfo(userId, testMode = false) {
|
|
57
|
+
if (!userId || typeof userId !== "string") {
|
|
58
|
+
throw new Error("userId must be a non-empty string");
|
|
59
|
+
}
|
|
22
60
|
const url = `${this.baseUrl}/subscribers/${encodeURIComponent(userId)}`;
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
61
|
+
const controller = new AbortController();
|
|
62
|
+
const timeoutId = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
63
|
+
let response;
|
|
64
|
+
try {
|
|
65
|
+
response = await fetch(url, {
|
|
66
|
+
method: "GET",
|
|
67
|
+
headers: {
|
|
68
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
69
|
+
"Content-Type": "application/json",
|
|
70
|
+
},
|
|
71
|
+
signal: controller.signal,
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
clearTimeout(timeoutId);
|
|
76
|
+
}
|
|
30
77
|
if (response.status === 404) {
|
|
31
78
|
return {
|
|
32
79
|
entitlements: [NONE_ENTITLEMENT],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SubscriptionHelper.js","sourceRoot":"","sources":["../../src/helpers/SubscriptionHelper.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"SubscriptionHelper.js","sourceRoot":"","sources":["../../src/helpers/SubscriptionHelper.ts"],"names":[],"mappings":"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"}
|
package/dist/helpers/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/helpers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,EAClB,KAAK,wBAAwB,GAC9B,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/helpers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,kBAAkB,EAClB,KAAK,wBAAwB,GAC9B,MAAM,sBAAsB,CAAC"}
|
package/dist/helpers/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/helpers/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,kBAAkB,GAEnB,MAAM,sBAAsB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/helpers/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,kBAAkB,GAEnB,MAAM,sBAAsB,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Public API for @sudobility/subscription_service.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports all types and the SubscriptionHelper class for server-side
|
|
5
|
+
* subscription management via RevenueCat.
|
|
6
|
+
*/
|
|
1
7
|
export { type RevenueCatEntitlement, type RevenueCatSubscription, type RevenueCatSubscriberResponse, type SubscriptionInfo, } from "./types";
|
|
8
|
+
export { NONE_ENTITLEMENT } from "@sudobility/types";
|
|
2
9
|
export { SubscriptionHelper, type SubscriptionHelperConfig, } from "./helpers";
|
|
3
10
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,4BAA4B,EACjC,KAAK,gBAAgB,GACtB,MAAM,SAAS,CAAC;AAGjB,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAGrD,OAAO,EACL,kBAAkB,EAClB,KAAK,wBAAwB,GAC9B,MAAM,WAAW,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Public API for @sudobility/subscription_service.
|
|
3
|
+
*
|
|
4
|
+
* Re-exports all types and the SubscriptionHelper class for server-side
|
|
5
|
+
* subscription management via RevenueCat.
|
|
6
|
+
*/
|
|
7
|
+
// Constants (convenience re-export)
|
|
8
|
+
export { NONE_ENTITLEMENT } from "@sudobility/types";
|
|
1
9
|
// Helpers
|
|
2
10
|
export { SubscriptionHelper, } from "./helpers";
|
|
3
11
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAUH,oCAAoC;AACpC,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAErD,UAAU;AACV,OAAO,EACL,kBAAkB,GAEnB,MAAM,WAAW,CAAC"}
|
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview RevenueCat API response types for the subscriber endpoint.
|
|
3
|
+
*
|
|
4
|
+
* These interfaces model the JSON response from RevenueCat's
|
|
5
|
+
* `GET /v1/subscribers/{user_id}` endpoint.
|
|
6
|
+
*/
|
|
1
7
|
/**
|
|
2
8
|
* RevenueCat entitlement information from the subscriber API.
|
|
3
9
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entitlements.d.ts","sourceRoot":"","sources":["../../src/types/entitlements.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,yDAAyD;IACzD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mCAAmC;IACnC,yBAAyB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,0CAA0C;IAC1C,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kCAAkC;IAClC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,yDAAyD;IACzD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kCAAkC;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C,UAAU,EAAE;QACV,YAAY,EAAE;YACZ,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB,CAAC;SACtC,CAAC;QACF,aAAa,EAAE;YACb,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,CAAC;SACvC,CAAC;KACH,CAAC;CACH"}
|
|
1
|
+
{"version":3,"file":"entitlements.d.ts","sourceRoot":"","sources":["../../src/types/entitlements.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH;;GAEG;AACH,MAAM,WAAW,qBAAqB;IACpC,yDAAyD;IACzD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mCAAmC;IACnC,yBAAyB,EAAE,MAAM,GAAG,IAAI,CAAC;IACzC,0CAA0C;IAC1C,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kCAAkC;IAClC,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,yDAAyD;IACzD,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,kCAAkC;IAClC,aAAa,EAAE,MAAM,CAAC;IACtB,yCAAyC;IACzC,OAAO,EAAE,OAAO,CAAC;IACjB,wCAAwC;IACxC,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C,UAAU,EAAE;QACV,YAAY,EAAE;YACZ,CAAC,GAAG,EAAE,MAAM,GAAG,qBAAqB,CAAC;SACtC,CAAC;QACF,aAAa,EAAE;YACb,CAAC,GAAG,EAAE,MAAM,GAAG,sBAAsB,CAAC;SACvC,CAAC;KACH,CAAC;CACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"entitlements.js","sourceRoot":"","sources":["../../src/types/entitlements.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"entitlements.js","sourceRoot":"","sources":["../../src/types/entitlements.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Type re-exports for subscription_service.
|
|
3
|
+
*/
|
|
1
4
|
export { type RevenueCatEntitlement, type RevenueCatSubscription, type RevenueCatSubscriberResponse, } from "./entitlements";
|
|
2
5
|
export { type SubscriptionInfo } from "./subscription";
|
|
3
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,4BAA4B,GAClC,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EACL,KAAK,qBAAqB,EAC1B,KAAK,sBAAsB,EAC3B,KAAK,4BAA4B,GAClC,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,gBAAgB,CAAC"}
|
package/dist/types/index.js
CHANGED
package/dist/types/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
|
@@ -1,8 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Domain types for subscription information returned by SubscriptionHelper.
|
|
3
|
+
*/
|
|
1
4
|
/**
|
|
2
5
|
* Subscription information returned by SubscriptionHelper.
|
|
3
6
|
*/
|
|
4
7
|
export interface SubscriptionInfo {
|
|
5
|
-
/** Array of active entitlement names */
|
|
8
|
+
/** Array of active entitlement names, or ["none"] if no active entitlements */
|
|
6
9
|
entitlements: string[];
|
|
7
10
|
/** When the subscription started (earliest purchase date), or null if no subscription */
|
|
8
11
|
subscriptionStartedAt: Date | null;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscription.d.ts","sourceRoot":"","sources":["../../src/types/subscription.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B
|
|
1
|
+
{"version":3,"file":"subscription.d.ts","sourceRoot":"","sources":["../../src/types/subscription.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,+EAA+E;IAC/E,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,yFAAyF;IACzF,qBAAqB,EAAE,IAAI,GAAG,IAAI,CAAC;CACpC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscription.js","sourceRoot":"","sources":["../../src/types/subscription.ts"],"names":[],"mappings":""}
|
|
1
|
+
{"version":3,"file":"subscription.js","sourceRoot":"","sources":["../../src/types/subscription.ts"],"names":[],"mappings":"AAAA;;GAEG"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sudobility/subscription_service",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.7",
|
|
4
4
|
"description": "Shared subscription management library using RevenueCat for entitlements",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"author": "Sudobility",
|
|
39
39
|
"license": "BUSL-1.1",
|
|
40
40
|
"peerDependencies": {
|
|
41
|
-
"@sudobility/types": "^1.9.
|
|
41
|
+
"@sudobility/types": "^1.9.54"
|
|
42
42
|
},
|
|
43
43
|
"devDependencies": {
|
|
44
44
|
"vitest": "^4.0.4",
|