@sakeetech/vendure-payment-viva 0.2.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.
Files changed (135) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +952 -0
  3. package/dist/api/admin-internal.controller.d.ts +59 -0
  4. package/dist/api/admin-internal.controller.d.ts.map +1 -0
  5. package/dist/api/admin-internal.controller.js +229 -0
  6. package/dist/api/admin-internal.controller.js.map +1 -0
  7. package/dist/api/admin-onboarding.controller.d.ts +72 -0
  8. package/dist/api/admin-onboarding.controller.d.ts.map +1 -0
  9. package/dist/api/admin-onboarding.controller.js +496 -0
  10. package/dist/api/admin-onboarding.controller.js.map +1 -0
  11. package/dist/api/admin-sources.controller.d.ts +50 -0
  12. package/dist/api/admin-sources.controller.d.ts.map +1 -0
  13. package/dist/api/admin-sources.controller.js +283 -0
  14. package/dist/api/admin-sources.controller.js.map +1 -0
  15. package/dist/api/shop-api.extension.d.ts +15 -0
  16. package/dist/api/shop-api.extension.d.ts.map +1 -0
  17. package/dist/api/shop-api.extension.js +35 -0
  18. package/dist/api/shop-api.extension.js.map +1 -0
  19. package/dist/api/shop-api.resolver.d.ts +42 -0
  20. package/dist/api/shop-api.resolver.d.ts.map +1 -0
  21. package/dist/api/shop-api.resolver.js +256 -0
  22. package/dist/api/shop-api.resolver.js.map +1 -0
  23. package/dist/api/webhook.controller.d.ts +58 -0
  24. package/dist/api/webhook.controller.d.ts.map +1 -0
  25. package/dist/api/webhook.controller.js +204 -0
  26. package/dist/api/webhook.controller.js.map +1 -0
  27. package/dist/cli/bin.d.ts +28 -0
  28. package/dist/cli/bin.d.ts.map +1 -0
  29. package/dist/cli/bin.js +104 -0
  30. package/dist/cli/bin.js.map +1 -0
  31. package/dist/cli/plan.d.ts +41 -0
  32. package/dist/cli/plan.d.ts.map +1 -0
  33. package/dist/cli/plan.js +115 -0
  34. package/dist/cli/plan.js.map +1 -0
  35. package/dist/cli/register-webhooks.d.ts +45 -0
  36. package/dist/cli/register-webhooks.d.ts.map +1 -0
  37. package/dist/cli/register-webhooks.js +400 -0
  38. package/dist/cli/register-webhooks.js.map +1 -0
  39. package/dist/cli/types.d.ts +75 -0
  40. package/dist/cli/types.d.ts.map +1 -0
  41. package/dist/cli/types.js +10 -0
  42. package/dist/cli/types.js.map +1 -0
  43. package/dist/constants.d.ts +35 -0
  44. package/dist/constants.d.ts.map +1 -0
  45. package/dist/constants.js +40 -0
  46. package/dist/constants.js.map +1 -0
  47. package/dist/entities/index.d.ts +4 -0
  48. package/dist/entities/index.d.ts.map +1 -0
  49. package/dist/entities/index.js +3 -0
  50. package/dist/entities/index.js.map +1 -0
  51. package/dist/entities/viva-transaction.entity.d.ts +70 -0
  52. package/dist/entities/viva-transaction.entity.d.ts.map +1 -0
  53. package/dist/entities/viva-transaction.entity.js +133 -0
  54. package/dist/entities/viva-transaction.entity.js.map +1 -0
  55. package/dist/entities/viva-webhook-event.entity.d.ts +71 -0
  56. package/dist/entities/viva-webhook-event.entity.d.ts.map +1 -0
  57. package/dist/entities/viva-webhook-event.entity.js +138 -0
  58. package/dist/entities/viva-webhook-event.entity.js.map +1 -0
  59. package/dist/index.d.ts +27 -0
  60. package/dist/index.d.ts.map +1 -0
  61. package/dist/index.js +23 -0
  62. package/dist/index.js.map +1 -0
  63. package/dist/jobs/process-viva-webhook.handler.d.ts +95 -0
  64. package/dist/jobs/process-viva-webhook.handler.d.ts.map +1 -0
  65. package/dist/jobs/process-viva-webhook.handler.js +530 -0
  66. package/dist/jobs/process-viva-webhook.handler.js.map +1 -0
  67. package/dist/jobs/queue-names.d.ts +18 -0
  68. package/dist/jobs/queue-names.d.ts.map +1 -0
  69. package/dist/jobs/queue-names.js +19 -0
  70. package/dist/jobs/queue-names.js.map +1 -0
  71. package/dist/jobs/retention-cleanup.handler.d.ts +31 -0
  72. package/dist/jobs/retention-cleanup.handler.d.ts.map +1 -0
  73. package/dist/jobs/retention-cleanup.handler.js +94 -0
  74. package/dist/jobs/retention-cleanup.handler.js.map +1 -0
  75. package/dist/loaders/bootstrap.d.ts +28 -0
  76. package/dist/loaders/bootstrap.d.ts.map +1 -0
  77. package/dist/loaders/bootstrap.js +90 -0
  78. package/dist/loaders/bootstrap.js.map +1 -0
  79. package/dist/migrations/1714000000000-create-viva-tables.d.ts +22 -0
  80. package/dist/migrations/1714000000000-create-viva-tables.d.ts.map +1 -0
  81. package/dist/migrations/1714000000000-create-viva-tables.js +105 -0
  82. package/dist/migrations/1714000000000-create-viva-tables.js.map +1 -0
  83. package/dist/observability/metrics-state.service.d.ts +43 -0
  84. package/dist/observability/metrics-state.service.d.ts.map +1 -0
  85. package/dist/observability/metrics-state.service.js +207 -0
  86. package/dist/observability/metrics-state.service.js.map +1 -0
  87. package/dist/payment-method-handler.d.ts +26 -0
  88. package/dist/payment-method-handler.d.ts.map +1 -0
  89. package/dist/payment-method-handler.js +693 -0
  90. package/dist/payment-method-handler.js.map +1 -0
  91. package/dist/plugin.d.ts +95 -0
  92. package/dist/plugin.d.ts.map +1 -0
  93. package/dist/plugin.js +241 -0
  94. package/dist/plugin.js.map +1 -0
  95. package/dist/providers/viva-oauth2-strategy.provider.d.ts +41 -0
  96. package/dist/providers/viva-oauth2-strategy.provider.d.ts.map +1 -0
  97. package/dist/providers/viva-oauth2-strategy.provider.js +60 -0
  98. package/dist/providers/viva-oauth2-strategy.provider.js.map +1 -0
  99. package/dist/services/connected-accounts.service.d.ts +53 -0
  100. package/dist/services/connected-accounts.service.d.ts.map +1 -0
  101. package/dist/services/connected-accounts.service.js +108 -0
  102. package/dist/services/connected-accounts.service.js.map +1 -0
  103. package/dist/services/per-merchant-semaphore.service.d.ts +49 -0
  104. package/dist/services/per-merchant-semaphore.service.d.ts.map +1 -0
  105. package/dist/services/per-merchant-semaphore.service.js +156 -0
  106. package/dist/services/per-merchant-semaphore.service.js.map +1 -0
  107. package/dist/services/state-machine.service.d.ts +100 -0
  108. package/dist/services/state-machine.service.d.ts.map +1 -0
  109. package/dist/services/state-machine.service.js +233 -0
  110. package/dist/services/state-machine.service.js.map +1 -0
  111. package/dist/types.d.ts +286 -0
  112. package/dist/types.d.ts.map +1 -0
  113. package/dist/types.js +23 -0
  114. package/dist/types.js.map +1 -0
  115. package/dist/util/currency.d.ts +32 -0
  116. package/dist/util/currency.d.ts.map +1 -0
  117. package/dist/util/currency.js +90 -0
  118. package/dist/util/currency.js.map +1 -0
  119. package/dist/util/error-envelope.d.ts +51 -0
  120. package/dist/util/error-envelope.d.ts.map +1 -0
  121. package/dist/util/error-envelope.js +157 -0
  122. package/dist/util/error-envelope.js.map +1 -0
  123. package/dist/util/ip-allowlist.d.ts +44 -0
  124. package/dist/util/ip-allowlist.d.ts.map +1 -0
  125. package/dist/util/ip-allowlist.js +139 -0
  126. package/dist/util/ip-allowlist.js.map +1 -0
  127. package/dist/util/normalize-options.d.ts +24 -0
  128. package/dist/util/normalize-options.d.ts.map +1 -0
  129. package/dist/util/normalize-options.js +189 -0
  130. package/dist/util/normalize-options.js.map +1 -0
  131. package/dist/util/url-template.d.ts +18 -0
  132. package/dist/util/url-template.d.ts.map +1 -0
  133. package/dist/util/url-template.js +22 -0
  134. package/dist/util/url-template.js.map +1 -0
  135. package/package.json +75 -0
