@onesub/server 0.9.1 → 0.10.0
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/README.md +86 -1
- package/dist/__tests__/entitlements.test.d.ts +14 -0
- package/dist/__tests__/entitlements.test.d.ts.map +1 -0
- package/dist/__tests__/entitlements.test.js +268 -0
- package/dist/__tests__/entitlements.test.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/routes/entitlements.d.ts +23 -0
- package/dist/routes/entitlements.d.ts.map +1 -0
- package/dist/routes/entitlements.js +130 -0
- package/dist/routes/entitlements.js.map +1 -0
- package/dist/store.d.ts +16 -0
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +14 -2
- package/dist/store.js.map +1 -1
- package/dist/stores/postgres.d.ts +7 -0
- package/dist/stores/postgres.d.ts.map +1 -1
- package/dist/stores/postgres.js +14 -0
- package/dist/stores/postgres.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -24,7 +24,15 @@ import { createOneSubMiddleware, PostgresSubscriptionStore, PostgresPurchaseStor
|
|
|
24
24
|
const app = express();
|
|
25
25
|
|
|
26
26
|
app.use(createOneSubMiddleware({
|
|
27
|
-
apple:
|
|
27
|
+
apple: {
|
|
28
|
+
bundleId: 'com.yourapp.id',
|
|
29
|
+
sharedSecret: process.env.APPLE_SHARED_SECRET,
|
|
30
|
+
// Optional — required only for the App Store Server API features below
|
|
31
|
+
// (status fetch fallback, consumption response).
|
|
32
|
+
keyId: process.env.APPLE_KEY_ID,
|
|
33
|
+
issuerId: process.env.APPLE_ISSUER_ID,
|
|
34
|
+
privateKey: process.env.APPLE_PRIVATE_KEY,
|
|
35
|
+
},
|
|
28
36
|
google: { packageName: 'com.yourapp.id', serviceAccountKey: process.env.GOOGLE_SERVICE_ACCOUNT_KEY },
|
|
29
37
|
database: { url: process.env.DATABASE_URL },
|
|
30
38
|
store: new PostgresSubscriptionStore(process.env.DATABASE_URL),
|
|
@@ -32,6 +40,7 @@ app.use(createOneSubMiddleware({
|
|
|
32
40
|
// Optional:
|
|
33
41
|
adminSecret: process.env.ADMIN_SECRET, // enables /onesub/purchase/admin/*
|
|
34
42
|
logger: require('pino')(), // any { info, warn, error } logger
|
|
43
|
+
refundPolicy: 'immediate', // 'immediate' (default) | 'until_expiry'
|
|
35
44
|
}));
|
|
36
45
|
|
|
37
46
|
app.listen(4100);
|
|
@@ -51,10 +60,86 @@ app.listen(4100);
|
|
|
51
60
|
| `POST /onesub/purchase/admin/grant` | Manually grant a purchase (requires `adminSecret`) |
|
|
52
61
|
| `POST /onesub/purchase/admin/transfer` | Reassign a `transactionId` to a new `userId` (requires `adminSecret`) |
|
|
53
62
|
|
|
63
|
+
## Lifecycle states (`0.4.0+`)
|
|
64
|
+
|
|
65
|
+
`SubscriptionInfo.status` carries the full lifecycle. The status route's `active: boolean` is computed as `(active || grace_period) && expiresAt > now` — but the raw status lets you render accurate UX:
|
|
66
|
+
|
|
67
|
+
| Status | active | UX hint |
|
|
68
|
+
|--------|--------|---------|
|
|
69
|
+
| `active` | ✅ | normal |
|
|
70
|
+
| `grace_period` | ✅ | "결제 정보 확인 필요 (계속 사용 가능)" |
|
|
71
|
+
| `on_hold` | ❌ | "결제 정보를 업데이트하세요" |
|
|
72
|
+
| `paused` | ❌ | "재개 예정: \{autoResumeTime\}" |
|
|
73
|
+
| `expired` / `canceled` | ❌ | re-purchase or restore |
|
|
74
|
+
|
|
75
|
+
See [`@onesub/shared` README](../shared/README.md) for the full mapping.
|
|
76
|
+
|
|
77
|
+
## Refund policy (`0.8.0+`)
|
|
78
|
+
|
|
79
|
+
```ts
|
|
80
|
+
refundPolicy: 'immediate' | 'until_expiry' // default 'immediate'
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
- `'immediate'` — subscription refunds (Apple `REFUND`/`REVOKE`, Google voided productType=1) flip status to `canceled` right away. Strict, fraud-resistant.
|
|
84
|
+
- `'until_expiry'` — keep `status`/`expiresAt` untouched, only flip `willRenew = false`. User keeps entitlement until the original expiry. Better UX for goodwill refunds.
|
|
85
|
+
|
|
86
|
+
IAP refunds (consumable / non-consumable) are **always immediate** regardless of policy — they have no expiry concept.
|
|
87
|
+
|
|
88
|
+
## Optional Apple App Store Server API features (`0.8.0+`)
|
|
89
|
+
|
|
90
|
+
Set `apple.keyId` / `apple.issuerId` / `apple.privateKey` (PKCS8 ES256 from App Store Connect → Users and Access → Keys) to unlock:
|
|
91
|
+
|
|
92
|
+
### Status API fallback (automatic)
|
|
93
|
+
|
|
94
|
+
If a webhook arrives for an `originalTransactionId` the store doesn't know (server downtime, queue truncation, fresh install), the webhook handler calls `GET /inApps/v1/subscriptions/{originalTransactionId}` to fetch canonical state from Apple and saves a record under a placeholder `userId`. Subsequent `/onesub/validate` from the host can claim ownership.
|
|
95
|
+
|
|
96
|
+
You can also call it directly:
|
|
97
|
+
|
|
98
|
+
```ts
|
|
99
|
+
import { fetchAppleSubscriptionStatus } from '@onesub/server';
|
|
100
|
+
|
|
101
|
+
const sub = await fetchAppleSubscriptionStatus(originalTxId, config.apple, { sandbox: false });
|
|
102
|
+
// sub: SubscriptionInfo | null — null on missing creds / 404 / network failure
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### CONSUMPTION_REQUEST response hook
|
|
106
|
+
|
|
107
|
+
When Apple sends a `CONSUMPTION_REQUEST` notification (consumable refund review), without a hook Apple has no usage signal and tends to grant the refund. Provide a hook to PUT consumption info back to `/inApps/v1/transactions/consumption/{txId}`:
|
|
108
|
+
|
|
109
|
+
```ts
|
|
110
|
+
apple: {
|
|
111
|
+
// ...
|
|
112
|
+
consumptionInfoProvider: async (ctx) => ({
|
|
113
|
+
customerConsented: true, // required; false makes Apple ignore the response
|
|
114
|
+
consumptionStatus: 3, // 0=undeclared, 1=not consumed, 2=partial, 3=full
|
|
115
|
+
deliveryStatus: 1, // 0=undeclared, 1=delivered & working, 2=quality issue, ...
|
|
116
|
+
refundPreference: 2, // 0=undeclared, 1=grant, 2=decline, 3=no preference
|
|
117
|
+
// see AppleConsumptionRequest for the full set of optional fields
|
|
118
|
+
}),
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Fire-and-forget; failures are logged but don't block the webhook 200.
|
|
123
|
+
|
|
124
|
+
## Optional Google hooks (`0.8.0+`)
|
|
125
|
+
|
|
126
|
+
```ts
|
|
127
|
+
google: {
|
|
128
|
+
// ...
|
|
129
|
+
// Called when SUBSCRIPTION_PRICE_CHANGE_CONFIRMED (8) arrives — user agreed
|
|
130
|
+
// to a price change; new price applies on next renewal. Useful for analytics.
|
|
131
|
+
onPriceChangeConfirmed: async (ctx) => {
|
|
132
|
+
await analytics.track('price_change_confirmed', ctx);
|
|
133
|
+
},
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
54
137
|
## Schema
|
|
55
138
|
|
|
56
139
|
Canonical Postgres DDL shipped at [`sql/schema.sql`](./sql/schema.sql). Apply with `psql -f` or let `store.initSchema()` run it for you on startup.
|
|
57
140
|
|
|
141
|
+
`store.initSchema()` is **safe to call on every boot** — all DDL is `IF NOT EXISTS`. New columns added in later releases (e.g. `linked_purchase_token`, `auto_resume_time`) ship with `ALTER TABLE IF NOT EXISTS` so existing installs auto-backfill on the next startup.
|
|
142
|
+
|
|
58
143
|
## Security
|
|
59
144
|
|
|
60
145
|
- Apple JWS signature verified end-to-end against **Apple Root CA G3** (as of `0.6.0`)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entitlements abstraction tests.
|
|
3
|
+
*
|
|
4
|
+
* Covers:
|
|
5
|
+
* - evaluateEntitlement helper (subscription / purchase / mixed / none /
|
|
6
|
+
* expired sub / wrong status / consumable excluded)
|
|
7
|
+
* - GET /onesub/entitlement single-check route (404 unknown id, 400 bad input)
|
|
8
|
+
* - GET /onesub/entitlements bulk route
|
|
9
|
+
* - Router not mounted when config.entitlements is absent (404)
|
|
10
|
+
* - getAllByUserId returns multi-product subscriptions (regression for the
|
|
11
|
+
* InMemoryStore change that backs entitlements)
|
|
12
|
+
*/
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=entitlements.test.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entitlements.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/entitlements.test.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG"}
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Entitlements abstraction tests.
|
|
3
|
+
*
|
|
4
|
+
* Covers:
|
|
5
|
+
* - evaluateEntitlement helper (subscription / purchase / mixed / none /
|
|
6
|
+
* expired sub / wrong status / consumable excluded)
|
|
7
|
+
* - GET /onesub/entitlement single-check route (404 unknown id, 400 bad input)
|
|
8
|
+
* - GET /onesub/entitlements bulk route
|
|
9
|
+
* - Router not mounted when config.entitlements is absent (404)
|
|
10
|
+
* - getAllByUserId returns multi-product subscriptions (regression for the
|
|
11
|
+
* InMemoryStore change that backs entitlements)
|
|
12
|
+
*/
|
|
13
|
+
import { describe, it, expect, beforeEach } from 'vitest';
|
|
14
|
+
import express from 'express';
|
|
15
|
+
import { SUBSCRIPTION_STATUS, PURCHASE_TYPE } from '@onesub/shared';
|
|
16
|
+
import { createOneSubMiddleware } from '../index.js';
|
|
17
|
+
import { evaluateEntitlement } from '../routes/entitlements.js';
|
|
18
|
+
import { InMemorySubscriptionStore, InMemoryPurchaseStore } from '../store.js';
|
|
19
|
+
// ── helpers ─────────────────────────────────────────────────────────────────
|
|
20
|
+
const futureExpiry = '2099-01-01T00:00:00.000Z';
|
|
21
|
+
const pastExpiry = '2024-01-01T00:00:00.000Z';
|
|
22
|
+
function sub(overrides) {
|
|
23
|
+
return {
|
|
24
|
+
userId: 'u',
|
|
25
|
+
productId: 'pro_monthly',
|
|
26
|
+
platform: 'apple',
|
|
27
|
+
status: 'active',
|
|
28
|
+
expiresAt: futureExpiry,
|
|
29
|
+
originalTransactionId: `orig_${Math.random()}`,
|
|
30
|
+
purchasedAt: '2026-01-01T00:00:00.000Z',
|
|
31
|
+
willRenew: true,
|
|
32
|
+
...overrides,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function purchase(overrides) {
|
|
36
|
+
return {
|
|
37
|
+
userId: 'u',
|
|
38
|
+
productId: 'lifetime_pass',
|
|
39
|
+
platform: 'apple',
|
|
40
|
+
type: 'non_consumable',
|
|
41
|
+
transactionId: `tx_${Math.random()}`,
|
|
42
|
+
purchasedAt: '2026-01-01T00:00:00.000Z',
|
|
43
|
+
quantity: 1,
|
|
44
|
+
...overrides,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function spinUp(handler) {
|
|
48
|
+
return {
|
|
49
|
+
async get(path) {
|
|
50
|
+
const httpServer = handler.listen(0);
|
|
51
|
+
const port = httpServer.address().port;
|
|
52
|
+
try {
|
|
53
|
+
const resp = await fetch(`http://127.0.0.1:${port}${path}`);
|
|
54
|
+
const text = await resp.text();
|
|
55
|
+
let parsed = text;
|
|
56
|
+
try {
|
|
57
|
+
parsed = JSON.parse(text);
|
|
58
|
+
}
|
|
59
|
+
catch { /* keep as text */ }
|
|
60
|
+
return { status: resp.status, body: parsed };
|
|
61
|
+
}
|
|
62
|
+
finally {
|
|
63
|
+
await new Promise((r) => httpServer.close(() => r()));
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
function buildServer(opts) {
|
|
69
|
+
const store = new InMemorySubscriptionStore();
|
|
70
|
+
const purchaseStore = new InMemoryPurchaseStore();
|
|
71
|
+
const config = {
|
|
72
|
+
apple: { bundleId: 'com.example.app', skipJwsVerification: true },
|
|
73
|
+
database: { url: '' },
|
|
74
|
+
entitlements: opts.entitlements,
|
|
75
|
+
};
|
|
76
|
+
const app = express();
|
|
77
|
+
// createOneSubMiddleware mounts express.json itself, but the entitlement
|
|
78
|
+
// routes are GET-only so it's fine either way.
|
|
79
|
+
const middleware = createOneSubMiddleware({ ...config, store, purchaseStore });
|
|
80
|
+
app.use(middleware);
|
|
81
|
+
return { store, purchaseStore, server: spinUp(app) };
|
|
82
|
+
}
|
|
83
|
+
const PREMIUM = {
|
|
84
|
+
premium: { productIds: ['pro_monthly', 'pro_yearly', 'lifetime_pass'] },
|
|
85
|
+
};
|
|
86
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
87
|
+
// evaluateEntitlement (unit, no HTTP)
|
|
88
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
89
|
+
describe('evaluateEntitlement', () => {
|
|
90
|
+
let store;
|
|
91
|
+
let purchaseStore;
|
|
92
|
+
beforeEach(() => {
|
|
93
|
+
store = new InMemorySubscriptionStore();
|
|
94
|
+
purchaseStore = new InMemoryPurchaseStore();
|
|
95
|
+
});
|
|
96
|
+
it('active subscription matching one of the productIds → entitled', async () => {
|
|
97
|
+
await store.save(sub({ userId: 'u1', productId: 'pro_yearly' }));
|
|
98
|
+
const result = await evaluateEntitlement('u1', PREMIUM.premium, store, purchaseStore);
|
|
99
|
+
expect(result.active).toBe(true);
|
|
100
|
+
expect(result.source).toBe('subscription');
|
|
101
|
+
expect(result.productId).toBe('pro_yearly');
|
|
102
|
+
expect(result.expiresAt).toBe(futureExpiry);
|
|
103
|
+
});
|
|
104
|
+
it('non-consumable purchase matching one of the productIds → entitled', async () => {
|
|
105
|
+
await purchaseStore.savePurchase(purchase({ userId: 'u2', productId: 'lifetime_pass' }));
|
|
106
|
+
const result = await evaluateEntitlement('u2', PREMIUM.premium, store, purchaseStore);
|
|
107
|
+
expect(result.active).toBe(true);
|
|
108
|
+
expect(result.source).toBe('purchase');
|
|
109
|
+
expect(result.productId).toBe('lifetime_pass');
|
|
110
|
+
expect(result.expiresAt).toBeUndefined();
|
|
111
|
+
});
|
|
112
|
+
it('no matching record → not entitled', async () => {
|
|
113
|
+
const result = await evaluateEntitlement('u_none', PREMIUM.premium, store, purchaseStore);
|
|
114
|
+
expect(result).toEqual({ active: false, source: null });
|
|
115
|
+
});
|
|
116
|
+
it('subscription preferred over purchase when both match', async () => {
|
|
117
|
+
await store.save(sub({ userId: 'u3', productId: 'pro_monthly' }));
|
|
118
|
+
await purchaseStore.savePurchase(purchase({ userId: 'u3', productId: 'lifetime_pass' }));
|
|
119
|
+
const result = await evaluateEntitlement('u3', PREMIUM.premium, store, purchaseStore);
|
|
120
|
+
expect(result.source).toBe('subscription');
|
|
121
|
+
expect(result.productId).toBe('pro_monthly');
|
|
122
|
+
});
|
|
123
|
+
it('expired subscription (expiresAt < now) → not entitled even if status=active', async () => {
|
|
124
|
+
await store.save(sub({ userId: 'u4', productId: 'pro_monthly', expiresAt: pastExpiry }));
|
|
125
|
+
const result = await evaluateEntitlement('u4', PREMIUM.premium, store, purchaseStore);
|
|
126
|
+
expect(result.active).toBe(false);
|
|
127
|
+
});
|
|
128
|
+
it('grace_period subscription → entitled (still has valid expiresAt)', async () => {
|
|
129
|
+
await store.save(sub({ userId: 'u5', productId: 'pro_monthly', status: 'grace_period' }));
|
|
130
|
+
const result = await evaluateEntitlement('u5', PREMIUM.premium, store, purchaseStore);
|
|
131
|
+
expect(result.active).toBe(true);
|
|
132
|
+
expect(result.source).toBe('subscription');
|
|
133
|
+
});
|
|
134
|
+
it('on_hold / paused / canceled / expired status → not entitled', async () => {
|
|
135
|
+
for (const status of ['on_hold', 'paused', 'canceled', 'expired']) {
|
|
136
|
+
const localStore = new InMemorySubscriptionStore();
|
|
137
|
+
await localStore.save(sub({ userId: 'u', productId: 'pro_monthly', status }));
|
|
138
|
+
const result = await evaluateEntitlement('u', PREMIUM.premium, localStore, purchaseStore);
|
|
139
|
+
expect(result.active).toBe(false);
|
|
140
|
+
}
|
|
141
|
+
});
|
|
142
|
+
it('consumable purchase is NOT considered for entitlement', async () => {
|
|
143
|
+
await purchaseStore.savePurchase(purchase({
|
|
144
|
+
userId: 'u6',
|
|
145
|
+
productId: 'pro_monthly', // even matching productId
|
|
146
|
+
type: 'consumable',
|
|
147
|
+
}));
|
|
148
|
+
const result = await evaluateEntitlement('u6', PREMIUM.premium, store, purchaseStore);
|
|
149
|
+
expect(result.active).toBe(false);
|
|
150
|
+
});
|
|
151
|
+
it('multi-product subscriptions: returns the first matching active sub', async () => {
|
|
152
|
+
// User has two subs — one for pro_yearly (matches), one for off-premium product (no match)
|
|
153
|
+
await store.save(sub({ userId: 'u7', productId: 'unrelated_product' }));
|
|
154
|
+
await store.save(sub({ userId: 'u7', productId: 'pro_yearly' }));
|
|
155
|
+
const result = await evaluateEntitlement('u7', PREMIUM.premium, store, purchaseStore);
|
|
156
|
+
expect(result.active).toBe(true);
|
|
157
|
+
expect(result.productId).toBe('pro_yearly');
|
|
158
|
+
});
|
|
159
|
+
});
|
|
160
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
161
|
+
// HTTP routes
|
|
162
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
163
|
+
describe('GET /onesub/entitlement', () => {
|
|
164
|
+
it('returns active=true when user has matching active sub', async () => {
|
|
165
|
+
const { store, server } = buildServer({ entitlements: PREMIUM });
|
|
166
|
+
await store.save(sub({ userId: 'u_yes', productId: 'pro_monthly' }));
|
|
167
|
+
const resp = await server.get('/onesub/entitlement?userId=u_yes&id=premium');
|
|
168
|
+
expect(resp.status).toBe(200);
|
|
169
|
+
expect(resp.body.id).toBe('premium');
|
|
170
|
+
expect(resp.body.active).toBe(true);
|
|
171
|
+
expect(resp.body.source).toBe('subscription');
|
|
172
|
+
});
|
|
173
|
+
it('returns active=false when no matching record', async () => {
|
|
174
|
+
const { server } = buildServer({ entitlements: PREMIUM });
|
|
175
|
+
const resp = await server.get('/onesub/entitlement?userId=u_none&id=premium');
|
|
176
|
+
expect(resp.status).toBe(200);
|
|
177
|
+
expect(resp.body.active).toBe(false);
|
|
178
|
+
expect(resp.body.source).toBeNull();
|
|
179
|
+
});
|
|
180
|
+
it('404 + ENTITLEMENT_NOT_FOUND for unknown id', async () => {
|
|
181
|
+
const { server } = buildServer({ entitlements: PREMIUM });
|
|
182
|
+
const resp = await server.get('/onesub/entitlement?userId=u&id=enterprise');
|
|
183
|
+
expect(resp.status).toBe(404);
|
|
184
|
+
expect(resp.body.errorCode).toBe('ENTITLEMENT_NOT_FOUND');
|
|
185
|
+
});
|
|
186
|
+
it('400 INVALID_INPUT when userId or id is missing', async () => {
|
|
187
|
+
const { server } = buildServer({ entitlements: PREMIUM });
|
|
188
|
+
const resp = await server.get('/onesub/entitlement?userId=u');
|
|
189
|
+
expect(resp.status).toBe(400);
|
|
190
|
+
expect(resp.body.errorCode).toBe('INVALID_INPUT');
|
|
191
|
+
});
|
|
192
|
+
});
|
|
193
|
+
describe('GET /onesub/entitlements (bulk)', () => {
|
|
194
|
+
it('evaluates every configured entitlement in one round-trip', async () => {
|
|
195
|
+
const config = {
|
|
196
|
+
premium: { productIds: ['pro_monthly', 'pro_yearly'] },
|
|
197
|
+
promode: { productIds: ['dev_tools_addon'] },
|
|
198
|
+
};
|
|
199
|
+
const { store, server } = buildServer({ entitlements: config });
|
|
200
|
+
await store.save(sub({ userId: 'u_bulk', productId: 'pro_yearly' }));
|
|
201
|
+
const resp = await server.get('/onesub/entitlements?userId=u_bulk');
|
|
202
|
+
expect(resp.status).toBe(200);
|
|
203
|
+
expect(resp.body.entitlements.premium.active).toBe(true);
|
|
204
|
+
expect(resp.body.entitlements.premium.productId).toBe('pro_yearly');
|
|
205
|
+
expect(resp.body.entitlements.promode.active).toBe(false);
|
|
206
|
+
});
|
|
207
|
+
it('returns empty entitlement statuses for a user with nothing', async () => {
|
|
208
|
+
const config = {
|
|
209
|
+
premium: { productIds: ['pro_monthly'] },
|
|
210
|
+
addon: { productIds: ['some_addon'] },
|
|
211
|
+
};
|
|
212
|
+
const { server } = buildServer({ entitlements: config });
|
|
213
|
+
const resp = await server.get('/onesub/entitlements?userId=u_empty');
|
|
214
|
+
expect(resp.body.entitlements.premium.active).toBe(false);
|
|
215
|
+
expect(resp.body.entitlements.addon.active).toBe(false);
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
describe('Entitlement routes are NOT mounted without config', () => {
|
|
219
|
+
it('returns 404 when config.entitlements is absent', async () => {
|
|
220
|
+
const { server } = buildServer({}); // no entitlements
|
|
221
|
+
const resp = await server.get('/onesub/entitlement?userId=u&id=premium');
|
|
222
|
+
expect(resp.status).toBe(404);
|
|
223
|
+
const respBulk = await server.get('/onesub/entitlements?userId=u');
|
|
224
|
+
expect(respBulk.status).toBe(404);
|
|
225
|
+
});
|
|
226
|
+
it('returns 404 when config.entitlements is empty {}', async () => {
|
|
227
|
+
const { server } = buildServer({ entitlements: {} });
|
|
228
|
+
const resp = await server.get('/onesub/entitlement?userId=u&id=premium');
|
|
229
|
+
expect(resp.status).toBe(404);
|
|
230
|
+
});
|
|
231
|
+
});
|
|
232
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
233
|
+
// Store regression: getAllByUserId returns multi-product subs
|
|
234
|
+
// ─────────────────────────────────────────────────────────────────────────────
|
|
235
|
+
describe('InMemorySubscriptionStore — multi-sub per user (entitlement support)', () => {
|
|
236
|
+
it('getAllByUserId returns all subs across productIds, latest first', async () => {
|
|
237
|
+
const store = new InMemorySubscriptionStore();
|
|
238
|
+
await store.save(sub({ userId: 'u', productId: 'pro_monthly', originalTransactionId: 'orig_a' }));
|
|
239
|
+
await store.save(sub({ userId: 'u', productId: 'pro_yearly', originalTransactionId: 'orig_b' }));
|
|
240
|
+
await store.save(sub({ userId: 'u', productId: 'addon', originalTransactionId: 'orig_c' }));
|
|
241
|
+
const all = await store.getAllByUserId('u');
|
|
242
|
+
expect(all.map((s) => s.productId)).toEqual(['addon', 'pro_yearly', 'pro_monthly']);
|
|
243
|
+
});
|
|
244
|
+
it('getByUserId still returns the most recent (legacy contract preserved)', async () => {
|
|
245
|
+
const store = new InMemorySubscriptionStore();
|
|
246
|
+
await store.save(sub({ userId: 'u', productId: 'pro_monthly', originalTransactionId: 'orig_a' }));
|
|
247
|
+
await store.save(sub({ userId: 'u', productId: 'pro_yearly', originalTransactionId: 'orig_b' }));
|
|
248
|
+
const latest = await store.getByUserId('u');
|
|
249
|
+
expect(latest?.productId).toBe('pro_yearly');
|
|
250
|
+
});
|
|
251
|
+
it('save() with same originalTransactionId replaces prior record (no duplicates)', async () => {
|
|
252
|
+
const store = new InMemorySubscriptionStore();
|
|
253
|
+
await store.save(sub({
|
|
254
|
+
userId: 'u', productId: 'pro_monthly', originalTransactionId: 'orig_x',
|
|
255
|
+
status: 'active',
|
|
256
|
+
}));
|
|
257
|
+
await store.save(sub({
|
|
258
|
+
userId: 'u', productId: 'pro_monthly', originalTransactionId: 'orig_x',
|
|
259
|
+
status: 'canceled',
|
|
260
|
+
}));
|
|
261
|
+
const all = await store.getAllByUserId('u');
|
|
262
|
+
expect(all).toHaveLength(1);
|
|
263
|
+
expect(all[0].status).toBe(SUBSCRIPTION_STATUS.CANCELED);
|
|
264
|
+
});
|
|
265
|
+
});
|
|
266
|
+
// keep the import honest
|
|
267
|
+
PURCHASE_TYPE;
|
|
268
|
+
//# sourceMappingURL=entitlements.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entitlements.test.js","sourceRoot":"","sources":["../../src/__tests__/entitlements.test.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -49,6 +49,7 @@ export type { SubscriptionStore, PurchaseStore } from './store.js';
|
|
|
49
49
|
export { PostgresSubscriptionStore, PostgresPurchaseStore } from './stores/postgres.js';
|
|
50
50
|
export { validateAppleReceipt, fetchAppleSubscriptionStatus } from './providers/apple.js';
|
|
51
51
|
export { validateGoogleReceipt } from './providers/google.js';
|
|
52
|
+
export { evaluateEntitlement } from './routes/entitlements.js';
|
|
52
53
|
export { setLogger, log } from './logger.js';
|
|
53
54
|
export default createOneSubMiddleware;
|
|
54
55
|
//# 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":"AAAA,OAAO,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAC1C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAGzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AASnE;;GAEG;AACH,MAAM,WAAW,sBAAuB,SAAQ,kBAAkB;IAChE;;;OAGG;IACH,KAAK,CAAC,EAAE,iBAAiB,CAAC;IAC1B;;;;OAIG;IACH,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,sBAAsB,GAAG,MAAM,CAmC7E;AAED;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,sBAAsB,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAW7F;AAGD,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAC9E,YAAY,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACnE,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAGxF,OAAO,EAAE,oBAAoB,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAI9D,OAAO,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAI/D,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAG7C,eAAe,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -6,6 +6,7 @@ import { createStatusRouter } from './routes/status.js';
|
|
|
6
6
|
import { createWebhookRouter } from './routes/webhook.js';
|
|
7
7
|
import { createPurchaseRouter } from './routes/purchase.js';
|
|
8
8
|
import { createAdminRouter } from './routes/admin.js';
|
|
9
|
+
import { createEntitlementRouter } from './routes/entitlements.js';
|
|
9
10
|
import { setLogger } from './logger.js';
|
|
10
11
|
/**
|
|
11
12
|
* Create an Express Router with all OneSub routes mounted.
|
|
@@ -46,6 +47,10 @@ export function createOneSubMiddleware(config) {
|
|
|
46
47
|
const adminRouter = createAdminRouter(config, purchaseStore);
|
|
47
48
|
if (adminRouter)
|
|
48
49
|
router.use(adminRouter);
|
|
50
|
+
// Entitlement routes — only mounted when config.entitlements is set
|
|
51
|
+
const entitlementRouter = createEntitlementRouter(config, store, purchaseStore);
|
|
52
|
+
if (entitlementRouter)
|
|
53
|
+
router.use(entitlementRouter);
|
|
49
54
|
return router;
|
|
50
55
|
}
|
|
51
56
|
/**
|
|
@@ -71,6 +76,9 @@ export { PostgresSubscriptionStore, PostgresPurchaseStore } from './stores/postg
|
|
|
71
76
|
// Provider functions for direct (non-HTTP) usage
|
|
72
77
|
export { validateAppleReceipt, fetchAppleSubscriptionStatus } from './providers/apple.js';
|
|
73
78
|
export { validateGoogleReceipt } from './providers/google.js';
|
|
79
|
+
// Entitlement evaluator — exported so hosts can evaluate entitlements
|
|
80
|
+
// in-process (e.g. from non-HTTP background workers, custom routes).
|
|
81
|
+
export { evaluateEntitlement } from './routes/entitlements.js';
|
|
74
82
|
// Logger plumbing — expose so non-middleware callers (direct provider use)
|
|
75
83
|
// can still redirect logs.
|
|
76
84
|
export { setLogger, log } from './logger.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,EAAE,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAE1C,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAE9E,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAmBxC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,sBAAsB,CAAC,MAA8B;IACnE,SAAS,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;IAEzB,0EAA0E;IAC1E,2EAA2E;IAC3E,0EAA0E;IAC1E,2DAA2D;IAC3D,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,IAAI,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,YAAY,EAAE,CAAC;QACpG,MAAM,IAAI,KAAK,CACb,iIAAiI,CAClI,CAAC;IACJ,CAAC;IAED,MAAM,KAAK,GAAsB,MAAM,CAAC,KAAK,IAAI,IAAI,yBAAyB,EAAE,CAAC;IACjF,MAAM,aAAa,GAAkB,MAAM,CAAC,aAAa,IAAI,IAAI,qBAAqB,EAAE,CAAC;IAEzF,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC;IAExB,kFAAkF;IAClF,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC;IAE5C,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC;IAChD,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC;IACtC,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,MAAM,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC;IAC9D,MAAM,CAAC,GAAG,CAAC,oBAAoB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC;IAExD,6DAA6D;IAC7D,MAAM,WAAW,GAAG,iBAAiB,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC7D,IAAI,WAAW;QAAE,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;IAEzC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,kBAAkB,CAAC,MAA8B;IAC/D,MAAM,GAAG,GAAG,OAAO,EAAE,CAAC;IAEtB,eAAe;IACf,GAAG,CAAC,GAAG,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,EAAE;QAC/B,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,GAAG,CAAC,GAAG,CAAC,sBAAsB,CAAC,MAAM,CAAC,CAAC,CAAC;IAExC,OAAO,GAAG,CAAC;AACb,CAAC;AAED,mEAAmE;AACnE,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAE9E,OAAO,EAAE,yBAAyB,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAExF,iDAAiD;AACjD,OAAO,EAAE,oBAAoB,EAAE,4BAA4B,EAAE,MAAM,sBAAsB,CAAC;AAC1F,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAE9D,2EAA2E;AAC3E,2BAA2B;AAC3B,OAAO,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAE7C,yCAAyC;AACzC,eAAe,sBAAsB,CAAC;AAEtC,6CAA6C;AAC7C,mEAAmE;AACnE,MAAM,MAAM,GACV,OAAO,OAAO,KAAK,WAAW;IAC9B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI;IACvB,IAAI,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;AAElF,IAAI,MAAM,EAAE,CAAC;IACX,MAAM,MAAM,GAA2B;QACrC,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;YACnC,CAAC,CAAC;gBACE,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;gBACxC,YAAY,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;gBAChD,KAAK,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC;gBAClC,QAAQ,EAAE,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;gBACxC,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC;aAC7C;YACH,CAAC,CAAC,SAAS;QACb,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;YACxC,CAAC,CAAC;gBACE,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC;gBAC/C,iBAAiB,EAAE,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC;aAC7D;YACH,CAAC,CAAC,SAAS;QACb,QAAQ,EAAE;YACR,GAAG,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,EAAE;SACvC;QACD,aAAa,EAAE,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC;KAC7C,CAAC;IAEF,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC;IAEpF,kBAAkB,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,GAAG,EAAE;QAC3C,OAAO,CAAC,GAAG,CAAC,qCAAqC,IAAI,EAAE,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import type { Entitlement, EntitlementStatus, OneSubServerConfig, PurchaseInfo, SubscriptionInfo } from '@onesub/shared';
|
|
3
|
+
import type { PurchaseStore, SubscriptionStore } from '../store.js';
|
|
4
|
+
/**
|
|
5
|
+
* Evaluate a single entitlement for a user.
|
|
6
|
+
*
|
|
7
|
+
* A user is entitled when EITHER condition holds for any productId in
|
|
8
|
+
* `entitlement.productIds`:
|
|
9
|
+
* 1. an active subscription (status === active|grace_period AND
|
|
10
|
+
* expiresAt > now) for that productId exists
|
|
11
|
+
* 2. a non-consumable purchase for that productId exists
|
|
12
|
+
*
|
|
13
|
+
* Consumables are intentionally excluded — they grant a one-time resource,
|
|
14
|
+
* not an ongoing right.
|
|
15
|
+
*
|
|
16
|
+
* Subscription is preferred over purchase when both match (subs carry an
|
|
17
|
+
* expiry; non-consumables are forever) so the source field skews toward the
|
|
18
|
+
* more "interesting" signal for ops/analytics.
|
|
19
|
+
*/
|
|
20
|
+
export declare function evaluateEntitlement(userId: string, entitlement: Entitlement, store: SubscriptionStore, purchaseStore: PurchaseStore): Promise<EntitlementStatus>;
|
|
21
|
+
export declare function createEntitlementRouter(config: OneSubServerConfig, store: SubscriptionStore, purchaseStore: PurchaseStore): Router | null;
|
|
22
|
+
export type { Entitlement, EntitlementStatus, PurchaseInfo, SubscriptionInfo };
|
|
23
|
+
//# sourceMappingURL=entitlements.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entitlements.d.ts","sourceRoot":"","sources":["../../src/routes/entitlements.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC,OAAO,KAAK,EACV,WAAW,EAEX,iBAAiB,EAGjB,kBAAkB,EAClB,YAAY,EACZ,gBAAgB,EACjB,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAIpE;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,mBAAmB,CACvC,MAAM,EAAE,MAAM,EACd,WAAW,EAAE,WAAW,EACxB,KAAK,EAAE,iBAAiB,EACxB,aAAa,EAAE,aAAa,GAC3B,OAAO,CAAC,iBAAiB,CAAC,CAkC5B;AAKD,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,kBAAkB,EAC1B,KAAK,EAAE,iBAAiB,EACxB,aAAa,EAAE,aAAa,GAC3B,MAAM,GAAG,IAAI,CA0Ef;AAID,YAAY,EAAE,WAAW,EAAE,iBAAiB,EAAE,YAAY,EAAE,gBAAgB,EAAE,CAAC"}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { ROUTES, SUBSCRIPTION_STATUS, ONESUB_ERROR_CODE, PURCHASE_TYPE } from '@onesub/shared';
|
|
4
|
+
import { log } from '../logger.js';
|
|
5
|
+
import { sendError } from '../errors.js';
|
|
6
|
+
/**
|
|
7
|
+
* Evaluate a single entitlement for a user.
|
|
8
|
+
*
|
|
9
|
+
* A user is entitled when EITHER condition holds for any productId in
|
|
10
|
+
* `entitlement.productIds`:
|
|
11
|
+
* 1. an active subscription (status === active|grace_period AND
|
|
12
|
+
* expiresAt > now) for that productId exists
|
|
13
|
+
* 2. a non-consumable purchase for that productId exists
|
|
14
|
+
*
|
|
15
|
+
* Consumables are intentionally excluded — they grant a one-time resource,
|
|
16
|
+
* not an ongoing right.
|
|
17
|
+
*
|
|
18
|
+
* Subscription is preferred over purchase when both match (subs carry an
|
|
19
|
+
* expiry; non-consumables are forever) so the source field skews toward the
|
|
20
|
+
* more "interesting" signal for ops/analytics.
|
|
21
|
+
*/
|
|
22
|
+
export async function evaluateEntitlement(userId, entitlement, store, purchaseStore) {
|
|
23
|
+
const productIdSet = new Set(entitlement.productIds);
|
|
24
|
+
const now = Date.now();
|
|
25
|
+
// 1. Check subscriptions first (richer signal — has expiry).
|
|
26
|
+
const subs = await store.getAllByUserId(userId);
|
|
27
|
+
for (const sub of subs) {
|
|
28
|
+
if (!productIdSet.has(sub.productId))
|
|
29
|
+
continue;
|
|
30
|
+
const statusAllows = sub.status === SUBSCRIPTION_STATUS.ACTIVE ||
|
|
31
|
+
sub.status === SUBSCRIPTION_STATUS.GRACE_PERIOD;
|
|
32
|
+
if (!statusAllows)
|
|
33
|
+
continue;
|
|
34
|
+
if (new Date(sub.expiresAt).getTime() <= now)
|
|
35
|
+
continue;
|
|
36
|
+
return {
|
|
37
|
+
active: true,
|
|
38
|
+
source: 'subscription',
|
|
39
|
+
productId: sub.productId,
|
|
40
|
+
expiresAt: sub.expiresAt,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
// 2. Check non-consumable purchases.
|
|
44
|
+
const purchases = await purchaseStore.getPurchasesByUserId(userId);
|
|
45
|
+
for (const p of purchases) {
|
|
46
|
+
if (p.type !== PURCHASE_TYPE.NON_CONSUMABLE)
|
|
47
|
+
continue;
|
|
48
|
+
if (!productIdSet.has(p.productId))
|
|
49
|
+
continue;
|
|
50
|
+
return {
|
|
51
|
+
active: true,
|
|
52
|
+
source: 'purchase',
|
|
53
|
+
productId: p.productId,
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
return { active: false, source: null };
|
|
57
|
+
}
|
|
58
|
+
const userIdSchema = z.string().min(1).max(256);
|
|
59
|
+
const entitlementIdSchema = z.string().min(1).max(128);
|
|
60
|
+
export function createEntitlementRouter(config, store, purchaseStore) {
|
|
61
|
+
// Only mount when entitlements are configured. Without this guard, the
|
|
62
|
+
// routes would always 503 — better to make the absence loud (404 from
|
|
63
|
+
// express) so misconfiguration is obvious during dev.
|
|
64
|
+
if (!config.entitlements || Object.keys(config.entitlements).length === 0) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
const entitlements = config.entitlements;
|
|
68
|
+
const router = Router();
|
|
69
|
+
/**
|
|
70
|
+
* GET /onesub/entitlement?userId=&id=premium
|
|
71
|
+
* Single entitlement check.
|
|
72
|
+
*/
|
|
73
|
+
router.get(ROUTES.ENTITLEMENT, async (req, res) => {
|
|
74
|
+
let userId;
|
|
75
|
+
let id;
|
|
76
|
+
try {
|
|
77
|
+
userId = userIdSchema.parse(req.query['userId']);
|
|
78
|
+
id = entitlementIdSchema.parse(req.query['id']);
|
|
79
|
+
}
|
|
80
|
+
catch {
|
|
81
|
+
sendError(res, 400, ONESUB_ERROR_CODE.INVALID_INPUT, 'userId and id are required');
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
const entitlement = entitlements[id];
|
|
85
|
+
if (!entitlement) {
|
|
86
|
+
sendError(res, 404, ONESUB_ERROR_CODE.ENTITLEMENT_NOT_FOUND, `Unknown entitlement: ${id}`);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
try {
|
|
90
|
+
const status = await evaluateEntitlement(userId, entitlement, store, purchaseStore);
|
|
91
|
+
const response = { id, ...status };
|
|
92
|
+
res.status(200).json(response);
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
log.error('[onesub/entitlement] evaluation error:', err);
|
|
96
|
+
sendError(res, 500, ONESUB_ERROR_CODE.STORE_ERROR, 'Internal server error');
|
|
97
|
+
}
|
|
98
|
+
});
|
|
99
|
+
/**
|
|
100
|
+
* GET /onesub/entitlements?userId=
|
|
101
|
+
* Evaluate every configured entitlement in one round-trip — useful on
|
|
102
|
+
* app launch / login when the host wants the full entitlement map.
|
|
103
|
+
*/
|
|
104
|
+
router.get(ROUTES.ENTITLEMENTS, async (req, res) => {
|
|
105
|
+
let userId;
|
|
106
|
+
try {
|
|
107
|
+
userId = userIdSchema.parse(req.query['userId']);
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
sendError(res, 400, ONESUB_ERROR_CODE.INVALID_INPUT, 'userId is required');
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
try {
|
|
114
|
+
const entries = await Promise.all(Object.entries(entitlements).map(async ([id, entitlement]) => {
|
|
115
|
+
const status = await evaluateEntitlement(userId, entitlement, store, purchaseStore);
|
|
116
|
+
return [id, status];
|
|
117
|
+
}));
|
|
118
|
+
const response = {
|
|
119
|
+
entitlements: Object.fromEntries(entries),
|
|
120
|
+
};
|
|
121
|
+
res.status(200).json(response);
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
log.error('[onesub/entitlements] evaluation error:', err);
|
|
125
|
+
sendError(res, 500, ONESUB_ERROR_CODE.STORE_ERROR, 'Internal server error', { entitlements: {} });
|
|
126
|
+
}
|
|
127
|
+
});
|
|
128
|
+
return router;
|
|
129
|
+
}
|
|
130
|
+
//# sourceMappingURL=entitlements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entitlements.js","sourceRoot":"","sources":["../../src/routes/entitlements.ts"],"names":[],"mappings":"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"}
|
package/dist/store.d.ts
CHANGED
|
@@ -6,8 +6,23 @@ import type { SubscriptionInfo, PurchaseInfo } from '@onesub/shared';
|
|
|
6
6
|
*/
|
|
7
7
|
export interface SubscriptionStore {
|
|
8
8
|
save(sub: SubscriptionInfo): Promise<void>;
|
|
9
|
+
/**
|
|
10
|
+
* Returns the most recent subscription for the user, or null if none exist.
|
|
11
|
+
* Use this for legacy single-product checks (`/onesub/status`); for
|
|
12
|
+
* entitlements that span multiple productIds, prefer `getAllByUserId`.
|
|
13
|
+
*/
|
|
9
14
|
getByUserId(userId: string): Promise<SubscriptionInfo | null>;
|
|
10
15
|
getByTransactionId(txId: string): Promise<SubscriptionInfo | null>;
|
|
16
|
+
/**
|
|
17
|
+
* Returns every subscription record for the user (across all productIds),
|
|
18
|
+
* ordered most-recent-first. Used by entitlement evaluation, which needs to
|
|
19
|
+
* see all of a user's active subscriptions to decide whether any of them
|
|
20
|
+
* grants the requested entitlement.
|
|
21
|
+
*
|
|
22
|
+
* Implementations: in-memory currently coalesces by userId so this returns
|
|
23
|
+
* at most one row; Postgres returns the full history.
|
|
24
|
+
*/
|
|
25
|
+
getAllByUserId(userId: string): Promise<SubscriptionInfo[]>;
|
|
11
26
|
}
|
|
12
27
|
/**
|
|
13
28
|
* In-memory implementation — suitable for development and testing.
|
|
@@ -18,6 +33,7 @@ export declare class InMemorySubscriptionStore implements SubscriptionStore {
|
|
|
18
33
|
private readonly byTransactionId;
|
|
19
34
|
save(sub: SubscriptionInfo): Promise<void>;
|
|
20
35
|
getByUserId(userId: string): Promise<SubscriptionInfo | null>;
|
|
36
|
+
getAllByUserId(userId: string): Promise<SubscriptionInfo[]>;
|
|
21
37
|
getByTransactionId(txId: string): Promise<SubscriptionInfo | null>;
|
|
22
38
|
}
|
|
23
39
|
/**
|
package/dist/store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAErE;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC9D,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAErE;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3C;;;;OAIG;IACH,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC9D,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACnE;;;;;;;;OAQG;IACH,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;CAC7D;AAED;;;GAGG;AACH,qBAAa,yBAA0B,YAAW,iBAAiB;IAIjE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAyC;IAClE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAuC;IAEjE,IAAI,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAW1C,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAK7D,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAI3D,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;CAGzE;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,YAAY,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpD,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAC9D,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;IACvE,4EAA4E;IAC5E,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClE;;;;OAIG;IACH,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACpE;;;;;;OAMG;IACH,6BAA6B,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvE;;;;;;;OAOG;IACH,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC9E;AAED;;;GAGG;AACH,qBAAa,qBAAsB,YAAW,aAAa;IACzD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAmC;IACnE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAqC;IAExD,YAAY,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBnD,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAI7D,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAItE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAMjE,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAkB5E,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAWnE,6BAA6B,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;CAW7E"}
|
package/dist/store.js
CHANGED
|
@@ -3,14 +3,26 @@
|
|
|
3
3
|
* Data is lost on process restart.
|
|
4
4
|
*/
|
|
5
5
|
export class InMemorySubscriptionStore {
|
|
6
|
+
// Multiple records per user (different originalTransactionIds) — required
|
|
7
|
+
// for entitlement evaluation across multiple productIds. Ordering is
|
|
8
|
+
// last-written-first so getByUserId returns "most recent" naturally.
|
|
6
9
|
byUserId = new Map();
|
|
7
10
|
byTransactionId = new Map();
|
|
8
11
|
async save(sub) {
|
|
9
|
-
this.byUserId.set(sub.userId, sub);
|
|
10
12
|
this.byTransactionId.set(sub.originalTransactionId, sub);
|
|
13
|
+
const existing = this.byUserId.get(sub.userId) ?? [];
|
|
14
|
+
// Replace any prior record with the same originalTransactionId, then
|
|
15
|
+
// unshift to the front so the latest write is index 0 (= getByUserId result).
|
|
16
|
+
const filtered = existing.filter((s) => s.originalTransactionId !== sub.originalTransactionId);
|
|
17
|
+
filtered.unshift(sub);
|
|
18
|
+
this.byUserId.set(sub.userId, filtered);
|
|
11
19
|
}
|
|
12
20
|
async getByUserId(userId) {
|
|
13
|
-
|
|
21
|
+
const list = this.byUserId.get(userId);
|
|
22
|
+
return list?.[0] ?? null;
|
|
23
|
+
}
|
|
24
|
+
async getAllByUserId(userId) {
|
|
25
|
+
return [...(this.byUserId.get(userId) ?? [])];
|
|
14
26
|
}
|
|
15
27
|
async getByTransactionId(txId) {
|
|
16
28
|
return this.byTransactionId.get(txId) ?? null;
|
package/dist/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -38,6 +38,13 @@ export declare class PostgresSubscriptionStore implements SubscriptionStore {
|
|
|
38
38
|
* status change is always returned when a user has multiple subscriptions.
|
|
39
39
|
*/
|
|
40
40
|
getByUserId(userId: string): Promise<SubscriptionInfo | null>;
|
|
41
|
+
/**
|
|
42
|
+
* Returns every subscription record for the user (across all productIds),
|
|
43
|
+
* ordered most-recent-first. Used by entitlement evaluation, which needs to
|
|
44
|
+
* see all of a user's active subscriptions to decide whether any of them
|
|
45
|
+
* grants the requested entitlement.
|
|
46
|
+
*/
|
|
47
|
+
getAllByUserId(userId: string): Promise<SubscriptionInfo[]>;
|
|
41
48
|
/**
|
|
42
49
|
* Returns the subscription identified by `originalTransactionId` (the
|
|
43
50
|
* table primary key), or `null` if it does not exist.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/stores/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGpE;;;;;;;;;;;;;GAaG;AACH,qBAAa,yBAA0B,YAAW,iBAAiB;IAIrD,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAF7C,OAAO,CAAC,WAAW,CAA2C;gBAEjC,gBAAgB,EAAE,MAAM;IAErD,OAAO,CAAC,OAAO;IAkBf;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAOjC;;;;OAIG;IACG,IAAI,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAkChD;;;;;;OAMG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAanE;;;OAGG;IACG,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAWxE,uDAAuD;IACjD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAO7B;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,qBAAsB,YAAW,aAAa;IAG7C,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAF7C,OAAO,CAAC,WAAW,CAA2C;gBAEjC,gBAAgB,EAAE,MAAM;IAErD,OAAO,CAAC,OAAO;IAgBf;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,YAAY,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAyCnD,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAY7D,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAWtE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAYjE,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAS5E,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASnE,6BAA6B,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAS5E,uDAAuD;IACjD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAO7B"}
|
|
1
|
+
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/stores/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAGpE;;;;;;;;;;;;;GAaG;AACH,qBAAa,yBAA0B,YAAW,iBAAiB;IAIrD,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAF7C,OAAO,CAAC,WAAW,CAA2C;gBAEjC,gBAAgB,EAAE,MAAM;IAErD,OAAO,CAAC,OAAO;IAkBf;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAOjC;;;;OAIG;IACG,IAAI,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAkChD;;;;;;OAMG;IACG,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAanE;;;;;OAKG;IACG,cAAc,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;IAYjE;;;OAGG;IACG,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAWxE,uDAAuD;IACjD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAO7B;AAED;;;;;;;;;;;;GAYG;AACH,qBAAa,qBAAsB,YAAW,aAAa;IAG7C,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAF7C,OAAO,CAAC,WAAW,CAA2C;gBAEjC,gBAAgB,EAAE,MAAM;IAErD,OAAO,CAAC,OAAO;IAgBf;;;OAGG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAO3B,YAAY,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAyCnD,oBAAoB,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;IAY7D,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAWtE,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAYjE,gBAAgB,CAAC,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAS5E,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IASnE,6BAA6B,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAS5E,uDAAuD;IACjD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAO7B"}
|
package/dist/stores/postgres.js
CHANGED
|
@@ -96,6 +96,20 @@ export class PostgresSubscriptionStore {
|
|
|
96
96
|
LIMIT 1`, [userId]);
|
|
97
97
|
return result.rows.length > 0 ? rowToSubscriptionInfo(result.rows[0]) : null;
|
|
98
98
|
}
|
|
99
|
+
/**
|
|
100
|
+
* Returns every subscription record for the user (across all productIds),
|
|
101
|
+
* ordered most-recent-first. Used by entitlement evaluation, which needs to
|
|
102
|
+
* see all of a user's active subscriptions to decide whether any of them
|
|
103
|
+
* grants the requested entitlement.
|
|
104
|
+
*/
|
|
105
|
+
async getAllByUserId(userId) {
|
|
106
|
+
const pool = await this.getPool();
|
|
107
|
+
const result = await pool.query(`SELECT *
|
|
108
|
+
FROM onesub_subscriptions
|
|
109
|
+
WHERE user_id = $1
|
|
110
|
+
ORDER BY updated_at DESC`, [userId]);
|
|
111
|
+
return result.rows.map(rowToSubscriptionInfo);
|
|
112
|
+
}
|
|
99
113
|
/**
|
|
100
114
|
* Returns the subscription identified by `originalTransactionId` (the
|
|
101
115
|
* table primary key), or `null` if it does not exist.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres.js","sourceRoot":"","sources":["../../src/stores/postgres.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"postgres.js","sourceRoot":"","sources":["../../src/stores/postgres.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onesub/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.0",
|
|
4
4
|
"description": "Server-side receipt validation middleware for react-native-iap. Apple StoreKit 2 + Google Play Billing. One line.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -41,7 +41,7 @@
|
|
|
41
41
|
},
|
|
42
42
|
"license": "MIT",
|
|
43
43
|
"dependencies": {
|
|
44
|
-
"@onesub/shared": "0.
|
|
44
|
+
"@onesub/shared": "0.6.0",
|
|
45
45
|
"jose": "^6.2.2",
|
|
46
46
|
"zod": "^4.3.6"
|
|
47
47
|
},
|