@sakeetech/medusa-payment-viva 0.2.2
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/LICENSE +21 -0
- package/README.md +816 -0
- package/dist/api/index.d.ts +15 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +22 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/middlewares.d.ts +27 -0
- package/dist/api/middlewares.d.ts.map +1 -0
- package/dist/api/middlewares.js +62 -0
- package/dist/api/middlewares.js.map +1 -0
- package/dist/api/viva/admin/_admin-auth.d.ts +26 -0
- package/dist/api/viva/admin/_admin-auth.d.ts.map +1 -0
- package/dist/api/viva/admin/_admin-auth.js +49 -0
- package/dist/api/viva/admin/_admin-auth.js.map +1 -0
- package/dist/api/viva/admin/_mode-gate.d.ts +28 -0
- package/dist/api/viva/admin/_mode-gate.d.ts.map +1 -0
- package/dist/api/viva/admin/_mode-gate.js +45 -0
- package/dist/api/viva/admin/_mode-gate.js.map +1 -0
- package/dist/api/viva/admin/connected-accounts/[id]/reconcile/route.d.ts +21 -0
- package/dist/api/viva/admin/connected-accounts/[id]/reconcile/route.d.ts.map +1 -0
- package/dist/api/viva/admin/connected-accounts/[id]/reconcile/route.js +93 -0
- package/dist/api/viva/admin/connected-accounts/[id]/reconcile/route.js.map +1 -0
- package/dist/api/viva/admin/connected-accounts/[id]/route.d.ts +18 -0
- package/dist/api/viva/admin/connected-accounts/[id]/route.d.ts.map +1 -0
- package/dist/api/viva/admin/connected-accounts/[id]/route.js +59 -0
- package/dist/api/viva/admin/connected-accounts/[id]/route.js.map +1 -0
- package/dist/api/viva/admin/connected-accounts/[id]/sources/route.d.ts +34 -0
- package/dist/api/viva/admin/connected-accounts/[id]/sources/route.d.ts.map +1 -0
- package/dist/api/viva/admin/connected-accounts/[id]/sources/route.js +234 -0
- package/dist/api/viva/admin/connected-accounts/[id]/sources/route.js.map +1 -0
- package/dist/api/viva/admin/connected-accounts/route.d.ts +19 -0
- package/dist/api/viva/admin/connected-accounts/route.d.ts.map +1 -0
- package/dist/api/viva/admin/connected-accounts/route.js +78 -0
- package/dist/api/viva/admin/connected-accounts/route.js.map +1 -0
- package/dist/api/viva/internal/auth-status/route.d.ts +19 -0
- package/dist/api/viva/internal/auth-status/route.d.ts.map +1 -0
- package/dist/api/viva/internal/auth-status/route.js +91 -0
- package/dist/api/viva/internal/auth-status/route.js.map +1 -0
- package/dist/api/viva/internal/metrics/route.d.ts +13 -0
- package/dist/api/viva/internal/metrics/route.d.ts.map +1 -0
- package/dist/api/viva/internal/metrics/route.js +48 -0
- package/dist/api/viva/internal/metrics/route.js.map +1 -0
- package/dist/api/viva/webhook/health/route.d.ts +16 -0
- package/dist/api/viva/webhook/health/route.d.ts.map +1 -0
- package/dist/api/viva/webhook/health/route.js +27 -0
- package/dist/api/viva/webhook/health/route.js.map +1 -0
- package/dist/api/viva/webhook/route.d.ts +57 -0
- package/dist/api/viva/webhook/route.d.ts.map +1 -0
- package/dist/api/viva/webhook/route.js +269 -0
- package/dist/api/viva/webhook/route.js.map +1 -0
- package/dist/cli/bin.d.ts +12 -0
- package/dist/cli/bin.d.ts.map +1 -0
- package/dist/cli/bin.js +78 -0
- package/dist/cli/bin.js.map +1 -0
- package/dist/cli/index.d.ts +12 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +14 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/plan.d.ts +51 -0
- package/dist/cli/plan.d.ts.map +1 -0
- package/dist/cli/plan.js +128 -0
- package/dist/cli/plan.js.map +1 -0
- package/dist/cli/register-webhooks.d.ts +54 -0
- package/dist/cli/register-webhooks.d.ts.map +1 -0
- package/dist/cli/register-webhooks.js +366 -0
- package/dist/cli/register-webhooks.js.map +1 -0
- package/dist/cli/types.d.ts +62 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +12 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/config.d.ts +158 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +236 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +29 -0
- package/dist/index.js.map +1 -0
- package/dist/loaders/viva-oauth2-strategy.d.ts +26 -0
- package/dist/loaders/viva-oauth2-strategy.d.ts.map +1 -0
- package/dist/loaders/viva-oauth2-strategy.js +58 -0
- package/dist/loaders/viva-oauth2-strategy.js.map +1 -0
- package/dist/migrations/Migration_20260425000001_init_viva_payments.d.ts +19 -0
- package/dist/migrations/Migration_20260425000001_init_viva_payments.d.ts.map +1 -0
- package/dist/migrations/Migration_20260425000001_init_viva_payments.js +136 -0
- package/dist/migrations/Migration_20260425000001_init_viva_payments.js.map +1 -0
- package/dist/migrations/Migration_20260425000002_allow_null_order_code.d.ts +31 -0
- package/dist/migrations/Migration_20260425000002_allow_null_order_code.d.ts.map +1 -0
- package/dist/migrations/Migration_20260425000002_allow_null_order_code.js +71 -0
- package/dist/migrations/Migration_20260425000002_allow_null_order_code.js.map +1 -0
- package/dist/migrations/Migration_20260425000003_webhook_retry_count.d.ts +18 -0
- package/dist/migrations/Migration_20260425000003_webhook_retry_count.d.ts.map +1 -0
- package/dist/migrations/Migration_20260425000003_webhook_retry_count.js +42 -0
- package/dist/migrations/Migration_20260425000003_webhook_retry_count.js.map +1 -0
- package/dist/migrations/Migration_20260425000004_webhook_error_and_nullable_merchant.d.ts +29 -0
- package/dist/migrations/Migration_20260425000004_webhook_error_and_nullable_merchant.d.ts.map +1 -0
- package/dist/migrations/Migration_20260425000004_webhook_error_and_nullable_merchant.js +74 -0
- package/dist/migrations/Migration_20260425000004_webhook_error_and_nullable_merchant.js.map +1 -0
- package/dist/models/index.d.ts +7 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/models/index.js +10 -0
- package/dist/models/index.js.map +1 -0
- package/dist/models/viva-tenant-merchant.d.ts +11 -0
- package/dist/models/viva-tenant-merchant.d.ts.map +1 -0
- package/dist/models/viva-tenant-merchant.js +54 -0
- package/dist/models/viva-tenant-merchant.js.map +1 -0
- package/dist/models/viva-transaction.d.ts +34 -0
- package/dist/models/viva-transaction.d.ts.map +1 -0
- package/dist/models/viva-transaction.js +104 -0
- package/dist/models/viva-transaction.js.map +1 -0
- package/dist/models/viva-webhook-event.d.ts +32 -0
- package/dist/models/viva-webhook-event.d.ts.map +1 -0
- package/dist/models/viva-webhook-event.js +88 -0
- package/dist/models/viva-webhook-event.js.map +1 -0
- package/dist/observability/config.d.ts +34 -0
- package/dist/observability/config.d.ts.map +1 -0
- package/dist/observability/config.js +57 -0
- package/dist/observability/config.js.map +1 -0
- package/dist/observability/index.d.ts +8 -0
- package/dist/observability/index.d.ts.map +1 -0
- package/dist/observability/index.js +15 -0
- package/dist/observability/index.js.map +1 -0
- package/dist/observability/prom-metrics.d.ts +41 -0
- package/dist/observability/prom-metrics.d.ts.map +1 -0
- package/dist/observability/prom-metrics.js +219 -0
- package/dist/observability/prom-metrics.js.map +1 -0
- package/dist/providers/payment-provider.d.ts +19 -0
- package/dist/providers/payment-provider.d.ts.map +1 -0
- package/dist/providers/payment-provider.js +24 -0
- package/dist/providers/payment-provider.js.map +1 -0
- package/dist/resolvers/auth-strategy-factory.d.ts +42 -0
- package/dist/resolvers/auth-strategy-factory.d.ts.map +1 -0
- package/dist/resolvers/auth-strategy-factory.js +60 -0
- package/dist/resolvers/auth-strategy-factory.js.map +1 -0
- package/dist/resolvers/tenant-resolver.d.ts +104 -0
- package/dist/resolvers/tenant-resolver.d.ts.map +1 -0
- package/dist/resolvers/tenant-resolver.js +118 -0
- package/dist/resolvers/tenant-resolver.js.map +1 -0
- package/dist/service.d.ts +200 -0
- package/dist/service.d.ts.map +1 -0
- package/dist/service.js +1003 -0
- package/dist/service.js.map +1 -0
- package/dist/subscribers/index.d.ts +5 -0
- package/dist/subscribers/index.d.ts.map +1 -0
- package/dist/subscribers/index.js +10 -0
- package/dist/subscribers/index.js.map +1 -0
- package/dist/subscribers/viva-webhook-event.d.ts +38 -0
- package/dist/subscribers/viva-webhook-event.d.ts.map +1 -0
- package/dist/subscribers/viva-webhook-event.js +133 -0
- package/dist/subscribers/viva-webhook-event.js.map +1 -0
- package/dist/workflows/cleanup-old-webhook-events.d.ts +39 -0
- package/dist/workflows/cleanup-old-webhook-events.d.ts.map +1 -0
- package/dist/workflows/cleanup-old-webhook-events.js +68 -0
- package/dist/workflows/cleanup-old-webhook-events.js.map +1 -0
- package/dist/workflows/index.d.ts +14 -0
- package/dist/workflows/index.d.ts.map +1 -0
- package/dist/workflows/index.js +19 -0
- package/dist/workflows/index.js.map +1 -0
- package/dist/workflows/per-tenant-semaphore.d.ts +47 -0
- package/dist/workflows/per-tenant-semaphore.d.ts.map +1 -0
- package/dist/workflows/per-tenant-semaphore.js +89 -0
- package/dist/workflows/per-tenant-semaphore.js.map +1 -0
- package/dist/workflows/process-webhook-event.d.ts +80 -0
- package/dist/workflows/process-webhook-event.d.ts.map +1 -0
- package/dist/workflows/process-webhook-event.js +280 -0
- package/dist/workflows/process-webhook-event.js.map +1 -0
- package/dist/workflows/reprocess-unresolved-tenants.d.ts +58 -0
- package/dist/workflows/reprocess-unresolved-tenants.d.ts.map +1 -0
- package/dist/workflows/reprocess-unresolved-tenants.js +121 -0
- package/dist/workflows/reprocess-unresolved-tenants.js.map +1 -0
- package/package.json +63 -0
package/dist/cli/plan.js
ADDED
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* plan.ts — pure, IO-free webhook plan computation.
|
|
4
|
+
*
|
|
5
|
+
* Computes the diff between desired webhook state (from config) and current
|
|
6
|
+
* registrations (from Viva API), returning a deterministic action list.
|
|
7
|
+
*
|
|
8
|
+
* Per Viva docs, max 10 webhook URLs per event type.
|
|
9
|
+
*
|
|
10
|
+
* @see references/viva-docs/md/webhooks-for-payments.txt:134 (10-URL limit)
|
|
11
|
+
* @see references/viva-docs/md/isv-partner-program.txt:196 (ISV webhook setup flow)
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.computePlan = computePlan;
|
|
15
|
+
// ---------------------------------------------------------------------------
|
|
16
|
+
// computePlan
|
|
17
|
+
// ---------------------------------------------------------------------------
|
|
18
|
+
/**
|
|
19
|
+
* Computes the desired-vs-current diff and returns an ordered action list.
|
|
20
|
+
*
|
|
21
|
+
* Action ordering for human readability:
|
|
22
|
+
* 1. REGISTER (sorted by eventTypeId)
|
|
23
|
+
* 2. SKIP_ALREADY_REGISTERED (sorted by eventTypeId)
|
|
24
|
+
* 3. DEACTIVATE_DRIFT (sorted by eventTypeId)
|
|
25
|
+
* 4. WARN_LIMIT_NEAR (sorted by eventTypeId)
|
|
26
|
+
* 5. ABORT_LIMIT_HIT (sorted by eventTypeId)
|
|
27
|
+
*
|
|
28
|
+
* This is deterministic: same logical inputs always produce the same output
|
|
29
|
+
* regardless of input ordering.
|
|
30
|
+
*/
|
|
31
|
+
function computePlan(input) {
|
|
32
|
+
const { desired, current, perEventTypeLimit = 10, nearLimitFraction = 0.8, reconcileDrift = false, ownedHostnamePattern, } = input;
|
|
33
|
+
const nearLimitThreshold = Math.floor(perEventTypeLimit * nearLimitFraction);
|
|
34
|
+
// -------------------------------------------------------------------------
|
|
35
|
+
// Build a fast-lookup index of current registrations by eventTypeId + url.
|
|
36
|
+
// -------------------------------------------------------------------------
|
|
37
|
+
// Index: eventTypeId → url → WebhookRegistration
|
|
38
|
+
const currentByTypeAndUrl = new Map();
|
|
39
|
+
// Index: eventTypeId → all registrations (for limit counting)
|
|
40
|
+
const currentByType = new Map();
|
|
41
|
+
for (const reg of current) {
|
|
42
|
+
if (!currentByType.has(reg.eventTypeId)) {
|
|
43
|
+
currentByType.set(reg.eventTypeId, []);
|
|
44
|
+
}
|
|
45
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
46
|
+
currentByType.get(reg.eventTypeId).push(reg);
|
|
47
|
+
if (!currentByTypeAndUrl.has(reg.eventTypeId)) {
|
|
48
|
+
currentByTypeAndUrl.set(reg.eventTypeId, new Map());
|
|
49
|
+
}
|
|
50
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
51
|
+
currentByTypeAndUrl.get(reg.eventTypeId).set(reg.url, reg);
|
|
52
|
+
}
|
|
53
|
+
// -------------------------------------------------------------------------
|
|
54
|
+
// Accumulators (by bucket for deterministic ordering).
|
|
55
|
+
// -------------------------------------------------------------------------
|
|
56
|
+
const registerActions = [];
|
|
57
|
+
const skipActions = [];
|
|
58
|
+
const warnActions = [];
|
|
59
|
+
const abortActions = [];
|
|
60
|
+
// Work on a sorted copy of desired for deterministic output.
|
|
61
|
+
const sortedDesired = [...desired].sort((a, b) => a.eventTypeId - b.eventTypeId);
|
|
62
|
+
for (const d of sortedDesired) {
|
|
63
|
+
const urlIndex = currentByTypeAndUrl.get(d.eventTypeId);
|
|
64
|
+
const existingForType = currentByType.get(d.eventTypeId) ?? [];
|
|
65
|
+
const registeredCount = existingForType.length;
|
|
66
|
+
// Already registered with exact URL → skip.
|
|
67
|
+
if (urlIndex?.has(d.url)) {
|
|
68
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
69
|
+
skipActions.push({ kind: 'SKIP_ALREADY_REGISTERED', existing: urlIndex.get(d.url) });
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
// At limit → abort, no registration attempted.
|
|
73
|
+
if (registeredCount >= perEventTypeLimit) {
|
|
74
|
+
abortActions.push({
|
|
75
|
+
kind: 'ABORT_LIMIT_HIT',
|
|
76
|
+
eventTypeId: d.eventTypeId,
|
|
77
|
+
current: registeredCount,
|
|
78
|
+
limit: perEventTypeLimit,
|
|
79
|
+
});
|
|
80
|
+
continue;
|
|
81
|
+
}
|
|
82
|
+
// Near limit → warn AND register (still proceeds).
|
|
83
|
+
if (registeredCount >= nearLimitThreshold) {
|
|
84
|
+
warnActions.push({
|
|
85
|
+
kind: 'WARN_LIMIT_NEAR',
|
|
86
|
+
eventTypeId: d.eventTypeId,
|
|
87
|
+
current: registeredCount,
|
|
88
|
+
limit: perEventTypeLimit,
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
registerActions.push({ kind: 'REGISTER', desired: d });
|
|
92
|
+
}
|
|
93
|
+
// -------------------------------------------------------------------------
|
|
94
|
+
// Drift reconciliation.
|
|
95
|
+
// -------------------------------------------------------------------------
|
|
96
|
+
const deactivateActions = [];
|
|
97
|
+
if (reconcileDrift) {
|
|
98
|
+
// Build set of desired URLs for fast membership test.
|
|
99
|
+
const desiredUrlSet = new Set(desired.map((d) => d.url));
|
|
100
|
+
const sortedCurrent = [...current].sort((a, b) => a.eventTypeId - b.eventTypeId);
|
|
101
|
+
for (const reg of sortedCurrent) {
|
|
102
|
+
// Only deactivate if:
|
|
103
|
+
// 1. URL is not in desired set.
|
|
104
|
+
// 2. URL matches our owned hostname pattern (don't touch foreign webhooks).
|
|
105
|
+
const isOwned = ownedHostnamePattern ? ownedHostnamePattern.test(reg.url) : true;
|
|
106
|
+
if (!desiredUrlSet.has(reg.url) && isOwned) {
|
|
107
|
+
deactivateActions.push({
|
|
108
|
+
kind: 'DEACTIVATE_DRIFT',
|
|
109
|
+
existing: reg,
|
|
110
|
+
reason: 'URL_NOT_IN_DESIRED',
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
// -------------------------------------------------------------------------
|
|
116
|
+
// Compose final ordered list.
|
|
117
|
+
// -------------------------------------------------------------------------
|
|
118
|
+
const actions = [
|
|
119
|
+
...registerActions,
|
|
120
|
+
...skipActions,
|
|
121
|
+
...deactivateActions,
|
|
122
|
+
...warnActions,
|
|
123
|
+
...abortActions,
|
|
124
|
+
];
|
|
125
|
+
const hasFatalError = abortActions.length > 0;
|
|
126
|
+
return { actions, hasFatalError };
|
|
127
|
+
}
|
|
128
|
+
//# sourceMappingURL=plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"plan.js","sourceRoot":"","sources":["../../src/cli/plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* register-webhooks.ts — CLI entry point for idempotent webhook registration.
|
|
3
|
+
*
|
|
4
|
+
* Mode-aware:
|
|
5
|
+
* - ISV mode: builds the ISV webhook client and POSTs one /isv/v1/webhooks
|
|
6
|
+
* registration per V1 event type (existing behaviour, unchanged).
|
|
7
|
+
* - Merchant mode: Viva offers no programmatic registration. The CLI fetches
|
|
8
|
+
* the verification key from GET /api/messages/config/token (Basic auth,
|
|
9
|
+
* merchant variant) and prints the URLs the operator must paste into Viva
|
|
10
|
+
* Self Care → Sales → API Access → Webhooks. `--reconcile-drift` is
|
|
11
|
+
* non-applicable in merchant mode.
|
|
12
|
+
*
|
|
13
|
+
* Design: deploy-time orchestrated, not runtime self-registration (plan P12).
|
|
14
|
+
* Re-running after a successful apply produces all SKIP_ALREADY_REGISTERED
|
|
15
|
+
* actions, proving idempotency.
|
|
16
|
+
*
|
|
17
|
+
* Exit codes:
|
|
18
|
+
* 0 — clean (no actions OR all applied successfully OR merchant manual setup printed)
|
|
19
|
+
* 1 — plan has actions but --apply was not passed (CI gate use case — ISV mode only)
|
|
20
|
+
* 2 — apply failed (HTTP error, 4xx/5xx from Viva)
|
|
21
|
+
* 3 — fatal precondition (config invalid, ABORT_LIMIT_HIT, missing webhook URL)
|
|
22
|
+
*
|
|
23
|
+
* @see references/viva-docs/md/webhooks-for-payments.txt:134 (10-URL limit)
|
|
24
|
+
* @see references/viva-docs/md/isv-partner-program.txt:196 (ISV webhook setup)
|
|
25
|
+
* @see docs/ENDPOINTS.md §8.1 (merchant verification-key endpoint)
|
|
26
|
+
* @see docs/plans/multi-mode-v0.md §9.5 (CLI behaviour matrix)
|
|
27
|
+
*/
|
|
28
|
+
type Dispatcher = any;
|
|
29
|
+
export interface RunOptions {
|
|
30
|
+
/** Print the plan and exit; do NOT mutate. */
|
|
31
|
+
dryRun: boolean;
|
|
32
|
+
/** Apply REGISTER + DEACTIVATE_DRIFT actions. */
|
|
33
|
+
apply: boolean;
|
|
34
|
+
/**
|
|
35
|
+
* Override target webhook URL; default is built from env (VIVA_WEBHOOK_BASE_URL).
|
|
36
|
+
* Must be provided here or via VIVA_WEBHOOK_BASE_URL env var.
|
|
37
|
+
*/
|
|
38
|
+
webhookBaseUrl?: string | undefined;
|
|
39
|
+
/** When true, run drift reconciliation. */
|
|
40
|
+
reconcileDrift?: boolean | undefined;
|
|
41
|
+
/** Output format: 'human' | 'json'. */
|
|
42
|
+
output: 'human' | 'json';
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Programmatic entry — also called by bin.ts for the CLI.
|
|
46
|
+
* Reads VIVA_* env via loadConfigFromEnv() and branches on config.mode.
|
|
47
|
+
*
|
|
48
|
+
* @param opts - CLI run options.
|
|
49
|
+
* @param env - Optional env override (defaults to process.env). Used in tests.
|
|
50
|
+
* @param dispatcher - Optional undici Dispatcher override (MockAgent in tests).
|
|
51
|
+
*/
|
|
52
|
+
export declare function run(opts: RunOptions, env?: NodeJS.ProcessEnv, dispatcher?: Dispatcher): Promise<number>;
|
|
53
|
+
export {};
|
|
54
|
+
//# sourceMappingURL=register-webhooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-webhooks.d.ts","sourceRoot":"","sources":["../../src/cli/register-webhooks.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAMH,KAAK,UAAU,GAAG,GAAG,CAAC;AAqBtB,MAAM,WAAW,UAAU;IACzB,8CAA8C;IAC9C,MAAM,EAAE,OAAO,CAAC;IAChB,iDAAiD;IACjD,KAAK,EAAE,OAAO,CAAC;IACf;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,2CAA2C;IAC3C,cAAc,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACrC,uCAAuC;IACvC,MAAM,EAAE,OAAO,GAAG,MAAM,CAAC;CAC1B;AA4BD;;;;;;;GAOG;AACH,wBAAsB,GAAG,CACvB,IAAI,EAAE,UAAU,EAChB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,EACvB,UAAU,CAAC,EAAE,UAAU,GACtB,OAAO,CAAC,MAAM,CAAC,CAsDjB"}
|
|
@@ -0,0 +1,366 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* register-webhooks.ts — CLI entry point for idempotent webhook registration.
|
|
4
|
+
*
|
|
5
|
+
* Mode-aware:
|
|
6
|
+
* - ISV mode: builds the ISV webhook client and POSTs one /isv/v1/webhooks
|
|
7
|
+
* registration per V1 event type (existing behaviour, unchanged).
|
|
8
|
+
* - Merchant mode: Viva offers no programmatic registration. The CLI fetches
|
|
9
|
+
* the verification key from GET /api/messages/config/token (Basic auth,
|
|
10
|
+
* merchant variant) and prints the URLs the operator must paste into Viva
|
|
11
|
+
* Self Care → Sales → API Access → Webhooks. `--reconcile-drift` is
|
|
12
|
+
* non-applicable in merchant mode.
|
|
13
|
+
*
|
|
14
|
+
* Design: deploy-time orchestrated, not runtime self-registration (plan P12).
|
|
15
|
+
* Re-running after a successful apply produces all SKIP_ALREADY_REGISTERED
|
|
16
|
+
* actions, proving idempotency.
|
|
17
|
+
*
|
|
18
|
+
* Exit codes:
|
|
19
|
+
* 0 — clean (no actions OR all applied successfully OR merchant manual setup printed)
|
|
20
|
+
* 1 — plan has actions but --apply was not passed (CI gate use case — ISV mode only)
|
|
21
|
+
* 2 — apply failed (HTTP error, 4xx/5xx from Viva)
|
|
22
|
+
* 3 — fatal precondition (config invalid, ABORT_LIMIT_HIT, missing webhook URL)
|
|
23
|
+
*
|
|
24
|
+
* @see references/viva-docs/md/webhooks-for-payments.txt:134 (10-URL limit)
|
|
25
|
+
* @see references/viva-docs/md/isv-partner-program.txt:196 (ISV webhook setup)
|
|
26
|
+
* @see docs/ENDPOINTS.md §8.1 (merchant verification-key endpoint)
|
|
27
|
+
* @see docs/plans/multi-mode-v0.md §9.5 (CLI behaviour matrix)
|
|
28
|
+
*/
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.run = run;
|
|
31
|
+
const isv_1 = require("@sakeetech/viva-payments-core/isv");
|
|
32
|
+
const auth_1 = require("@sakeetech/viva-payments-core/auth");
|
|
33
|
+
const legacy_1 = require("@sakeetech/viva-payments-core/legacy");
|
|
34
|
+
const errors_1 = require("@sakeetech/viva-payments-core/errors");
|
|
35
|
+
const webhooks_1 = require("@sakeetech/viva-payments-core/webhooks");
|
|
36
|
+
const config_js_1 = require("../config.js");
|
|
37
|
+
const plan_js_1 = require("./plan.js");
|
|
38
|
+
const MERCHANT_EVENTS = Object.freeze([
|
|
39
|
+
{ id: 1796, name: 'Transaction Payment Created' },
|
|
40
|
+
{ id: 1797, name: 'Transaction Reversal Created' },
|
|
41
|
+
{ id: 1798, name: 'Transaction Payment Failed' },
|
|
42
|
+
{ id: 4865, name: 'Order Updated' },
|
|
43
|
+
]);
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
// Main entry
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
/**
|
|
48
|
+
* Programmatic entry — also called by bin.ts for the CLI.
|
|
49
|
+
* Reads VIVA_* env via loadConfigFromEnv() and branches on config.mode.
|
|
50
|
+
*
|
|
51
|
+
* @param opts - CLI run options.
|
|
52
|
+
* @param env - Optional env override (defaults to process.env). Used in tests.
|
|
53
|
+
* @param dispatcher - Optional undici Dispatcher override (MockAgent in tests).
|
|
54
|
+
*/
|
|
55
|
+
async function run(opts, env, dispatcher) {
|
|
56
|
+
const effectiveEnv = env ?? process.env;
|
|
57
|
+
// -------------------------------------------------------------------------
|
|
58
|
+
// 1. Load + validate config.
|
|
59
|
+
// -------------------------------------------------------------------------
|
|
60
|
+
let config;
|
|
61
|
+
try {
|
|
62
|
+
config = (0, config_js_1.loadConfigFromEnv)(effectiveEnv);
|
|
63
|
+
}
|
|
64
|
+
catch (err) {
|
|
65
|
+
if (err instanceof errors_1.VivaValidationError) {
|
|
66
|
+
console.error(`[viva-register-webhooks] Config error: ${err.message}`);
|
|
67
|
+
}
|
|
68
|
+
else {
|
|
69
|
+
console.error(`[viva-register-webhooks] Unexpected config error: ${String(err)}`);
|
|
70
|
+
}
|
|
71
|
+
return 3;
|
|
72
|
+
}
|
|
73
|
+
// -------------------------------------------------------------------------
|
|
74
|
+
// 2. Resolve webhook base URL (mode-agnostic).
|
|
75
|
+
// -------------------------------------------------------------------------
|
|
76
|
+
const webhookBaseUrl = opts.webhookBaseUrl ?? effectiveEnv['VIVA_WEBHOOK_BASE_URL'];
|
|
77
|
+
if (!webhookBaseUrl) {
|
|
78
|
+
console.error('[viva-register-webhooks] VIVA_WEBHOOK_BASE_URL is required (or pass --webhook-base-url).');
|
|
79
|
+
return 3;
|
|
80
|
+
}
|
|
81
|
+
// Strip trailing slash for consistent URL construction.
|
|
82
|
+
const baseUrl = webhookBaseUrl.replace(/\/$/, '');
|
|
83
|
+
const webhookUrl = `${baseUrl}/viva/webhook`;
|
|
84
|
+
// -------------------------------------------------------------------------
|
|
85
|
+
// 3. Branch on mode.
|
|
86
|
+
// -------------------------------------------------------------------------
|
|
87
|
+
if (config.mode === 'merchant') {
|
|
88
|
+
return runMerchant({
|
|
89
|
+
config,
|
|
90
|
+
opts,
|
|
91
|
+
webhookUrl,
|
|
92
|
+
...(dispatcher !== undefined ? { dispatcher } : {}),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return runIsv({
|
|
96
|
+
config,
|
|
97
|
+
opts,
|
|
98
|
+
webhookUrl,
|
|
99
|
+
baseUrl,
|
|
100
|
+
...(dispatcher !== undefined ? { dispatcher } : {}),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
async function runMerchant(input) {
|
|
104
|
+
const { config, opts, webhookUrl, dispatcher } = input;
|
|
105
|
+
// --reconcile-drift is non-applicable: Viva merchants cannot list/deactivate
|
|
106
|
+
// webhooks via API — Self Care UI is the only management surface.
|
|
107
|
+
if (opts.reconcileDrift) {
|
|
108
|
+
if (opts.output === 'json') {
|
|
109
|
+
console.log(JSON.stringify({
|
|
110
|
+
mode: 'merchant',
|
|
111
|
+
error: 'reconcile-drift-not-supported',
|
|
112
|
+
message: '--reconcile-drift is not supported in merchant mode (manual setup only). ' +
|
|
113
|
+
'ISV mode uses this flag against POST /isv/v1/webhooks.',
|
|
114
|
+
}, null, 2));
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
console.log('--reconcile-drift is not supported in merchant mode (manual setup only).');
|
|
118
|
+
console.log('ISV mode uses this flag against POST /isv/v1/webhooks.');
|
|
119
|
+
}
|
|
120
|
+
return 0;
|
|
121
|
+
}
|
|
122
|
+
// --dry-run: print expected URLs + placeholder for key, skip the network call.
|
|
123
|
+
if (opts.dryRun) {
|
|
124
|
+
printMerchantInstructions({
|
|
125
|
+
webhookUrl,
|
|
126
|
+
verificationKey: undefined,
|
|
127
|
+
output: opts.output,
|
|
128
|
+
});
|
|
129
|
+
return 0;
|
|
130
|
+
}
|
|
131
|
+
// --apply: fetch verification key from Viva legacy host, then print instructions.
|
|
132
|
+
if (opts.apply) {
|
|
133
|
+
const basicAuth = new legacy_1.BasicAuthClient({
|
|
134
|
+
authVariant: 'merchant',
|
|
135
|
+
environment: config.environment,
|
|
136
|
+
merchantId: config.legacyMerchantId,
|
|
137
|
+
apiKey: config.legacyApiKey,
|
|
138
|
+
...(dispatcher !== undefined ? { dispatcher } : {}),
|
|
139
|
+
});
|
|
140
|
+
let verificationKey;
|
|
141
|
+
try {
|
|
142
|
+
verificationKey = await basicAuth.fetchWebhookVerificationKey();
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
const msg = err instanceof errors_1.VivaApiError ? err.message : String(err);
|
|
146
|
+
console.error(`[viva-register-webhooks] Failed to fetch verification key: ${msg}`);
|
|
147
|
+
return 2;
|
|
148
|
+
}
|
|
149
|
+
printMerchantInstructions({
|
|
150
|
+
webhookUrl,
|
|
151
|
+
verificationKey,
|
|
152
|
+
output: opts.output,
|
|
153
|
+
});
|
|
154
|
+
return 0;
|
|
155
|
+
}
|
|
156
|
+
// Neither --dry-run nor --apply (should be caught by bin.ts but guard here).
|
|
157
|
+
console.error('[viva-register-webhooks] Specify --dry-run or --apply.');
|
|
158
|
+
return 3;
|
|
159
|
+
}
|
|
160
|
+
function printMerchantInstructions(input) {
|
|
161
|
+
const { webhookUrl, verificationKey, output } = input;
|
|
162
|
+
if (output === 'json') {
|
|
163
|
+
console.log(JSON.stringify({
|
|
164
|
+
mode: 'merchant',
|
|
165
|
+
verificationKey: verificationKey ?? '<dry-run — verification key not fetched>',
|
|
166
|
+
events: MERCHANT_EVENTS.map((e) => ({
|
|
167
|
+
id: e.id,
|
|
168
|
+
name: e.name,
|
|
169
|
+
url: webhookUrl,
|
|
170
|
+
})),
|
|
171
|
+
}, null, 2));
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
// Human-readable.
|
|
175
|
+
console.log('');
|
|
176
|
+
console.log('Manual webhook setup required (merchant mode).');
|
|
177
|
+
console.log('');
|
|
178
|
+
console.log('1. Go to Viva Self Care → Sales → API Access → Webhooks.');
|
|
179
|
+
console.log('2. For each event below, register the URL with your storefront base URL:');
|
|
180
|
+
console.log('');
|
|
181
|
+
for (const e of MERCHANT_EVENTS) {
|
|
182
|
+
console.log(` ${e.name} (${e.id}): ${webhookUrl}`);
|
|
183
|
+
}
|
|
184
|
+
console.log('');
|
|
185
|
+
console.log('3. Paste this verification key into VIVA_WEBHOOK_VERIFICATION_KEY in .env:');
|
|
186
|
+
console.log(` ${verificationKey ?? '<dry-run — verification key not fetched>'}`);
|
|
187
|
+
console.log('');
|
|
188
|
+
console.log('4. Restart your Medusa server.');
|
|
189
|
+
console.log('');
|
|
190
|
+
}
|
|
191
|
+
async function runIsv(input) {
|
|
192
|
+
const { config, opts, webhookUrl, baseUrl, dispatcher } = input;
|
|
193
|
+
// -------------------------------------------------------------------------
|
|
194
|
+
// Build IsvWebhooks client.
|
|
195
|
+
// Inject dispatcher when provided (undici MockAgent in tests).
|
|
196
|
+
// The OAuth2 strategy also needs the dispatcher so that MockAgent
|
|
197
|
+
// intercepts both /connect/token and /api/accounts/webhooks calls.
|
|
198
|
+
// -------------------------------------------------------------------------
|
|
199
|
+
const cache = new auth_1.InMemoryTokenCache();
|
|
200
|
+
const mutex = new auth_1.AsyncMutex();
|
|
201
|
+
const primary = new auth_1.OAuth2ClientCredentialsStrategy({
|
|
202
|
+
environment: config.environment,
|
|
203
|
+
clientId: config.clientId,
|
|
204
|
+
clientSecret: config.clientSecret,
|
|
205
|
+
cache,
|
|
206
|
+
mutex,
|
|
207
|
+
...(dispatcher !== undefined ? { dispatcher } : {}),
|
|
208
|
+
});
|
|
209
|
+
const httpClient = new isv_1.IsvHttpClient({
|
|
210
|
+
environment: config.environment,
|
|
211
|
+
authStrategy: primary,
|
|
212
|
+
...(dispatcher !== undefined ? { dispatcher } : {}),
|
|
213
|
+
});
|
|
214
|
+
const isvWebhooks = new isv_1.IsvWebhooks(httpClient);
|
|
215
|
+
// -------------------------------------------------------------------------
|
|
216
|
+
// Build desired state from V1_EVENT_TYPE_IDS.
|
|
217
|
+
// One URL per event type, all pointing to the same endpoint.
|
|
218
|
+
// -------------------------------------------------------------------------
|
|
219
|
+
const desired = webhooks_1.V1_EVENT_TYPE_IDS.map((eventTypeId) => ({
|
|
220
|
+
eventTypeId,
|
|
221
|
+
url: webhookUrl,
|
|
222
|
+
description: `viva-register-webhooks v1 (eventTypeId=${eventTypeId})`,
|
|
223
|
+
}));
|
|
224
|
+
// -------------------------------------------------------------------------
|
|
225
|
+
// Fetch current registrations.
|
|
226
|
+
//
|
|
227
|
+
// The ISV API exposes no list endpoint (probe-verified 2026-05-11). The
|
|
228
|
+
// computePlan model still expects a `current` slice, so we feed it an
|
|
229
|
+
// empty list — plan output reduces to REGISTER actions only. Drift
|
|
230
|
+
// reconciliation is a no-op (kept as a flag so callers don't break, but
|
|
231
|
+
// it cannot detect anything to deactivate).
|
|
232
|
+
// -------------------------------------------------------------------------
|
|
233
|
+
const current = [];
|
|
234
|
+
if (opts.reconcileDrift) {
|
|
235
|
+
console.warn('[viva-register-webhooks] --reconcile-drift is a no-op: the ISV API does not expose list/deactivate endpoints. ' +
|
|
236
|
+
'Existing webhook drift must be cleaned up via the Viva self-care UI.');
|
|
237
|
+
}
|
|
238
|
+
// -------------------------------------------------------------------------
|
|
239
|
+
// Compute plan.
|
|
240
|
+
// -------------------------------------------------------------------------
|
|
241
|
+
const planInput = {
|
|
242
|
+
desired,
|
|
243
|
+
current,
|
|
244
|
+
reconcileDrift: opts.reconcileDrift ?? false,
|
|
245
|
+
};
|
|
246
|
+
// Only pass ownedHostnamePattern when reconciling to satisfy exactOptionalPropertyTypes.
|
|
247
|
+
if (opts.reconcileDrift) {
|
|
248
|
+
planInput.ownedHostnamePattern = buildOwnedPattern(baseUrl);
|
|
249
|
+
}
|
|
250
|
+
const plan = (0, plan_js_1.computePlan)(planInput);
|
|
251
|
+
// -------------------------------------------------------------------------
|
|
252
|
+
// Dry-run: print and exit.
|
|
253
|
+
// -------------------------------------------------------------------------
|
|
254
|
+
if (opts.dryRun) {
|
|
255
|
+
printPlan(plan, opts.output);
|
|
256
|
+
if (plan.hasFatalError) {
|
|
257
|
+
return 3;
|
|
258
|
+
}
|
|
259
|
+
const hasActions = plan.actions.some((a) => a.kind === 'REGISTER' || a.kind === 'DEACTIVATE_DRIFT');
|
|
260
|
+
return hasActions ? 1 : 0;
|
|
261
|
+
}
|
|
262
|
+
// -------------------------------------------------------------------------
|
|
263
|
+
// Apply.
|
|
264
|
+
// -------------------------------------------------------------------------
|
|
265
|
+
if (opts.apply) {
|
|
266
|
+
// Abort immediately if the plan has a fatal error.
|
|
267
|
+
if (plan.hasFatalError) {
|
|
268
|
+
printPlan(plan, opts.output);
|
|
269
|
+
console.error('[viva-register-webhooks] Aborting: ABORT_LIMIT_HIT in plan. ' +
|
|
270
|
+
'Deregister unused webhooks before retrying.');
|
|
271
|
+
return 3;
|
|
272
|
+
}
|
|
273
|
+
printPlan(plan, opts.output);
|
|
274
|
+
const actionsToApply = plan.actions.filter((a) => a.kind === 'REGISTER' || a.kind === 'DEACTIVATE_DRIFT');
|
|
275
|
+
for (const action of actionsToApply) {
|
|
276
|
+
if (action.kind === 'REGISTER') {
|
|
277
|
+
try {
|
|
278
|
+
await isvWebhooks.registerWebhook({
|
|
279
|
+
eventTypeId: action.desired.eventTypeId,
|
|
280
|
+
url: action.desired.url,
|
|
281
|
+
});
|
|
282
|
+
logLine(opts.output, 'applied', `REGISTER eventTypeId=${action.desired.eventTypeId} url=${action.desired.url}`);
|
|
283
|
+
}
|
|
284
|
+
catch (err) {
|
|
285
|
+
const msg = err instanceof errors_1.VivaApiError
|
|
286
|
+
? err.message
|
|
287
|
+
: String(err);
|
|
288
|
+
console.error(`[viva-register-webhooks] REGISTER failed for eventTypeId=${action.desired.eventTypeId}: ${msg}`);
|
|
289
|
+
return 2;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
// DEACTIVATE_DRIFT is unreachable: current=[] means computePlan never emits it.
|
|
293
|
+
}
|
|
294
|
+
logLine(opts.output, 'done', `Applied ${actionsToApply.length} action(s).`);
|
|
295
|
+
return 0;
|
|
296
|
+
}
|
|
297
|
+
// Neither --dry-run nor --apply (should be caught by bin.ts but guard here).
|
|
298
|
+
console.error('[viva-register-webhooks] Specify --dry-run or --apply.');
|
|
299
|
+
return 3;
|
|
300
|
+
}
|
|
301
|
+
// ---------------------------------------------------------------------------
|
|
302
|
+
// Helpers
|
|
303
|
+
// ---------------------------------------------------------------------------
|
|
304
|
+
/**
|
|
305
|
+
* Builds a RegExp that matches URLs containing the hostname extracted from baseUrl.
|
|
306
|
+
*
|
|
307
|
+
* Used for drift reconciliation to avoid touching webhooks that belong to
|
|
308
|
+
* other operators on the same ISV account.
|
|
309
|
+
*/
|
|
310
|
+
function buildOwnedPattern(baseUrl) {
|
|
311
|
+
try {
|
|
312
|
+
const { hostname } = new URL(baseUrl);
|
|
313
|
+
// Escape dots for use in RegExp.
|
|
314
|
+
const escaped = hostname.replace(/\./g, '\\.');
|
|
315
|
+
return new RegExp(escaped);
|
|
316
|
+
}
|
|
317
|
+
catch {
|
|
318
|
+
// If URL parsing fails, fall back to a pattern that matches everything.
|
|
319
|
+
return /.*/;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
function printPlan(plan, output) {
|
|
323
|
+
if (output === 'json') {
|
|
324
|
+
console.log(JSON.stringify({ plan: plan.actions, hasFatalError: plan.hasFatalError }, null, 2));
|
|
325
|
+
return;
|
|
326
|
+
}
|
|
327
|
+
// Human-readable table.
|
|
328
|
+
console.log('');
|
|
329
|
+
console.log('viva-register-webhooks — Plan');
|
|
330
|
+
console.log('─'.repeat(72));
|
|
331
|
+
if (plan.actions.length === 0) {
|
|
332
|
+
console.log(' (no actions — all webhooks already registered)');
|
|
333
|
+
console.log('');
|
|
334
|
+
return;
|
|
335
|
+
}
|
|
336
|
+
for (const action of plan.actions) {
|
|
337
|
+
const line = formatAction(action);
|
|
338
|
+
console.log(` ${line}`);
|
|
339
|
+
}
|
|
340
|
+
console.log('─'.repeat(72));
|
|
341
|
+
console.log(` ${plan.actions.length} action(s) | fatal=${plan.hasFatalError}`);
|
|
342
|
+
console.log('');
|
|
343
|
+
}
|
|
344
|
+
function formatAction(action) {
|
|
345
|
+
switch (action.kind) {
|
|
346
|
+
case 'REGISTER':
|
|
347
|
+
return `[REGISTER] eventTypeId=${action.desired.eventTypeId} url=${action.desired.url}`;
|
|
348
|
+
case 'SKIP_ALREADY_REGISTERED':
|
|
349
|
+
return `[SKIP] eventTypeId=${action.existing.eventTypeId} url=${action.existing.url}`;
|
|
350
|
+
case 'DEACTIVATE_DRIFT':
|
|
351
|
+
return `[DEACTIVATE_DRIFT] eventTypeId=${action.existing.eventTypeId} url=${action.existing.url} reason=${action.reason}`;
|
|
352
|
+
case 'WARN_LIMIT_NEAR':
|
|
353
|
+
return `[WARN_LIMIT_NEAR] eventTypeId=${action.eventTypeId} current=${action.current}/${action.limit}`;
|
|
354
|
+
case 'ABORT_LIMIT_HIT':
|
|
355
|
+
return `[ABORT_LIMIT_HIT] eventTypeId=${action.eventTypeId} current=${action.current}/${action.limit} (operator must deregister)`;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
function logLine(output, level, message) {
|
|
359
|
+
if (output === 'json') {
|
|
360
|
+
console.log(JSON.stringify({ level, message, ts: new Date().toISOString() }));
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
console.log(`[${level}] ${message}`);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
//# sourceMappingURL=register-webhooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"register-webhooks.js","sourceRoot":"","sources":["../../src/cli/register-webhooks.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI types for viva-register-webhooks.
|
|
3
|
+
*
|
|
4
|
+
* Defines the DesiredWebhook input shape, the WebhookPlanAction discriminated
|
|
5
|
+
* union, and PlanResult returned by computePlan().
|
|
6
|
+
*
|
|
7
|
+
* @see references/viva-docs/md/webhooks-for-payments.txt:134 (10-URL limit per event type)
|
|
8
|
+
* @see references/viva-docs/md/isv-partner-program.txt:200 (ISV webhook registration)
|
|
9
|
+
*/
|
|
10
|
+
import type { VivaEventTypeId } from '@sakeetech/viva-payments-core/types';
|
|
11
|
+
/**
|
|
12
|
+
* Locally-defined shape preserved for `computePlan`'s historical model.
|
|
13
|
+
*
|
|
14
|
+
* The ISV API exposes no list endpoint, so the CLI never observes existing
|
|
15
|
+
* registrations — `current` is always supplied as `[]`. SKIP_ALREADY_REGISTERED
|
|
16
|
+
* and DEACTIVATE_DRIFT actions therefore cannot fire at runtime; the shape is
|
|
17
|
+
* retained so that snapshot tests over `computePlan` keep passing.
|
|
18
|
+
*/
|
|
19
|
+
export interface WebhookRegistration {
|
|
20
|
+
webhookId?: string;
|
|
21
|
+
eventTypeId: number;
|
|
22
|
+
url: string;
|
|
23
|
+
isActive: boolean;
|
|
24
|
+
}
|
|
25
|
+
export type { VivaEventTypeId };
|
|
26
|
+
/**
|
|
27
|
+
* A single webhook registration we want to ensure exists at deploy time.
|
|
28
|
+
*/
|
|
29
|
+
export interface DesiredWebhook {
|
|
30
|
+
eventTypeId: VivaEventTypeId;
|
|
31
|
+
/** Full HTTPS URL that will receive the POST. */
|
|
32
|
+
url: string;
|
|
33
|
+
/** Optional friendly description registered with Viva. */
|
|
34
|
+
description?: string;
|
|
35
|
+
}
|
|
36
|
+
export type WebhookPlanAction = {
|
|
37
|
+
kind: 'REGISTER';
|
|
38
|
+
desired: DesiredWebhook;
|
|
39
|
+
} | {
|
|
40
|
+
kind: 'SKIP_ALREADY_REGISTERED';
|
|
41
|
+
existing: WebhookRegistration;
|
|
42
|
+
} | {
|
|
43
|
+
kind: 'DEACTIVATE_DRIFT';
|
|
44
|
+
existing: WebhookRegistration;
|
|
45
|
+
reason: string;
|
|
46
|
+
} | {
|
|
47
|
+
kind: 'WARN_LIMIT_NEAR';
|
|
48
|
+
eventTypeId: number;
|
|
49
|
+
current: number;
|
|
50
|
+
limit: number;
|
|
51
|
+
} | {
|
|
52
|
+
kind: 'ABORT_LIMIT_HIT';
|
|
53
|
+
eventTypeId: number;
|
|
54
|
+
current: number;
|
|
55
|
+
limit: number;
|
|
56
|
+
};
|
|
57
|
+
export interface PlanResult {
|
|
58
|
+
actions: WebhookPlanAction[];
|
|
59
|
+
/** True if any ABORT_LIMIT_HIT is in actions. */
|
|
60
|
+
hasFatalError: boolean;
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/cli/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qCAAqC,CAAC;AAE3E;;;;;;;GAOG;AACH,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;IACZ,QAAQ,EAAE,OAAO,CAAC;CACnB;AAED,YAAY,EAAE,eAAe,EAAE,CAAC;AAMhC;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,eAAe,CAAC;IAC7B,iDAAiD;IACjD,GAAG,EAAE,MAAM,CAAC;IACZ,0DAA0D;IAC1D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAMD,MAAM,MAAM,iBAAiB,GACzB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,cAAc,CAAA;CAAE,GAC7C;IAAE,IAAI,EAAE,yBAAyB,CAAC;IAAC,QAAQ,EAAE,mBAAmB,CAAA;CAAE,GAClE;IAAE,IAAI,EAAE,kBAAkB,CAAC;IAAC,QAAQ,EAAE,mBAAmB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC3E;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAChF;IAAE,IAAI,EAAE,iBAAiB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAMrF,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,iBAAiB,EAAE,CAAC;IAC7B,iDAAiD;IACjD,aAAa,EAAE,OAAO,CAAC;CACxB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* CLI types for viva-register-webhooks.
|
|
4
|
+
*
|
|
5
|
+
* Defines the DesiredWebhook input shape, the WebhookPlanAction discriminated
|
|
6
|
+
* union, and PlanResult returned by computePlan().
|
|
7
|
+
*
|
|
8
|
+
* @see references/viva-docs/md/webhooks-for-payments.txt:134 (10-URL limit per event type)
|
|
9
|
+
* @see references/viva-docs/md/isv-partner-program.txt:200 (ISV webhook registration)
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/cli/types.ts"],"names":[],"mappings":";AAAA;;;;;;;;GAQG"}
|