@vivoa/plugin-sdk 0.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +71 -0
- package/dist/index.d.mts +788 -0
- package/dist/index.d.ts +788 -0
- package/dist/index.js +563 -0
- package/dist/index.mjs +526 -0
- package/package.json +59 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,788 @@
|
|
|
1
|
+
declare const PAYMENT_PLUGIN_TOKEN: "PAYMENT_PLUGINS";
|
|
2
|
+
declare const SHIPPING_PLUGIN_TOKEN: "SHIPPING_PLUGINS";
|
|
3
|
+
|
|
4
|
+
declare enum FieldType {
|
|
5
|
+
String = "string",
|
|
6
|
+
Password = "password",
|
|
7
|
+
Url = "url",
|
|
8
|
+
Number = "number",
|
|
9
|
+
Boolean = "boolean",
|
|
10
|
+
Select = "select"
|
|
11
|
+
}
|
|
12
|
+
declare enum ConfigScope {
|
|
13
|
+
Global = "global",
|
|
14
|
+
Country = "country"
|
|
15
|
+
}
|
|
16
|
+
interface SelectOption {
|
|
17
|
+
value: string;
|
|
18
|
+
label: string;
|
|
19
|
+
}
|
|
20
|
+
interface PluginConfigFieldDependency {
|
|
21
|
+
field: string;
|
|
22
|
+
value: string[];
|
|
23
|
+
}
|
|
24
|
+
interface PluginConfigField {
|
|
25
|
+
key: string;
|
|
26
|
+
label: string;
|
|
27
|
+
type: FieldType;
|
|
28
|
+
required: boolean;
|
|
29
|
+
scopedTo?: ConfigScope;
|
|
30
|
+
dependsOn?: PluginConfigFieldDependency;
|
|
31
|
+
placeholder?: string;
|
|
32
|
+
description?: string;
|
|
33
|
+
options?: SelectOption[];
|
|
34
|
+
internal?: boolean;
|
|
35
|
+
/** Visual group header rendered above the first field of each new group. */
|
|
36
|
+
group?: string;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
declare enum FieldVariant {
|
|
40
|
+
Text = "text",
|
|
41
|
+
Secret = "secret",
|
|
42
|
+
Url = "url",
|
|
43
|
+
Number = "number",
|
|
44
|
+
Select = "select",
|
|
45
|
+
Textarea = "textarea",
|
|
46
|
+
/**
|
|
47
|
+
* Renders a small option set (a `select`-typed schema field) as a segmented
|
|
48
|
+
* pill control instead of a dropdown. Purely presentational — the underlying
|
|
49
|
+
* value/options come from the referenced configSchema field.
|
|
50
|
+
*/
|
|
51
|
+
Segmented = "segmented"
|
|
52
|
+
}
|
|
53
|
+
declare enum ActionVariant {
|
|
54
|
+
Primary = "primary",
|
|
55
|
+
Secondary = "secondary",
|
|
56
|
+
Danger = "danger"
|
|
57
|
+
}
|
|
58
|
+
declare enum RepeaterSource {
|
|
59
|
+
SupportedCountries = "supportedCountries"
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Presentation mode for the whole layout. Declared by the plugin wins; when
|
|
63
|
+
* absent the HOST infers it (wizard when the layout iterates per-country,
|
|
64
|
+
* stacked otherwise). Inference is a host concern and is NOT part of this
|
|
65
|
+
* contract — the SDK only carries the optional declared value.
|
|
66
|
+
*/
|
|
67
|
+
declare enum LayoutMode {
|
|
68
|
+
Wizard = "wizard",
|
|
69
|
+
Stacked = "stacked",
|
|
70
|
+
Tabs = "tabs",
|
|
71
|
+
Sections = "sections"
|
|
72
|
+
}
|
|
73
|
+
declare enum BlockType {
|
|
74
|
+
Field = "field",
|
|
75
|
+
Group = "group",
|
|
76
|
+
Toggle = "toggle",
|
|
77
|
+
Action = "action",
|
|
78
|
+
Callout = "callout",
|
|
79
|
+
Markdown = "markdown",
|
|
80
|
+
Divider = "divider",
|
|
81
|
+
Conditional = "conditional",
|
|
82
|
+
Repeater = "repeater",
|
|
83
|
+
Card = "card",
|
|
84
|
+
Banner = "banner",
|
|
85
|
+
CopyField = "copyField",
|
|
86
|
+
InlineRow = "inlineRow",
|
|
87
|
+
Tabs = "tabs",
|
|
88
|
+
Accordion = "accordion",
|
|
89
|
+
KeyValue = "keyValue"
|
|
90
|
+
}
|
|
91
|
+
declare enum StepStatusFrom {
|
|
92
|
+
Fields = "fields",
|
|
93
|
+
Action = "action"
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Shared base every block extends. Carries the optional 12-col grid span
|
|
97
|
+
* (1–12). Out-of-range values are clamped by the HOST at render time; the
|
|
98
|
+
* contract accepts any number so a newer plugin is never bricked by an older
|
|
99
|
+
* host.
|
|
100
|
+
*/
|
|
101
|
+
interface BlockBase {
|
|
102
|
+
span?: number;
|
|
103
|
+
}
|
|
104
|
+
interface FieldBlock extends BlockBase {
|
|
105
|
+
type: BlockType.Field;
|
|
106
|
+
/** References a key in the plugin's configSchema. */
|
|
107
|
+
key: string;
|
|
108
|
+
variant?: FieldVariant;
|
|
109
|
+
/** Override the configSchema label inside this layout. */
|
|
110
|
+
labelOverride?: string;
|
|
111
|
+
/**
|
|
112
|
+
* Name of a `resolveOptions` source. When set, the host resolves the option
|
|
113
|
+
* list at runtime via `plugin.resolveOptions(optionsFrom, ctx)` instead of a
|
|
114
|
+
* static option set. NOT a configSchema key — it is a runtime source id.
|
|
115
|
+
*/
|
|
116
|
+
optionsFrom?: string;
|
|
117
|
+
}
|
|
118
|
+
interface GroupBlock extends BlockBase {
|
|
119
|
+
type: BlockType.Group;
|
|
120
|
+
title: string;
|
|
121
|
+
description?: string;
|
|
122
|
+
/** configSchema keys included in this group. */
|
|
123
|
+
fields: string[];
|
|
124
|
+
collapsible?: boolean;
|
|
125
|
+
defaultOpen?: boolean;
|
|
126
|
+
}
|
|
127
|
+
interface ToggleBlock extends BlockBase {
|
|
128
|
+
type: BlockType.Toggle;
|
|
129
|
+
/** Logical id, not necessarily a config key. */
|
|
130
|
+
key: string;
|
|
131
|
+
label: string;
|
|
132
|
+
description?: string;
|
|
133
|
+
}
|
|
134
|
+
interface ActionBlock extends BlockBase {
|
|
135
|
+
type: BlockType.Action;
|
|
136
|
+
/** Matches a manifest.actions[id]. */
|
|
137
|
+
id: string;
|
|
138
|
+
label: string;
|
|
139
|
+
variant?: ActionVariant;
|
|
140
|
+
/** When set, the action result feeds the named callout slot. */
|
|
141
|
+
resultSlot?: string;
|
|
142
|
+
}
|
|
143
|
+
interface CalloutBlock extends BlockBase {
|
|
144
|
+
type: BlockType.Callout;
|
|
145
|
+
variant: MessageVariant;
|
|
146
|
+
text: string;
|
|
147
|
+
/** Slot id for `action.resultSlot` to write into. */
|
|
148
|
+
slot?: string;
|
|
149
|
+
}
|
|
150
|
+
interface MarkdownBlock extends BlockBase {
|
|
151
|
+
type: BlockType.Markdown;
|
|
152
|
+
content: string;
|
|
153
|
+
}
|
|
154
|
+
interface DividerBlock extends BlockBase {
|
|
155
|
+
type: BlockType.Divider;
|
|
156
|
+
}
|
|
157
|
+
type ConditionalEquals = string | number | boolean | null;
|
|
158
|
+
interface ConditionalWhen {
|
|
159
|
+
key: string;
|
|
160
|
+
equals: ConditionalEquals;
|
|
161
|
+
}
|
|
162
|
+
interface ConditionalBlock extends BlockBase {
|
|
163
|
+
type: BlockType.Conditional;
|
|
164
|
+
when: ConditionalWhen;
|
|
165
|
+
blocks: Block[];
|
|
166
|
+
}
|
|
167
|
+
interface RepeaterBlock extends BlockBase {
|
|
168
|
+
type: BlockType.Repeater;
|
|
169
|
+
source: RepeaterSource;
|
|
170
|
+
/** Token interpolation: {countryCode}, {countryName}. */
|
|
171
|
+
blocks: Block[];
|
|
172
|
+
}
|
|
173
|
+
/** Titled container. Recurses into `blocks`. */
|
|
174
|
+
interface CardBlock extends BlockBase {
|
|
175
|
+
type: BlockType.Card;
|
|
176
|
+
title?: string;
|
|
177
|
+
description?: string;
|
|
178
|
+
blocks: Block[];
|
|
179
|
+
}
|
|
180
|
+
/** Prominent variant-styled message. Leaf. */
|
|
181
|
+
interface BannerBlock extends BlockBase {
|
|
182
|
+
type: BlockType.Banner;
|
|
183
|
+
variant: MessageVariant;
|
|
184
|
+
title?: string;
|
|
185
|
+
text: string;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Read-only value with a copy affordance. EXACTLY ONE source of the value:
|
|
189
|
+
* a literal, a host `computedValues` key, or a read-only echo of a config key.
|
|
190
|
+
*/
|
|
191
|
+
interface CopyFieldBlock extends BlockBase {
|
|
192
|
+
type: BlockType.CopyField;
|
|
193
|
+
label: string;
|
|
194
|
+
/** Literal value. */
|
|
195
|
+
value?: string;
|
|
196
|
+
/** Key into the host-provided `computedValues` map. */
|
|
197
|
+
computedKey?: string;
|
|
198
|
+
/** Read-only echo of a configSchema field value. */
|
|
199
|
+
fieldKey?: string;
|
|
200
|
+
}
|
|
201
|
+
/** Horizontal row on wide viewports, stacks on narrow. Recurses. */
|
|
202
|
+
interface InlineRowBlock extends BlockBase {
|
|
203
|
+
type: BlockType.InlineRow;
|
|
204
|
+
blocks: Block[];
|
|
205
|
+
}
|
|
206
|
+
interface TabItem {
|
|
207
|
+
id: string;
|
|
208
|
+
label: string;
|
|
209
|
+
blocks: Block[];
|
|
210
|
+
}
|
|
211
|
+
/** One panel visible at a time. Recurses per tab. */
|
|
212
|
+
interface TabsBlock extends BlockBase {
|
|
213
|
+
type: BlockType.Tabs;
|
|
214
|
+
tabs: TabItem[];
|
|
215
|
+
}
|
|
216
|
+
interface AccordionSection {
|
|
217
|
+
id: string;
|
|
218
|
+
title: string;
|
|
219
|
+
defaultOpen?: boolean;
|
|
220
|
+
blocks: Block[];
|
|
221
|
+
}
|
|
222
|
+
/** Collapsible sections. Local toggle, not persisted. Recurses per section. */
|
|
223
|
+
interface AccordionBlock extends BlockBase {
|
|
224
|
+
type: BlockType.Accordion;
|
|
225
|
+
sections: AccordionSection[];
|
|
226
|
+
}
|
|
227
|
+
interface KeyValueRow {
|
|
228
|
+
label: string;
|
|
229
|
+
value?: string;
|
|
230
|
+
computedKey?: string;
|
|
231
|
+
}
|
|
232
|
+
/** Read-only label/value list. Leaf. */
|
|
233
|
+
interface KeyValueBlock extends BlockBase {
|
|
234
|
+
type: BlockType.KeyValue;
|
|
235
|
+
rows: KeyValueRow[];
|
|
236
|
+
}
|
|
237
|
+
type Block = FieldBlock | GroupBlock | ToggleBlock | ActionBlock | CalloutBlock | MarkdownBlock | DividerBlock | ConditionalBlock | RepeaterBlock | CardBlock | BannerBlock | CopyFieldBlock | InlineRowBlock | TabsBlock | AccordionBlock | KeyValueBlock;
|
|
238
|
+
interface StepStatusFromFields {
|
|
239
|
+
from: StepStatusFrom.Fields;
|
|
240
|
+
}
|
|
241
|
+
interface StepStatusFromAction {
|
|
242
|
+
from: StepStatusFrom.Action;
|
|
243
|
+
actionId: string;
|
|
244
|
+
}
|
|
245
|
+
type StepStatusSource = StepStatusFromFields | StepStatusFromAction;
|
|
246
|
+
interface SetupStep {
|
|
247
|
+
id: string;
|
|
248
|
+
title: string;
|
|
249
|
+
intro?: string;
|
|
250
|
+
blocks: Block[];
|
|
251
|
+
/** When set, the step renders once per item of the source. */
|
|
252
|
+
repeatFor?: RepeaterSource;
|
|
253
|
+
status?: StepStatusSource;
|
|
254
|
+
}
|
|
255
|
+
interface SetupAction {
|
|
256
|
+
id: string;
|
|
257
|
+
/** Optional human label (admin can render in audit logs). */
|
|
258
|
+
label?: string;
|
|
259
|
+
/** Whether the action runs per-country. Default: false. */
|
|
260
|
+
perCountry?: boolean;
|
|
261
|
+
}
|
|
262
|
+
interface SetupLayout {
|
|
263
|
+
/** Reserved for Phase 2 — points to a plugin-shipped React bundle. */
|
|
264
|
+
customScreen?: string;
|
|
265
|
+
/**
|
|
266
|
+
* Presentation mode. Declared wins; when absent the host infers it. Additive
|
|
267
|
+
* in 0.4.0 — an older host ignores it and keeps its inferred layout.
|
|
268
|
+
*/
|
|
269
|
+
mode?: LayoutMode;
|
|
270
|
+
intro?: string;
|
|
271
|
+
steps: SetupStep[];
|
|
272
|
+
actions?: SetupAction[];
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
interface SetupLayoutValidation {
|
|
276
|
+
success: boolean;
|
|
277
|
+
data?: SetupLayout;
|
|
278
|
+
errors?: string[];
|
|
279
|
+
}
|
|
280
|
+
/** Validates the full layout including recursive blocks. */
|
|
281
|
+
declare function validateSetupLayout(input: unknown): SetupLayoutValidation;
|
|
282
|
+
declare function crossValidateSetupLayout(layout: SetupLayout, configSchema: PluginConfigField[]): string[];
|
|
283
|
+
|
|
284
|
+
interface PluginManifest {
|
|
285
|
+
name: string;
|
|
286
|
+
displayName?: string;
|
|
287
|
+
version: string;
|
|
288
|
+
entry: string;
|
|
289
|
+
type?: PluginType;
|
|
290
|
+
icon?: string;
|
|
291
|
+
description?: string;
|
|
292
|
+
dependencies?: string[];
|
|
293
|
+
/** Minimum @vivoa/store host version this plugin runs on (semver). */
|
|
294
|
+
minHostVersion?: string;
|
|
295
|
+
/**
|
|
296
|
+
* SDK contract version the plugin was compiled against (see SDK_VERSION).
|
|
297
|
+
* Hosts refuse plugins with an incompatible contract via isSdkCompatible.
|
|
298
|
+
*/
|
|
299
|
+
sdkVersion?: string;
|
|
300
|
+
/**
|
|
301
|
+
* Declarative admin setup screen. When omitted, host renders the legacy
|
|
302
|
+
* auto-form derived from the plugin's configSchema.
|
|
303
|
+
*/
|
|
304
|
+
setup?: SetupLayout;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
declare enum PluginType {
|
|
308
|
+
Payment = "payment",
|
|
309
|
+
Shipping = "shipping",
|
|
310
|
+
Analytics = "analytics",
|
|
311
|
+
Generic = "generic"
|
|
312
|
+
}
|
|
313
|
+
/** Visual tone for messages, callouts and action results. */
|
|
314
|
+
declare enum MessageVariant {
|
|
315
|
+
Info = "info",
|
|
316
|
+
Warning = "warning",
|
|
317
|
+
Success = "success",
|
|
318
|
+
Danger = "danger"
|
|
319
|
+
}
|
|
320
|
+
interface PluginActionResult {
|
|
321
|
+
ok: boolean;
|
|
322
|
+
message?: string;
|
|
323
|
+
variant?: MessageVariant;
|
|
324
|
+
data?: unknown;
|
|
325
|
+
}
|
|
326
|
+
interface PluginActionContext {
|
|
327
|
+
/** When the action was triggered from a country-scoped step. */
|
|
328
|
+
country?: string;
|
|
329
|
+
/** Free-form payload sent from the admin UI. */
|
|
330
|
+
payload?: unknown;
|
|
331
|
+
/**
|
|
332
|
+
* Resolved GLOBAL-scope config for the current tenant. The host populates
|
|
333
|
+
* this so actions (e.g. testConnection) can build a client without any
|
|
334
|
+
* prior `initialize()` — same stateless discipline as the dispatch methods.
|
|
335
|
+
*/
|
|
336
|
+
config?: Record<string, unknown>;
|
|
337
|
+
/** Resolved config for `country`, when the action is country-scoped. */
|
|
338
|
+
countryConfig?: Record<string, unknown>;
|
|
339
|
+
}
|
|
340
|
+
/** Option resolved at runtime for a field whose `optionsFrom` is set. */
|
|
341
|
+
interface FieldOption {
|
|
342
|
+
value: string;
|
|
343
|
+
label: string;
|
|
344
|
+
}
|
|
345
|
+
interface IPlugin {
|
|
346
|
+
readonly manifest: PluginManifest;
|
|
347
|
+
onActivate?(): Promise<void>;
|
|
348
|
+
onDeactivate?(): Promise<void>;
|
|
349
|
+
invokeAction?(actionId: string, ctx: PluginActionContext): Promise<PluginActionResult>;
|
|
350
|
+
/**
|
|
351
|
+
* Resolve the option list for a field whose `optionsFrom` matches `source`.
|
|
352
|
+
* PURE (query semantics) — the host never persists anything as a side effect
|
|
353
|
+
* of calling it. Optional: a plugin without it degrades the field to a plain
|
|
354
|
+
* input. Draft-aware via `ctx` (same resolved-config discipline as
|
|
355
|
+
* `invokeAction`).
|
|
356
|
+
*/
|
|
357
|
+
resolveOptions?(source: string, ctx: PluginActionContext): Promise<FieldOption[]>;
|
|
358
|
+
}
|
|
359
|
+
interface ConfigurablePlugin {
|
|
360
|
+
loadConfig(config: Record<string, unknown>): void;
|
|
361
|
+
}
|
|
362
|
+
declare function isConfigurablePlugin(plugin: unknown): plugin is ConfigurablePlugin;
|
|
363
|
+
|
|
364
|
+
interface FieldDependsOn {
|
|
365
|
+
field: string;
|
|
366
|
+
value: string | string[];
|
|
367
|
+
}
|
|
368
|
+
interface FieldDefinition {
|
|
369
|
+
label: string;
|
|
370
|
+
type: FieldType;
|
|
371
|
+
required?: boolean;
|
|
372
|
+
scopedTo?: ConfigScope;
|
|
373
|
+
dependsOn?: FieldDependsOn;
|
|
374
|
+
placeholder?: string;
|
|
375
|
+
description?: string;
|
|
376
|
+
options?: SelectOption[];
|
|
377
|
+
internal?: boolean;
|
|
378
|
+
group?: string;
|
|
379
|
+
}
|
|
380
|
+
declare function field(def: FieldDefinition): FieldDefinition;
|
|
381
|
+
type FieldMap = Record<string, FieldDefinition>;
|
|
382
|
+
interface PluginConfigValidation {
|
|
383
|
+
success: boolean;
|
|
384
|
+
data?: Record<string, unknown>;
|
|
385
|
+
errors?: string[];
|
|
386
|
+
}
|
|
387
|
+
interface PluginConfigResult {
|
|
388
|
+
configFields: PluginConfigField[];
|
|
389
|
+
validate: (data: unknown) => PluginConfigValidation;
|
|
390
|
+
}
|
|
391
|
+
declare function createPluginConfig(fields: FieldMap): PluginConfigResult;
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Everything a plugin needs to serve ONE operation for ONE tenant, resolved by
|
|
395
|
+
* the host up front. Nothing here is cached on the plugin instance — the same
|
|
396
|
+
* plugin object serves every tenant, and each call carries its own context.
|
|
397
|
+
* This is what removes the "init + dispatch in the same synchronous block"
|
|
398
|
+
* hazard the stateful contract used to require.
|
|
399
|
+
*/
|
|
400
|
+
interface DispatchContext {
|
|
401
|
+
/** Resolved, merged GLOBAL-scope config for the current tenant. */
|
|
402
|
+
readonly config: Record<string, unknown>;
|
|
403
|
+
/**
|
|
404
|
+
* Resolved config for the country in scope, when the operation is
|
|
405
|
+
* country-bound (e.g. a shipping quote for SV). Merged defaults + tenant DB.
|
|
406
|
+
*/
|
|
407
|
+
readonly countryConfig?: Record<string, unknown>;
|
|
408
|
+
/**
|
|
409
|
+
* All resolved country configs keyed by ISO code, for operations that span
|
|
410
|
+
* countries. Prefer {@link countryConfig} for single-country dispatch.
|
|
411
|
+
*/
|
|
412
|
+
readonly countryConfigs?: Record<string, Record<string, unknown>>;
|
|
413
|
+
/** The ISO country code in scope, when applicable. */
|
|
414
|
+
readonly countryCode?: string;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/**
|
|
418
|
+
* Free-form gateway code defined by each plugin in its manifest/config.
|
|
419
|
+
* The host stores this string verbatim; no enum of allowed providers.
|
|
420
|
+
*/
|
|
421
|
+
type PaymentGatewayCode = string;
|
|
422
|
+
declare enum TransactionStatus {
|
|
423
|
+
Pending = "Pending",
|
|
424
|
+
PendingRedirect = "Pending_Redirect",
|
|
425
|
+
Approved = "Approved",
|
|
426
|
+
Declined = "Declined",
|
|
427
|
+
Failed = "Failed",
|
|
428
|
+
Error = "Error"
|
|
429
|
+
}
|
|
430
|
+
declare enum GatewayEnvironment {
|
|
431
|
+
Sandbox = "sandbox",
|
|
432
|
+
Production = "production"
|
|
433
|
+
}
|
|
434
|
+
interface PaymentCard {
|
|
435
|
+
number: string;
|
|
436
|
+
cvv: string;
|
|
437
|
+
expirationMonth: string;
|
|
438
|
+
expirationYear: string;
|
|
439
|
+
holderFirstName: string;
|
|
440
|
+
holderLastName: string;
|
|
441
|
+
}
|
|
442
|
+
interface PaymentCustomer {
|
|
443
|
+
email: string;
|
|
444
|
+
phone: string;
|
|
445
|
+
address?: string;
|
|
446
|
+
city?: string;
|
|
447
|
+
state?: string;
|
|
448
|
+
country?: string;
|
|
449
|
+
zip?: string;
|
|
450
|
+
}
|
|
451
|
+
interface PaymentPayload {
|
|
452
|
+
amount: number;
|
|
453
|
+
currency: string;
|
|
454
|
+
orderId: string;
|
|
455
|
+
card: PaymentCard;
|
|
456
|
+
customer: PaymentCustomer;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Generic verify payload. Provider-specific data travels in `providerData`,
|
|
460
|
+
* each plugin casts it to its own type. The host passes it through opaquely.
|
|
461
|
+
*/
|
|
462
|
+
interface PaymentVerifyPayload {
|
|
463
|
+
transactionId: string;
|
|
464
|
+
providerData?: unknown;
|
|
465
|
+
}
|
|
466
|
+
interface PaymentResult {
|
|
467
|
+
status: TransactionStatus;
|
|
468
|
+
gatewayTransactionId: string;
|
|
469
|
+
message: string;
|
|
470
|
+
authorizationCode?: string;
|
|
471
|
+
redirectUrl?: string;
|
|
472
|
+
rawResponse?: unknown;
|
|
473
|
+
}
|
|
474
|
+
interface GatewayStaticConfig {
|
|
475
|
+
code: PaymentGatewayCode;
|
|
476
|
+
displayName: string;
|
|
477
|
+
description: string;
|
|
478
|
+
environment: GatewayEnvironment;
|
|
479
|
+
supportedMethods: string[];
|
|
480
|
+
requiredEnvVars: string[];
|
|
481
|
+
}
|
|
482
|
+
interface PaymentPluginConfig {
|
|
483
|
+
configSchema: PluginConfigField[];
|
|
484
|
+
}
|
|
485
|
+
interface WebhookSignatureResult {
|
|
486
|
+
isValid: boolean;
|
|
487
|
+
error?: string;
|
|
488
|
+
}
|
|
489
|
+
interface IPaymentPlugin extends IPlugin {
|
|
490
|
+
readonly gatewayCode: PaymentGatewayCode;
|
|
491
|
+
readonly staticConfig: GatewayStaticConfig;
|
|
492
|
+
readonly paymentConfig?: PaymentPluginConfig;
|
|
493
|
+
processPayment(payload: PaymentPayload, ctx: DispatchContext): Promise<PaymentResult>;
|
|
494
|
+
verifyTransaction?(payload: PaymentVerifyPayload, ctx: DispatchContext): Promise<PaymentResult>;
|
|
495
|
+
validateWebhookSignature?(rawBody: string | Buffer, headers: Record<string, string>, ctx: DispatchContext): WebhookSignatureResult;
|
|
496
|
+
processWebhook?(payload: unknown, ctx: DispatchContext): Promise<void>;
|
|
497
|
+
/**
|
|
498
|
+
* Query the gateway for the current status of a previously attempted charge.
|
|
499
|
+
* Called by the host when `processPayment` returns `status: Error` with a
|
|
500
|
+
* non-empty `gatewayTransactionId` (e.g. Serfinsa `audit_no` on timeout).
|
|
501
|
+
* MUST NOT accept or re-use card data — ID-only reconciliation.
|
|
502
|
+
*/
|
|
503
|
+
queryTransaction?(ref: {
|
|
504
|
+
transactionId: string;
|
|
505
|
+
}, ctx: DispatchContext): Promise<PaymentResult>;
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
declare enum ShippingFeature {
|
|
509
|
+
Tracking = "tracking",
|
|
510
|
+
Cod = "cod",
|
|
511
|
+
Quotes = "quotes",
|
|
512
|
+
Labels = "labels"
|
|
513
|
+
}
|
|
514
|
+
declare enum CodFeeType {
|
|
515
|
+
Percentage = "percentage",
|
|
516
|
+
Fixed = "fixed"
|
|
517
|
+
}
|
|
518
|
+
interface CodFeeConfig {
|
|
519
|
+
type: CodFeeType;
|
|
520
|
+
value: number;
|
|
521
|
+
description: string;
|
|
522
|
+
}
|
|
523
|
+
interface ShippingDefaultConfig {
|
|
524
|
+
global?: Record<string, unknown>;
|
|
525
|
+
countries?: Record<string, Record<string, unknown>>;
|
|
526
|
+
}
|
|
527
|
+
interface ShippingPluginConfig {
|
|
528
|
+
supportedCountries: string[];
|
|
529
|
+
supportedFeatures: ShippingFeature[];
|
|
530
|
+
configSchema: PluginConfigField[];
|
|
531
|
+
codFeeConfig?: CodFeeConfig;
|
|
532
|
+
defaultConfig?: ShippingDefaultConfig;
|
|
533
|
+
}
|
|
534
|
+
interface ShippingStaticConfig {
|
|
535
|
+
code: string;
|
|
536
|
+
displayName: string;
|
|
537
|
+
description: string;
|
|
538
|
+
iconUrl?: string;
|
|
539
|
+
supportedCountries: string[];
|
|
540
|
+
supportedFeatures: ShippingFeature[];
|
|
541
|
+
configSchema: PluginConfigField[];
|
|
542
|
+
codFeeConfig?: CodFeeConfig;
|
|
543
|
+
}
|
|
544
|
+
interface ShipmentAddress {
|
|
545
|
+
fullName: string;
|
|
546
|
+
phone: string;
|
|
547
|
+
phoneAreaCode: string;
|
|
548
|
+
email: string | null;
|
|
549
|
+
address: string;
|
|
550
|
+
referencePoint: string;
|
|
551
|
+
instructions?: string;
|
|
552
|
+
city: string;
|
|
553
|
+
cityId?: string;
|
|
554
|
+
state: string;
|
|
555
|
+
stateId?: string;
|
|
556
|
+
zip?: string;
|
|
557
|
+
country: string;
|
|
558
|
+
latitude?: number;
|
|
559
|
+
longitude?: number;
|
|
560
|
+
}
|
|
561
|
+
interface ShipmentParcel {
|
|
562
|
+
content: string;
|
|
563
|
+
length: number;
|
|
564
|
+
width: number;
|
|
565
|
+
height: number;
|
|
566
|
+
weight: number;
|
|
567
|
+
price?: number;
|
|
568
|
+
isFragile?: boolean;
|
|
569
|
+
}
|
|
570
|
+
interface ShippingQuoteParams {
|
|
571
|
+
origin: ShipmentAddress;
|
|
572
|
+
destination: ShipmentAddress;
|
|
573
|
+
countryCode: string;
|
|
574
|
+
parcels?: ShipmentParcel[];
|
|
575
|
+
}
|
|
576
|
+
interface ShippingQuote {
|
|
577
|
+
carrierId: string;
|
|
578
|
+
carrierName: string;
|
|
579
|
+
price: number;
|
|
580
|
+
codCommission: number;
|
|
581
|
+
codFee?: number;
|
|
582
|
+
supportsCod: boolean;
|
|
583
|
+
deliveryType: string;
|
|
584
|
+
logo: string | null;
|
|
585
|
+
isPricePromotion: boolean;
|
|
586
|
+
isCommissionPromotion: boolean;
|
|
587
|
+
provider: string;
|
|
588
|
+
}
|
|
589
|
+
interface CodConfig {
|
|
590
|
+
enabled: boolean;
|
|
591
|
+
amount: number;
|
|
592
|
+
}
|
|
593
|
+
interface CreateShipmentParams {
|
|
594
|
+
orderId: string;
|
|
595
|
+
pickup: ShipmentAddress;
|
|
596
|
+
delivery: ShipmentAddress;
|
|
597
|
+
parcels: ShipmentParcel[];
|
|
598
|
+
recolectionDate: Date;
|
|
599
|
+
cod?: CodConfig;
|
|
600
|
+
courierId?: string;
|
|
601
|
+
serviceLevelToken?: string;
|
|
602
|
+
}
|
|
603
|
+
interface ShipmentResult {
|
|
604
|
+
externalId: string;
|
|
605
|
+
trackingNumber: string;
|
|
606
|
+
trackingUrl: string;
|
|
607
|
+
labelUrl: string | null;
|
|
608
|
+
provider: string;
|
|
609
|
+
courierName: string;
|
|
610
|
+
status: string;
|
|
611
|
+
rawResponse?: Record<string, unknown>;
|
|
612
|
+
}
|
|
613
|
+
interface IShippingPlugin extends IPlugin {
|
|
614
|
+
readonly name: string;
|
|
615
|
+
readonly shippingConfig: ShippingPluginConfig;
|
|
616
|
+
createShipment(params: CreateShipmentParams, ctx: DispatchContext): Promise<ShipmentResult>;
|
|
617
|
+
getQuotes?(params: ShippingQuoteParams, ctx: DispatchContext): Promise<ShippingQuote[]>;
|
|
618
|
+
/** Pure — a tracking URL never depends on tenant config. */
|
|
619
|
+
getTrackingUrl(trackingNumber: string): string;
|
|
620
|
+
isConfigured?(ctx: DispatchContext): boolean;
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/** A named unit of behaviour a plugin exposes to the host registry. */
|
|
624
|
+
interface Capability<T = unknown> {
|
|
625
|
+
kind: string;
|
|
626
|
+
impl: T;
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Canonical built-in capability kinds. Open set — a plugin MAY register a
|
|
630
|
+
* `kind` not listed here; the host routes by string. These constants exist so
|
|
631
|
+
* first-party contracts share one spelling.
|
|
632
|
+
*/
|
|
633
|
+
declare const CapabilityKind: {
|
|
634
|
+
readonly Payment: "payment";
|
|
635
|
+
readonly Shipping: "shipping";
|
|
636
|
+
readonly Analytics: "analytics";
|
|
637
|
+
};
|
|
638
|
+
type CapabilityKind = (typeof CapabilityKind)[keyof typeof CapabilityKind];
|
|
639
|
+
declare function capability<T>(kind: string, impl: T): Capability<T>;
|
|
640
|
+
declare function paymentCapability(impl: IPaymentPlugin): Capability<IPaymentPlugin>;
|
|
641
|
+
declare function shippingCapability(impl: IShippingPlugin): Capability<IShippingPlugin>;
|
|
642
|
+
/**
|
|
643
|
+
* A constructed plugin. `capabilities` is the static declaration the host reads
|
|
644
|
+
* up front; `onActivate` runs when the host mounts the plugin for a tenant and
|
|
645
|
+
* is where side-effecting registration/subscription happens.
|
|
646
|
+
*/
|
|
647
|
+
interface Plugin {
|
|
648
|
+
readonly manifest: PluginManifest;
|
|
649
|
+
readonly capabilities: Capability[];
|
|
650
|
+
onActivate?(host: HostApi): void | Promise<void>;
|
|
651
|
+
onDeactivate?(): void | Promise<void>;
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* The plugin entry point. The compiled bundle's default export is a
|
|
655
|
+
* `PluginFactory`; the host calls it with a per-tenant `HostApi`. No NestJS,
|
|
656
|
+
* no decorators — the host owns dependency injection on its side.
|
|
657
|
+
*/
|
|
658
|
+
type PluginFactory = (host: HostApi) => Plugin | Promise<Plugin>;
|
|
659
|
+
/**
|
|
660
|
+
* Anchors the factory type for plugin authors AND brands the function so the
|
|
661
|
+
* host loader can tell a `PluginFactory` (new, framework-agnostic) apart from a
|
|
662
|
+
* legacy NestJS `@Module` default export at runtime.
|
|
663
|
+
*/
|
|
664
|
+
declare function definePlugin(factory: PluginFactory): PluginFactory;
|
|
665
|
+
/** True when `value` was produced by {@link definePlugin}. */
|
|
666
|
+
declare function isPluginFactory(value: unknown): value is PluginFactory;
|
|
667
|
+
|
|
668
|
+
interface Logger {
|
|
669
|
+
debug(message: string, ...meta: unknown[]): void;
|
|
670
|
+
info(message: string, ...meta: unknown[]): void;
|
|
671
|
+
warn(message: string, ...meta: unknown[]): void;
|
|
672
|
+
error(message: string, ...meta: unknown[]): void;
|
|
673
|
+
}
|
|
674
|
+
interface HttpRequest {
|
|
675
|
+
method: string;
|
|
676
|
+
url: string;
|
|
677
|
+
headers?: Record<string, string>;
|
|
678
|
+
body?: unknown;
|
|
679
|
+
}
|
|
680
|
+
interface HttpResponse {
|
|
681
|
+
status: number;
|
|
682
|
+
headers: Record<string, string>;
|
|
683
|
+
body: unknown;
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* Outbound HTTP mediated by the host. The host enforces the plugin's
|
|
687
|
+
* `http.outbound:<host>` permissions before the request leaves the process —
|
|
688
|
+
* the plugin cannot reach the network directly.
|
|
689
|
+
*/
|
|
690
|
+
interface HttpClient {
|
|
691
|
+
request(req: HttpRequest): Promise<HttpResponse>;
|
|
692
|
+
}
|
|
693
|
+
/**
|
|
694
|
+
* Secret access mediated by the host (never `process.env` directly). Gated by
|
|
695
|
+
* `secrets.read:<key>` permissions. Returns the resolved per-tenant secret.
|
|
696
|
+
*/
|
|
697
|
+
interface SecretStore {
|
|
698
|
+
get(key: string): Promise<string | undefined>;
|
|
699
|
+
}
|
|
700
|
+
/** Object storage mediated by the host (presigned broker under the hood). */
|
|
701
|
+
interface StorageBroker {
|
|
702
|
+
getUrl(key: string): Promise<string>;
|
|
703
|
+
put(key: string, body: Uint8Array | string): Promise<void>;
|
|
704
|
+
}
|
|
705
|
+
/**
|
|
706
|
+
* Monotonic sequence numbers owned and PERSISTED by the host. A stateless
|
|
707
|
+
* plugin cannot keep its own counter (it holds no per-tenant state and the same
|
|
708
|
+
* object serves every tenant), yet some gateways require a strictly increasing,
|
|
709
|
+
* unique-per-merchant number (e.g. Serfinsa's `audit_no`). The plugin asks the
|
|
710
|
+
* host for the next value under a plugin-chosen `scope` string; the host does
|
|
711
|
+
* the atomic increment and durable storage.
|
|
712
|
+
*
|
|
713
|
+
* `scope` namespaces the counter — encode everything that must have its own run
|
|
714
|
+
* of numbers, e.g. `serfinsa:audit_no:<merchantId>`. Two calls with the same
|
|
715
|
+
* scope never return the same value; different scopes are independent.
|
|
716
|
+
*/
|
|
717
|
+
interface SequenceStore {
|
|
718
|
+
next(scope: string): Promise<number>;
|
|
719
|
+
}
|
|
720
|
+
type DomainEventName = string;
|
|
721
|
+
type DomainEventHandler = (payload: unknown) => void | Promise<void>;
|
|
722
|
+
/**
|
|
723
|
+
* The one object a plugin factory receives. It is the plugin's ENTIRE window
|
|
724
|
+
* into the host — no `@nestjs/*`, no prisma, no `process`. Everything the
|
|
725
|
+
* plugin can do flows through these ports, which lets the host enforce the
|
|
726
|
+
* plugin's declared permissions and swap the transport (in-process today,
|
|
727
|
+
* worker/WASM later) without touching plugin code.
|
|
728
|
+
*/
|
|
729
|
+
interface HostApi {
|
|
730
|
+
readonly logger: Logger;
|
|
731
|
+
readonly http: HttpClient;
|
|
732
|
+
readonly secrets: SecretStore;
|
|
733
|
+
readonly storage: StorageBroker;
|
|
734
|
+
readonly sequence: SequenceStore;
|
|
735
|
+
/** Subscribe to a host domain event (order.created, product.updated, ...). */
|
|
736
|
+
on(event: DomainEventName, handler: DomainEventHandler): void;
|
|
737
|
+
/** Expose a capability to the host's generic registry. */
|
|
738
|
+
registerCapability<T = unknown>(cap: Capability<T>): void;
|
|
739
|
+
}
|
|
740
|
+
|
|
741
|
+
/** Wire format: `domain.action` or `domain.action:resource`. */
|
|
742
|
+
interface Permission {
|
|
743
|
+
domain: string;
|
|
744
|
+
action: string;
|
|
745
|
+
resource?: string;
|
|
746
|
+
}
|
|
747
|
+
declare function parsePermission(raw: string): Permission | null;
|
|
748
|
+
/**
|
|
749
|
+
* True when `required` is covered by `granted`. Domain+action must match. For
|
|
750
|
+
* the resource dimension:
|
|
751
|
+
* - required has no resource → a granted domain.action (any resource) covers it.
|
|
752
|
+
* - required has a resource → needs a granted entry with the same resource,
|
|
753
|
+
* or a wildcard '*' grant. A resource-less grant
|
|
754
|
+
* does NOT cover a resource-scoped requirement.
|
|
755
|
+
*/
|
|
756
|
+
declare function isPermissionGranted(required: Permission, granted: Permission[]): boolean;
|
|
757
|
+
interface PermissionCheck {
|
|
758
|
+
ok: boolean;
|
|
759
|
+
granted: string[];
|
|
760
|
+
missing: string[];
|
|
761
|
+
}
|
|
762
|
+
/**
|
|
763
|
+
* Splits `required` raw strings into granted vs missing against `grantedRaw`.
|
|
764
|
+
* Malformed required strings are always reported as missing (fail closed).
|
|
765
|
+
*/
|
|
766
|
+
declare function checkPermissions(required: string[], grantedRaw: string[]): PermissionCheck;
|
|
767
|
+
|
|
768
|
+
/**
|
|
769
|
+
* Version of the plugin SDK CONTRACT (kept in sync with package.json by the
|
|
770
|
+
* release script). Plugins compiled against this SDK declare it in their
|
|
771
|
+
* manifest (`sdkVersion`); hosts use it to refuse loading plugins built
|
|
772
|
+
* against an incompatible contract.
|
|
773
|
+
*
|
|
774
|
+
* Semver discipline for the contract:
|
|
775
|
+
* - MAJOR: breaking change to any exported type/token — hosts refuse mismatched majors.
|
|
776
|
+
* - MINOR: additive (new optional fields, new tokens) — backwards compatible.
|
|
777
|
+
* - PATCH: docs/fixes with zero shape changes.
|
|
778
|
+
*/
|
|
779
|
+
declare const SDK_VERSION = "0.5.0";
|
|
780
|
+
/**
|
|
781
|
+
* True when a plugin built against `pluginSdkVersion` can run on a host that
|
|
782
|
+
* ships `hostSdkVersion`. Rule: same major, host minor >= plugin minor.
|
|
783
|
+
* Pre-1.0 caveat: majors are 0, so minors act as breaking boundaries — hence
|
|
784
|
+
* the stricter equality check while major is 0 (npm-style ^0.x semantics).
|
|
785
|
+
*/
|
|
786
|
+
declare function isSdkCompatible(pluginSdkVersion: string, hostSdkVersion: string): boolean;
|
|
787
|
+
|
|
788
|
+
export { type AccordionBlock, type AccordionSection, type ActionBlock, ActionVariant, type BannerBlock, type Block, type BlockBase, BlockType, type CalloutBlock, type Capability, CapabilityKind, type CardBlock, type CodConfig, type CodFeeConfig, CodFeeType, type ConditionalBlock, type ConditionalEquals, type ConditionalWhen, ConfigScope, type ConfigurablePlugin, type CopyFieldBlock, type CreateShipmentParams, type DispatchContext, type DividerBlock, type DomainEventHandler, type DomainEventName, type FieldBlock, type FieldDefinition, type FieldDependsOn, type FieldMap, type FieldOption, FieldType, FieldVariant, GatewayEnvironment, type GatewayStaticConfig, type GroupBlock, type HostApi, type HttpClient, type HttpRequest, type HttpResponse, type IPaymentPlugin, type IPlugin, type IShippingPlugin, type InlineRowBlock, type KeyValueBlock, type KeyValueRow, LayoutMode, type Logger, type MarkdownBlock, MessageVariant, PAYMENT_PLUGIN_TOKEN, type PaymentCard, type PaymentCustomer, type PaymentGatewayCode, type PaymentPayload, type PaymentPluginConfig, type PaymentResult, type PaymentVerifyPayload, type Permission, type PermissionCheck, type Plugin, type PluginActionContext, type PluginActionResult, type PluginConfigField, type PluginConfigFieldDependency, type PluginConfigResult, type PluginConfigValidation, type PluginFactory, type PluginManifest, PluginType, type RepeaterBlock, RepeaterSource, SDK_VERSION, SHIPPING_PLUGIN_TOKEN, type SecretStore, type SelectOption, type SequenceStore, type SetupAction, type SetupLayout, type SetupLayoutValidation, type SetupStep, type ShipmentAddress, type ShipmentParcel, type ShipmentResult, type ShippingDefaultConfig, ShippingFeature, type ShippingPluginConfig, type ShippingQuote, type ShippingQuoteParams, type ShippingStaticConfig, StepStatusFrom, type StepStatusFromAction, type StepStatusFromFields, type StepStatusSource, type StorageBroker, type TabItem, type TabsBlock, type ToggleBlock, TransactionStatus, type WebhookSignatureResult, capability, checkPermissions, createPluginConfig, crossValidateSetupLayout, definePlugin, field, isConfigurablePlugin, isPermissionGranted, isPluginFactory, isSdkCompatible, parsePermission, paymentCapability, shippingCapability, validateSetupLayout };
|