@onesub/server 0.1.0 → 0.2.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/dist/index.d.ts +11 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -3
- package/dist/index.js.map +1 -1
- package/dist/routes/purchase.d.ts +5 -0
- package/dist/routes/purchase.d.ts.map +1 -0
- package/dist/routes/purchase.js +176 -0
- package/dist/routes/purchase.js.map +1 -0
- package/dist/store.d.ts +23 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +26 -0
- package/dist/store.js.map +1 -1
- package/dist/stores/postgres.d.ts +32 -2
- package/dist/stores/postgres.d.ts.map +1 -1
- package/dist/stores/postgres.js +119 -0
- package/dist/stores/postgres.js.map +1 -1
- package/package.json +4 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import express, { Router } from 'express';
|
|
2
2
|
import type { OneSubServerConfig } from '@onesub/shared';
|
|
3
|
-
import type { SubscriptionStore } from './store.js';
|
|
3
|
+
import type { SubscriptionStore, PurchaseStore } from './store.js';
|
|
4
4
|
/**
|
|
5
|
-
* Extended config with optional pluggable
|
|
5
|
+
* Extended config with optional pluggable stores.
|
|
6
6
|
*/
|
|
7
7
|
export interface OneSubMiddlewareConfig extends OneSubServerConfig {
|
|
8
8
|
/**
|
|
@@ -10,6 +10,12 @@ export interface OneSubMiddlewareConfig extends OneSubServerConfig {
|
|
|
10
10
|
* For production, provide a PostgreSQL or Redis backed implementation.
|
|
11
11
|
*/
|
|
12
12
|
store?: SubscriptionStore;
|
|
13
|
+
/**
|
|
14
|
+
* Custom purchase store for consumables and non-consumables.
|
|
15
|
+
* Defaults to InMemoryPurchaseStore.
|
|
16
|
+
* For production, provide a PostgreSQL backed implementation.
|
|
17
|
+
*/
|
|
18
|
+
purchaseStore?: PurchaseStore;
|
|
13
19
|
}
|
|
14
20
|
/**
|
|
15
21
|
* Create an Express Router with all OneSub routes mounted.
|
|
@@ -38,9 +44,9 @@ export declare function createOneSubMiddleware(config: OneSubMiddlewareConfig):
|
|
|
38
44
|
* ```
|
|
39
45
|
*/
|
|
40
46
|
export declare function createOneSubServer(config: OneSubMiddlewareConfig): ReturnType<typeof express>;
|
|
41
|
-
export { InMemorySubscriptionStore } from './store.js';
|
|
42
|
-
export type { SubscriptionStore } from './store.js';
|
|
43
|
-
export { PostgresSubscriptionStore } from './stores/postgres.js';
|
|
47
|
+
export { InMemorySubscriptionStore, InMemoryPurchaseStore } from './store.js';
|
|
48
|
+
export type { SubscriptionStore, PurchaseStore } from './store.js';
|
|
49
|
+
export { PostgresSubscriptionStore, PostgresPurchaseStore } from './stores/postgres.js';
|
|
44
50
|
export { validateAppleReceipt } from './providers/apple.js';
|
|
45
51
|
export { validateGoogleReceipt } from './providers/google.js';
|
|
46
52
|
export default createOneSubMiddleware;
|
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,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;AAMnE;;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,CAe7E;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,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AAG9D,eAAe,sBAAsB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import express, { Router } from 'express';
|
|
2
2
|
import { DEFAULT_PORT } from '@onesub/shared';
|
|
3
|
-
import { InMemorySubscriptionStore } from './store.js';
|
|
3
|
+
import { InMemorySubscriptionStore, InMemoryPurchaseStore } from './store.js';
|
|
4
4
|
import { createValidateRouter } from './routes/validate.js';
|
|
5
5
|
import { createStatusRouter } from './routes/status.js';
|
|
6
6
|
import { createWebhookRouter } from './routes/webhook.js';
|
|
7
|
+
import { createPurchaseRouter } from './routes/purchase.js';
|
|
7
8
|
/**
|
|
8
9
|
* Create an Express Router with all OneSub routes mounted.
|
|
9
10
|
*
|
|
@@ -23,12 +24,14 @@ import { createWebhookRouter } from './routes/webhook.js';
|
|
|
23
24
|
*/
|
|
24
25
|
export function createOneSubMiddleware(config) {
|
|
25
26
|
const store = config.store ?? new InMemorySubscriptionStore();
|
|
27
|
+
const purchaseStore = config.purchaseStore ?? new InMemoryPurchaseStore();
|
|
26
28
|
const router = Router();
|
|
27
29
|
// Parse JSON bodies for all OneSub routes (50 kb cap to prevent payload flooding)
|
|
28
30
|
router.use(express.json({ limit: '50kb' }));
|
|
29
31
|
router.use(createValidateRouter(config, store));
|
|
30
32
|
router.use(createStatusRouter(store));
|
|
31
33
|
router.use(createWebhookRouter(config, store));
|
|
34
|
+
router.use(createPurchaseRouter(config, purchaseStore));
|
|
32
35
|
return router;
|
|
33
36
|
}
|
|
34
37
|
/**
|
|
@@ -49,8 +52,8 @@ export function createOneSubServer(config) {
|
|
|
49
52
|
return app;
|
|
50
53
|
}
|
|
51
54
|
// Named re-exports for consumers who want to bring their own store
|
|
52
|
-
export { InMemorySubscriptionStore } from './store.js';
|
|
53
|
-
export { PostgresSubscriptionStore } from './stores/postgres.js';
|
|
55
|
+
export { InMemorySubscriptionStore, InMemoryPurchaseStore } from './store.js';
|
|
56
|
+
export { PostgresSubscriptionStore, PostgresPurchaseStore } from './stores/postgres.js';
|
|
54
57
|
// Provider functions for direct (non-HTTP) usage
|
|
55
58
|
export { validateAppleReceipt } from './providers/apple.js';
|
|
56
59
|
export { validateGoogleReceipt } from './providers/google.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,MAAM,YAAY,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import type { OneSubServerConfig } from '@onesub/shared';
|
|
3
|
+
import type { PurchaseStore } from '../store.js';
|
|
4
|
+
export declare function createPurchaseRouter(config: OneSubServerConfig, purchaseStore: PurchaseStore): Router;
|
|
5
|
+
//# sourceMappingURL=purchase.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"purchase.d.ts","sourceRoot":"","sources":["../../src/routes/purchase.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC,OAAO,KAAK,EAIV,kBAAkB,EACnB,MAAM,gBAAgB,CAAC;AAExB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAiBjD,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,kBAAkB,EAC1B,aAAa,EAAE,aAAa,GAC3B,MAAM,CA2KR"}
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import { z } from 'zod';
|
|
3
|
+
import { ROUTES, PURCHASE_TYPE } from '@onesub/shared';
|
|
4
|
+
import { validateAppleReceipt } from '../providers/apple.js';
|
|
5
|
+
import { validateGoogleReceipt } from '../providers/google.js';
|
|
6
|
+
const validatePurchaseSchema = z.object({
|
|
7
|
+
platform: z.enum(['apple', 'google']),
|
|
8
|
+
receipt: z.string().min(1).max(10000),
|
|
9
|
+
userId: z.string().min(1).max(256),
|
|
10
|
+
productId: z.string().min(1).max(256),
|
|
11
|
+
type: z.enum([PURCHASE_TYPE.CONSUMABLE, PURCHASE_TYPE.NON_CONSUMABLE]),
|
|
12
|
+
});
|
|
13
|
+
const purchaseStatusQuerySchema = z.object({
|
|
14
|
+
userId: z.string().min(1).max(256),
|
|
15
|
+
productId: z.string().min(1).max(256).optional(),
|
|
16
|
+
});
|
|
17
|
+
export function createPurchaseRouter(config, purchaseStore) {
|
|
18
|
+
const router = Router();
|
|
19
|
+
/**
|
|
20
|
+
* POST /onesub/purchase/validate
|
|
21
|
+
*
|
|
22
|
+
* Validate a receipt for a consumable or non-consumable purchase.
|
|
23
|
+
* - Non-consumables: rejected if the user already owns the product.
|
|
24
|
+
* - Consumables: always recorded (multiple purchases allowed).
|
|
25
|
+
*/
|
|
26
|
+
router.post(ROUTES.VALIDATE_PURCHASE, async (req, res) => {
|
|
27
|
+
let body;
|
|
28
|
+
try {
|
|
29
|
+
body = validatePurchaseSchema.parse(req.body);
|
|
30
|
+
}
|
|
31
|
+
catch (err) {
|
|
32
|
+
if (err instanceof z.ZodError) {
|
|
33
|
+
const response = {
|
|
34
|
+
valid: false,
|
|
35
|
+
purchase: null,
|
|
36
|
+
error: err.issues.map((e) => e.message).join(', '),
|
|
37
|
+
};
|
|
38
|
+
res.status(400).json(response);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
43
|
+
const { platform, receipt, userId, productId, type } = body;
|
|
44
|
+
try {
|
|
45
|
+
// Non-consumable duplicate check
|
|
46
|
+
if (type === PURCHASE_TYPE.NON_CONSUMABLE) {
|
|
47
|
+
const alreadyOwned = await purchaseStore.hasPurchased(userId, productId);
|
|
48
|
+
if (alreadyOwned) {
|
|
49
|
+
const response = {
|
|
50
|
+
valid: false,
|
|
51
|
+
purchase: null,
|
|
52
|
+
error: 'NON_CONSUMABLE_ALREADY_OWNED',
|
|
53
|
+
};
|
|
54
|
+
res.status(409).json(response);
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Validate receipt via the appropriate provider.
|
|
59
|
+
// Both providers return a SubscriptionInfo-shaped object; we extract only
|
|
60
|
+
// the fields we need for PurchaseInfo (transactionId, purchasedAt).
|
|
61
|
+
let transactionId = null;
|
|
62
|
+
let purchasedAt = new Date().toISOString();
|
|
63
|
+
if (platform === 'apple') {
|
|
64
|
+
if (!config.apple) {
|
|
65
|
+
const response = {
|
|
66
|
+
valid: false,
|
|
67
|
+
purchase: null,
|
|
68
|
+
error: 'Apple configuration not provided',
|
|
69
|
+
};
|
|
70
|
+
res.status(500).json(response);
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const sub = await validateAppleReceipt(receipt, config.apple);
|
|
74
|
+
if (sub) {
|
|
75
|
+
transactionId = sub.originalTransactionId;
|
|
76
|
+
purchasedAt = sub.purchasedAt;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
if (!config.google) {
|
|
81
|
+
const response = {
|
|
82
|
+
valid: false,
|
|
83
|
+
purchase: null,
|
|
84
|
+
error: 'Google configuration not provided',
|
|
85
|
+
};
|
|
86
|
+
res.status(500).json(response);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
const sub = await validateGoogleReceipt(receipt, productId, config.google);
|
|
90
|
+
if (sub) {
|
|
91
|
+
transactionId = sub.originalTransactionId;
|
|
92
|
+
purchasedAt = sub.purchasedAt;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
if (!transactionId) {
|
|
96
|
+
const response = {
|
|
97
|
+
valid: false,
|
|
98
|
+
purchase: null,
|
|
99
|
+
error: 'Receipt validation failed',
|
|
100
|
+
};
|
|
101
|
+
res.status(422).json(response);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
// Check for duplicate transaction (idempotency)
|
|
105
|
+
const existing = await purchaseStore.getPurchaseByTransactionId(transactionId);
|
|
106
|
+
if (existing) {
|
|
107
|
+
const response = {
|
|
108
|
+
valid: true,
|
|
109
|
+
purchase: existing,
|
|
110
|
+
};
|
|
111
|
+
res.status(200).json(response);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
114
|
+
const purchase = {
|
|
115
|
+
userId,
|
|
116
|
+
productId,
|
|
117
|
+
platform,
|
|
118
|
+
type,
|
|
119
|
+
transactionId,
|
|
120
|
+
purchasedAt,
|
|
121
|
+
quantity: 1,
|
|
122
|
+
};
|
|
123
|
+
await purchaseStore.savePurchase(purchase);
|
|
124
|
+
const response = {
|
|
125
|
+
valid: true,
|
|
126
|
+
purchase,
|
|
127
|
+
};
|
|
128
|
+
res.status(200).json(response);
|
|
129
|
+
}
|
|
130
|
+
catch (err) {
|
|
131
|
+
console.error('[onesub/purchase/validate] Unexpected error:', err);
|
|
132
|
+
const response = {
|
|
133
|
+
valid: false,
|
|
134
|
+
purchase: null,
|
|
135
|
+
error: 'Internal server error during purchase validation',
|
|
136
|
+
};
|
|
137
|
+
res.status(500).json(response);
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
/**
|
|
141
|
+
* GET /onesub/purchase/status?userId=xxx[&productId=yyy]
|
|
142
|
+
*
|
|
143
|
+
* Returns all purchases for a user, optionally filtered by productId.
|
|
144
|
+
*/
|
|
145
|
+
router.get(ROUTES.PURCHASE_STATUS, async (req, res) => {
|
|
146
|
+
let query;
|
|
147
|
+
try {
|
|
148
|
+
query = purchaseStatusQuerySchema.parse(req.query);
|
|
149
|
+
}
|
|
150
|
+
catch (err) {
|
|
151
|
+
if (err instanceof z.ZodError) {
|
|
152
|
+
res.status(400).json({
|
|
153
|
+
purchases: [],
|
|
154
|
+
error: err.issues.map((e) => e.message).join(', '),
|
|
155
|
+
});
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
throw err;
|
|
159
|
+
}
|
|
160
|
+
const { userId, productId } = query;
|
|
161
|
+
try {
|
|
162
|
+
let purchases = await purchaseStore.getPurchasesByUserId(userId);
|
|
163
|
+
if (productId !== undefined) {
|
|
164
|
+
purchases = purchases.filter((p) => p.productId === productId);
|
|
165
|
+
}
|
|
166
|
+
const response = { purchases };
|
|
167
|
+
res.status(200).json(response);
|
|
168
|
+
}
|
|
169
|
+
catch (err) {
|
|
170
|
+
console.error('[onesub/purchase/status] Store error:', err);
|
|
171
|
+
res.status(500).json({ purchases: [], error: 'Internal server error' });
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
return router;
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=purchase.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"purchase.js","sourceRoot":"","sources":["../../src/routes/purchase.ts"],"names":[],"mappings":"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"}
|
package/dist/store.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { SubscriptionInfo } from '@onesub/shared';
|
|
1
|
+
import type { SubscriptionInfo, PurchaseInfo } from '@onesub/shared';
|
|
2
2
|
/**
|
|
3
3
|
* Pluggable subscription store interface.
|
|
4
4
|
* Default is in-memory. Replace with a PostgreSQL/Redis implementation
|
|
@@ -20,4 +20,26 @@ export declare class InMemorySubscriptionStore implements SubscriptionStore {
|
|
|
20
20
|
getByUserId(userId: string): Promise<SubscriptionInfo | null>;
|
|
21
21
|
getByTransactionId(txId: string): Promise<SubscriptionInfo | null>;
|
|
22
22
|
}
|
|
23
|
+
/**
|
|
24
|
+
* Pluggable purchase store interface for consumables and non-consumables.
|
|
25
|
+
*/
|
|
26
|
+
export interface PurchaseStore {
|
|
27
|
+
savePurchase(purchase: PurchaseInfo): Promise<void>;
|
|
28
|
+
getPurchasesByUserId(userId: string): Promise<PurchaseInfo[]>;
|
|
29
|
+
getPurchaseByTransactionId(txId: string): Promise<PurchaseInfo | null>;
|
|
30
|
+
/** For non-consumables: check if a user has already purchased a product. */
|
|
31
|
+
hasPurchased(userId: string, productId: string): Promise<boolean>;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* In-memory implementation of PurchaseStore — suitable for development and testing.
|
|
35
|
+
* Data is lost on process restart.
|
|
36
|
+
*/
|
|
37
|
+
export declare class InMemoryPurchaseStore implements PurchaseStore {
|
|
38
|
+
private readonly byTransactionId;
|
|
39
|
+
private readonly byUserId;
|
|
40
|
+
savePurchase(purchase: PurchaseInfo): Promise<void>;
|
|
41
|
+
getPurchasesByUserId(userId: string): Promise<PurchaseInfo[]>;
|
|
42
|
+
getPurchaseByTransactionId(txId: string): Promise<PurchaseInfo | null>;
|
|
43
|
+
hasPurchased(userId: string, productId: string): Promise<boolean>;
|
|
44
|
+
}
|
|
23
45
|
//# sourceMappingURL=store.d.ts.map
|
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,MAAM,gBAAgB,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,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;CACpE;AAED;;;GAGG;AACH,qBAAa,yBAA0B,YAAW,iBAAiB;IACjE,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAuC;IAChE,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAuC;IAEjE,IAAI,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAK1C,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAI7D,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;CACnE;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;IAOnD,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;CAKxE"}
|
package/dist/store.js
CHANGED
|
@@ -16,4 +16,30 @@ export class InMemorySubscriptionStore {
|
|
|
16
16
|
return this.byTransactionId.get(txId) ?? null;
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
+
/**
|
|
20
|
+
* In-memory implementation of PurchaseStore — suitable for development and testing.
|
|
21
|
+
* Data is lost on process restart.
|
|
22
|
+
*/
|
|
23
|
+
export class InMemoryPurchaseStore {
|
|
24
|
+
byTransactionId = new Map();
|
|
25
|
+
byUserId = new Map();
|
|
26
|
+
async savePurchase(purchase) {
|
|
27
|
+
this.byTransactionId.set(purchase.transactionId, purchase);
|
|
28
|
+
const list = this.byUserId.get(purchase.userId) ?? [];
|
|
29
|
+
list.push(purchase);
|
|
30
|
+
this.byUserId.set(purchase.userId, list);
|
|
31
|
+
}
|
|
32
|
+
async getPurchasesByUserId(userId) {
|
|
33
|
+
return this.byUserId.get(userId) ?? [];
|
|
34
|
+
}
|
|
35
|
+
async getPurchaseByTransactionId(txId) {
|
|
36
|
+
return this.byTransactionId.get(txId) ?? null;
|
|
37
|
+
}
|
|
38
|
+
async hasPurchased(userId, productId) {
|
|
39
|
+
const purchases = this.byUserId.get(userId);
|
|
40
|
+
if (!purchases)
|
|
41
|
+
return false;
|
|
42
|
+
return purchases.some((p) => p.productId === productId);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
19
45
|
//# sourceMappingURL=store.js.map
|
package/dist/store.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAaA;;;GAGG;AACH,MAAM,OAAO,yBAAyB;IACnB,QAAQ,GAAG,IAAI,GAAG,EAA4B,CAAC;IAC/C,eAAe,GAAG,IAAI,GAAG,EAA4B,CAAC;IAEvE,KAAK,CAAC,IAAI,CAAC,GAAqB;QAC9B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;IAC3D,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAc;QAC9B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,IAAY;QACnC,OAAO,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IAChD,CAAC;CACF"}
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAaA;;;GAGG;AACH,MAAM,OAAO,yBAAyB;IACnB,QAAQ,GAAG,IAAI,GAAG,EAA4B,CAAC;IAC/C,eAAe,GAAG,IAAI,GAAG,EAA4B,CAAC;IAEvE,KAAK,CAAC,IAAI,CAAC,GAAqB;QAC9B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;QACnC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,GAAG,CAAC,qBAAqB,EAAE,GAAG,CAAC,CAAC;IAC3D,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,MAAc;QAC9B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,IAAY;QACnC,OAAO,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IAChD,CAAC;CACF;AAaD;;;GAGG;AACH,MAAM,OAAO,qBAAqB;IACf,eAAe,GAAG,IAAI,GAAG,EAAwB,CAAC;IAClD,QAAQ,GAAG,IAAI,GAAG,EAA0B,CAAC;IAE9D,KAAK,CAAC,YAAY,CAAC,QAAsB;QACvC,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAC;QAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACtD,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACpB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,MAAc;QACvC,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,0BAA0B,CAAC,IAAY;QAC3C,OAAO,IAAI,CAAC,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IAChD,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAAc,EAAE,SAAiB;QAClD,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC5C,IAAI,CAAC,SAAS;YAAE,OAAO,KAAK,CAAC;QAC7B,OAAO,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC;IAC1D,CAAC;CACF"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { SubscriptionInfo } from '@onesub/shared';
|
|
2
|
-
import type { SubscriptionStore } from '../store.js';
|
|
1
|
+
import type { SubscriptionInfo, PurchaseInfo } from '@onesub/shared';
|
|
2
|
+
import type { SubscriptionStore, PurchaseStore } from '../store.js';
|
|
3
3
|
/**
|
|
4
4
|
* PostgreSQL-backed subscription store.
|
|
5
5
|
*
|
|
@@ -46,4 +46,34 @@ export declare class PostgresSubscriptionStore implements SubscriptionStore {
|
|
|
46
46
|
/** Gracefully close the underlying connection pool. */
|
|
47
47
|
close(): Promise<void>;
|
|
48
48
|
}
|
|
49
|
+
/**
|
|
50
|
+
* PostgreSQL-backed purchase store for consumables and non-consumables.
|
|
51
|
+
*
|
|
52
|
+
* Uses raw `pg` (node-postgres). The `pg` package must be installed separately:
|
|
53
|
+
*
|
|
54
|
+
* npm install pg
|
|
55
|
+
* npm install -D @types/pg
|
|
56
|
+
*
|
|
57
|
+
* Usage:
|
|
58
|
+
* const store = new PostgresPurchaseStore(process.env.DATABASE_URL!);
|
|
59
|
+
* await store.initSchema();
|
|
60
|
+
* app.use(createOneSubMiddleware({ ...config, purchaseStore: store }));
|
|
61
|
+
*/
|
|
62
|
+
export declare class PostgresPurchaseStore implements PurchaseStore {
|
|
63
|
+
private readonly connectionString;
|
|
64
|
+
private poolPromise;
|
|
65
|
+
constructor(connectionString: string);
|
|
66
|
+
private getPool;
|
|
67
|
+
/**
|
|
68
|
+
* Creates the `onesub_purchases` table and indexes if they do not already exist.
|
|
69
|
+
* Call this once during application startup.
|
|
70
|
+
*/
|
|
71
|
+
initSchema(): Promise<void>;
|
|
72
|
+
savePurchase(purchase: PurchaseInfo): Promise<void>;
|
|
73
|
+
getPurchasesByUserId(userId: string): Promise<PurchaseInfo[]>;
|
|
74
|
+
getPurchaseByTransactionId(txId: string): Promise<PurchaseInfo | null>;
|
|
75
|
+
hasPurchased(userId: string, productId: string): Promise<boolean>;
|
|
76
|
+
/** Gracefully close the underlying connection pool. */
|
|
77
|
+
close(): Promise<void>;
|
|
78
|
+
}
|
|
49
79
|
//# sourceMappingURL=postgres.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"postgres.d.ts","sourceRoot":"","sources":["../../src/stores/postgres.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,gBAAgB,CAAC;
|
|
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;AAEpE;;;;;;;;;;;;;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;IAoBjC;;;;OAIG;IACG,IAAI,CAAC,GAAG,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IA6BhD;;;;;;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;IA0B3B,YAAY,CAAC,QAAQ,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBnD,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;IAYvE,uDAAuD;IACjD,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAO7B"}
|
package/dist/stores/postgres.js
CHANGED
|
@@ -123,6 +123,114 @@ export class PostgresSubscriptionStore {
|
|
|
123
123
|
}
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* PostgreSQL-backed purchase store for consumables and non-consumables.
|
|
128
|
+
*
|
|
129
|
+
* Uses raw `pg` (node-postgres). The `pg` package must be installed separately:
|
|
130
|
+
*
|
|
131
|
+
* npm install pg
|
|
132
|
+
* npm install -D @types/pg
|
|
133
|
+
*
|
|
134
|
+
* Usage:
|
|
135
|
+
* const store = new PostgresPurchaseStore(process.env.DATABASE_URL!);
|
|
136
|
+
* await store.initSchema();
|
|
137
|
+
* app.use(createOneSubMiddleware({ ...config, purchaseStore: store }));
|
|
138
|
+
*/
|
|
139
|
+
export class PostgresPurchaseStore {
|
|
140
|
+
connectionString;
|
|
141
|
+
poolPromise = null;
|
|
142
|
+
constructor(connectionString) {
|
|
143
|
+
this.connectionString = connectionString;
|
|
144
|
+
}
|
|
145
|
+
getPool() {
|
|
146
|
+
if (!this.poolPromise) {
|
|
147
|
+
this.poolPromise = (async () => {
|
|
148
|
+
const pg = await import('pg').catch(() => {
|
|
149
|
+
throw new Error('[onesub] PostgresPurchaseStore requires the `pg` package. ' +
|
|
150
|
+
'Run: npm install pg');
|
|
151
|
+
});
|
|
152
|
+
const Pool = pg.default?.Pool ?? pg.Pool;
|
|
153
|
+
return new Pool({ connectionString: this.connectionString, max: 10 });
|
|
154
|
+
})();
|
|
155
|
+
}
|
|
156
|
+
return this.poolPromise;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Creates the `onesub_purchases` table and indexes if they do not already exist.
|
|
160
|
+
* Call this once during application startup.
|
|
161
|
+
*/
|
|
162
|
+
async initSchema() {
|
|
163
|
+
const pool = await this.getPool();
|
|
164
|
+
await pool.query(`
|
|
165
|
+
CREATE TABLE IF NOT EXISTS onesub_purchases (
|
|
166
|
+
transaction_id TEXT PRIMARY KEY,
|
|
167
|
+
user_id TEXT NOT NULL,
|
|
168
|
+
product_id TEXT NOT NULL,
|
|
169
|
+
platform TEXT NOT NULL,
|
|
170
|
+
type TEXT NOT NULL,
|
|
171
|
+
quantity INTEGER NOT NULL DEFAULT 1,
|
|
172
|
+
purchased_at TIMESTAMPTZ NOT NULL,
|
|
173
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
|
|
174
|
+
);
|
|
175
|
+
|
|
176
|
+
CREATE INDEX IF NOT EXISTS idx_onesub_purchases_user_id
|
|
177
|
+
ON onesub_purchases (user_id, purchased_at DESC);
|
|
178
|
+
|
|
179
|
+
CREATE INDEX IF NOT EXISTS idx_onesub_purchases_user_product
|
|
180
|
+
ON onesub_purchases (user_id, product_id);
|
|
181
|
+
|
|
182
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_onesub_purchases_non_consumable
|
|
183
|
+
ON onesub_purchases (user_id, product_id)
|
|
184
|
+
WHERE type = 'non_consumable';
|
|
185
|
+
`);
|
|
186
|
+
}
|
|
187
|
+
async savePurchase(purchase) {
|
|
188
|
+
const pool = await this.getPool();
|
|
189
|
+
await pool.query(`INSERT INTO onesub_purchases
|
|
190
|
+
(transaction_id, user_id, product_id, platform, type, quantity, purchased_at)
|
|
191
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7)
|
|
192
|
+
ON CONFLICT (transaction_id) DO NOTHING`, [
|
|
193
|
+
purchase.transactionId,
|
|
194
|
+
purchase.userId,
|
|
195
|
+
purchase.productId,
|
|
196
|
+
purchase.platform,
|
|
197
|
+
purchase.type,
|
|
198
|
+
purchase.quantity,
|
|
199
|
+
purchase.purchasedAt,
|
|
200
|
+
]);
|
|
201
|
+
}
|
|
202
|
+
async getPurchasesByUserId(userId) {
|
|
203
|
+
const pool = await this.getPool();
|
|
204
|
+
const result = await pool.query(`SELECT *
|
|
205
|
+
FROM onesub_purchases
|
|
206
|
+
WHERE user_id = $1
|
|
207
|
+
ORDER BY purchased_at DESC`, [userId]);
|
|
208
|
+
return result.rows.map(rowToPurchaseInfo);
|
|
209
|
+
}
|
|
210
|
+
async getPurchaseByTransactionId(txId) {
|
|
211
|
+
const pool = await this.getPool();
|
|
212
|
+
const result = await pool.query(`SELECT *
|
|
213
|
+
FROM onesub_purchases
|
|
214
|
+
WHERE transaction_id = $1`, [txId]);
|
|
215
|
+
return result.rows.length > 0 ? rowToPurchaseInfo(result.rows[0]) : null;
|
|
216
|
+
}
|
|
217
|
+
async hasPurchased(userId, productId) {
|
|
218
|
+
const pool = await this.getPool();
|
|
219
|
+
const result = await pool.query(`SELECT EXISTS(
|
|
220
|
+
SELECT 1 FROM onesub_purchases
|
|
221
|
+
WHERE user_id = $1 AND product_id = $2
|
|
222
|
+
) AS exists`, [userId, productId]);
|
|
223
|
+
return result.rows[0]?.exists === true;
|
|
224
|
+
}
|
|
225
|
+
/** Gracefully close the underlying connection pool. */
|
|
226
|
+
async close() {
|
|
227
|
+
if (this.poolPromise) {
|
|
228
|
+
const pool = await this.poolPromise;
|
|
229
|
+
await pool.end();
|
|
230
|
+
this.poolPromise = null;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
}
|
|
126
234
|
function rowToSubscriptionInfo(row) {
|
|
127
235
|
return {
|
|
128
236
|
originalTransactionId: row.original_transaction_id,
|
|
@@ -135,4 +243,15 @@ function rowToSubscriptionInfo(row) {
|
|
|
135
243
|
willRenew: row.will_renew,
|
|
136
244
|
};
|
|
137
245
|
}
|
|
246
|
+
function rowToPurchaseInfo(row) {
|
|
247
|
+
return {
|
|
248
|
+
transactionId: row.transaction_id,
|
|
249
|
+
userId: row.user_id,
|
|
250
|
+
productId: row.product_id,
|
|
251
|
+
platform: row.platform,
|
|
252
|
+
type: row.type,
|
|
253
|
+
quantity: row.quantity,
|
|
254
|
+
purchasedAt: row.purchased_at.toISOString(),
|
|
255
|
+
};
|
|
256
|
+
}
|
|
138
257
|
//# sourceMappingURL=postgres.js.map
|
|
@@ -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":"AAGA;;;;;;;;;;;;;GAaG;AACH,MAAM,OAAO,yBAAyB;IAIP;IAH7B,kFAAkF;IAC1E,WAAW,GAAsC,IAAI,CAAC;IAE9D,YAA6B,gBAAwB;QAAxB,qBAAgB,GAAhB,gBAAgB,CAAQ;IAAG,CAAC;IAEjD,OAAO;QACb,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,IAAI,CAAC,WAAW,GAAG,CAAC,KAAK,IAAI,EAAE;gBAC7B,+DAA+D;gBAC/D,gEAAgE;gBAChE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;oBACvC,MAAM,IAAI,KAAK,CACb,gEAAgE;wBAC9D,qBAAqB,CACxB,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE,IAAI,IAAK,EAAoD,CAAC,IAAI,CAAC;gBAC5F,OAAO,IAAI,IAAI,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;YACxE,CAAC,CAAC,EAAE,CAAC;QACP,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU;QACd,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAClC,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;KAehB,CAAC,CAAC;IACL,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,IAAI,CAAC,GAAqB;QAC9B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAClC,MAAM,IAAI,CAAC,KAAK,CACd;;;;;;;;;;;;4BAYsB,EACtB;YACE,GAAG,CAAC,qBAAqB;YACzB,GAAG,CAAC,MAAM;YACV,GAAG,CAAC,SAAS;YACb,GAAG,CAAC,QAAQ;YACZ,GAAG,CAAC,MAAM;YACV,GAAG,CAAC,SAAS;YACb,GAAG,CAAC,WAAW;YACf,GAAG,CAAC,SAAS;SACd,CACF,CAAC;IACJ,CAAC;IAED;;;;;;OAMG;IACH,KAAK,CAAC,WAAW,CAAC,MAAc;QAC9B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B;;;;gBAIU,EACV,CAAC,MAAM,CAAC,CACT,CAAC;QACF,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/E,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,kBAAkB,CAAC,IAAY;QACnC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B;;2CAEqC,EACrC,CAAC,IAAI,CAAC,CACP,CAAC;QACF,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/E,CAAC;IAED,uDAAuD;IACvD,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC;YACpC,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC;YACjB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAC1B,CAAC;IACH,CAAC;CACF;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,qBAAqB;IAGH;IAFrB,WAAW,GAAsC,IAAI,CAAC;IAE9D,YAA6B,gBAAwB;QAAxB,qBAAgB,GAAhB,gBAAgB,CAAQ;IAAG,CAAC;IAEjD,OAAO;QACb,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC;YACtB,IAAI,CAAC,WAAW,GAAG,CAAC,KAAK,IAAI,EAAE;gBAC7B,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;oBACvC,MAAM,IAAI,KAAK,CACb,4DAA4D;wBAC1D,qBAAqB,CACxB,CAAC;gBACJ,CAAC,CAAC,CAAC;gBACH,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE,IAAI,IAAK,EAAoD,CAAC,IAAI,CAAC;gBAC5F,OAAO,IAAI,IAAI,CAAC,EAAE,gBAAgB,EAAE,IAAI,CAAC,gBAAgB,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;YACxE,CAAC,CAAC,EAAE,CAAC;QACP,CAAC;QACD,OAAO,IAAI,CAAC,WAAW,CAAC;IAC1B,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,UAAU;QACd,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAClC,MAAM,IAAI,CAAC,KAAK,CAAC;;;;;;;;;;;;;;;;;;;;;KAqBhB,CAAC,CAAC;IACL,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,QAAsB;QACvC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAClC,MAAM,IAAI,CAAC,KAAK,CACd;;;+CAGyC,EACzC;YACE,QAAQ,CAAC,aAAa;YACtB,QAAQ,CAAC,MAAM;YACf,QAAQ,CAAC,SAAS;YAClB,QAAQ,CAAC,QAAQ;YACjB,QAAQ,CAAC,IAAI;YACb,QAAQ,CAAC,QAAQ;YACjB,QAAQ,CAAC,WAAW;SACrB,CACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,MAAc;QACvC,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B;;;mCAG6B,EAC7B,CAAC,MAAM,CAAC,CACT,CAAC;QACF,OAAO,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;IAC5C,CAAC;IAED,KAAK,CAAC,0BAA0B,CAAC,IAAY;QAC3C,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B;;kCAE4B,EAC5B,CAAC,IAAI,CAAC,CACP,CAAC;QACF,OAAO,MAAM,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3E,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,MAAc,EAAE,SAAiB;QAClD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;QAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B;;;mBAGa,EACb,CAAC,MAAM,EAAE,SAAS,CAAC,CACpB,CAAC;QACF,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,CAAC;IAED,uDAAuD;IACvD,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,WAAW,EAAE,CAAC;YACrB,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC;YACpC,MAAM,IAAI,CAAC,GAAG,EAAE,CAAC;YACjB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAC1B,CAAC;IACH,CAAC;CACF;AAiBD,SAAS,qBAAqB,CAAC,GAAU;IACvC,OAAO;QACL,qBAAqB,EAAE,GAAG,CAAC,uBAAuB;QAClD,MAAM,EAAE,GAAG,CAAC,OAAO;QACnB,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,QAAQ,EAAE,GAAG,CAAC,QAAwC;QACtD,MAAM,EAAE,GAAG,CAAC,MAAoC;QAChD,SAAS,EAAE,GAAG,CAAC,UAAU,CAAC,WAAW,EAAE;QACvC,WAAW,EAAE,GAAG,CAAC,YAAY,CAAC,WAAW,EAAE;QAC3C,SAAS,EAAE,GAAG,CAAC,UAAU;KAC1B,CAAC;AACJ,CAAC;AAYD,SAAS,iBAAiB,CAAC,GAAkB;IAC3C,OAAO;QACL,aAAa,EAAE,GAAG,CAAC,cAAc;QACjC,MAAM,EAAE,GAAG,CAAC,OAAO;QACnB,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,QAAQ,EAAE,GAAG,CAAC,QAAoC;QAClD,IAAI,EAAE,GAAG,CAAC,IAA4B;QACtC,QAAQ,EAAE,GAAG,CAAC,QAAQ;QACtB,WAAW,EAAE,GAAG,CAAC,YAAY,CAAC,WAAW,EAAE;KAC5C,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@onesub/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.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",
|
|
7
7
|
"type": "module",
|
|
8
|
-
"files": [
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
9
11
|
"scripts": {
|
|
10
12
|
"build": "tsc",
|
|
11
13
|
"dev": "tsc --watch",
|