@mostajs/subscriptions-plan 0.3.5 → 0.4.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/CHANGELOG.md +26 -0
- package/README.md +24 -0
- package/dist/api/subscriptions.route.d.ts.map +1 -1
- package/dist/api/subscriptions.route.js +22 -5
- package/dist/api/subscriptions.route.js.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lib/subscribe.d.ts +26 -0
- package/dist/lib/subscribe.d.ts.map +1 -1
- package/dist/lib/subscribe.js +46 -7
- package/dist/lib/subscribe.js.map +1 -1
- package/dist/schemas/subscription.schema.d.ts.map +1 -1
- package/dist/schemas/subscription.schema.js +8 -0
- package/dist/schemas/subscription.schema.js.map +1 -1
- package/dist/server.d.ts +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/types/index.d.ts +10 -1
- package/dist/types/index.d.ts.map +1 -1
- package/llms.txt +93 -0
- package/package.json +6 -3
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Changelog — `@mostajs/subscriptions-plan`
|
|
2
|
+
|
|
3
|
+
**Auteur** : Dr Hamid MADANI <drmdh@msn.com>
|
|
4
|
+
|
|
5
|
+
## 0.4.0 — 2026-06-10
|
|
6
|
+
|
|
7
|
+
### Ajouté (additif, **non-breaking**)
|
|
8
|
+
- **Scope générique sur `Subscription`** : champs optionnels `scopeType` (défaut `'account'`) et
|
|
9
|
+
`scopeId`. Permet de rattacher un abonnement à une **entité** autre que le compte
|
|
10
|
+
(`'course'` pour race-event, `'project'`, …) → un compte peut avoir **plusieurs abonnements
|
|
11
|
+
actifs**, un par entité scopée. L'annulation des abos existants ne touche que le **même scope**.
|
|
12
|
+
- **`subscribeToPlan(dialect, { …, scope?: { type, id } })`** : propage le scope (chemin direct
|
|
13
|
+
et `metadata` du provider de paiement).
|
|
14
|
+
- **`findActiveSubscription(dialect, { accountId?, scope? })`** : trouve l'abo actif d'un compte
|
|
15
|
+
ou d'une entité scopée (exporté depuis `./server`).
|
|
16
|
+
- **Routes `/subscription`** : `GET` accepte `?scopeType=&scopeId=` (ou `accountId`) ; `POST`
|
|
17
|
+
persiste `scopeType/scopeId` et annule les abos actifs du même scope.
|
|
18
|
+
- **`Plan.interval`** accepte désormais `'one_time'` (en plus de `'month' | 'year'`) — corrige
|
|
19
|
+
l'incohérence des plans ponctuels (sponsoring par édition) ; le défaut reste récurrent.
|
|
20
|
+
|
|
21
|
+
### Migration
|
|
22
|
+
Aucune action requise : les champs sont optionnels (auto-ALTER ORM). Les abonnements existants
|
|
23
|
+
(compte-scopés) restent valides ; en l'absence de scope, le comportement est identique à 0.3.x.
|
|
24
|
+
|
|
25
|
+
## 0.3.6
|
|
26
|
+
- Souscription multi-provider (`subscribeToPlan`), facturation Stripe, factures, quotas/usage.
|
package/README.md
CHANGED
|
@@ -20,6 +20,30 @@ C'est un module **système** *(au sens : ses 4 tables vivent dans la base systè
|
|
|
20
20
|
|
|
21
21
|
---
|
|
22
22
|
|
|
23
|
+
## Scope d'abonnement *(v0.4.0)*
|
|
24
|
+
|
|
25
|
+
Par défaut un abonnement est au niveau **compte** (`scopeType: 'account'`). Depuis 0.4.0, on peut
|
|
26
|
+
le **scoper à une entité** via les champs optionnels `scopeType` / `scopeId` — un même compte
|
|
27
|
+
peut alors avoir **plusieurs abonnements actifs**, un par entité :
|
|
28
|
+
|
|
29
|
+
```ts
|
|
30
|
+
import { subscribeToPlan, findActiveSubscription } from '@mostajs/subscriptions-plan/server'
|
|
31
|
+
|
|
32
|
+
// Sponsoriser une COURSE précise (race-event)
|
|
33
|
+
await subscribeToPlan(dialect, {
|
|
34
|
+
accountId, planId, provider: 'chargily',
|
|
35
|
+
scope: { type: 'course', id: courseId }, // ← abo rattaché à la course
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
// Retrouver l'abo actif de cette course
|
|
39
|
+
const sub = await findActiveSubscription(dialect, { scope: { type: 'course', id: courseId } })
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Additif et **non-breaking** : sans `scope`, le comportement est identique aux versions 0.3.x
|
|
43
|
+
(abo compte-scopé, annulation account-wide). Voir `CHANGELOG.md`.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
23
47
|
## Install
|
|
24
48
|
|
|
25
49
|
```bash
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscriptions.route.d.ts","sourceRoot":"","sources":["../../src/api/subscriptions.route.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAIlD;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,QAAQ;eAKlC,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"subscriptions.route.d.ts","sourceRoot":"","sources":["../../src/api/subscriptions.route.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAIlD;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,QAAQ;eAKlC,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC;gBA0B1B,OAAO,KAAG,OAAO,CAAC,QAAQ,CAAC;eAyC5B,OAAO,MAAM,MAAM,KAAG,OAAO,CAAC,QAAQ,CAAC;EAUhE"}
|
|
@@ -11,10 +11,20 @@ export function createSubscriptionHandlers(dialect) {
|
|
|
11
11
|
async function GET(req) {
|
|
12
12
|
const url = new URL(req.url);
|
|
13
13
|
const accountId = url.searchParams.get('accountId');
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
const scopeType = url.searchParams.get('scopeType');
|
|
15
|
+
const scopeId = url.searchParams.get('scopeId');
|
|
16
|
+
// Au moins un critère : compte OU scope (course, …).
|
|
17
|
+
if (!accountId && !(scopeType && scopeId)) {
|
|
18
|
+
return Response.json({ error: 'accountId or (scopeType & scopeId) required' }, { status: 400 });
|
|
16
19
|
}
|
|
17
|
-
const
|
|
20
|
+
const filter = { status: 'active' };
|
|
21
|
+
if (accountId)
|
|
22
|
+
filter.account = accountId;
|
|
23
|
+
if (scopeType && scopeId) {
|
|
24
|
+
filter.scopeType = scopeType;
|
|
25
|
+
filter.scopeId = scopeId;
|
|
26
|
+
}
|
|
27
|
+
const subs = await subRepo.findAll(filter);
|
|
18
28
|
if (subs.length === 0) {
|
|
19
29
|
return Response.json(null);
|
|
20
30
|
}
|
|
@@ -34,8 +44,13 @@ export function createSubscriptionHandlers(dialect) {
|
|
|
34
44
|
if (!plan) {
|
|
35
45
|
return Response.json({ error: 'Plan not found' }, { status: 404 });
|
|
36
46
|
}
|
|
37
|
-
// Cancel existing active subscriptions
|
|
38
|
-
const
|
|
47
|
+
// Cancel existing active subscriptions of the SAME scope (account-wide si pas de scope).
|
|
48
|
+
const cancelFilter = { account: data.accountId, status: 'active' };
|
|
49
|
+
if (data.scopeType && data.scopeId) {
|
|
50
|
+
cancelFilter.scopeType = data.scopeType;
|
|
51
|
+
cancelFilter.scopeId = data.scopeId;
|
|
52
|
+
}
|
|
53
|
+
const existing = await subRepo.findAll(cancelFilter);
|
|
39
54
|
for (const old of existing) {
|
|
40
55
|
await subRepo.update(old.id, { status: 'canceled' });
|
|
41
56
|
}
|
|
@@ -48,6 +63,8 @@ export function createSubscriptionHandlers(dialect) {
|
|
|
48
63
|
currentPeriodStart: data.currentPeriodStart ?? new Date().toISOString(),
|
|
49
64
|
currentPeriodEnd: data.currentPeriodEnd,
|
|
50
65
|
trialEnd: data.trialEnd,
|
|
66
|
+
...(data.scopeType ? { scopeType: data.scopeType } : {}),
|
|
67
|
+
...(data.scopeId ? { scopeId: data.scopeId } : {}),
|
|
51
68
|
});
|
|
52
69
|
return Response.json(sub, { status: 201 });
|
|
53
70
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscriptions.route.js","sourceRoot":"","sources":["../../src/api/subscriptions.route.ts"],"names":[],"mappings":"AAAA,iEAAiE;AACjE,wCAAwC;AAGxC,OAAO,EAAE,mBAAmB,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAA;AAGzE;;GAEG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAAiB;IAC1D,MAAM,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAA;IAC5C,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;IAErC,gEAAgE;IAChE,KAAK,UAAU,GAAG,CAAC,GAAY;QAC7B,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAA;QAC5B,MAAM,SAAS,GAAG,GAAG,CAAC,YAAY,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACnD,IAAI,CAAC,SAAS,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"subscriptions.route.js","sourceRoot":"","sources":["../../src/api/subscriptions.route.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export type { PlanDTO, PlanLimits, SubscriptionDTO, SubscriptionStatus, InvoiceDTO, InvoiceStatus, UsageLogDTO, BillingConfig, QuotaCheckResult, } from './types/index.js';
|
|
1
|
+
export type { PlanDTO, PlanLimits, SubscriptionDTO, SubscriptionStatus, SubscriptionScope, InvoiceDTO, InvoiceStatus, UsageLogDTO, BillingConfig, QuotaCheckResult, } from './types/index.js';
|
|
2
2
|
export { PlanSchema } from './schemas/plan.schema.js';
|
|
3
3
|
export { SubscriptionSchema } from './schemas/subscription.schema.js';
|
|
4
4
|
export { InvoiceSchema } from './schemas/invoice.schema.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,YAAY,EACV,OAAO,EACP,UAAU,EACV,eAAe,EACf,kBAAkB,EAClB,UAAU,EACV,aAAa,EACb,WAAW,EACX,aAAa,EACb,gBAAgB,GACjB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAG9D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,YAAY,EACV,OAAO,EACP,UAAU,EACV,eAAe,EACf,kBAAkB,EAClB,iBAAiB,EACjB,UAAU,EACV,aAAa,EACb,WAAW,EACX,aAAa,EACb,gBAAgB,GACjB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAG9D,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA"}
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,2DAA2D;AAC3D,wCAAwC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,2DAA2D;AAC3D,wCAAwC;AAgBxC,UAAU;AACV,OAAO,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AACrD,OAAO,EAAE,kBAAkB,EAAE,MAAM,kCAAkC,CAAA;AACrE,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAA;AAE9D,cAAc;AACd,OAAO,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA"}
|
package/dist/lib/subscribe.d.ts
CHANGED
|
@@ -14,6 +14,16 @@ export interface SubscribeParams {
|
|
|
14
14
|
customerName?: string;
|
|
15
15
|
/** Stripe customer ID (if already exists) */
|
|
16
16
|
stripeCustomerId?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Scope optionnel de l'abonnement. Par défaut { type:'account' } (historique).
|
|
19
|
+
* { type:'course', id:courseId } → abo rattaché à une course (race-event) : permet
|
|
20
|
+
* PLUSIEURS abos actifs par compte, un par entité scopée. L'annulation des abos
|
|
21
|
+
* existants ne touche que le MÊME scope.
|
|
22
|
+
*/
|
|
23
|
+
scope?: {
|
|
24
|
+
type: string;
|
|
25
|
+
id: string;
|
|
26
|
+
};
|
|
17
27
|
}
|
|
18
28
|
export interface SubscribeResult {
|
|
19
29
|
ok: boolean;
|
|
@@ -40,4 +50,20 @@ export declare function subscribeToPlan(dialect: IDialect, params: SubscribePara
|
|
|
40
50
|
* @returns { ok, subscription } with the new Free subscription
|
|
41
51
|
*/
|
|
42
52
|
export declare function cancelCurrentSubscription(dialect: import('@mostajs/data-plug').IDialect, accountId: string): Promise<SubscribeResult>;
|
|
53
|
+
/**
|
|
54
|
+
* Trouve l'abonnement ACTIF pour un scope donné.
|
|
55
|
+
*
|
|
56
|
+
* - `{ accountId }` seul → abo actif du compte (historique).
|
|
57
|
+
* - `{ scope:{type,id} }` → abo actif rattaché à cette entité (ex. course).
|
|
58
|
+
* `accountId` reste optionnel pour restreindre au compte.
|
|
59
|
+
*
|
|
60
|
+
* @returns la Subscription active ou `null`.
|
|
61
|
+
*/
|
|
62
|
+
export declare function findActiveSubscription(dialect: import('@mostajs/data-plug').IDialect, params: {
|
|
63
|
+
accountId?: string;
|
|
64
|
+
scope?: {
|
|
65
|
+
type: string;
|
|
66
|
+
id: string;
|
|
67
|
+
};
|
|
68
|
+
}): Promise<any | null>;
|
|
43
69
|
//# sourceMappingURL=subscribe.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscribe.d.ts","sourceRoot":"","sources":["../../src/lib/subscribe.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAGlD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,wFAAwF;IACxF,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,4CAA4C;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6CAA6C;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"subscribe.d.ts","sourceRoot":"","sources":["../../src/lib/subscribe.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAA;AAGlD,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,wFAAwF;IACxF,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,gCAAgC;IAChC,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gDAAgD;IAChD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,4CAA4C;IAC5C,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,6CAA6C;IAC7C,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB;;;;;OAKG;IACH,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;CACrC;AAED,MAAM,WAAW,eAAe;IAC9B,EAAE,EAAE,OAAO,CAAA;IACX,wCAAwC;IACxC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACnB,kEAAkE;IAClE,YAAY,CAAC,EAAE,GAAG,CAAA;IAClB,oBAAoB;IACpB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;GAMG;AACH,wBAAsB,eAAe,CACnC,OAAO,EAAE,QAAQ,EACjB,MAAM,EAAE,eAAe,GACtB,OAAO,CAAC,eAAe,CAAC,CA4C1B;AA2ED;;;;;;GAMG;AACH,wBAAsB,yBAAyB,CAC7C,OAAO,EAAE,OAAO,oBAAoB,EAAE,QAAQ,EAC9C,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,eAAe,CAAC,CAuB1B;AAED;;;;;;;;GAQG;AACH,wBAAsB,sBAAsB,CAC1C,OAAO,EAAE,OAAO,oBAAoB,EAAE,QAAQ,EAC9C,MAAM,EAAE;IAAE,SAAS,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,GACnE,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAOrB"}
|
package/dist/lib/subscribe.js
CHANGED
|
@@ -18,7 +18,7 @@ export async function subscribeToPlan(dialect, params) {
|
|
|
18
18
|
return { ok: false, error: 'Plan non trouve' };
|
|
19
19
|
// Free plan or no provider → direct subscription
|
|
20
20
|
if (!plan.price || plan.price === 0 || !params.provider || params.provider === 'direct') {
|
|
21
|
-
return directSubscribe(subRepo, params.accountId, params.planId);
|
|
21
|
+
return directSubscribe(subRepo, params.accountId, params.planId, params.scope);
|
|
22
22
|
}
|
|
23
23
|
// Paid plan → try payment provider
|
|
24
24
|
try {
|
|
@@ -36,7 +36,11 @@ export async function subscribeToPlan(dialect, params) {
|
|
|
36
36
|
webhookUrl: params.webhookUrl,
|
|
37
37
|
customerId: params.stripeCustomerId,
|
|
38
38
|
priceId: plan.stripePriceId,
|
|
39
|
-
metadata: {
|
|
39
|
+
metadata: {
|
|
40
|
+
accountId: params.accountId,
|
|
41
|
+
planId: params.planId,
|
|
42
|
+
...(params.scope ? { scopeType: params.scope.type, scopeId: params.scope.id } : {}),
|
|
43
|
+
},
|
|
40
44
|
});
|
|
41
45
|
return { ok: true, url: result.url };
|
|
42
46
|
}
|
|
@@ -47,10 +51,19 @@ export async function subscribeToPlan(dialect, params) {
|
|
|
47
51
|
}
|
|
48
52
|
/**
|
|
49
53
|
* Direct subscription — no payment required (free plan or fallback).
|
|
54
|
+
*
|
|
55
|
+
* Scope-aware : si un scope est fourni (ex. course), seuls les abos actifs du
|
|
56
|
+
* MÊME scope sont annulés (un compte peut sponsoriser plusieurs courses en //).
|
|
57
|
+
* Sans scope → comportement historique (annule les abos actifs du compte).
|
|
50
58
|
*/
|
|
51
|
-
async function directSubscribe(subRepo, accountId, planId) {
|
|
52
|
-
// Cancel existing active subscriptions
|
|
53
|
-
const
|
|
59
|
+
async function directSubscribe(subRepo, accountId, planId, scope) {
|
|
60
|
+
// Cancel existing active subscriptions of the SAME scope
|
|
61
|
+
const filter = { account: accountId, status: 'active' };
|
|
62
|
+
if (scope) {
|
|
63
|
+
filter.scopeType = scope.type;
|
|
64
|
+
filter.scopeId = scope.id;
|
|
65
|
+
}
|
|
66
|
+
const existing = await subRepo.findAll(filter);
|
|
54
67
|
for (const sub of existing) {
|
|
55
68
|
await subRepo.update(sub.id, { status: 'canceled' });
|
|
56
69
|
}
|
|
@@ -59,6 +72,7 @@ async function directSubscribe(subRepo, accountId, planId) {
|
|
|
59
72
|
account: accountId,
|
|
60
73
|
plan: planId,
|
|
61
74
|
status: 'active',
|
|
75
|
+
...(scope ? { scopeType: scope.type, scopeId: scope.id } : {}),
|
|
62
76
|
});
|
|
63
77
|
return { ok: true, subscription };
|
|
64
78
|
}
|
|
@@ -78,8 +92,12 @@ async function ensureProvider(name) {
|
|
|
78
92
|
break;
|
|
79
93
|
}
|
|
80
94
|
case 'chargily': {
|
|
81
|
-
|
|
82
|
-
|
|
95
|
+
// Cohérence Stripe-aligned : CHARGILY_SECRET_KEY (recommandé) avec
|
|
96
|
+
// fallback CHARGILY_API_KEY (legacy). Cf. createChargilyProvider.
|
|
97
|
+
const { getEnv } = await import('@mostajs/config');
|
|
98
|
+
const chargilyKey = getEnv('CHARGILY_SECRET_KEY') ?? getEnv('CHARGILY_API_KEY');
|
|
99
|
+
if (!chargilyKey)
|
|
100
|
+
throw new Error('CHARGILY_SECRET_KEY not configured');
|
|
83
101
|
const { createChargilyProvider, registerProvider } = await import('@mostajs/payment/server');
|
|
84
102
|
registerProvider(createChargilyProvider());
|
|
85
103
|
break;
|
|
@@ -129,4 +147,25 @@ export async function cancelCurrentSubscription(dialect, accountId) {
|
|
|
129
147
|
});
|
|
130
148
|
return { ok: true, subscription };
|
|
131
149
|
}
|
|
150
|
+
/**
|
|
151
|
+
* Trouve l'abonnement ACTIF pour un scope donné.
|
|
152
|
+
*
|
|
153
|
+
* - `{ accountId }` seul → abo actif du compte (historique).
|
|
154
|
+
* - `{ scope:{type,id} }` → abo actif rattaché à cette entité (ex. course).
|
|
155
|
+
* `accountId` reste optionnel pour restreindre au compte.
|
|
156
|
+
*
|
|
157
|
+
* @returns la Subscription active ou `null`.
|
|
158
|
+
*/
|
|
159
|
+
export async function findActiveSubscription(dialect, params) {
|
|
160
|
+
const subRepo = getSubscriptionRepo(dialect);
|
|
161
|
+
const filter = { status: 'active' };
|
|
162
|
+
if (params.accountId)
|
|
163
|
+
filter.account = params.accountId;
|
|
164
|
+
if (params.scope) {
|
|
165
|
+
filter.scopeType = params.scope.type;
|
|
166
|
+
filter.scopeId = params.scope.id;
|
|
167
|
+
}
|
|
168
|
+
const rows = await subRepo.findAll(filter);
|
|
169
|
+
return rows && rows.length > 0 ? rows[0] : null;
|
|
170
|
+
}
|
|
132
171
|
//# sourceMappingURL=subscribe.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscribe.js","sourceRoot":"","sources":["../../src/lib/subscribe.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,wCAAwC;AACxC,kDAAkD;AAGlD,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"subscribe.js","sourceRoot":"","sources":["../../src/lib/subscribe.ts"],"names":[],"mappings":"AAAA,mEAAmE;AACnE,wCAAwC;AACxC,kDAAkD;AAGlD,OAAO,EAAE,WAAW,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAoCpE;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,OAAiB,EACjB,MAAuB;IAEvB,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;IACrC,MAAM,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAA;IAE5C,qBAAqB;IACrB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAQ,CAAA;IAC1D,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAA;IAEzD,iDAAiD;IACjD,IAAI,CAAC,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACxF,OAAO,eAAe,CAAC,OAAO,EAAE,MAAM,CAAC,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IAChF,CAAC;IAED,mCAAmC;IACnC,IAAI,CAAC;QACH,MAAM,EAAE,WAAW,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAA;QAEjF,yCAAyC;QACzC,MAAM,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAErC,MAAM,QAAQ,GAAG,WAAW,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;QAE7C,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,cAAc,CAAC;YAC3C,OAAO,EAAE,OAAO,MAAM,CAAC,SAAS,IAAI,MAAM,CAAC,MAAM,EAAE;YACnD,MAAM,EAAE,IAAI,CAAC,KAAK,GAAG,GAAG,EAAE,gBAAgB;YAC1C,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,KAAK;YAChC,WAAW,EAAE,cAAc,IAAI,CAAC,IAAI,EAAE;YACtC,UAAU,EAAE,MAAM,CAAC,UAAU,IAAI,8BAA8B;YAC/D,SAAS,EAAE,MAAM,CAAC,SAAS,IAAI,+BAA+B;YAC9D,UAAU,EAAE,MAAM,CAAC,UAAU;YAC7B,UAAU,EAAE,MAAM,CAAC,gBAAgB;YACnC,OAAO,EAAE,IAAI,CAAC,aAAa;YAC3B,QAAQ,EAAE;gBACR,SAAS,EAAE,MAAM,CAAC,SAAS;gBAC3B,MAAM,EAAE,MAAM,CAAC,MAAM;gBACrB,GAAG,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,MAAM,CAAC,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;aACpF;SACF,CAAC,CAAA;QAEF,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,CAAC,GAAG,EAAE,CAAA;IACtC,CAAC;IAAC,OAAO,CAAM,EAAE,CAAC;QAChB,OAAO,CAAC,IAAI,CAAC,wBAAwB,MAAM,CAAC,QAAQ,UAAU,EAAE,CAAC,CAAC,OAAO,CAAC,CAAA;QAC1E,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,CAAC,OAAO,EAAE,CAAA;IACxC,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,eAAe,CAC5B,OAAY,EACZ,SAAiB,EACjB,MAAc,EACd,KAAoC;IAEpC,yDAAyD;IACzD,MAAM,MAAM,GAAQ,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA;IAC5D,IAAI,KAAK,EAAE,CAAC;QAAC,MAAM,CAAC,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC;QAAC,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC,EAAE,CAAA;IAAC,CAAC;IACvE,MAAM,QAAQ,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAC9C,KAAK,MAAM,GAAG,IAAI,QAAQ,EAAE,CAAC;QAC3B,MAAM,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAS,CAAC,CAAA;IAC7D,CAAC;IAED,0BAA0B;IAC1B,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC;QACxC,OAAO,EAAE,SAAS;QAClB,IAAI,EAAE,MAAM;QACZ,MAAM,EAAE,QAAQ;QAChB,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACxD,CAAC,CAAA;IAET,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,CAAA;AACnC,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,cAAc,CAAC,IAAY;IACxC,MAAM,EAAE,aAAa,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAA;IACjE,IAAI,aAAa,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAM;IAE1C,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB;gBAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAA;YACvF,MAAM,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAA;YAC1F,gBAAgB,CAAC,oBAAoB,EAAE,CAAC,CAAA;YACxC,MAAK;QACP,CAAC;QACD,KAAK,UAAU,CAAC,CAAC,CAAC;YAChB,mEAAmE;YACnE,kEAAkE;YAClE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,MAAM,CAAC,iBAAiB,CAAC,CAAA;YAClD,MAAM,WAAW,GAAG,MAAM,CAAC,qBAAqB,CAAC,IAAI,MAAM,CAAC,kBAAkB,CAAC,CAAA;YAC/E,IAAI,CAAC,WAAW;gBAAE,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAA;YACvE,MAAM,EAAE,sBAAsB,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAA;YAC5F,gBAAgB,CAAC,sBAAsB,EAAE,CAAC,CAAA;YAC1C,MAAK;QACP,CAAC;QACD,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB;gBAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAA;YACrF,MAAM,EAAE,oBAAoB,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAA;YAC1F,gBAAgB,CAAC,oBAAoB,EAAE,CAAC,CAAA;YACxC,MAAK;QACP,CAAC;QACD,KAAK,OAAO,CAAC,CAAC,CAAC;YACb,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB;gBAAE,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAA;YACvF,MAAM,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,GAAG,MAAM,MAAM,CAAC,yBAAyB,CAAC,CAAA;YACzF,gBAAgB,CAAC,mBAAmB,EAAE,CAAC,CAAA;YACvC,MAAK;QACP,CAAC;QACD;YACE,MAAM,IAAI,KAAK,CAAC,6BAA6B,IAAI,EAAE,CAAC,CAAA;IACxD,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC7C,OAA8C,EAC9C,SAAiB;IAEjB,MAAM,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAA;IAC5C,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAA;IAErC,kCAAkC;IAClC,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAA;IAC9E,KAAK,MAAM,GAAG,IAAI,MAAM,EAAE,CAAC;QACzB,MAAM,OAAO,CAAC,MAAM,CAAE,GAAW,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,UAAU,EAAS,CAAC,CAAA;IACtE,CAAC;IAED,8BAA8B;IAC9B,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,OAAO,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC,CAAA;IAC1D,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC3B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,CAAA,CAAC,uBAAuB;IAC7C,CAAC;IAED,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,MAAM,CAAC;QACxC,OAAO,EAAE,SAAS;QAClB,IAAI,EAAG,SAAS,CAAC,CAAC,CAAS,CAAC,EAAE;QAC9B,MAAM,EAAE,QAAQ;KACV,CAAC,CAAA;IAET,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,CAAA;AACnC,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,OAA8C,EAC9C,MAAoE;IAEpE,MAAM,OAAO,GAAG,mBAAmB,CAAC,OAAO,CAAC,CAAA;IAC5C,MAAM,MAAM,GAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAA;IACxC,IAAI,MAAM,CAAC,SAAS;QAAE,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,SAAS,CAAA;IACvD,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QAAC,MAAM,CAAC,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;QAAC,MAAM,CAAC,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,EAAE,CAAA;IAAC,CAAC;IAC5F,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IAC1C,OAAO,IAAI,IAAI,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;AACjD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscription.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/subscription.schema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEtD,eAAO,MAAM,kBAAkB,EAAE,
|
|
1
|
+
{"version":3,"file":"subscription.schema.d.ts","sourceRoot":"","sources":["../../src/schemas/subscription.schema.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEtD,eAAO,MAAM,kBAAkB,EAAE,YA+BhC,CAAA"}
|
|
@@ -11,6 +11,12 @@ export const SubscriptionSchema = {
|
|
|
11
11
|
currentPeriodEnd: { type: 'date' },
|
|
12
12
|
cancelAt: { type: 'date' },
|
|
13
13
|
trialEnd: { type: 'date' },
|
|
14
|
+
// Scope générique (optionnel, additif/non-breaking) : à quelle ENTITÉ l'abonnement
|
|
15
|
+
// est rattaché. Par défaut 'account' = comportement historique (abo niveau compte).
|
|
16
|
+
// 'course' (race-event), 'project', … → permet PLUSIEURS abos actifs par compte,
|
|
17
|
+
// un par entité scopée. Cf. findActiveSubscription().
|
|
18
|
+
scopeType: { type: 'string', default: 'account' },
|
|
19
|
+
scopeId: { type: 'string' },
|
|
14
20
|
},
|
|
15
21
|
relations: {
|
|
16
22
|
account: { type: 'many-to-one', target: 'Account', required: true },
|
|
@@ -19,6 +25,8 @@ export const SubscriptionSchema = {
|
|
|
19
25
|
indexes: [
|
|
20
26
|
{ fields: { status: 'asc' } },
|
|
21
27
|
{ fields: { stripeSubId: 'asc' }, unique: true },
|
|
28
|
+
// Recherche d'abo actif par scope (account|course|…)
|
|
29
|
+
{ fields: { scopeType: 'asc', scopeId: 'asc' } },
|
|
22
30
|
],
|
|
23
31
|
};
|
|
24
32
|
//# sourceMappingURL=subscription.schema.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"subscription.schema.js","sourceRoot":"","sources":["../../src/schemas/subscription.schema.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,wCAAwC;AAIxC,MAAM,CAAC,MAAM,kBAAkB,GAAiB;IAC9C,IAAI,EAAE,cAAc;IACpB,UAAU,EAAE,eAAe;IAC3B,UAAU,EAAE,IAAI;IAEhB,MAAM,EAAE;QACN,MAAM,EAAc,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE;QACzE,WAAW,EAAS,EAAE,IAAI,EAAE,QAAQ,EAAE;QACtC,kBAAkB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;QACpC,gBAAgB,EAAI,EAAE,IAAI,EAAE,MAAM,EAAE;QACpC,QAAQ,EAAY,EAAE,IAAI,EAAE,MAAM,EAAE;QACpC,QAAQ,EAAY,EAAE,IAAI,EAAE,MAAM,EAAE;
|
|
1
|
+
{"version":3,"file":"subscription.schema.js","sourceRoot":"","sources":["../../src/schemas/subscription.schema.ts"],"names":[],"mappings":"AAAA,oDAAoD;AACpD,wCAAwC;AAIxC,MAAM,CAAC,MAAM,kBAAkB,GAAiB;IAC9C,IAAI,EAAE,cAAc;IACpB,UAAU,EAAE,eAAe;IAC3B,UAAU,EAAE,IAAI;IAEhB,MAAM,EAAE;QACN,MAAM,EAAc,EAAE,IAAI,EAAE,QAAQ,EAAE,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAE;QACzE,WAAW,EAAS,EAAE,IAAI,EAAE,QAAQ,EAAE;QACtC,kBAAkB,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE;QACpC,gBAAgB,EAAI,EAAE,IAAI,EAAE,MAAM,EAAE;QACpC,QAAQ,EAAY,EAAE,IAAI,EAAE,MAAM,EAAE;QACpC,QAAQ,EAAY,EAAE,IAAI,EAAE,MAAM,EAAE;QACpC,mFAAmF;QACnF,oFAAoF;QACpF,iFAAiF;QACjF,sDAAsD;QACtD,SAAS,EAAW,EAAE,IAAI,EAAE,QAAQ,EAAE,OAAO,EAAE,SAAS,EAAE;QAC1D,OAAO,EAAa,EAAE,IAAI,EAAE,QAAQ,EAAE;KACvC;IAED,SAAS,EAAE;QACT,OAAO,EAAE,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,IAAI,EAAE;QACnE,IAAI,EAAK,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE;KACjE;IAED,OAAO,EAAE;QACP,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE;QAC7B,EAAE,MAAM,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;QAChD,qDAAqD;QACrD,EAAE,MAAM,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;KACjD;CACF,CAAA"}
|
package/dist/server.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
export { getPlanRepo, getSubscriptionRepo, getInvoiceRepo, getUsageLogRepo, resetRepos, } from './lib/plan-factory.js';
|
|
2
2
|
export { checkQuota, isDialectAllowed, isTransportAllowed, getUsageSummary, incrementUsage, DEFAULT_PLANS, } from './lib/quota-check.js';
|
|
3
3
|
export { createBillingSession, createPortalSession, createStripeCustomer, cancelSubscription, changeSubscriptionPlan, verifyWebhookEvent, parseBillingEvent, } from './lib/stripe-billing.js';
|
|
4
|
-
export { subscribeToPlan, cancelCurrentSubscription } from './lib/subscribe.js';
|
|
4
|
+
export { subscribeToPlan, cancelCurrentSubscription, findActiveSubscription } from './lib/subscribe.js';
|
|
5
5
|
export type { SubscribeParams, SubscribeResult } from './lib/subscribe.js';
|
|
6
6
|
export { createPlanHandlers } from './api/plans.route.js';
|
|
7
7
|
export { createSubscriptionHandlers } from './api/subscriptions.route.js';
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,UAAU,GACX,MAAM,uBAAuB,CAAA;AAG9B,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,aAAa,GACd,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,yBAAyB,CAAA;AAGhC,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAIA,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,UAAU,GACX,MAAM,uBAAuB,CAAA;AAG9B,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,aAAa,GACd,MAAM,sBAAsB,CAAA;AAG7B,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,yBAAyB,CAAA;AAGhC,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AACvG,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AAG1E,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAA;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAG1D,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAG7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,eAAe,CAAA"}
|
package/dist/server.js
CHANGED
|
@@ -7,7 +7,7 @@ export { checkQuota, isDialectAllowed, isTransportAllowed, getUsageSummary, incr
|
|
|
7
7
|
// Stripe Billing
|
|
8
8
|
export { createBillingSession, createPortalSession, createStripeCustomer, cancelSubscription, changeSubscriptionPlan, verifyWebhookEvent, parseBillingEvent, } from './lib/stripe-billing.js';
|
|
9
9
|
// Subscribe (multi-provider via @mostajs/payment)
|
|
10
|
-
export { subscribeToPlan, cancelCurrentSubscription } from './lib/subscribe.js';
|
|
10
|
+
export { subscribeToPlan, cancelCurrentSubscription, findActiveSubscription } from './lib/subscribe.js';
|
|
11
11
|
// API handlers
|
|
12
12
|
export { createPlanHandlers } from './api/plans.route.js';
|
|
13
13
|
export { createSubscriptionHandlers } from './api/subscriptions.route.js';
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,wCAAwC;AAExC,eAAe;AACf,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,UAAU,GACX,MAAM,uBAAuB,CAAA;AAE9B,oBAAoB;AACpB,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,aAAa,GACd,MAAM,sBAAsB,CAAA;AAE7B,iBAAiB;AACjB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,yBAAyB,CAAA;AAEhC,kDAAkD;AAClD,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,6EAA6E;AAC7E,wCAAwC;AAExC,eAAe;AACf,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,cAAc,EACd,eAAe,EACf,UAAU,GACX,MAAM,uBAAuB,CAAA;AAE9B,oBAAoB;AACpB,OAAO,EACL,UAAU,EACV,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,aAAa,GACd,MAAM,sBAAsB,CAAA;AAE7B,iBAAiB;AACjB,OAAO,EACL,oBAAoB,EACpB,mBAAmB,EACnB,oBAAoB,EACpB,kBAAkB,EAClB,sBAAsB,EACtB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,yBAAyB,CAAA;AAEhC,kDAAkD;AAClD,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAA;AAGvG,eAAe;AACf,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAA;AACzD,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAA;AACzE,OAAO,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAA;AAE1D,wBAAwB;AACxB,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AAE7D,eAAe;AACf,OAAO,EAAE,4BAA4B,EAAE,MAAM,eAAe,CAAA"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export interface PlanDTO {
|
|
|
13
13
|
slug: string;
|
|
14
14
|
price: number;
|
|
15
15
|
currency: string;
|
|
16
|
-
interval: 'month' | 'year';
|
|
16
|
+
interval: 'month' | 'year' | 'one_time';
|
|
17
17
|
stripePriceId?: string;
|
|
18
18
|
limits: PlanLimits;
|
|
19
19
|
features: string[];
|
|
@@ -33,9 +33,18 @@ export interface SubscriptionDTO {
|
|
|
33
33
|
currentPeriodEnd?: string;
|
|
34
34
|
cancelAt?: string;
|
|
35
35
|
trialEnd?: string;
|
|
36
|
+
/** Scope générique (optionnel) : 'account' (défaut) | 'course' | 'project' | … */
|
|
37
|
+
scopeType?: string;
|
|
38
|
+
/** Id de l'entité scopée (ex. courseId) quand scopeType ≠ 'account' */
|
|
39
|
+
scopeId?: string;
|
|
36
40
|
createdAt?: string;
|
|
37
41
|
updatedAt?: string;
|
|
38
42
|
}
|
|
43
|
+
/** Scope d'un abonnement — entité à laquelle il est rattaché. */
|
|
44
|
+
export interface SubscriptionScope {
|
|
45
|
+
type: string;
|
|
46
|
+
id: string;
|
|
47
|
+
}
|
|
39
48
|
export type InvoiceStatus = 'open' | 'paid' | 'void' | 'uncollectible';
|
|
40
49
|
export interface InvoiceDTO {
|
|
41
50
|
id: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,UAAU;IACzB,WAAW,EAAE,MAAM,CAAA;IACnB,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;IACtB,WAAW,EAAE,MAAM,CAAA;IACnB,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAG,CAAA;IACxB,UAAU,EAAE,MAAM,EAAE,GAAG,GAAG,CAAA;IAC1B,WAAW,EAAE,OAAO,CAAA;CACrB;AAED,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,EAAE,MAAM,CAAA;IACb,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,OAAO,GAAG,MAAM,CAAA;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|
package/llms.txt
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# @mostajs/subscriptions-plan — fiche LLM
|
|
2
|
+
> Plans d'abonnement, facturation, factures et suivi de consommation (quotas) pour @mostajs.
|
|
3
|
+
|
|
4
|
+
- Version: 0.4.0 · Licence: AGPL-3.0-or-later · Auteur: Dr Hamid MADANI <drmdh@msn.com>
|
|
5
|
+
- Chemin: mostajs/mosta-subscriptions-plan · Statut audit: complet (dist/)
|
|
6
|
+
- v0.4.0: SCOPE générique sur Subscription (`scopeType`/`scopeId`, optionnels, défaut 'account') → un compte peut avoir PLUSIEURS abos actifs, un par entité scopée (ex. 'course' pour race-event). Helper `findActiveSubscription({accountId?,scope?})`. `subscribeToPlan(..., {scope})`. `Plan.interval` accepte 'one_time'. Additif/non-breaking (auto-ALTER ORM).
|
|
7
|
+
|
|
8
|
+
## RÔLE
|
|
9
|
+
Gère le cycle de vie d'abonnement SaaS : catalogue de plans (Free/Medium/Premium), souscription (gratuite directe ou payante déléguée à `@mostajs/payment`), facturation Stripe, factures, suivi de consommation journalière (UsageLog) et contrôle de quota par ressource. Fournit les 4 schémas ORM (`Plan`, `Subscription`, `Invoice`, `UsageLog`) et des handlers de routes Next.js App Router.
|
|
10
|
+
|
|
11
|
+
## INSTALLATION
|
|
12
|
+
npm i @mostajs/subscriptions-plan
|
|
13
|
+
|
|
14
|
+
## EXPORTS
|
|
15
|
+
Entrée `.` (types + schémas, sans dépendance serveur lourde) :
|
|
16
|
+
- Schémas: `PlanSchema`, `SubscriptionSchema`, `InvoiceSchema`, `UsageLogSchema`
|
|
17
|
+
- Constante: `moduleInfo`
|
|
18
|
+
- Types: `PlanDTO`, `PlanLimits`, `SubscriptionDTO`, `SubscriptionStatus`, `InvoiceDTO`, `InvoiceStatus`, `UsageLogDTO`, `BillingConfig`, `QuotaCheckResult`
|
|
19
|
+
|
|
20
|
+
## EXPORTS PAR SOUS-CHEMIN
|
|
21
|
+
Entrée `@mostajs/subscriptions-plan/server` :
|
|
22
|
+
- Repos: `getPlanRepo`, `getSubscriptionRepo`, `getInvoiceRepo`, `getUsageLogRepo`, `resetRepos`
|
|
23
|
+
- Quota/usage: `checkQuota`, `isDialectAllowed`, `isTransportAllowed`, `getUsageSummary`, `incrementUsage`, constante `DEFAULT_PLANS`
|
|
24
|
+
- Souscription: `subscribeToPlan`, `cancelCurrentSubscription` (+ types `SubscribeParams`, `SubscribeResult`)
|
|
25
|
+
- Billing Stripe: `createBillingSession`, `createPortalSession`, `createStripeCustomer`, `cancelSubscription`, `changeSubscriptionPlan`, `verifyWebhookEvent`, `parseBillingEvent`
|
|
26
|
+
- Routes Next.js: `createPlanHandlers`, `createSubscriptionHandlers`, `createUsageHandlers`
|
|
27
|
+
- Module: `getSchemas`, `moduleInfo`, `subscriptionPlanRegistration`
|
|
28
|
+
|
|
29
|
+
## API — SIGNATURES
|
|
30
|
+
- `checkQuota(dialect, accountId, resource: 'requests'|'projects'|'apiKeys', currentCount?): Promise<QuotaCheckResult>`
|
|
31
|
+
- `isDialectAllowed(limits: PlanLimits, dialect: string): boolean` · `isTransportAllowed(limits, transport): boolean`
|
|
32
|
+
- `getUsageSummary(dialect, accountId, periodStart): Promise<{ totalRequests; totalReads; totalWrites; totalErrors; days }>`
|
|
33
|
+
- `incrementUsage(dialect, accountId, projectId: string|undefined, type: 'read'|'write'|'error'): Promise<void>` — fire-and-forget
|
|
34
|
+
- `subscribeToPlan(dialect, params: SubscribeParams): Promise<SubscribeResult>`
|
|
35
|
+
- `cancelCurrentSubscription(dialect, accountId): Promise<SubscribeResult>` — annule et repasse en Free
|
|
36
|
+
- `createBillingSession(stripe, config: BillingConfig, params): Promise<{ url; sessionId }>`
|
|
37
|
+
- `createPortalSession(stripe, config, customerId): Promise<{ url }>`
|
|
38
|
+
- `createStripeCustomer(stripe, { email; name; metadata? }): Promise<string>`
|
|
39
|
+
- `cancelSubscription(stripe, stripeSubId, immediate?): Promise<void>` · `changeSubscriptionPlan(stripe, stripeSubId, newPriceId): Promise<void>`
|
|
40
|
+
- `verifyWebhookEvent(stripe, body, sig, secret): Promise<Stripe.Event>`
|
|
41
|
+
- `parseBillingEvent(event: Stripe.Event): { type: 'subscription_created'|'subscription_updated'|'subscription_deleted'|'invoice_paid'|'invoice_failed'|'checkout_completed'|'unknown'; data }`
|
|
42
|
+
- `createPlanHandlers(dialect, checkPermission?): { GET; POST; PUT; DELETE }` — GET public, écritures admin
|
|
43
|
+
- `createSubscriptionHandlers(dialect): { GET; POST; PUT }`
|
|
44
|
+
- `createUsageHandlers(dialect): { GET; GETToday; POST }`
|
|
45
|
+
- Repos: `getPlanRepo(dialect): BaseRepository<PlanDTO>` (idem Subscription/Invoice/UsageLog)
|
|
46
|
+
|
|
47
|
+
## TYPES CLÉS
|
|
48
|
+
- `PlanLimits { maxProjects: number; maxApiKeys: number; requestsPerDay: number; maxPoolSize: number; dialects: string[]|'*'; transports: string[]|'*'; replication: boolean }`
|
|
49
|
+
- `PlanDTO { id; name; slug; price: number; currency; interval: 'month'|'year'; stripePriceId?; limits: PlanLimits; features: string[]; active: boolean; sortOrder: number; createdAt?; updatedAt? }`
|
|
50
|
+
- `SubscriptionStatus = 'active'|'trialing'|'past_due'|'canceled'|'unpaid'`
|
|
51
|
+
- `SubscriptionDTO { id; accountId; planId; status: SubscriptionStatus; stripeSubId?; currentPeriodStart?; currentPeriodEnd?; cancelAt?; trialEnd?; ... }`
|
|
52
|
+
- `InvoiceStatus = 'open'|'paid'|'void'|'uncollectible'`
|
|
53
|
+
- `InvoiceDTO { id; accountId; subscriptionId?; stripeInvoiceId?; amount; currency; status: InvoiceStatus; paidAt?; periodStart?; periodEnd?; pdfUrl?; hostedUrl?; ... }`
|
|
54
|
+
- `UsageLogDTO { id; accountId; projectId?; date: string; requests; reads; writes; errors; bandwidth; ... }`
|
|
55
|
+
- `BillingConfig { stripeSecretKey; stripeWebhookSecret; successUrl; cancelUrl; portalReturnUrl }`
|
|
56
|
+
- `QuotaCheckResult { allowed: boolean; reason?; current: number; limit: number; resource: string }`
|
|
57
|
+
- `SubscribeParams { accountId; planId; provider?: 'direct'|'stripe'|'chargily'|'paypal'|'satim'; successUrl?; cancelUrl?; webhookUrl?; customerEmail?; customerName?; stripeCustomerId? }`
|
|
58
|
+
- `SubscribeResult { ok: boolean; url?: string|null; subscription?: any; error?: string }`
|
|
59
|
+
|
|
60
|
+
## PATTERN
|
|
61
|
+
```ts
|
|
62
|
+
import { subscribeToPlan, checkQuota } from '@mostajs/subscriptions-plan/server'
|
|
63
|
+
|
|
64
|
+
// Souscription : Free → direct en DB, payant → redirect provider
|
|
65
|
+
const r = await subscribeToPlan(dialect, {
|
|
66
|
+
accountId: 'acc-1', planId: 'plan-premium', provider: 'stripe',
|
|
67
|
+
successUrl: '/billing/ok', cancelUrl: '/billing/ko', customerEmail: 'u@x.com',
|
|
68
|
+
})
|
|
69
|
+
if (r.url) redirect(r.url) // paiement requis
|
|
70
|
+
|
|
71
|
+
// Contrôle de quota
|
|
72
|
+
const q = await checkQuota(dialect, 'acc-1', 'projects')
|
|
73
|
+
if (!q.allowed) throw new Error(q.reason)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## DÉPEND DE
|
|
77
|
+
- `@mostajs/data-plug` (peer dep `^1.2.4`) — façade ORM : `BaseRepository`, `IDialect`, `EntitySchema`.
|
|
78
|
+
- `@mostajs/config` (peer dep) — résolution env.
|
|
79
|
+
- `@mostajs/payment` (peer dep optionnelle `>=0.4.2`) — checkout des plans payants ; `subscribeToPlan` lui délègue.
|
|
80
|
+
- `stripe` (peer dep optionnelle), `next`/`react` (peer deps optionnelles).
|
|
81
|
+
|
|
82
|
+
## PIÈGES
|
|
83
|
+
- `subscribeToPlan` : plan gratuit (`price=0`) → souscription directe en DB ; plan payant → délègue à `@mostajs/payment` et retourne une `url` de redirect ; si aucun provider dispo, fallback en souscription directe.
|
|
84
|
+
- Vérifier `SubscribeResult.url` : non-nul ⇒ il faut rediriger l'utilisateur ; nul ⇒ souscription déjà créée (`subscription`).
|
|
85
|
+
- `incrementUsage` est fire-and-forget — ne pas s'appuyer sur son `await` pour garantir la persistance avant un check de quota.
|
|
86
|
+
- Le sous-chemin `/server` contient la logique sensible (clés Stripe) — ne pas l'importer côté client.
|
|
87
|
+
- `createPlanHandlers` : `GET` est public (page pricing), `POST/PUT/DELETE` exigent le `PermissionChecker` admin — sans checker, les écritures restent ouvertes.
|
|
88
|
+
- `PlanLimits.dialects`/`transports` acceptent `'*'` (tout autorisé) — `isDialectAllowed`/`isTransportAllowed` gèrent ce cas.
|
|
89
|
+
- Repos mis en cache via WeakMap par dialect ; `resetRepos` est un no-op de rétro-compat.
|
|
90
|
+
- Module distinct de `@mostajs/subscriptions` (qui gère plans/accès clients/activités) — ici l'axe est facturation + quotas.
|
|
91
|
+
|
|
92
|
+
## RÉFÉRENCES
|
|
93
|
+
README.md
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mostajs/subscriptions-plan",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Subscription plans, billing, invoices and usage tracking for @mostajs",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -25,13 +25,16 @@
|
|
|
25
25
|
},
|
|
26
26
|
"files": [
|
|
27
27
|
"dist",
|
|
28
|
-
"README.md"
|
|
28
|
+
"README.md",
|
|
29
|
+
"CHANGELOG.md",
|
|
30
|
+
"llms.txt"
|
|
29
31
|
],
|
|
30
32
|
"author": "Dr Hamid MADANI <drmdh@msn.com>",
|
|
31
33
|
"license": "AGPL-3.0-or-later",
|
|
32
34
|
"peerDependencies": {
|
|
35
|
+
"@mostajs/config": "^1.0.0",
|
|
33
36
|
"@mostajs/data-plug": "^1.2.4",
|
|
34
|
-
"@mostajs/payment": ">=0.4.
|
|
37
|
+
"@mostajs/payment": ">=0.4.2",
|
|
35
38
|
"next": ">=14.0.0",
|
|
36
39
|
"react": ">=18.0.0",
|
|
37
40
|
"stripe": ">=17.0.0"
|