@vivoa/partner-sdk 0.1.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -155,7 +155,7 @@ class FakeVivoa {
155
155
  async route(op, method, url, rawBody) {
156
156
  const path = url.pathname.replace(/^\/partner\/v1/, '');
157
157
  const body = rawBody ? JSON.parse(rawBody) : {};
158
- const merchantRoute = path.match(/^\/merchants\/([^/]+)\/(status|activate|suspend|reactivate)$/);
158
+ const merchantRoute = path.match(/^\/merchants\/([^/]+)\/(status|activate|suspend|reactivate|admin-ticket)$/);
159
159
  if (method === 'GET' && path === '/me')
160
160
  return this.profile(op);
161
161
  if (method === 'POST' && path === '/me/rotate-secret') {
@@ -192,6 +192,16 @@ class FakeVivoa {
192
192
  this.emit(op, 'merchant.reactivated', merchant);
193
193
  return { storeId: merchant.id, status: 'active' };
194
194
  }
195
+ if (action === 'admin-ticket') {
196
+ if (merchant.status !== 'active')
197
+ throw new HttpError(403, 'Store is not active');
198
+ const rawPath = typeof body.returnPath === 'string' ? body.returnPath : '/admin';
199
+ const returnPath = rawPath.startsWith('/') && !rawPath.startsWith('//') ? rawPath : '/admin';
200
+ const base = merchant.domain ? `https://${merchant.domain}` : `https://${merchant.handle}.vivoa.test`;
201
+ return {
202
+ redirectUrl: `${base}/auth/admin-redeem?token=fake-${merchant.id}${returnPath === '/admin' ? '' : `&rp=${encodeURIComponent(returnPath)}`}`,
203
+ };
204
+ }
195
205
  }
196
206
  }
197
207
  if (method === 'GET' && path === '/fleet/analytics')
@@ -1,5 +1,5 @@
1
1
  import type { SignedHttpClient } from '../signed-http.ts';
2
- import { type CreateMerchantInput, type ListMerchantsQuery, type Merchant, type MerchantStatus, type Page } from '../../domain/merchant.ts';
2
+ import { type AdminTicketOptions, type CreateMerchantInput, type ListMerchantsQuery, type Merchant, type MerchantAdminTicket, type MerchantStatus, type Page } from '../../domain/merchant.ts';
3
3
  /** Provisioning is synchronous on the platform: allow it minutes, not seconds. */
4
4
  export declare const DEFAULT_ACTIVATE_TIMEOUT_MS: number;
5
5
  export declare class MerchantsResource {
@@ -33,5 +33,11 @@ export declare class MerchantsResource {
33
33
  storeId: string;
34
34
  status: 'active';
35
35
  }>;
36
+ /**
37
+ * Mints a single-use SSO URL into this merchant's store admin, signed in AS
38
+ * the store owner. The link expires in ~60s — redirect to it right away, do
39
+ * not store it. 403 if the merchant is not in your fleet or is not active.
40
+ */
41
+ adminTicket(merchantId: string, options?: AdminTicketOptions): Promise<MerchantAdminTicket>;
36
42
  }
37
43
  export declare function validateCreate(input: CreateMerchantInput): void;
@@ -62,6 +62,16 @@ class MerchantsResource {
62
62
  async reactivate(merchantId) {
63
63
  return this.http.request('POST', `/partner/v1/merchants/${encodeId(merchantId)}/reactivate`);
64
64
  }
65
+ /**
66
+ * Mints a single-use SSO URL into this merchant's store admin, signed in AS
67
+ * the store owner. The link expires in ~60s — redirect to it right away, do
68
+ * not store it. 403 if the merchant is not in your fleet or is not active.
69
+ */
70
+ async adminTicket(merchantId, options = {}) {
71
+ return this.http.request('POST', `/partner/v1/merchants/${encodeId(merchantId)}/admin-ticket`, {
72
+ body: options.returnPath ? { returnPath: options.returnPath } : {},
73
+ });
74
+ }
65
75
  }
66
76
  exports.MerchantsResource = MerchantsResource;
67
77
  function encodeId(id) {
@@ -49,6 +49,22 @@ export interface CreateMerchantInput {
49
49
  */
50
50
  externalId?: string;
51
51
  }
52
+ /** Options for `merchants.adminTicket()`. */
53
+ export interface AdminTicketOptions {
54
+ /**
55
+ * Same-origin absolute path to land on inside the store admin (defaults to
56
+ * `/admin`). Must start with a single `/` — the platform re-validates and
57
+ * falls back to `/admin` on anything scheme-relative or malformed.
58
+ */
59
+ returnPath?: string;
60
+ }
61
+ /**
62
+ * Single-use SSO handoff into a merchant's store admin. `redirectUrl` is signed
63
+ * in AS the store owner and expires in ~60s — open it immediately, never cache.
64
+ */
65
+ export interface MerchantAdminTicket {
66
+ redirectUrl: string;
67
+ }
52
68
  export interface ListMerchantsQuery {
53
69
  page?: number;
54
70
  /** Max 100. */
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "0.1.1";
1
+ export declare const SDK_VERSION = "0.2.0";
@@ -1,4 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.SDK_VERSION = void 0;
4
- exports.SDK_VERSION = '0.1.1';
4
+ exports.SDK_VERSION = '0.2.0';
@@ -152,7 +152,7 @@ export class FakeVivoa {
152
152
  async route(op, method, url, rawBody) {
153
153
  const path = url.pathname.replace(/^\/partner\/v1/, '');
154
154
  const body = rawBody ? JSON.parse(rawBody) : {};
155
- const merchantRoute = path.match(/^\/merchants\/([^/]+)\/(status|activate|suspend|reactivate)$/);
155
+ const merchantRoute = path.match(/^\/merchants\/([^/]+)\/(status|activate|suspend|reactivate|admin-ticket)$/);
156
156
  if (method === 'GET' && path === '/me')
157
157
  return this.profile(op);
158
158
  if (method === 'POST' && path === '/me/rotate-secret') {
@@ -189,6 +189,16 @@ export class FakeVivoa {
189
189
  this.emit(op, 'merchant.reactivated', merchant);
190
190
  return { storeId: merchant.id, status: 'active' };
191
191
  }
192
+ if (action === 'admin-ticket') {
193
+ if (merchant.status !== 'active')
194
+ throw new HttpError(403, 'Store is not active');
195
+ const rawPath = typeof body.returnPath === 'string' ? body.returnPath : '/admin';
196
+ const returnPath = rawPath.startsWith('/') && !rawPath.startsWith('//') ? rawPath : '/admin';
197
+ const base = merchant.domain ? `https://${merchant.domain}` : `https://${merchant.handle}.vivoa.test`;
198
+ return {
199
+ redirectUrl: `${base}/auth/admin-redeem?token=fake-${merchant.id}${returnPath === '/admin' ? '' : `&rp=${encodeURIComponent(returnPath)}`}`,
200
+ };
201
+ }
192
202
  }
193
203
  }
194
204
  if (method === 'GET' && path === '/fleet/analytics')
@@ -1,5 +1,5 @@
1
1
  import type { SignedHttpClient } from '../signed-http.ts';
2
- import { type CreateMerchantInput, type ListMerchantsQuery, type Merchant, type MerchantStatus, type Page } from '../../domain/merchant.ts';
2
+ import { type AdminTicketOptions, type CreateMerchantInput, type ListMerchantsQuery, type Merchant, type MerchantAdminTicket, type MerchantStatus, type Page } from '../../domain/merchant.ts';
3
3
  /** Provisioning is synchronous on the platform: allow it minutes, not seconds. */
4
4
  export declare const DEFAULT_ACTIVATE_TIMEOUT_MS: number;
5
5
  export declare class MerchantsResource {
@@ -33,5 +33,11 @@ export declare class MerchantsResource {
33
33
  storeId: string;
34
34
  status: 'active';
35
35
  }>;
36
+ /**
37
+ * Mints a single-use SSO URL into this merchant's store admin, signed in AS
38
+ * the store owner. The link expires in ~60s — redirect to it right away, do
39
+ * not store it. 403 if the merchant is not in your fleet or is not active.
40
+ */
41
+ adminTicket(merchantId: string, options?: AdminTicketOptions): Promise<MerchantAdminTicket>;
36
42
  }
37
43
  export declare function validateCreate(input: CreateMerchantInput): void;
@@ -58,6 +58,16 @@ export class MerchantsResource {
58
58
  async reactivate(merchantId) {
59
59
  return this.http.request('POST', `/partner/v1/merchants/${encodeId(merchantId)}/reactivate`);
60
60
  }
61
+ /**
62
+ * Mints a single-use SSO URL into this merchant's store admin, signed in AS
63
+ * the store owner. The link expires in ~60s — redirect to it right away, do
64
+ * not store it. 403 if the merchant is not in your fleet or is not active.
65
+ */
66
+ async adminTicket(merchantId, options = {}) {
67
+ return this.http.request('POST', `/partner/v1/merchants/${encodeId(merchantId)}/admin-ticket`, {
68
+ body: options.returnPath ? { returnPath: options.returnPath } : {},
69
+ });
70
+ }
61
71
  }
62
72
  function encodeId(id) {
63
73
  if (!id)
package/dist/esm/cli.js CHANGED
@@ -13,6 +13,7 @@ const USAGE = `vivoa-partner <command> [options]
13
13
  merchants list [--search s] [--external-id id] [--page n] [--limit n]
14
14
  merchants status <id>
15
15
  merchants suspend <id> | reactivate <id>
16
+ merchants admin-ticket <id> [--return-path /admin/team]
16
17
  store create --external-id id --name n --email e --countries SV,GT [--industry i] --yes
17
18
  Create (or resume) + activate + wait until live.
18
19
  The platform assigns the handle; --external-id is
@@ -36,6 +37,7 @@ async function main(argv) {
36
37
  industry: { type: 'string' },
37
38
  url: { type: 'string' },
38
39
  events: { type: 'string' },
40
+ 'return-path': { type: 'string' },
39
41
  yes: { type: 'boolean', default: false },
40
42
  help: { type: 'boolean', short: 'h', default: false },
41
43
  },
@@ -69,6 +71,10 @@ async function main(argv) {
69
71
  return client.merchants.suspend(required(arg, '<id>'));
70
72
  case 'merchants reactivate':
71
73
  return client.merchants.reactivate(required(arg, '<id>'));
74
+ case 'merchants admin-ticket':
75
+ return client.merchants.adminTicket(required(arg, '<id>'), {
76
+ returnPath: values['return-path'],
77
+ });
72
78
  case 'store create': {
73
79
  if (!values.yes)
74
80
  throw new VivoaError('store create provisions REAL infrastructure — re-run with --yes');
@@ -49,6 +49,22 @@ export interface CreateMerchantInput {
49
49
  */
50
50
  externalId?: string;
51
51
  }
52
+ /** Options for `merchants.adminTicket()`. */
53
+ export interface AdminTicketOptions {
54
+ /**
55
+ * Same-origin absolute path to land on inside the store admin (defaults to
56
+ * `/admin`). Must start with a single `/` — the platform re-validates and
57
+ * falls back to `/admin` on anything scheme-relative or malformed.
58
+ */
59
+ returnPath?: string;
60
+ }
61
+ /**
62
+ * Single-use SSO handoff into a merchant's store admin. `redirectUrl` is signed
63
+ * in AS the store owner and expires in ~60s — open it immediately, never cache.
64
+ */
65
+ export interface MerchantAdminTicket {
66
+ redirectUrl: string;
67
+ }
52
68
  export interface ListMerchantsQuery {
53
69
  page?: number;
54
70
  /** Max 100. */
@@ -1 +1 @@
1
- export declare const SDK_VERSION = "0.1.1";
1
+ export declare const SDK_VERSION = "0.2.0";
@@ -1 +1 @@
1
- export const SDK_VERSION = '0.1.1';
1
+ export const SDK_VERSION = '0.2.0';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vivoa/partner-sdk",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "Official SDK for the Vivoa Partner API — create and operate stores for your merchants",
5
5
  "license": "UNLICENSED",
6
6
  "type": "module",