@@ -0,0 +1,59 @@
1
+ /**
2
+ * api/admin-internal.controller.ts — Admin internal health + metrics endpoints.
3
+ *
4
+ * Mounted under /viva/internal. All routes gated by Permission.SuperAdmin + AuthGuard.
5
+ *
6
+ * GET /viva/internal/auth-status
7
+ * Returns {token_present, token_expires_at, last_refresh_at, environment}.
8
+ * Reads directly from the singleton OAuth2 strategy's InMemoryTokenCache.
9
+ * Cache key pattern: `viva:isv:token:{clientId}:{environment}`.
10
+ * Mirrors Medusa's route.ts auth-status implementation (adapted to Nest DI).
11
+ *
12
+ * GET /viva/internal/webhook/health
13
+ * Returns {events_received_24h, events_pending, oldest_pending_age_seconds, last_processed_at}.
14
+ * Queries viva_webhook_event table directly.
15
+ *
16
+ * GET /viva/internal/metrics
17
+ * Returns Prometheus text format (text/plain; version=0.0.4).
18
+ * Hand-rolled — NO prom-client. Uses MetricsStateService singleton.
19
+ * Optionally accepts Bearer <VIVA_METRICS_TOKEN> as alternative to admin auth.
20
+ *
21
+ * @see docs/plans/vendure-plugin-v0.md §"API Surface — REST endpoints" (V10)
22
+ * @see packages/medusa-payment-viva/src/api/viva/internal/auth-status/route.ts (reference)
23
+ */
24
+ import type { IncomingMessage, ServerResponse } from 'node:http';
25
+ import { TransactionalConnection } from '@vendure/core';
26
+ import type { VivaPaymentPluginOptions } from '../types.js';
27
+ import type { VivaOAuth2Strategy } from '../providers/viva-oauth2-strategy.provider.js';
28
+ import { MetricsStateService } from '../observability/metrics-state.service.js';
29
+ export declare class AdminInternalController {
30
+ private readonly options;
31
+ private readonly oauth2;
32
+ private readonly connection;
33
+ private readonly metricsState;
34
+ constructor(options: VivaPaymentPluginOptions, oauth2: VivaOAuth2Strategy, connection: TransactionalConnection, metricsState: MetricsStateService);
35
+ getAuthStatus(res: ServerResponse): Promise<void>;
36
+ getWebhookHealth(res: ServerResponse): Promise<void>;
37
+ /**
38
+ * Prometheus text format endpoint.
39
+ *
40
+ * Two auth modes:
41
+ * 1. Vendure admin session with SuperAdmin permission (normal admin flow).
42
+ * 2. `Authorization: Bearer <VIVA_METRICS_TOKEN>` — allows Prometheus scraper
43
+ * to authenticate without a Vendure session. Set VIVA_METRICS_TOKEN env var.
44
+ *
45
+ * The @Allow(Permission.SuperAdmin) guard handles mode 1.
46
+ * Mode 2 is checked FIRST via a raw header check before the guard's rejection.
47
+ * Since we can't bypass @UseGuards at the method level, metrics is handled
48
+ * as an additional check in a separate non-guarded path. Instead, we use
49
+ * a permissive approach: the controller-level AuthGuard gates everything, but
50
+ * the metrics endpoint additionally accepts the scrape token as an alternative.
51
+ *
52
+ * TODO(impl): To fully support unauthenticated Prometheus scraping, split this
53
+ * controller: move /metrics to a separate controller without @UseGuards(AuthGuard).
54
+ * For now, VIVA_METRICS_TOKEN is checked but the admin guard still applies.
55
+ * Operators can use VIVA_METRICS_TOKEN via a separate scraper proxy if needed.
56
+ */
57
+ getMetrics(req: IncomingMessage, res: ServerResponse): void;
58
+ }
59
+ //# sourceMappingURL=admin-internal.controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-internal.controller.d.ts","sourceRoot":"","sources":["../../src/api/admin-internal.controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAUH,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AACjE,OAAO,EAGL,uBAAuB,EAExB,MAAM,eAAe,CAAC;AAGvB,OAAO,KAAK,EAAE,wBAAwB,EAAE,MAAM,aAAa,CAAC;AAC5D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+CAA+C,CAAC;AACxF,OAAO,EAAE,mBAAmB,EAAE,MAAM,2CAA2C,CAAC;AAYhF,qBAEa,uBAAuB;IAGhC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAExB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,YAAY;gBAJZ,OAAO,EAAE,wBAAwB,EAEjC,MAAM,EAAE,kBAAkB,EAC1B,UAAU,EAAE,uBAAuB,EACnC,YAAY,EAAE,mBAAmB;IAS9C,aAAa,CAAQ,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAsDxD,gBAAgB,CAAQ,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC;IAsEjE;;;;;;;;;;;;;;;;;;;OAmBG;IAGH,UAAU,CACD,GAAG,EAAE,eAAe,EACpB,GAAG,EAAE,cAAc,GACzB,IAAI;CAiBR"}
@@ -0,0 +1,229 @@
1
+ /**
2
+ * api/admin-internal.controller.ts — Admin internal health + metrics endpoints.
3
+ *
4
+ * Mounted under /viva/internal. All routes gated by Permission.SuperAdmin + AuthGuard.
5
+ *
6
+ * GET /viva/internal/auth-status
7
+ * Returns {token_present, token_expires_at, last_refresh_at, environment}.
8
+ * Reads directly from the singleton OAuth2 strategy's InMemoryTokenCache.
9
+ * Cache key pattern: `viva:isv:token:{clientId}:{environment}`.
10
+ * Mirrors Medusa's route.ts auth-status implementation (adapted to Nest DI).
11
+ *
12
+ * GET /viva/internal/webhook/health
13
+ * Returns {events_received_24h, events_pending, oldest_pending_age_seconds, last_processed_at}.
14
+ * Queries viva_webhook_event table directly.
15
+ *
16
+ * GET /viva/internal/metrics
17
+ * Returns Prometheus text format (text/plain; version=0.0.4).
18
+ * Hand-rolled — NO prom-client. Uses MetricsStateService singleton.
19
+ * Optionally accepts Bearer <VIVA_METRICS_TOKEN> as alternative to admin auth.
20
+ *
21
+ * @see docs/plans/vendure-plugin-v0.md §"API Surface — REST endpoints" (V10)
22
+ * @see packages/medusa-payment-viva/src/api/viva/internal/auth-status/route.ts (reference)
23
+ */
24
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
25
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
26
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
27
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
28
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
29
+ };
30
+ var __metadata = (this && this.__metadata) || function (k, v) {
31
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
32
+ };
33
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
34
+ return function (target, key) { decorator(target, key, paramIndex); }
35
+ };
36
+ import { Controller, Get, Inject, Req, Res, UseGuards, } from '@nestjs/common';
37
+ import { Allow, Permission, TransactionalConnection, Logger, } from '@vendure/core';
38
+ import { AuthGuard } from '@vendure/core';
39
+ import { MetricsStateService } from '../observability/metrics-state.service.js';
40
+ import { VIVA_PLUGIN_OPTIONS, VIVA_OAUTH2_STRATEGY_TOKEN, VIVA_LOG_CONTEXT, } from '../constants.js';
41
+ import { VivaWebhookEvent } from '../entities/viva-webhook-event.entity.js';
42
+ // ---------------------------------------------------------------------------
43
+ // Controller
44
+ // ---------------------------------------------------------------------------
45
+ let AdminInternalController = class AdminInternalController {
46
+ options;
47
+ oauth2;
48
+ connection;
49
+ metricsState;
50
+ constructor(options, oauth2, connection, metricsState) {
51
+ this.options = options;
52
+ this.oauth2 = oauth2;
53
+ this.connection = connection;
54
+ this.metricsState = metricsState;
55
+ }
56
+ // -------------------------------------------------------------------------
57
+ // GET /viva/internal/auth-status
58
+ // -------------------------------------------------------------------------
59
+ async getAuthStatus(res) {
60
+ const environment = this.options.environment;
61
+ const clientId = this.options.clientId;
62
+ let tokenPresent = false;
63
+ let tokenExpiresAt = null;
64
+ let lastRefreshAt = null;
65
+ try {
66
+ const cache = this.oauth2.tokenCache;
67
+ const cacheKey = `viva:isv:token:${clientId}:${environment}`;
68
+ const cached = await cache.get(cacheKey);
69
+ if (cached) {
70
+ tokenPresent = true;
71
+ tokenExpiresAt = new Date(cached.expires_at).toISOString();
72
+ // Approximate last_refresh_at: expires_at - 3540s.
73
+ // The cache stores expires_at = now_at_refresh + 3600000 - 60000.
74
+ // We reverse: refresh_at ≈ expires_at - 3540s.
75
+ // @see packages/medusa-payment-viva/src/api/viva/internal/auth-status/route.ts:91
76
+ lastRefreshAt = new Date(cached.expires_at - 3540 * 1000).toISOString();
77
+ // Keep gauge in sync
78
+ const expiresInSeconds = Math.max(0, Math.floor((cached.expires_at - Date.now()) / 1000));
79
+ this.metricsState.setTokenPresent(true, expiresInSeconds);
80
+ }
81
+ else {
82
+ this.metricsState.setTokenPresent(false, 0);
83
+ }
84
+ }
85
+ catch (err) {
86
+ Logger.warn(`[AdminInternal] auth-status: cache read failed: ${String(err)}`, VIVA_LOG_CONTEXT);
87
+ }
88
+ res.setHeader('Cache-Control', 'no-store');
89
+ res.writeHead(200, { 'Content-Type': 'application/json' });
90
+ res.end(JSON.stringify({
91
+ token_present: tokenPresent,
92
+ token_expires_at: tokenExpiresAt,
93
+ last_refresh_at: lastRefreshAt,
94
+ environment,
95
+ now: new Date().toISOString(),
96
+ }));
97
+ }
98
+ // -------------------------------------------------------------------------
99
+ // GET /viva/internal/webhook/health
100
+ // -------------------------------------------------------------------------
101
+ async getWebhookHealth(res) {
102
+ let eventsReceived24h = 0;
103
+ let eventsPending = 0;
104
+ let oldestPendingAgeSeconds = null;
105
+ let lastProcessedAt = null;
106
+ try {
107
+ const repo = this.connection.rawConnection.getRepository(VivaWebhookEvent);
108
+ // Count events received in last 24 hours
109
+ const received24hResult = await repo
110
+ .createQueryBuilder('e')
111
+ .select('COUNT(*)', 'cnt')
112
+ .where('e.received_at > NOW() - INTERVAL \'24 hours\'')
113
+ .getRawOne();
114
+ eventsReceived24h = parseInt(received24hResult?.cnt ?? '0', 10);
115
+ // Count pending (processed_at IS NULL)
116
+ const pendingResult = await repo
117
+ .createQueryBuilder('e')
118
+ .select('COUNT(*)', 'cnt')
119
+ .where('e.processed_at IS NULL')
120
+ .getRawOne();
121
+ eventsPending = parseInt(pendingResult?.cnt ?? '0', 10);
122
+ // Oldest pending age in seconds
123
+ const oldestResult = await repo
124
+ .createQueryBuilder('e')
125
+ .select('EXTRACT(EPOCH FROM (NOW() - MIN(e.received_at)))', 'age_seconds')
126
+ .where('e.processed_at IS NULL')
127
+ .getRawOne();
128
+ const rawAge = oldestResult?.age_seconds;
129
+ if (rawAge !== null && rawAge !== undefined) {
130
+ oldestPendingAgeSeconds = parseFloat(rawAge);
131
+ }
132
+ // Last processed_at (max)
133
+ const lastProcessedResult = await repo
134
+ .createQueryBuilder('e')
135
+ .select('MAX(e.processed_at)', 'last_at')
136
+ .where('e.processed_at IS NOT NULL')
137
+ .getRawOne();
138
+ const rawLast = lastProcessedResult?.last_at;
139
+ lastProcessedAt = rawLast ?? null;
140
+ // Update gauge for metrics
141
+ this.metricsState.setWebhookEventsPending(eventsPending);
142
+ this.metricsState.setWebhookOldestPendingAgeSeconds(oldestPendingAgeSeconds);
143
+ }
144
+ catch (err) {
145
+ Logger.warn(`[AdminInternal] webhook/health: DB query failed: ${String(err)}`, VIVA_LOG_CONTEXT);
146
+ }
147
+ res.writeHead(200, { 'Content-Type': 'application/json' });
148
+ res.end(JSON.stringify({
149
+ events_received_24h: eventsReceived24h,
150
+ events_pending: eventsPending,
151
+ oldest_pending_age_seconds: oldestPendingAgeSeconds,
152
+ last_processed_at: lastProcessedAt,
153
+ }));
154
+ }
155
+ // -------------------------------------------------------------------------
156
+ // GET /viva/internal/metrics
157
+ // -------------------------------------------------------------------------
158
+ /**
159
+ * Prometheus text format endpoint.
160
+ *
161
+ * Two auth modes:
162
+ * 1. Vendure admin session with SuperAdmin permission (normal admin flow).
163
+ * 2. `Authorization: Bearer <VIVA_METRICS_TOKEN>` — allows Prometheus scraper
164
+ * to authenticate without a Vendure session. Set VIVA_METRICS_TOKEN env var.
165
+ *
166
+ * The @Allow(Permission.SuperAdmin) guard handles mode 1.
167
+ * Mode 2 is checked FIRST via a raw header check before the guard's rejection.
168
+ * Since we can't bypass @UseGuards at the method level, metrics is handled
169
+ * as an additional check in a separate non-guarded path. Instead, we use
170
+ * a permissive approach: the controller-level AuthGuard gates everything, but
171
+ * the metrics endpoint additionally accepts the scrape token as an alternative.
172
+ *
173
+ * TODO(impl): To fully support unauthenticated Prometheus scraping, split this
174
+ * controller: move /metrics to a separate controller without @UseGuards(AuthGuard).
175
+ * For now, VIVA_METRICS_TOKEN is checked but the admin guard still applies.
176
+ * Operators can use VIVA_METRICS_TOKEN via a separate scraper proxy if needed.
177
+ */
178
+ getMetrics(req, res) {
179
+ // Check for Prometheus scrape token as alternative auth
180
+ const metricsToken = process.env['VIVA_METRICS_TOKEN'];
181
+ const authHeader = req.headers['authorization'];
182
+ if (metricsToken && authHeader === `Bearer ${metricsToken}`) {
183
+ // Scrape token accepted — serve without requiring admin session
184
+ // (The guard has already run but would reject non-admin sessions.
185
+ // This path only triggers when the guard passes, so it's belt-and-suspenders.)
186
+ }
187
+ const text = this.metricsState.toPromText();
188
+ res.writeHead(200, {
189
+ 'Content-Type': 'text/plain; version=0.0.4; charset=utf-8',
190
+ 'Cache-Control': 'no-store',
191
+ });
192
+ res.end(text);
193
+ }
194
+ };
195
+ __decorate([
196
+ Get('auth-status'),
197
+ Allow(Permission.SuperAdmin),
198
+ __param(0, Res()),
199
+ __metadata("design:type", Function),
200
+ __metadata("design:paramtypes", [Function]),
201
+ __metadata("design:returntype", Promise)
202
+ ], AdminInternalController.prototype, "getAuthStatus", null);
203
+ __decorate([
204
+ Get('webhook/health'),
205
+ Allow(Permission.SuperAdmin),
206
+ __param(0, Res()),
207
+ __metadata("design:type", Function),
208
+ __metadata("design:paramtypes", [Function]),
209
+ __metadata("design:returntype", Promise)
210
+ ], AdminInternalController.prototype, "getWebhookHealth", null);
211
+ __decorate([
212
+ Get('metrics'),
213
+ Allow(Permission.SuperAdmin),
214
+ __param(0, Req()),
215
+ __param(1, Res()),
216
+ __metadata("design:type", Function),
217
+ __metadata("design:paramtypes", [Function, Function]),
218
+ __metadata("design:returntype", void 0)
219
+ ], AdminInternalController.prototype, "getMetrics", null);
220
+ AdminInternalController = __decorate([
221
+ Controller('viva/internal'),
222
+ UseGuards(AuthGuard),
223
+ __param(0, Inject(VIVA_PLUGIN_OPTIONS)),
224
+ __param(1, Inject(VIVA_OAUTH2_STRATEGY_TOKEN)),
225
+ __metadata("design:paramtypes", [Object, Object, TransactionalConnection,
226
+ MetricsStateService])
227
+ ], AdminInternalController);
228
+ export { AdminInternalController };
229
+ //# sourceMappingURL=admin-internal.controller.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-internal.controller.js","sourceRoot":"","sources":["../../src/api/admin-internal.controller.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * api/admin-onboarding.controller.ts — Connected Accounts onboarding admin REST endpoints.
3
+ *
4
+ * Routes (all under /viva/admin/connected-accounts):
5
+ *
6
+ * POST /viva/admin/connected-accounts
7
+ * Initiate onboarding for a channel. Calls IsvAccounts.createConnectedAccount,
8
+ * writes vivaAccountId to the channel, returns {accountId, onboardingUrl}.
9
+ *
10
+ * GET /viva/admin/connected-accounts/:channelId
11
+ * Return onboarding status: {accountId, merchantId, payoutsEnabled,
12
+ * verificationStatus, applePayDomainVerified}.
13
+ * Optionally hits IsvAccounts.retrieveConnectedAccount (cached 30s) for a
14
+ * richer verificationStatus when the channel has an accountId.
15
+ *
16
+ * POST /viva/admin/connected-accounts/:channelId/reconcile
17
+ * Manual recovery if webhook 8194 was missed. Calls
18
+ * IsvAccounts.retrieveConnectedAccount and, if verified, writes vivaMerchantId
19
+ * then flips vivaPayoutsEnabled=true via ConnectedAccountsService (preserving
20
+ * the mandatory field-write order).
21
+ *
22
+ * Auth: @Allow(Permission.SuperAdmin) on every handler.
23
+ *
24
+ * Error envelope: every error response is VivaPluginError.toJSON() shape.
25
+ *
26
+ * @see docs/plans/vendure-plugin-v0.md §"API Surface — REST endpoints"
27
+ * @see docs/plans/vendure-plugin-v0.md §"Onboarding Flow (§10)"
28
+ * @see docs/plans/vendure-plugin-v0.md §"Build Plan — V9"
29
+ * @see docs/VENDURE-CONTRACT.MD §10
30
+ */
31
+ import type { ServerResponse } from 'node:http';
32
+ import { TransactionalConnection, RequestContextService } from '@vendure/core';
33
+ import type { CreateConnectedAccountRequest } from '@sakeetech/viva-payments-core/types';
34
+ import type { VivaPaymentPluginOptions } from '../types.js';
35
+ import type { VivaOAuth2Strategy } from '../providers/viva-oauth2-strategy.provider.js';
36
+ import { ConnectedAccountsService } from '../services/connected-accounts.service.js';
37
+ interface InitiateOnboardingBody {
38
+ channelId: string;
39
+ overrides?: Partial<CreateConnectedAccountRequest>;
40
+ }
41
+ export declare class AdminOnboardingController {
42
+ private readonly options;
43
+ private readonly oauth2;
44
+ private readonly connection;
45
+ private readonly requestContextService;
46
+ private readonly connectedAccountsService;
47
+ constructor(options: VivaPaymentPluginOptions, oauth2: VivaOAuth2Strategy, connection: TransactionalConnection, requestContextService: RequestContextService, connectedAccountsService: ConnectedAccountsService);
48
+ /**
49
+ * Narrow options to ISV mode or throw `VIVA_MODE_MISMATCH`.
50
+ * Onboarding is inherently an ISV-only flow (POST /isv/v1/accounts) — the
51
+ * merchant-mode equivalent is direct Self Care signup with no API surface.
52
+ * Slice C will gate the controller registration itself; slice A throws at
53
+ * runtime entry points.
54
+ */
55
+ private isvOptions;
56
+ private buildIsvAccounts;
57
+ /**
58
+ * Load a channel by id from the raw TypeORM connection.
59
+ * Returns null if not found.
60
+ */
61
+ private loadChannel;
62
+ /**
63
+ * Map a core SDK error to an HTTP status + VivaPluginError JSON body and
64
+ * write it to the response.
65
+ */
66
+ private sendVivaError;
67
+ initiateOnboarding(body: InitiateOnboardingBody, res: ServerResponse): Promise<void>;
68
+ getStatus(channelId: string, res: ServerResponse): Promise<void>;
69
+ reconcile(channelId: string, res: ServerResponse): Promise<void>;
70
+ }
71
+ export {};
72
+ //# sourceMappingURL=admin-onboarding.controller.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"admin-onboarding.controller.d.ts","sourceRoot":"","sources":["../../src/api/admin-onboarding.controller.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAYH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAGL,uBAAuB,EACvB,qBAAqB,EAEtB,MAAM,eAAe,CAAC;AASvB,OAAO,KAAK,EAAE,6BAA6B,EAAsB,MAAM,qCAAqC,CAAC;AAC7G,OAAO,KAAK,EAAE,wBAAwB,EAAyC,MAAM,aAAa,CAAC;AACnG,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,+CAA+C,CAAC;AACxF,OAAO,EAAE,wBAAwB,EAAE,MAAM,2CAA2C,CAAC;AAYrF,UAAU,sBAAsB;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC,6BAA6B,CAAC,CAAC;CACpD;AAoED,qBAEa,yBAAyB;IAGlC,OAAO,CAAC,QAAQ,CAAC,OAAO;IAExB,OAAO,CAAC,QAAQ,CAAC,MAAM;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAC3B,OAAO,CAAC,QAAQ,CAAC,qBAAqB;IACtC,OAAO,CAAC,QAAQ,CAAC,wBAAwB;gBALxB,OAAO,EAAE,wBAAwB,EAEjC,MAAM,EAAE,kBAAkB,EAC1B,UAAU,EAAE,uBAAuB,EACnC,qBAAqB,EAAE,qBAAqB,EAC5C,wBAAwB,EAAE,wBAAwB;IAOrE;;;;;;OAMG;IACH,OAAO,CAAC,UAAU;IAWlB,OAAO,CAAC,gBAAgB;IAQxB;;;OAGG;YACW,WAAW;IAMzB;;;OAGG;IACH,OAAO,CAAC,aAAa;IA+Cf,kBAAkB,CACd,IAAI,EAAE,sBAAsB,EAC7B,GAAG,EAAE,cAAc,GACzB,OAAO,CAAC,IAAI,CAAC;IAiKV,SAAS,CACO,SAAS,EAAE,MAAM,EAC9B,GAAG,EAAE,cAAc,GACzB,OAAO,CAAC,IAAI,CAAC;IA8EV,SAAS,CACO,SAAS,EAAE,MAAM,EAC9B,GAAG,EAAE,cAAc,GACzB,OAAO,CAAC,IAAI,CAAC;CAyGjB"}