@qelos/sdk 4.0.0 → 4.1.1

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.
@@ -1,6 +1,36 @@
1
1
  import { QelosSDKOptions } from '../types';
2
2
  import BaseSDK from '../base-sdk';
3
- import { IPlan, ISubscription, IInvoice, ICoupon, BillableEntityType, SubscriptionStatus, InvoiceStatus } from '@qelos/global-types';
3
+ import { IPlan, ISubscription, IInvoice, ICoupon, BillableEntityType, SubscriptionStatus, InvoiceStatus, BillingCycle } from '@qelos/global-types';
4
+ export interface AdminCheckoutRequest {
5
+ planId: string;
6
+ billingCycle: BillingCycle;
7
+ /** When omitted, the authenticated user / default billable entity is used (same as public checkout). */
8
+ billableEntityType?: BillableEntityType;
9
+ billableEntityId?: string;
10
+ couponCode?: string;
11
+ successUrl?: string;
12
+ cancelUrl?: string;
13
+ /**
14
+ * Admin-only. For plans with `dynamic: true`, sets the `dynamicAmount` on the
15
+ * pending subscription before initiating checkout. Regular users cannot set this;
16
+ * use `setSubscriptionDynamicAmount()` + a separate `checkout()` call instead.
17
+ */
18
+ amount?: number;
19
+ }
20
+ export interface CreateSubscriptionData {
21
+ planId: string;
22
+ billingCycle: BillingCycle;
23
+ billableEntityType: BillableEntityType;
24
+ billableEntityId: string;
25
+ /** Required for plans with `dynamic: true` before checkout can be initiated. */
26
+ dynamicAmount?: number;
27
+ couponCode?: string;
28
+ }
29
+ export interface AdminCheckoutResponse {
30
+ subscriptionId: string;
31
+ checkoutUrl?: string;
32
+ clientToken?: string;
33
+ }
4
34
  export default class QlPaymentsAdmin extends BaseSDK {
5
35
  private options;
6
36
  constructor(options: QelosSDKOptions);
@@ -11,13 +41,29 @@ export default class QlPaymentsAdmin extends BaseSDK {
11
41
  createPlan(data: Omit<IPlan, '_id' | 'tenant' | 'created'>): Promise<IPlan>;
12
42
  updatePlan(planId: string, data: Partial<IPlan>): Promise<IPlan>;
13
43
  deletePlan(planId: string): Promise<IPlan>;
44
+ /**
45
+ * Start subscription checkout (same as `sdk.payments.checkout`, plus optional billable-entity overrides for admins).
46
+ * For plans with `dynamic: true`, `amount` is required.
47
+ */
48
+ checkout(params: AdminCheckoutRequest): Promise<AdminCheckoutResponse>;
14
49
  getSubscriptions(query?: {
15
50
  billableEntityType?: BillableEntityType;
16
51
  billableEntityId?: string;
17
52
  status?: SubscriptionStatus;
18
53
  }): Promise<ISubscription[]>;
19
54
  getSubscription(subscriptionId: string): Promise<ISubscription>;
55
+ /**
56
+ * Creates a pending subscription on behalf of any billable entity. Admins can
57
+ * also set `dynamicAmount` here for dynamic plans, making the subscription
58
+ * immediately ready for checkout.
59
+ */
60
+ createSubscription(data: CreateSubscriptionData): Promise<ISubscription>;
20
61
  cancelSubscription(subscriptionId: string): Promise<ISubscription>;
62
+ /**
63
+ * Sets or updates the dynamic amount for a pending subscription. Only admins
64
+ * can call this. Must be done before a user can complete checkout on a dynamic plan.
65
+ */
66
+ setSubscriptionDynamicAmount(subscriptionId: string, amount: number): Promise<ISubscription>;
21
67
  getInvoices(query?: {
22
68
  billableEntityType?: BillableEntityType;
23
69
  billableEntityId?: string;
@@ -30,6 +30,17 @@ export default class QlPaymentsAdmin extends BaseSDK {
30
30
  deletePlan(planId) {
31
31
  return this.callJsonApi(`/api/plans/${planId}`, { method: 'delete' });
32
32
  }
33
+ /**
34
+ * Start subscription checkout (same as `sdk.payments.checkout`, plus optional billable-entity overrides for admins).
35
+ * For plans with `dynamic: true`, `amount` is required.
36
+ */
37
+ checkout(params) {
38
+ return this.callJsonApi('/api/checkout', {
39
+ method: 'post',
40
+ headers: { 'content-type': 'application/json' },
41
+ body: JSON.stringify(params),
42
+ });
43
+ }
33
44
  // --- Subscriptions ---
34
45
  getSubscriptions(query) {
35
46
  const qs = query ? `?${new URLSearchParams(query)}` : '';
@@ -38,9 +49,32 @@ export default class QlPaymentsAdmin extends BaseSDK {
38
49
  getSubscription(subscriptionId) {
39
50
  return this.callJsonApi(`/api/subscriptions/${subscriptionId}`);
40
51
  }
52
+ /**
53
+ * Creates a pending subscription on behalf of any billable entity. Admins can
54
+ * also set `dynamicAmount` here for dynamic plans, making the subscription
55
+ * immediately ready for checkout.
56
+ */
57
+ createSubscription(data) {
58
+ return this.callJsonApi('/api/subscriptions', {
59
+ method: 'post',
60
+ headers: { 'content-type': 'application/json' },
61
+ body: JSON.stringify(data),
62
+ });
63
+ }
41
64
  cancelSubscription(subscriptionId) {
42
65
  return this.callJsonApi(`/api/subscriptions/${subscriptionId}/cancel`, { method: 'put' });
43
66
  }
67
+ /**
68
+ * Sets or updates the dynamic amount for a pending subscription. Only admins
69
+ * can call this. Must be done before a user can complete checkout on a dynamic plan.
70
+ */
71
+ setSubscriptionDynamicAmount(subscriptionId, amount) {
72
+ return this.callJsonApi(`/api/subscriptions/${subscriptionId}/dynamic-amount`, {
73
+ method: 'put',
74
+ headers: { 'content-type': 'application/json' },
75
+ body: JSON.stringify({ amount }),
76
+ });
77
+ }
44
78
  // --- Invoices ---
45
79
  getInvoices(query) {
46
80
  const qs = query ? `?${new URLSearchParams(query)}` : '';
@@ -1 +1 @@
1
- {"version":3,"file":"payments.js","sourceRoot":"","sources":["../../src/administrator/payments.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"payments.js","sourceRoot":"","sources":["../../src/administrator/payments.ts"],"names":[],"mappings":"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"}
@@ -49,7 +49,18 @@ export interface IApiToken {
49
49
  export type SocialProvider = 'linkedin' | 'facebook' | 'google' | 'github';
50
50
  export interface SocialLoginOptions {
51
51
  state?: string;
52
+ /**
53
+ * Where Qelos redirects after OAuth with `?rt=<refreshToken>` (SDK flow).
54
+ * Absolute URLs must use a host listed in app-configuration `metadata.websiteUrls`.
55
+ */
52
56
  returnUrl?: string;
57
+ /**
58
+ * Overrides the OAuth provider callback origin when its host is listed in
59
+ * app-configuration `metadata.websiteUrls`. The callback path stays
60
+ * `/api/auth/<provider>/callback` on that origin. When omitted, Qelos uses
61
+ * the request tenant host (`tenanthost`).
62
+ */
63
+ redirectUrl?: string;
53
64
  }
54
65
  export interface SocialAuthCallbackPayload {
55
66
  payload: BasicPayload & {
@@ -1,4 +1,5 @@
1
1
  import BaseSDK from './base-sdk';
2
+ import { decodeMeUser } from './services/decode-uri-fields';
2
3
  function collectSetCookieHeaders(res) {
3
4
  const h = res.headers;
4
5
  if (typeof h.getSetCookie === 'function') {
@@ -166,7 +167,7 @@ export default class QlAuthentication extends BaseSDK {
166
167
  async apiTokenSignin(apiToken) {
167
168
  this.#apiToken = apiToken;
168
169
  this.qlOptions.apiToken = apiToken;
169
- return this.callJsonApi('/api/me');
170
+ return this.callJsonApi('/api/me').then(decodeMeUser);
170
171
  }
171
172
  listApiTokens() {
172
173
  return this.callJsonApi('/api/me/api-tokens');
@@ -192,6 +193,8 @@ export default class QlAuthentication extends BaseSDK {
192
193
  params.state = options.state;
193
194
  if (options.returnUrl)
194
195
  params.returnUrl = options.returnUrl;
196
+ if (options.redirectUrl)
197
+ params.redirectUrl = options.redirectUrl;
195
198
  const qs = Object.keys(params).length ? `?${new URLSearchParams(params)}` : '';
196
199
  return this.buildUrl(`/api/auth/${provider}${qs}`);
197
200
  }
@@ -249,14 +252,14 @@ export default class QlAuthentication extends BaseSDK {
249
252
  return this.exchangeAuthCallback(refreshToken);
250
253
  }
251
254
  getLoggedInUser() {
252
- return this.callJsonApi('/api/me');
255
+ return this.callJsonApi('/api/me').then(decodeMeUser);
253
256
  }
254
257
  updateLoggedInUser(changes) {
255
258
  return this.callJsonApi('/api/me', {
256
259
  method: 'post',
257
260
  headers: { 'content-type': 'application/json' },
258
261
  body: JSON.stringify(changes)
259
- });
262
+ }).then(decodeMeUser);
260
263
  }
261
264
  }
262
265
  //# sourceMappingURL=authentication.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"authentication.js","sourceRoot":"","sources":["../src/authentication.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"authentication.js","sourceRoot":"","sources":["../src/authentication.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,YAAY,CAAC;AACjC,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAsF5D,SAAS,uBAAuB,CAAC,GAAa;IAC5C,MAAM,CAAC,GAAG,GAAG,CAAC,OAAsD,CAAC;IACrE,IAAI,OAAO,CAAC,CAAC,YAAY,KAAK,UAAU,EAAE;QACxC,MAAM,IAAI,GAAG,CAAC,CAAC,YAAY,EAAE,CAAC;QAC9B,OAAO,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;KACvC;IACD,MAAM,MAAM,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;IAC7C,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACvC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,+BAA+B,CAAC,KAA0B;IACxE,IAAI,KAAK,YAAY,GAAG,EAAE;QACxB,OAAO,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;KAClD;IACD,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;QAC7B,IAAI;YACF,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,EAAE,sCAAsC,CAAC,CAAC;YACjE,OAAO,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;SAC9C;QAAC,MAAM;YACN,OAAO,SAAS,CAAC;SAClB;KACF;IACD,IAAI,KAAK,YAAY,eAAe,EAAE;QACpC,OAAO,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC;KACrC;IACD,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC;IACxB,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE;QACtB,OAAO,GAAG,CAAC,CAAC,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;KAClE;IACD,OAAO,OAAO,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,CAAC;AACnD,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,2BAA2B,CAAC,MAAiC;IAC3E,IAAI,MAAM,CAAC,gBAAgB,EAAE,MAAM,EAAE;QACnC,OAAO,MAAM,CAAC,gBAAgB,CAAC;KAChC;IACD,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACvC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACtB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sCAAsC,CACpD,GAAgE,EAChE,MAAiC;IAEjC,MAAM,KAAK,GAAG,2BAA2B,CAAC,MAAM,CAAC,CAAC;IAClD,IAAI,CAAC,KAAK,CAAC,MAAM;QAAE,OAAO;IAC1B,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,CAAC,OAAO,OAAO,gBAAiB,SAAQ,OAAO;IAEnD,aAAa,CAAS;IACtB,YAAY,CAAS;IACrB,SAAS,CAAS;IAElB,IAAI,WAAW;QACb,OAAO,IAAI,CAAC,YAAY,CAAC;IAC3B,CAAC;IAED,IAAI,cAAc;QAChB,OAAO,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC;IAC1B,CAAC;IAED,YAAY,OAAwB;QAClC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,cAAc,EAAE;YACjD,IAAI,CAAC,YAAY,GAAG,OAAO,CAAC,WAAW,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;YACpE,OAAO,OAAO,CAAC,WAAW,CAAC;SAC5B;QACD,IAAI,OAAO,CAAC,YAAY,EAAE;YACxB,IAAI,CAAC,aAAa,GAAG,OAAO,CAAC,YAAY,CAAC;YAC1C,OAAO,OAAO,CAAC,YAAY,CAAC;SAC7B;QACD,IAAI,OAAO,CAAC,QAAQ,EAAE;YACpB,IAAI,CAAC,SAAS,GAAG,OAAO,CAAC,QAAQ,CAAC;SACnC;IACH,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,WAAyB;QACpC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE;YAC5C,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;SAClC,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE;YACX,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAA;SACnC;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAA8B,CAAA;QAE5D,OAAO;YACL,GAAG,IAAI;YACP,OAAO,EAAE;gBACP,YAAY,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,YAAY,CAAC;aAC7C;SACF,CAAA;IACH,CAAC;IAED,WAAW,CAAC,WAAyB;QACnC,OAAO,IAAI,CAAC,WAAW,CACrB,aAAa,EACb;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;SAC5D,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,EAAE;YACX,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;YACvC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;YAC/C,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAA;IACN,CAAC;IAED,MAAM,CAAC,WAA+B;QACpC,OAAO,IAAI,CAAC,WAAW,CACrB,aAAa,EACb;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC;SAClC,CAAC,CAAA;IACN,CAAC;IAED,WAAW,CAAC,WAA+B;QACzC,OAAO,IAAI,CAAC,WAAW,CACrB,aAAa,EACb;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,WAAW,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC;SAC5D,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,EAAE;YACX,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;YACvC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;YAC/C,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAA;IACN,CAAC;IAED,YAAY,CAAC,YAAqB;QAChC,YAAY,GAAG,YAAY,IAAI,IAAI,CAAC,aAAa,CAAC;QAClD,IAAI,CAAC,YAAY,EAAE;YACjB,MAAM,IAAI,KAAK,CAAC,kCAAkC,CAAC,CAAC;SACrD;QACD,OAAO,IAAI,CAAC,WAAW,CACrB,oBAAoB,EACpB;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE;gBACP,aAAa,EAAE,SAAS,GAAG,YAAY;aACxC;SACF,CAAC;aACD,IAAI,CAAC,IAAI,CAAC,EAAE;YACX,IAAI,CAAC,YAAY,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC;YACvC,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;YAC/C,OAAO,IAAI,CAAC;QACd,CAAC,CAAC,CAAA;IACN,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,WAAoB;QAC3C,MAAM,OAAO,GAA2B,EAAE,CAAC;QAC3C,IAAI,WAAW,EAAE;YACf,OAAO,CAAC,aAAa,GAAG,SAAS,GAAG,WAAW,CAAC;SACjD;QACD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,qBAAqB,EAAE;YACpD,MAAM,EAAE,MAAM;YACd,OAAO;SACR,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE;YACX,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;SACnD;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAK7B,CAAC;QACF,OAAO;YACL,GAAG,IAAI;YACP,OAAO,EAAE;gBACP,YAAY,EAAE,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,YAAY,CAAC;aAC7C;SACF,CAAC;IACJ,CAAC;IAED,KAAK,CAAC,cAAc,CAAC,QAAgB;QACnC,IAAI,CAAC,SAAS,GAAG,QAAQ,CAAC;QAC1B,IAAI,CAAC,SAAS,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACnC,OAAO,IAAI,CAAC,WAAW,CAAQ,SAAS,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC/D,CAAC;IAED,aAAa;QACX,OAAO,IAAI,CAAC,WAAW,CAAc,oBAAoB,CAAC,CAAC;IAC7D,CAAC;IAED,cAAc,CAAC,IAAiE;QAC9E,OAAO,IAAI,CAAC,WAAW,CAAyC,oBAAoB,EAAE;YACpF,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC;SAC3B,CAAC,CAAC;IACL,CAAC;IAED,cAAc,CAAC,OAAe;QAC5B,OAAO,IAAI,CAAC,WAAW,CAAO,sBAAsB,OAAO,EAAE,EAAE;YAC7D,MAAM,EAAE,QAAQ;SACjB,CAAC,CAAC;IACL,CAAC;IAED,MAAM;QACJ,OAAO,IAAI,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAA;IACxD,CAAC;IAED,iBAAiB,CAAC,QAAwB,EAAE,UAA8B,EAAE;QAC1E,MAAM,MAAM,GAA2B,EAAE,CAAC;QAC1C,IAAI,OAAO,CAAC,KAAK;YAAE,MAAM,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC;QAChD,IAAI,OAAO,CAAC,SAAS;YAAE,MAAM,CAAC,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;QAC5D,IAAI,OAAO,CAAC,WAAW;YAAE,MAAM,CAAC,WAAW,GAAG,OAAO,CAAC,WAAW,CAAC;QAClE,MAAM,EAAE,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,eAAe,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC/E,OAAO,IAAI,CAAC,QAAQ,CAAC,aAAa,QAAQ,GAAG,EAAE,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,oBAAoB,CAAC,QAAwB;QAC3C,OAAO,IAAI,CAAC,QAAQ,CAAC,aAAa,QAAQ,WAAW,CAAC,CAAC;IACzD,CAAC;IAED,gBAAgB,CAAC,QAAwB,EAAE,OAA4B;QACrE,MAAM,QAAQ,GAAI,UAAkB,CAAC,QAAQ,CAAC;QAC9C,IAAI,CAAC,QAAQ,EAAE;YACb,MAAM,IAAI,KAAK,CAAC,iDAAiD,CAAC,CAAC;SACpE;QACD,QAAQ,CAAC,IAAI,GAAG,IAAI,CAAC,iBAAiB,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC5D,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,YAAoB;QAC7C,IAAI,CAAC,YAAY,EAAE;YACjB,MAAM,IAAI,KAAK,CAAC,2BAA2B,CAAC,CAAC;SAC9C;QACD,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,yBAAyB,kBAAkB,CAAC,YAAY,CAAC,EAAE,EAAE;YAC1F,MAAM,EAAE,MAAM;YACd,KAAK,EAAE,UAAU;SAClB,CAAC,CAAC;QACH,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE;YACX,IAAI,MAAM,GAAG,EAAE,CAAC;YAChB,IAAI;gBACF,MAAM,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;aAC3C;YAAC,MAAM;gBACN,YAAY;aACb;YACD,MAAM,IAAI,KAAK,CACb,0CAA0C,GAAG,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,MAAM,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACtF,CAAC;SACH;QACD,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,IAAI,EAAE,CAAoD,CAAC;QACnF,MAAM,WAAW,GAAG,uBAAuB,CAAC,GAAG,CAAC,CAAC;QACjD,MAAM,YAAY,GAChB,WAAW,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,YAAY,CAAC,CAAC;QACrD,OAAO;YACL,GAAG,IAAI;YACP,OAAO,EAAE;gBACP,YAAY,EAAE,YAAY,IAAI,IAAI;aACnC;YACD,GAAG,CAAC,WAAW,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC;gBACvC,CAAC,CAAC,EAAE,gBAAgB,EAAE,WAAW,EAAE;gBACnC,CAAC,CAAC,EAAE,CAAC;SACR,CAAC;IACJ,CAAC;IAED;;;;OAIG;IACH,KAAK,CAAC,cAAc,CAAC,KAA0B;QAC7C,MAAM,YAAY,GAAG,+BAA+B,CAAC,KAAK,CAAC,CAAC;QAC5D,IAAI,CAAC,YAAY,EAAE;YACjB,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;SAC/C;QACD,OAAO,IAAI,CAAC,oBAAoB,CAAC,YAAY,CAAC,CAAC;IACjD,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,WAAW,CAAQ,SAAS,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IAC/D,CAAC;IAED,kBAAkB,CAAC,OAA+C;QAChE,OAAO,IAAI,CAAC,WAAW,CAAQ,SAAS,EAAE;YACxC,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;SAC9B,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;IACxB,CAAC;CACF"}
@@ -2,11 +2,19 @@ import { QelosSDKOptions } from './types';
2
2
  import BaseSDK from './base-sdk';
3
3
  import { IPlan, ISubscription, IInvoice, ICoupon, BillingCycle } from '@qelos/global-types';
4
4
  export interface CheckoutRequest {
5
- planId: string;
6
- billingCycle: BillingCycle;
5
+ /** Required when not providing `subscriptionId`. Must be a non-dynamic plan. */
6
+ planId?: string;
7
+ /** Required when not providing `subscriptionId`. */
8
+ billingCycle?: BillingCycle;
7
9
  couponCode?: string;
8
10
  successUrl?: string;
9
11
  cancelUrl?: string;
12
+ /**
13
+ * Pre-created subscription ID. Required for dynamic plans — the admin must set
14
+ * `dynamicAmount` on the subscription before this checkout call will succeed.
15
+ * When provided, `planId` and `billingCycle` are ignored.
16
+ */
17
+ subscriptionId?: string;
10
18
  }
11
19
  export interface CheckoutResponse {
12
20
  subscriptionId: string;
@@ -22,6 +30,24 @@ export default class QlPayments extends BaseSDK {
22
30
  isActive?: boolean;
23
31
  }): Promise<IPlan[]>;
24
32
  getPlan(planId: string): Promise<IPlan>;
33
+ /**
34
+ * Creates a pending subscription for the authenticated user without initiating
35
+ * payment. Use this as the first step for any plan, and the only step before
36
+ * `checkout()` for dynamic plans (the admin must call `setSubscriptionDynamicAmount`
37
+ * before the user can complete checkout).
38
+ */
39
+ subscribeToPlan(planId: string, billingCycle: BillingCycle, couponCode?: string): Promise<ISubscription>;
40
+ /**
41
+ * Initiates a provider checkout session.
42
+ *
43
+ * **Static plans**: pass `planId` + `billingCycle` (a subscription is created
44
+ * inline).
45
+ *
46
+ * **Dynamic plans**: the user must first call `subscribeToPlan()` to create a
47
+ * pending subscription, then an admin must set the dynamic amount via
48
+ * `setSubscriptionDynamicAmount()`. Only then should this method be called with
49
+ * `subscriptionId` pointing to that pending subscription.
50
+ */
25
51
  checkout(params: CheckoutRequest): Promise<CheckoutResponse>;
26
52
  getMySubscription(): Promise<ISubscription>;
27
53
  cancelSubscription(subscriptionId: string): Promise<ISubscription>;
package/dist/payments.js CHANGED
@@ -11,6 +11,30 @@ export default class QlPayments extends BaseSDK {
11
11
  getPlan(planId) {
12
12
  return this.callJsonApi(`${this.relativePath}/plans/${planId}`);
13
13
  }
14
+ /**
15
+ * Creates a pending subscription for the authenticated user without initiating
16
+ * payment. Use this as the first step for any plan, and the only step before
17
+ * `checkout()` for dynamic plans (the admin must call `setSubscriptionDynamicAmount`
18
+ * before the user can complete checkout).
19
+ */
20
+ subscribeToPlan(planId, billingCycle, couponCode) {
21
+ return this.callJsonApi(`${this.relativePath}/subscriptions`, {
22
+ method: 'post',
23
+ headers: { 'content-type': 'application/json' },
24
+ body: JSON.stringify({ planId, billingCycle, couponCode }),
25
+ });
26
+ }
27
+ /**
28
+ * Initiates a provider checkout session.
29
+ *
30
+ * **Static plans**: pass `planId` + `billingCycle` (a subscription is created
31
+ * inline).
32
+ *
33
+ * **Dynamic plans**: the user must first call `subscribeToPlan()` to create a
34
+ * pending subscription, then an admin must set the dynamic amount via
35
+ * `setSubscriptionDynamicAmount()`. Only then should this method be called with
36
+ * `subscriptionId` pointing to that pending subscription.
37
+ */
14
38
  checkout(params) {
15
39
  return this.callJsonApi(`${this.relativePath}/checkout`, {
16
40
  method: 'post',
@@ -1 +1 @@
1
- {"version":3,"file":"payments.js","sourceRoot":"","sources":["../src/payments.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,YAAY,CAAC;AAmBjC,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,OAAO;IACrC,YAAY,GAAG,MAAM,CAAC;IAE9B,YAAY,OAAwB;QAClC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;IAED,QAAQ,CAAC,KAA8B;QACrC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,eAAe,CAAC,KAAY,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC,WAAW,CAAU,GAAG,IAAI,CAAC,YAAY,gBAAgB,EAAE,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,OAAO,CAAC,MAAc;QACpB,OAAO,IAAI,CAAC,WAAW,CAAQ,GAAG,IAAI,CAAC,YAAY,UAAU,MAAM,EAAE,CAAC,CAAC;IACzE,CAAC;IAED,QAAQ,CAAC,MAAuB;QAC9B,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,WAAW,EAC/B;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;SAC7B,CACF,CAAC;IACJ,CAAC;IAED,iBAAiB;QACf,OAAO,IAAI,CAAC,WAAW,CAAgB,GAAG,IAAI,CAAC,YAAY,mBAAmB,CAAC,CAAC;IAClF,CAAC;IAED,kBAAkB,CAAC,cAAsB;QACvC,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,kBAAkB,cAAc,SAAS,EAC7D,EAAE,MAAM,EAAE,KAAK,EAAE,CAClB,CAAC;IACJ,CAAC;IAED,WAAW,CAAC,KAA2B;QACrC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,eAAe,CAAC,KAAY,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC,WAAW,CAAa,GAAG,IAAI,CAAC,YAAY,YAAY,EAAE,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,UAAU,CAAC,SAAiB;QAC1B,OAAO,IAAI,CAAC,WAAW,CAAW,GAAG,IAAI,CAAC,YAAY,aAAa,SAAS,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,cAAc,CAAC,IAAY,EAAE,MAAe;QAC1C,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,mBAAmB,EACvC;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;SACvC,CACF,CAAC;IACJ,CAAC;CACF"}
1
+ {"version":3,"file":"payments.js","sourceRoot":"","sources":["../src/payments.ts"],"names":[],"mappings":"AACA,OAAO,OAAO,MAAM,YAAY,CAAC;AA2BjC,MAAM,CAAC,OAAO,OAAO,UAAW,SAAQ,OAAO;IACrC,YAAY,GAAG,MAAM,CAAC;IAE9B,YAAY,OAAwB;QAClC,KAAK,CAAC,OAAO,CAAC,CAAC;IACjB,CAAC;IAED,QAAQ,CAAC,KAA8B;QACrC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,eAAe,CAAC,KAAY,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC,WAAW,CAAU,GAAG,IAAI,CAAC,YAAY,gBAAgB,EAAE,EAAE,CAAC,CAAC;IAC7E,CAAC;IAED,OAAO,CAAC,MAAc;QACpB,OAAO,IAAI,CAAC,WAAW,CAAQ,GAAG,IAAI,CAAC,YAAY,UAAU,MAAM,EAAE,CAAC,CAAC;IACzE,CAAC;IAED;;;;;OAKG;IACH,eAAe,CAAC,MAAc,EAAE,YAA0B,EAAE,UAAmB;QAC7E,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,gBAAgB,EACpC;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;SAC3D,CACF,CAAC;IACJ,CAAC;IAED;;;;;;;;;;OAUG;IACH,QAAQ,CAAC,MAAuB;QAC9B,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,WAAW,EAC/B;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC;SAC7B,CACF,CAAC;IACJ,CAAC;IAED,iBAAiB;QACf,OAAO,IAAI,CAAC,WAAW,CAAgB,GAAG,IAAI,CAAC,YAAY,mBAAmB,CAAC,CAAC;IAClF,CAAC;IAED,kBAAkB,CAAC,cAAsB;QACvC,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,kBAAkB,cAAc,SAAS,EAC7D,EAAE,MAAM,EAAE,KAAK,EAAE,CAClB,CAAC;IACJ,CAAC;IAED,WAAW,CAAC,KAA2B;QACrC,MAAM,EAAE,GAAG,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,eAAe,CAAC,KAAY,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC,WAAW,CAAa,GAAG,IAAI,CAAC,YAAY,YAAY,EAAE,EAAE,CAAC,CAAC;IAC5E,CAAC;IAED,UAAU,CAAC,SAAiB;QAC1B,OAAO,IAAI,CAAC,WAAW,CAAW,GAAG,IAAI,CAAC,YAAY,aAAa,SAAS,EAAE,CAAC,CAAC;IAClF,CAAC;IAED,cAAc,CAAC,IAAY,EAAE,MAAe;QAC1C,OAAO,IAAI,CAAC,WAAW,CACrB,GAAG,IAAI,CAAC,YAAY,mBAAmB,EACvC;YACE,MAAM,EAAE,MAAM;YACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;YAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;SACvC,CACF,CAAC;IACJ,CAAC;CACF"}
@@ -0,0 +1,4 @@
1
+ /** Mirrors auth `encodeIfNeeded` — only decodes values that are URI-encoded. */
2
+ export declare function decodeIfNeeded(value?: string): string | undefined;
3
+ /** Decodes URI-encoded user fields returned by `GET/POST /api/me`. */
4
+ export declare function decodeMeUser<T extends Record<string, unknown>>(user: T): T;
@@ -0,0 +1,42 @@
1
+ /** Mirrors auth `encodeIfNeeded` — only decodes values that are URI-encoded. */
2
+ export function decodeIfNeeded(value) {
3
+ if (value === undefined || value === null || value === '') {
4
+ return value;
5
+ }
6
+ try {
7
+ const decoded = decodeURIComponent(value);
8
+ if (encodeURIComponent(decoded) === value) {
9
+ return decoded;
10
+ }
11
+ }
12
+ catch {
13
+ // not a valid encoded URI component
14
+ }
15
+ return value;
16
+ }
17
+ const ME_USER_STRING_FIELDS = ['name', 'fullName', 'firstName', 'lastName'];
18
+ /** Decodes URI-encoded user fields returned by `GET/POST /api/me`. */
19
+ export function decodeMeUser(user) {
20
+ if (!user || typeof user !== 'object') {
21
+ return user;
22
+ }
23
+ const result = { ...user };
24
+ for (const field of ME_USER_STRING_FIELDS) {
25
+ const value = result[field];
26
+ if (typeof value === 'string') {
27
+ result[field] = decodeIfNeeded(value);
28
+ }
29
+ }
30
+ const workspace = result.workspace;
31
+ if (workspace && typeof workspace === 'object' && !Array.isArray(workspace)) {
32
+ const ws = workspace;
33
+ if (typeof ws.name === 'string') {
34
+ result.workspace = {
35
+ ...ws,
36
+ name: decodeIfNeeded(ws.name),
37
+ };
38
+ }
39
+ }
40
+ return result;
41
+ }
42
+ //# sourceMappingURL=decode-uri-fields.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"decode-uri-fields.js","sourceRoot":"","sources":["../../src/services/decode-uri-fields.ts"],"names":[],"mappings":"AAAA,gFAAgF;AAChF,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,EAAE,EAAE;QACzD,OAAO,KAAK,CAAC;KACd;IAED,IAAI;QACF,MAAM,OAAO,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAC1C,IAAI,kBAAkB,CAAC,OAAO,CAAC,KAAK,KAAK,EAAE;YACzC,OAAO,OAAO,CAAC;SAChB;KACF;IAAC,MAAM;QACN,oCAAoC;KACrC;IAED,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,qBAAqB,GAAG,CAAC,MAAM,EAAE,UAAU,EAAE,WAAW,EAAE,UAAU,CAAU,CAAC;AAErF,sEAAsE;AACtE,MAAM,UAAU,YAAY,CAAoC,IAAO;IACrE,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE;QACrC,OAAO,IAAI,CAAC;KACb;IAED,MAAM,MAAM,GAAG,EAAE,GAAG,IAAI,EAAE,CAAC;IAE3B,KAAK,MAAM,KAAK,IAAI,qBAAqB,EAAE;QACzC,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QAC5B,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE;YAC5B,MAAkC,CAAC,KAAK,CAAC,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;SACpE;KACF;IAED,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,CAAC;IACnC,IAAI,SAAS,IAAI,OAAO,SAAS,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE;QAC3E,MAAM,EAAE,GAAG,SAAoC,CAAC;QAChD,IAAI,OAAO,EAAE,CAAC,IAAI,KAAK,QAAQ,EAAE;YAC9B,MAAkC,CAAC,SAAS,GAAG;gBAC9C,GAAG,EAAE;gBACL,IAAI,EAAE,cAAc,CAAC,EAAE,CAAC,IAAI,CAAC;aAC9B,CAAC;SACH;KACF;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,301 @@
1
+ # Payments SDK
2
+
3
+ The payments SDK is split into two classes:
4
+
5
+ - **`QlPayments`** (`sdk.payments`) — available to any authenticated user. Covers subscribing, checkout, invoices, and coupon validation. Users cannot set prices.
6
+ - **`QlPaymentsAdmin`** (`adminSdk.payments`) — available to privileged callers only. Extends the user surface with plan/coupon management, cross-entity subscription control, and the ability to set dynamic amounts.
7
+
8
+ ---
9
+
10
+ ## Setup
11
+
12
+ ```typescript
13
+ import { QelosSDK } from '@qelos/sdk';
14
+ import { QelosAdminSDK } from '@qelos/sdk/administrator';
15
+
16
+ const sdk = new QelosSDK({ baseUrl: 'https://your-qelos-instance.com' });
17
+ const adminSdk = new QelosAdminSDK({ baseUrl: 'https://your-qelos-instance.com' });
18
+ ```
19
+
20
+ ---
21
+
22
+ ## Static Plan Checkout (One Step)
23
+
24
+ For plans where the price is fixed, the user can subscribe and pay in a single `checkout()` call. Qelos creates the pending subscription internally.
25
+
26
+ ```typescript
27
+ // List available plans
28
+ const plans = await sdk.payments.getPlans({ isActive: true });
29
+ const plan = plans.find(p => p.name === 'Pro');
30
+
31
+ // Validate an optional coupon
32
+ const coupon = await sdk.payments.validateCoupon('SUMMER20', plan._id);
33
+
34
+ // Initiate checkout — subscription is created inline
35
+ const result = await sdk.payments.checkout({
36
+ planId: plan._id,
37
+ billingCycle: 'monthly',
38
+ couponCode: 'SUMMER20',
39
+ successUrl: 'https://myapp.com/success',
40
+ cancelUrl: 'https://myapp.com/cancel',
41
+ });
42
+
43
+ // Redirect the user
44
+ window.location.href = result.checkoutUrl;
45
+ ```
46
+
47
+ ---
48
+
49
+ ## Dynamic Plan Two-Phase Flow
50
+
51
+ Dynamic plans have variable pricing (e.g., usage-based). The user cannot set the amount — only an admin can. The flow is:
52
+
53
+ 1. User creates a pending subscription.
54
+ 2. Admin reviews usage / context and sets the amount.
55
+ 3. User initiates checkout with the subscription ID.
56
+
57
+ ### Step 1 — User subscribes
58
+
59
+ ```typescript
60
+ const subscription = await sdk.payments.subscribeToPlan(
61
+ 'dynamic-plan-id',
62
+ 'monthly',
63
+ );
64
+ // subscription.status === 'pending'
65
+ // Store subscription._id and show the user a "waiting for quote" state
66
+ ```
67
+
68
+ ### Step 2 — Admin sets the amount
69
+
70
+ ```typescript
71
+ // Admin SDK — run server-side or in the admin dashboard
72
+ await adminSdk.payments.setSubscriptionDynamicAmount(
73
+ subscription._id,
74
+ 149.00, // amount in the plan's currency
75
+ );
76
+ ```
77
+
78
+ ### Step 3 — User completes checkout
79
+
80
+ ```typescript
81
+ const result = await sdk.payments.checkout({
82
+ subscriptionId: subscription._id,
83
+ successUrl: 'https://myapp.com/success',
84
+ cancelUrl: 'https://myapp.com/cancel',
85
+ });
86
+
87
+ window.location.href = result.checkoutUrl;
88
+ ```
89
+
90
+ ### Admin convenience shortcut
91
+
92
+ Admins can collapse steps 1–3 into a single call. This creates a pending subscription with the given amount and immediately initiates checkout:
93
+
94
+ ```typescript
95
+ const result = await adminSdk.payments.checkout({
96
+ planId: 'dynamic-plan-id',
97
+ billingCycle: 'monthly',
98
+ amount: 149.00,
99
+ billableEntityType: 'workspace',
100
+ billableEntityId: 'workspace-id',
101
+ successUrl: 'https://myapp.com/success',
102
+ });
103
+ ```
104
+
105
+ ---
106
+
107
+ ## Listing Plans and Subscriptions
108
+
109
+ ### User SDK
110
+
111
+ ```typescript
112
+ // Public plan listing (unauthenticated)
113
+ const plans = await sdk.payments.getPlans({ isActive: true });
114
+
115
+ // Single plan
116
+ const plan = await sdk.payments.getPlan('plan-id');
117
+
118
+ // Current user's active subscription
119
+ const subscription = await sdk.payments.getMySubscription();
120
+
121
+ // User's invoices
122
+ const invoices = await sdk.payments.getInvoices();
123
+ const invoice = await sdk.payments.getInvoice('invoice-id');
124
+ ```
125
+
126
+ ### Admin SDK
127
+
128
+ ```typescript
129
+ // All plans (including inactive)
130
+ const allPlans = await adminSdk.payments.getPlans();
131
+
132
+ // All subscriptions with optional filters
133
+ const workspaceSubs = await adminSdk.payments.getSubscriptions({
134
+ billableEntityType: 'workspace',
135
+ billableEntityId: 'workspace-id',
136
+ status: 'active',
137
+ });
138
+
139
+ // All invoices across entities
140
+ const invoices = await adminSdk.payments.getInvoices({
141
+ billableEntityType: 'user',
142
+ billableEntityId: 'user-id',
143
+ status: 'paid',
144
+ });
145
+ ```
146
+
147
+ ---
148
+
149
+ ## Coupon Validation
150
+
151
+ Validate a coupon before showing it applied in the UI:
152
+
153
+ ```typescript
154
+ try {
155
+ const coupon = await sdk.payments.validateCoupon('PROMO10', 'plan-id');
156
+ console.log(coupon.discountType); // 'percentage' | 'fixed'
157
+ console.log(coupon.discountValue); // e.g. 10 (%)
158
+ } catch (err) {
159
+ // err.code: COUPON_NOT_FOUND | COUPON_EXPIRED | COUPON_NOT_APPLICABLE | ...
160
+ }
161
+ ```
162
+
163
+ ---
164
+
165
+ ## Invoice Retrieval
166
+
167
+ ```typescript
168
+ // User's own invoices
169
+ const invoices = await sdk.payments.getInvoices({ status: 'paid' });
170
+
171
+ // Single invoice (e.g. for download link)
172
+ const invoice = await sdk.payments.getInvoice('invoice-id');
173
+ console.log(invoice.invoiceUrl);
174
+ ```
175
+
176
+ ---
177
+
178
+ ## Cancellation
179
+
180
+ ```typescript
181
+ // User cancels their own subscription
182
+ await sdk.payments.cancelSubscription('subscription-id');
183
+
184
+ // Admin cancels any subscription
185
+ await adminSdk.payments.cancelSubscription('subscription-id');
186
+ ```
187
+
188
+ ---
189
+
190
+ ## Admin Plan Management
191
+
192
+ ```typescript
193
+ // Create a plan
194
+ const plan = await adminSdk.payments.createPlan({
195
+ name: 'Enterprise',
196
+ monthlyPrice: 299,
197
+ yearlyPrice: 2990,
198
+ currency: 'USD',
199
+ dynamic: false,
200
+ isActive: true,
201
+ });
202
+
203
+ // Create a dynamic plan
204
+ const dynamicPlan = await adminSdk.payments.createPlan({
205
+ name: 'Usage-Based',
206
+ currency: 'USD',
207
+ dynamic: true,
208
+ isActive: true,
209
+ monthlyPrice: 0,
210
+ yearlyPrice: 0,
211
+ });
212
+
213
+ // Update
214
+ await adminSdk.payments.updatePlan(plan._id, { monthlyPrice: 349 });
215
+
216
+ // Delete
217
+ await adminSdk.payments.deletePlan(plan._id);
218
+ ```
219
+
220
+ ---
221
+
222
+ ## Admin Coupon Management
223
+
224
+ ```typescript
225
+ // Create a 20% off coupon
226
+ const coupon = await adminSdk.payments.createCoupon({
227
+ code: 'SUMMER20',
228
+ discountType: 'percentage',
229
+ discountValue: 20,
230
+ isActive: true,
231
+ applicablePlanIds: ['plan-id'],
232
+ maxRedemptions: 100,
233
+ });
234
+
235
+ // Update
236
+ await adminSdk.payments.updateCoupon(coupon._id, { isActive: false });
237
+
238
+ // Delete
239
+ await adminSdk.payments.deleteCoupon(coupon._id);
240
+ ```
241
+
242
+ ---
243
+
244
+ ## `QlPayments` Reference (User SDK)
245
+
246
+ | Method | Description |
247
+ |---|---|
248
+ | `getPlans(query?)` | List public plans |
249
+ | `getPlan(planId)` | Get a single plan |
250
+ | `subscribeToPlan(planId, billingCycle, couponCode?)` | Create a pending subscription (first step for dynamic plans) |
251
+ | `checkout(params)` | Initiate a checkout session |
252
+ | `getMySubscription()` | Get the current user's active subscription |
253
+ | `cancelSubscription(subscriptionId)` | Cancel a subscription |
254
+ | `getInvoices(query?)` | List the current user's invoices |
255
+ | `getInvoice(invoiceId)` | Get a single invoice |
256
+ | `validateCoupon(code, planId?)` | Validate a coupon code |
257
+
258
+ ---
259
+
260
+ ## `QlPaymentsAdmin` Reference (Admin SDK)
261
+
262
+ | Method | Description |
263
+ |---|---|
264
+ | `getPlans(query?)` | List all plans |
265
+ | `getPlan(planId)` | Get a single plan |
266
+ | `createPlan(data)` | Create a plan |
267
+ | `updatePlan(planId, data)` | Update a plan |
268
+ | `deletePlan(planId)` | Delete a plan |
269
+ | `checkout(params)` | Initiate checkout with entity overrides and optional `amount` |
270
+ | `getSubscriptions(query?)` | List subscriptions across all entities |
271
+ | `getSubscription(subscriptionId)` | Get a single subscription |
272
+ | `createSubscription(data)` | Create a pending subscription on behalf of any entity |
273
+ | `cancelSubscription(subscriptionId)` | Cancel any subscription |
274
+ | `setSubscriptionDynamicAmount(subscriptionId, amount)` | Set or update the dynamic amount on a pending subscription |
275
+ | `getInvoices(query?)` | List invoices across all entities |
276
+ | `getInvoice(invoiceId)` | Get a single invoice |
277
+ | `getCoupons(query?)` | List coupons |
278
+ | `getCoupon(couponId)` | Get a single coupon |
279
+ | `createCoupon(data)` | Create a coupon |
280
+ | `updateCoupon(couponId, data)` | Update a coupon |
281
+ | `deleteCoupon(couponId)` | Delete a coupon |
282
+
283
+ ---
284
+
285
+ ## Permissions Summary
286
+
287
+ | Action | User SDK | Admin SDK |
288
+ |---|---|---|
289
+ | List/get plans | public plans only | all plans |
290
+ | Create/update/delete plans | no | yes |
291
+ | Create subscription (own entity) | yes | yes |
292
+ | Create subscription (any entity) | no | yes |
293
+ | Set `dynamicAmount` | no | yes |
294
+ | Initiate checkout | yes | yes, with entity override |
295
+ | Set checkout `amount` directly | no | yes (dynamic plans) |
296
+ | List own subscriptions/invoices | yes | yes |
297
+ | List all subscriptions/invoices | no | yes |
298
+ | Cancel own subscription | yes | yes |
299
+ | Cancel any subscription | no | yes |
300
+ | Validate coupon | yes | yes |
301
+ | Manage coupons | no | yes |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qelos/sdk",
3
- "version": "4.0.0",
3
+ "version": "4.1.1",
4
4
  "description": "SDK for Qelos API",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -102,7 +102,7 @@
102
102
  "access": "public"
103
103
  },
104
104
  "dependencies": {
105
- "@qelos/global-types": "^4.0.0"
105
+ "@qelos/global-types": "^4.1.1"
106
106
  },
107
107
  "devDependencies": {
108
108
  "tsx": "^4.21.0",
@@ -2,9 +2,42 @@ import { QelosSDKOptions } from '../types';
2
2
  import BaseSDK from '../base-sdk';
3
3
  import {
4
4
  IPlan, ISubscription, IInvoice, ICoupon,
5
- BillableEntityType, SubscriptionStatus, InvoiceStatus,
5
+ BillableEntityType, SubscriptionStatus, InvoiceStatus, BillingCycle,
6
6
  } from '@qelos/global-types';
7
7
 
8
+ export interface AdminCheckoutRequest {
9
+ planId: string;
10
+ billingCycle: BillingCycle;
11
+ /** When omitted, the authenticated user / default billable entity is used (same as public checkout). */
12
+ billableEntityType?: BillableEntityType;
13
+ billableEntityId?: string;
14
+ couponCode?: string;
15
+ successUrl?: string;
16
+ cancelUrl?: string;
17
+ /**
18
+ * Admin-only. For plans with `dynamic: true`, sets the `dynamicAmount` on the
19
+ * pending subscription before initiating checkout. Regular users cannot set this;
20
+ * use `setSubscriptionDynamicAmount()` + a separate `checkout()` call instead.
21
+ */
22
+ amount?: number;
23
+ }
24
+
25
+ export interface CreateSubscriptionData {
26
+ planId: string;
27
+ billingCycle: BillingCycle;
28
+ billableEntityType: BillableEntityType;
29
+ billableEntityId: string;
30
+ /** Required for plans with `dynamic: true` before checkout can be initiated. */
31
+ dynamicAmount?: number;
32
+ couponCode?: string;
33
+ }
34
+
35
+ export interface AdminCheckoutResponse {
36
+ subscriptionId: string;
37
+ checkoutUrl?: string;
38
+ clientToken?: string;
39
+ }
40
+
8
41
  export default class QlPaymentsAdmin extends BaseSDK {
9
42
  constructor(private options: QelosSDKOptions) {
10
43
  super(options);
@@ -41,6 +74,18 @@ export default class QlPaymentsAdmin extends BaseSDK {
41
74
  return this.callJsonApi<IPlan>(`/api/plans/${planId}`, { method: 'delete' });
42
75
  }
43
76
 
77
+ /**
78
+ * Start subscription checkout (same as `sdk.payments.checkout`, plus optional billable-entity overrides for admins).
79
+ * For plans with `dynamic: true`, `amount` is required.
80
+ */
81
+ checkout(params: AdminCheckoutRequest) {
82
+ return this.callJsonApi<AdminCheckoutResponse>('/api/checkout', {
83
+ method: 'post',
84
+ headers: { 'content-type': 'application/json' },
85
+ body: JSON.stringify(params),
86
+ });
87
+ }
88
+
44
89
  // --- Subscriptions ---
45
90
 
46
91
  getSubscriptions(query?: {
@@ -56,6 +101,19 @@ export default class QlPaymentsAdmin extends BaseSDK {
56
101
  return this.callJsonApi<ISubscription>(`/api/subscriptions/${subscriptionId}`);
57
102
  }
58
103
 
104
+ /**
105
+ * Creates a pending subscription on behalf of any billable entity. Admins can
106
+ * also set `dynamicAmount` here for dynamic plans, making the subscription
107
+ * immediately ready for checkout.
108
+ */
109
+ createSubscription(data: CreateSubscriptionData) {
110
+ return this.callJsonApi<ISubscription>('/api/subscriptions', {
111
+ method: 'post',
112
+ headers: { 'content-type': 'application/json' },
113
+ body: JSON.stringify(data),
114
+ });
115
+ }
116
+
59
117
  cancelSubscription(subscriptionId: string) {
60
118
  return this.callJsonApi<ISubscription>(
61
119
  `/api/subscriptions/${subscriptionId}/cancel`,
@@ -63,6 +121,21 @@ export default class QlPaymentsAdmin extends BaseSDK {
63
121
  );
64
122
  }
65
123
 
124
+ /**
125
+ * Sets or updates the dynamic amount for a pending subscription. Only admins
126
+ * can call this. Must be done before a user can complete checkout on a dynamic plan.
127
+ */
128
+ setSubscriptionDynamicAmount(subscriptionId: string, amount: number) {
129
+ return this.callJsonApi<ISubscription>(
130
+ `/api/subscriptions/${subscriptionId}/dynamic-amount`,
131
+ {
132
+ method: 'put',
133
+ headers: { 'content-type': 'application/json' },
134
+ body: JSON.stringify({ amount }),
135
+ },
136
+ );
137
+ }
138
+
66
139
  // --- Invoices ---
67
140
 
68
141
  getInvoices(query?: {
@@ -1,5 +1,6 @@
1
1
  import { QelosSDKOptions } from './types';
2
2
  import BaseSDK from './base-sdk';
3
+ import { decodeMeUser } from './services/decode-uri-fields';
3
4
 
4
5
  export interface IUser {
5
6
  _id: string;
@@ -54,7 +55,18 @@ export type SocialProvider = 'linkedin' | 'facebook' | 'google' | 'github';
54
55
 
55
56
  export interface SocialLoginOptions {
56
57
  state?: string;
58
+ /**
59
+ * Where Qelos redirects after OAuth with `?rt=<refreshToken>` (SDK flow).
60
+ * Absolute URLs must use a host listed in app-configuration `metadata.websiteUrls`.
61
+ */
57
62
  returnUrl?: string;
63
+ /**
64
+ * Overrides the OAuth provider callback origin when its host is listed in
65
+ * app-configuration `metadata.websiteUrls`. The callback path stays
66
+ * `/api/auth/<provider>/callback` on that origin. When omitted, Qelos uses
67
+ * the request tenant host (`tenanthost`).
68
+ */
69
+ redirectUrl?: string;
58
70
  }
59
71
 
60
72
  export interface SocialAuthCallbackPayload {
@@ -271,7 +283,7 @@ export default class QlAuthentication extends BaseSDK {
271
283
  async apiTokenSignin(apiToken: string): Promise<IUser> {
272
284
  this.#apiToken = apiToken;
273
285
  this.qlOptions.apiToken = apiToken;
274
- return this.callJsonApi<IUser>('/api/me');
286
+ return this.callJsonApi<IUser>('/api/me').then(decodeMeUser);
275
287
  }
276
288
 
277
289
  listApiTokens(): Promise<IApiToken[]> {
@@ -300,6 +312,7 @@ export default class QlAuthentication extends BaseSDK {
300
312
  const params: Record<string, string> = {};
301
313
  if (options.state) params.state = options.state;
302
314
  if (options.returnUrl) params.returnUrl = options.returnUrl;
315
+ if (options.redirectUrl) params.redirectUrl = options.redirectUrl;
303
316
  const qs = Object.keys(params).length ? `?${new URLSearchParams(params)}` : '';
304
317
  return this.buildUrl(`/api/auth/${provider}${qs}`);
305
318
  }
@@ -364,7 +377,7 @@ export default class QlAuthentication extends BaseSDK {
364
377
  }
365
378
 
366
379
  getLoggedInUser() {
367
- return this.callJsonApi<IUser>('/api/me')
380
+ return this.callJsonApi<IUser>('/api/me').then(decodeMeUser);
368
381
  }
369
382
 
370
383
  updateLoggedInUser(changes: Partial<IUser & { password?: string }>): Promise<IUser> {
@@ -372,6 +385,6 @@ export default class QlAuthentication extends BaseSDK {
372
385
  method: 'post',
373
386
  headers: { 'content-type': 'application/json' },
374
387
  body: JSON.stringify(changes)
375
- })
388
+ }).then(decodeMeUser);
376
389
  }
377
390
  }
package/src/payments.ts CHANGED
@@ -3,11 +3,19 @@ import BaseSDK from './base-sdk';
3
3
  import { IPlan, ISubscription, IInvoice, ICoupon, BillingCycle } from '@qelos/global-types';
4
4
 
5
5
  export interface CheckoutRequest {
6
- planId: string;
7
- billingCycle: BillingCycle;
6
+ /** Required when not providing `subscriptionId`. Must be a non-dynamic plan. */
7
+ planId?: string;
8
+ /** Required when not providing `subscriptionId`. */
9
+ billingCycle?: BillingCycle;
8
10
  couponCode?: string;
9
11
  successUrl?: string;
10
12
  cancelUrl?: string;
13
+ /**
14
+ * Pre-created subscription ID. Required for dynamic plans — the admin must set
15
+ * `dynamicAmount` on the subscription before this checkout call will succeed.
16
+ * When provided, `planId` and `billingCycle` are ignored.
17
+ */
18
+ subscriptionId?: string;
11
19
  }
12
20
 
13
21
  export interface CheckoutResponse {
@@ -34,6 +42,34 @@ export default class QlPayments extends BaseSDK {
34
42
  return this.callJsonApi<IPlan>(`${this.relativePath}/plans/${planId}`);
35
43
  }
36
44
 
45
+ /**
46
+ * Creates a pending subscription for the authenticated user without initiating
47
+ * payment. Use this as the first step for any plan, and the only step before
48
+ * `checkout()` for dynamic plans (the admin must call `setSubscriptionDynamicAmount`
49
+ * before the user can complete checkout).
50
+ */
51
+ subscribeToPlan(planId: string, billingCycle: BillingCycle, couponCode?: string) {
52
+ return this.callJsonApi<ISubscription>(
53
+ `${this.relativePath}/subscriptions`,
54
+ {
55
+ method: 'post',
56
+ headers: { 'content-type': 'application/json' },
57
+ body: JSON.stringify({ planId, billingCycle, couponCode }),
58
+ },
59
+ );
60
+ }
61
+
62
+ /**
63
+ * Initiates a provider checkout session.
64
+ *
65
+ * **Static plans**: pass `planId` + `billingCycle` (a subscription is created
66
+ * inline).
67
+ *
68
+ * **Dynamic plans**: the user must first call `subscribeToPlan()` to create a
69
+ * pending subscription, then an admin must set the dynamic amount via
70
+ * `setSubscriptionDynamicAmount()`. Only then should this method be called with
71
+ * `subscriptionId` pointing to that pending subscription.
72
+ */
37
73
  checkout(params: CheckoutRequest) {
38
74
  return this.callJsonApi<CheckoutResponse>(
39
75
  `${this.relativePath}/checkout`,
@@ -0,0 +1,48 @@
1
+ /** Mirrors auth `encodeIfNeeded` — only decodes values that are URI-encoded. */
2
+ export function decodeIfNeeded(value?: string): string | undefined {
3
+ if (value === undefined || value === null || value === '') {
4
+ return value;
5
+ }
6
+
7
+ try {
8
+ const decoded = decodeURIComponent(value);
9
+ if (encodeURIComponent(decoded) === value) {
10
+ return decoded;
11
+ }
12
+ } catch {
13
+ // not a valid encoded URI component
14
+ }
15
+
16
+ return value;
17
+ }
18
+
19
+ const ME_USER_STRING_FIELDS = ['name', 'fullName', 'firstName', 'lastName'] as const;
20
+
21
+ /** Decodes URI-encoded user fields returned by `GET/POST /api/me`. */
22
+ export function decodeMeUser<T extends Record<string, unknown>>(user: T): T {
23
+ if (!user || typeof user !== 'object') {
24
+ return user;
25
+ }
26
+
27
+ const result = { ...user };
28
+
29
+ for (const field of ME_USER_STRING_FIELDS) {
30
+ const value = result[field];
31
+ if (typeof value === 'string') {
32
+ (result as Record<string, unknown>)[field] = decodeIfNeeded(value);
33
+ }
34
+ }
35
+
36
+ const workspace = result.workspace;
37
+ if (workspace && typeof workspace === 'object' && !Array.isArray(workspace)) {
38
+ const ws = workspace as Record<string, unknown>;
39
+ if (typeof ws.name === 'string') {
40
+ (result as Record<string, unknown>).workspace = {
41
+ ...ws,
42
+ name: decodeIfNeeded(ws.name),
43
+ };
44
+ }
45
+ }
46
+
47
+ return result;
48
+ }
@@ -0,0 +1,109 @@
1
+ import * as assert from 'node:assert/strict';
2
+ import { test } from 'node:test';
3
+ import { decodeIfNeeded, decodeMeUser } from '../src/services/decode-uri-fields';
4
+
5
+ test('decodeIfNeeded', async (t) => {
6
+ await t.test('decodes URI-encoded values', () => {
7
+ assert.equal(decodeIfNeeded('David%20Meir-Levy'), 'David Meir-Levy');
8
+ assert.equal(
9
+ decodeIfNeeded(encodeURIComponent('My Workspace / Special & Name')),
10
+ 'My Workspace / Special & Name',
11
+ );
12
+ assert.equal(decodeIfNeeded(encodeURIComponent('José García')), 'José García');
13
+ });
14
+
15
+ await t.test('leaves plain strings unchanged', () => {
16
+ assert.equal(decodeIfNeeded('David Meir-Levy'), 'David Meir-Levy');
17
+ assert.equal(decodeIfNeeded('user@example.com'), 'user@example.com');
18
+ assert.equal(decodeIfNeeded('100% legit'), '100% legit');
19
+ });
20
+
21
+ await t.test('passes through empty and undefined values', () => {
22
+ assert.equal(decodeIfNeeded(''), '');
23
+ assert.equal(decodeIfNeeded(undefined), undefined);
24
+ });
25
+ });
26
+
27
+ test('decodeMeUser', async (t) => {
28
+ await t.test('decodes user and workspace name fields', () => {
29
+ const encoded = {
30
+ _id: 'user-1',
31
+ name: 'David%20Meir-Levy',
32
+ fullName: 'David%20Meir-Levy',
33
+ firstName: 'David',
34
+ lastName: 'Meir-Levy',
35
+ workspace: {
36
+ _id: 'ws-1',
37
+ name: encodeURIComponent('My Workspace / Special & Name'),
38
+ roles: ['admin'],
39
+ },
40
+ };
41
+
42
+ const decoded = decodeMeUser(encoded);
43
+
44
+ assert.equal(decoded.name, 'David Meir-Levy');
45
+ assert.equal(decoded.fullName, 'David Meir-Levy');
46
+ assert.equal(decoded.firstName, 'David');
47
+ assert.equal(decoded.lastName, 'Meir-Levy');
48
+ assert.equal(decoded.workspace.name, 'My Workspace / Special & Name');
49
+ assert.equal(decoded._id, 'user-1');
50
+ assert.deepEqual(decoded.workspace.roles, ['admin']);
51
+ });
52
+
53
+ await t.test('leaves non-encoded fields unchanged', () => {
54
+ const user = {
55
+ _id: 'user-1',
56
+ username: 'david@example.com',
57
+ email: 'david@example.com',
58
+ name: 'David Meir-Levy',
59
+ fullName: 'David Meir-Levy',
60
+ firstName: 'David',
61
+ lastName: 'Meir-Levy',
62
+ roles: ['user'],
63
+ metadata: {},
64
+ };
65
+
66
+ assert.deepEqual(decodeMeUser(user), user);
67
+ });
68
+ });
69
+
70
+ test('getLoggedInUser decodes /api/me response', async (t) => {
71
+ const { default: QelosSDK } = await import('../src/index');
72
+
73
+ await t.test('returns decoded user fields', async () => {
74
+ const sdk = new QelosSDK({
75
+ appUrl: 'http://localhost:3000',
76
+ accessToken: 'test-token',
77
+ fetch: async () => {
78
+ const res = new Response(
79
+ JSON.stringify({
80
+ _id: '6a33dcba2c798875d68aa8ab',
81
+ tenant: '6a280e991bbd4078edefe097',
82
+ username: 'david@davidlevy.co.il',
83
+ email: 'david@davidlevy.co.il',
84
+ name: 'David%20Meir-Levy',
85
+ fullName: 'David%20Meir-Levy',
86
+ firstName: 'David',
87
+ lastName: 'Meir-Levy',
88
+ roles: ['user'],
89
+ metadata: {},
90
+ workspace: {
91
+ _id: 'ws-1',
92
+ name: encodeURIComponent('Acme / Dev'),
93
+ roles: ['admin'],
94
+ },
95
+ }),
96
+ );
97
+ res.headers.set('Content-Type', 'application/json');
98
+ return res;
99
+ },
100
+ });
101
+
102
+ const user = await sdk.authentication.getLoggedInUser();
103
+
104
+ assert.equal(user.name, 'David Meir-Levy');
105
+ assert.equal(user.fullName, 'David Meir-Levy');
106
+ assert.equal(user.workspace.name, 'Acme / Dev');
107
+ assert.equal(user.username, 'david@davidlevy.co.il');
108
+ });
109
+ });
@@ -28,6 +28,30 @@ test('parseSocialCallbackRefreshToken', async (t) => {
28
28
  });
29
29
  });
30
30
 
31
+ test('getSocialLoginUrl', async (t) => {
32
+ const { default: QelosSDK } = await import('../src/index');
33
+
34
+ await t.test('builds provider URL with state, returnUrl, and redirectUrl', () => {
35
+ const sdk = new QelosSDK({ appUrl: 'https://gateway.example.com' });
36
+ const url = sdk.authentication.getSocialLoginUrl('google', {
37
+ state: 'csrf-1',
38
+ returnUrl: 'https://app.example.com/auth/finish',
39
+ redirectUrl: 'https://app.example.com',
40
+ });
41
+ const parsed = new URL(url);
42
+ assert.equal(parsed.origin, 'https://gateway.example.com');
43
+ assert.equal(parsed.pathname, '/api/auth/google');
44
+ assert.equal(parsed.searchParams.get('state'), 'csrf-1');
45
+ assert.equal(parsed.searchParams.get('returnUrl'), 'https://app.example.com/auth/finish');
46
+ assert.equal(parsed.searchParams.get('redirectUrl'), 'https://app.example.com');
47
+ });
48
+
49
+ await t.test('omits query string when no options', () => {
50
+ const sdk = new QelosSDK({ appUrl: 'http://localhost:3000' });
51
+ assert.equal(sdk.authentication.getSocialLoginUrl('github'), 'http://localhost:3000/api/auth/github');
52
+ });
53
+ });
54
+
31
55
  test('getSocialAuthSetCookieParts', async (t) => {
32
56
  await t.test('prefers setCookieHeaders array', () => {
33
57
  const r = {