@open-mercato/cli 0.4.7-main-1768da2e43 → 0.4.7
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/build.mjs +8 -1
- package/dist/agentic/claude-code/CLAUDE.md.template +1 -0
- package/dist/agentic/claude-code/hooks/entity-migration-check.ts +121 -0
- package/dist/agentic/claude-code/mcp.json.example +13 -0
- package/dist/agentic/claude-code/settings.json +16 -0
- package/dist/agentic/codex/enforcement-rules.md +20 -0
- package/dist/agentic/codex/mcp.json.example +12 -0
- package/dist/agentic/cursor/hooks/entity-migration-check.mjs +69 -0
- package/dist/agentic/cursor/hooks.json +10 -0
- package/dist/agentic/cursor/mcp.json.example +13 -0
- package/dist/agentic/cursor/rules/entity-guard.mdc +29 -0
- package/dist/agentic/cursor/rules/generated-guard.mdc +12 -0
- package/dist/agentic/cursor/rules/open-mercato.mdc +34 -0
- package/dist/agentic/shared/AGENTS.md.template +180 -0
- package/dist/agentic/shared/ai/lessons.md +4 -0
- package/dist/agentic/shared/ai/skills/backend-ui-design/SKILL.md +197 -0
- package/dist/agentic/shared/ai/skills/backend-ui-design/references/ui-components.md +233 -0
- package/dist/agentic/shared/ai/skills/code-review/SKILL.md +144 -0
- package/dist/agentic/shared/ai/skills/code-review/references/review-checklist.md +77 -0
- package/dist/agentic/shared/ai/skills/data-model-design/SKILL.md +512 -0
- package/dist/agentic/shared/ai/skills/data-model-design/references/mikro-orm-cheatsheet.md +146 -0
- package/dist/agentic/shared/ai/skills/eject-and-customize/SKILL.md +318 -0
- package/dist/agentic/shared/ai/skills/integration-builder/SKILL.md +722 -0
- package/dist/agentic/shared/ai/skills/integration-builder/references/adapter-contracts.md +762 -0
- package/dist/agentic/shared/ai/skills/module-scaffold/SKILL.md +614 -0
- package/dist/agentic/shared/ai/skills/module-scaffold/references/naming-conventions.md +61 -0
- package/dist/agentic/shared/ai/skills/spec-writing/SKILL.md +76 -0
- package/dist/agentic/shared/ai/skills/spec-writing/references/spec-checklist.md +50 -0
- package/dist/agentic/shared/ai/skills/spec-writing/references/spec-template.md +86 -0
- package/dist/agentic/shared/ai/skills/system-extension/SKILL.md +858 -0
- package/dist/agentic/shared/ai/skills/system-extension/references/extension-contracts.md +271 -0
- package/dist/agentic/shared/ai/skills/troubleshooter/SKILL.md +421 -0
- package/dist/agentic/shared/ai/skills/troubleshooter/references/diagnostic-commands.md +101 -0
- package/dist/agentic/shared/ai/specs/README.md +26 -0
- package/dist/agentic/shared/ai/specs/SPEC-000-template.md +35 -0
- package/dist/lib/agentic-init.js +54 -0
- package/dist/lib/agentic-init.js.map +7 -0
- package/dist/lib/agentic-setup.js +209 -0
- package/dist/lib/agentic-setup.js.map +7 -0
- package/dist/lib/generators/module-registry.js +3 -3
- package/dist/lib/generators/module-registry.js.map +2 -2
- package/dist/lib/testing/integration.js +8 -2
- package/dist/lib/testing/integration.js.map +2 -2
- package/dist/mercato.js +5 -0
- package/dist/mercato.js.map +2 -2
- package/package.json +7 -4
- package/src/lib/agentic-init.ts +69 -0
- package/src/lib/agentic-setup.ts +277 -0
- package/src/lib/generators/module-registry.ts +3 -3
- package/src/lib/testing/integration.ts +8 -2
- package/src/mercato.ts +7 -0
|
@@ -0,0 +1,762 @@
|
|
|
1
|
+
# Adapter Contracts Reference
|
|
2
|
+
|
|
3
|
+
Full TypeScript type definitions for each integration hub adapter contract. Load this file during Pre-Flight to understand the interface your integration must implement.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. IntegrationDefinition & Registry (ALL categories)
|
|
8
|
+
|
|
9
|
+
**Source**: `packages/shared/src/modules/integrations/types.ts`
|
|
10
|
+
|
|
11
|
+
Every integration MUST export an `IntegrationDefinition`. Bundle integrations also export an `IntegrationBundle`.
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
export type IntegrationCategory =
|
|
15
|
+
| 'payment'
|
|
16
|
+
| 'shipping'
|
|
17
|
+
| 'data_sync'
|
|
18
|
+
| 'communication'
|
|
19
|
+
| 'webhook'
|
|
20
|
+
| 'storage'
|
|
21
|
+
| 'other'
|
|
22
|
+
|
|
23
|
+
export type IntegrationHubId =
|
|
24
|
+
| 'payment_gateways'
|
|
25
|
+
| 'shipping_carriers'
|
|
26
|
+
| 'data_sync'
|
|
27
|
+
| 'communication_channels'
|
|
28
|
+
| 'webhook_endpoints'
|
|
29
|
+
| 'storage_hubs'
|
|
30
|
+
| string
|
|
31
|
+
|
|
32
|
+
export type CredentialFieldType =
|
|
33
|
+
| 'text'
|
|
34
|
+
| 'secret'
|
|
35
|
+
| 'select'
|
|
36
|
+
| 'boolean'
|
|
37
|
+
| 'url'
|
|
38
|
+
| 'oauth'
|
|
39
|
+
| 'ssh_keypair'
|
|
40
|
+
|
|
41
|
+
export interface CredentialFieldOption {
|
|
42
|
+
value: string
|
|
43
|
+
label: string
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export interface CredentialFieldVisibleWhen {
|
|
47
|
+
field: string
|
|
48
|
+
equals: string | number | boolean
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface IntegrationCredentialWebhookHelp {
|
|
52
|
+
kind: 'webhook_setup'
|
|
53
|
+
title: string
|
|
54
|
+
summary: string
|
|
55
|
+
endpointPath: string
|
|
56
|
+
dashboardPathLabel: string
|
|
57
|
+
steps: string[]
|
|
58
|
+
events?: string[]
|
|
59
|
+
localDevelopment?: {
|
|
60
|
+
tunnelCommand: string
|
|
61
|
+
publicUrlExample: string
|
|
62
|
+
note?: string
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface IntegrationCredentialFieldBase {
|
|
67
|
+
key: string
|
|
68
|
+
label: string
|
|
69
|
+
required?: boolean
|
|
70
|
+
placeholder?: string
|
|
71
|
+
helpText?: string
|
|
72
|
+
helpDetails?: IntegrationCredentialWebhookHelp
|
|
73
|
+
visibleWhen?: CredentialFieldVisibleWhen
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export interface IntegrationCredentialFieldText extends IntegrationCredentialFieldBase {
|
|
77
|
+
type: Extract<CredentialFieldType, 'text' | 'secret' | 'url'>
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export interface IntegrationCredentialFieldBoolean extends IntegrationCredentialFieldBase {
|
|
81
|
+
type: Extract<CredentialFieldType, 'boolean'>
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
export interface IntegrationCredentialFieldSelect extends IntegrationCredentialFieldBase {
|
|
85
|
+
type: Extract<CredentialFieldType, 'select'>
|
|
86
|
+
options: CredentialFieldOption[]
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export interface IntegrationCredentialFieldOauth extends IntegrationCredentialFieldBase {
|
|
90
|
+
type: Extract<CredentialFieldType, 'oauth'>
|
|
91
|
+
authUrl?: string
|
|
92
|
+
tokenUrl?: string
|
|
93
|
+
scopes?: string[]
|
|
94
|
+
clientIdField?: string
|
|
95
|
+
clientSecretField?: string
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export interface IntegrationCredentialFieldSshKeypair extends IntegrationCredentialFieldBase {
|
|
99
|
+
type: Extract<CredentialFieldType, 'ssh_keypair'>
|
|
100
|
+
algorithm?: 'ed25519' | 'rsa'
|
|
101
|
+
rsaBits?: 2048 | 3072 | 4096
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export type IntegrationCredentialField =
|
|
105
|
+
| IntegrationCredentialFieldText
|
|
106
|
+
| IntegrationCredentialFieldBoolean
|
|
107
|
+
| IntegrationCredentialFieldSelect
|
|
108
|
+
| IntegrationCredentialFieldOauth
|
|
109
|
+
| IntegrationCredentialFieldSshKeypair
|
|
110
|
+
|
|
111
|
+
export interface IntegrationCredentialsSchema {
|
|
112
|
+
fields: IntegrationCredentialField[]
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export interface IntegrationHealthCheckConfig {
|
|
116
|
+
service: string
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export interface ApiVersionDefinition {
|
|
120
|
+
id: string
|
|
121
|
+
label: string
|
|
122
|
+
status: 'stable' | 'deprecated' | 'experimental'
|
|
123
|
+
default?: boolean
|
|
124
|
+
changelog?: string
|
|
125
|
+
deprecatedAt?: string
|
|
126
|
+
sunsetAt?: string
|
|
127
|
+
migrationGuide?: string
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export interface IntegrationBundle {
|
|
131
|
+
id: string
|
|
132
|
+
title: string
|
|
133
|
+
description: string
|
|
134
|
+
icon?: string
|
|
135
|
+
package?: string
|
|
136
|
+
version?: string
|
|
137
|
+
author?: string
|
|
138
|
+
credentials: IntegrationCredentialsSchema
|
|
139
|
+
healthCheck?: IntegrationHealthCheckConfig
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export interface IntegrationDefinition {
|
|
143
|
+
id: string
|
|
144
|
+
title: string
|
|
145
|
+
icon?: string
|
|
146
|
+
buildExternalUrl?: (externalId: string) => string
|
|
147
|
+
bundleId?: string
|
|
148
|
+
apiVersions?: ApiVersionDefinition[]
|
|
149
|
+
description?: string
|
|
150
|
+
category?: IntegrationCategory | string
|
|
151
|
+
hub?: IntegrationHubId
|
|
152
|
+
providerKey?: string
|
|
153
|
+
docsUrl?: string
|
|
154
|
+
package?: string
|
|
155
|
+
version?: string
|
|
156
|
+
author?: string
|
|
157
|
+
company?: string
|
|
158
|
+
license?: string
|
|
159
|
+
tags?: string[]
|
|
160
|
+
credentials?: IntegrationCredentialsSchema
|
|
161
|
+
healthCheck?: IntegrationHealthCheckConfig
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Registry functions
|
|
165
|
+
export function registerIntegration(definition: IntegrationDefinition): void
|
|
166
|
+
export function registerIntegrations(definitions: IntegrationDefinition[]): void
|
|
167
|
+
export function registerBundle(bundle: IntegrationBundle): void
|
|
168
|
+
export function registerBundles(bundles: IntegrationBundle[]): void
|
|
169
|
+
export function clearRegisteredIntegrations(): void
|
|
170
|
+
export function getIntegration(integrationId: string): IntegrationDefinition | undefined
|
|
171
|
+
export function getAllIntegrations(): IntegrationDefinition[]
|
|
172
|
+
export function getBundle(bundleId: string): IntegrationBundle | undefined
|
|
173
|
+
export function getAllBundles(): IntegrationBundle[]
|
|
174
|
+
export function getBundleIntegrations(bundleId: string): IntegrationDefinition[]
|
|
175
|
+
export function resolveIntegrationCredentialsSchema(integrationId: string): IntegrationCredentialsSchema | undefined
|
|
176
|
+
export function getIntegrationTitle(integrationId: string): string
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
## 2. GatewayAdapter (Payment Gateways Hub)
|
|
182
|
+
|
|
183
|
+
**Source**: `packages/shared/src/modules/payment_gateways/types.ts`
|
|
184
|
+
**Hub**: `payment_gateways` | **Category**: `payment` | **Package prefix**: `gateway-`
|
|
185
|
+
|
|
186
|
+
```typescript
|
|
187
|
+
export type UnifiedPaymentStatus =
|
|
188
|
+
| 'pending'
|
|
189
|
+
| 'authorized'
|
|
190
|
+
| 'captured'
|
|
191
|
+
| 'partially_captured'
|
|
192
|
+
| 'refunded'
|
|
193
|
+
| 'partially_refunded'
|
|
194
|
+
| 'cancelled'
|
|
195
|
+
| 'failed'
|
|
196
|
+
| 'expired'
|
|
197
|
+
| 'unknown'
|
|
198
|
+
|
|
199
|
+
export interface GatewayAdapter {
|
|
200
|
+
readonly providerKey: string
|
|
201
|
+
createSession(input: CreateSessionInput): Promise<CreateSessionResult>
|
|
202
|
+
capture(input: CaptureInput): Promise<CaptureResult>
|
|
203
|
+
refund(input: RefundInput): Promise<RefundResult>
|
|
204
|
+
cancel(input: CancelInput): Promise<CancelResult>
|
|
205
|
+
getStatus(input: GetStatusInput): Promise<GatewayPaymentStatus>
|
|
206
|
+
verifyWebhook(input: VerifyWebhookInput): Promise<WebhookEvent>
|
|
207
|
+
mapStatus(providerStatus: string, eventType?: string): UnifiedPaymentStatus
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
export interface CreateSessionInput {
|
|
211
|
+
orderId?: string
|
|
212
|
+
paymentId: string
|
|
213
|
+
tenantId: string
|
|
214
|
+
organizationId: string
|
|
215
|
+
amount: number
|
|
216
|
+
currencyCode: string
|
|
217
|
+
captureMethod?: 'automatic' | 'manual'
|
|
218
|
+
paymentTypes?: string[]
|
|
219
|
+
description?: string
|
|
220
|
+
successUrl?: string
|
|
221
|
+
cancelUrl?: string
|
|
222
|
+
metadata?: Record<string, unknown>
|
|
223
|
+
credentials: Record<string, unknown>
|
|
224
|
+
lineItems?: SessionLineItem[]
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export interface SessionLineItem {
|
|
228
|
+
name: string
|
|
229
|
+
quantity: number
|
|
230
|
+
unitAmount: number
|
|
231
|
+
currencyCode: string
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
export interface CreateSessionResult {
|
|
235
|
+
sessionId: string
|
|
236
|
+
clientSecret?: string
|
|
237
|
+
redirectUrl?: string
|
|
238
|
+
status: UnifiedPaymentStatus
|
|
239
|
+
providerData?: Record<string, unknown>
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
export interface CaptureInput {
|
|
243
|
+
sessionId: string
|
|
244
|
+
amount?: number
|
|
245
|
+
credentials: Record<string, unknown>
|
|
246
|
+
metadata?: Record<string, unknown>
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
export interface CaptureResult {
|
|
250
|
+
status: UnifiedPaymentStatus
|
|
251
|
+
capturedAmount: number
|
|
252
|
+
providerData?: Record<string, unknown>
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export interface RefundInput {
|
|
256
|
+
sessionId: string
|
|
257
|
+
amount?: number
|
|
258
|
+
reason?: string
|
|
259
|
+
credentials: Record<string, unknown>
|
|
260
|
+
metadata?: Record<string, unknown>
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export interface RefundResult {
|
|
264
|
+
refundId: string
|
|
265
|
+
status: UnifiedPaymentStatus
|
|
266
|
+
refundedAmount: number
|
|
267
|
+
providerData?: Record<string, unknown>
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
export interface CancelInput {
|
|
271
|
+
sessionId: string
|
|
272
|
+
reason?: string
|
|
273
|
+
credentials: Record<string, unknown>
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
export interface CancelResult {
|
|
277
|
+
status: UnifiedPaymentStatus
|
|
278
|
+
providerData?: Record<string, unknown>
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
export interface GetStatusInput {
|
|
282
|
+
sessionId: string
|
|
283
|
+
credentials: Record<string, unknown>
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export interface GatewayPaymentStatus {
|
|
287
|
+
status: UnifiedPaymentStatus
|
|
288
|
+
amount: number
|
|
289
|
+
amountReceived: number
|
|
290
|
+
currencyCode: string
|
|
291
|
+
providerData?: Record<string, unknown>
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
export interface VerifyWebhookInput {
|
|
295
|
+
rawBody: string | Buffer
|
|
296
|
+
headers: Record<string, string | string[] | undefined>
|
|
297
|
+
credentials: Record<string, unknown>
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
export interface WebhookEvent {
|
|
301
|
+
eventType: string
|
|
302
|
+
eventId: string
|
|
303
|
+
data: Record<string, unknown>
|
|
304
|
+
idempotencyKey: string
|
|
305
|
+
timestamp: Date
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
export interface RegisterAdapterOptions {
|
|
309
|
+
version?: string
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
// Registry functions
|
|
313
|
+
export function registerGatewayAdapter(adapter: GatewayAdapter, options?: RegisterAdapterOptions): () => void
|
|
314
|
+
export function getGatewayAdapter(providerKey: string, version?: string): GatewayAdapter | undefined
|
|
315
|
+
export function listGatewayAdapters(): GatewayAdapter[]
|
|
316
|
+
export function clearGatewayAdapters(): void
|
|
317
|
+
export function registerWebhookHandler(
|
|
318
|
+
providerKey: string,
|
|
319
|
+
handler: (input: VerifyWebhookInput) => Promise<WebhookEvent>,
|
|
320
|
+
options?: { queue?: string },
|
|
321
|
+
): () => void
|
|
322
|
+
export function getWebhookHandler(providerKey: string): WebhookHandlerRegistration | undefined
|
|
323
|
+
export function clearWebhookHandlers(): void
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
---
|
|
327
|
+
|
|
328
|
+
## 3. ShippingAdapter (Shipping Carriers Hub)
|
|
329
|
+
|
|
330
|
+
**Source**: `packages/core/src/modules/shipping_carriers/lib/adapter.ts`
|
|
331
|
+
**Hub**: `shipping_carriers` | **Category**: `shipping` | **Package prefix**: `carrier-`
|
|
332
|
+
|
|
333
|
+
```typescript
|
|
334
|
+
export type UnifiedShipmentStatus =
|
|
335
|
+
| 'label_created'
|
|
336
|
+
| 'picked_up'
|
|
337
|
+
| 'in_transit'
|
|
338
|
+
| 'out_for_delivery'
|
|
339
|
+
| 'delivered'
|
|
340
|
+
| 'failed_delivery'
|
|
341
|
+
| 'returned'
|
|
342
|
+
| 'cancelled'
|
|
343
|
+
| 'unknown'
|
|
344
|
+
|
|
345
|
+
export type Address = {
|
|
346
|
+
countryCode: string
|
|
347
|
+
postalCode: string
|
|
348
|
+
city: string
|
|
349
|
+
line1: string
|
|
350
|
+
line2?: string
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
export type PackageInfo = {
|
|
354
|
+
weightKg: number
|
|
355
|
+
lengthCm: number
|
|
356
|
+
widthCm: number
|
|
357
|
+
heightCm: number
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
export type ShippingRate = {
|
|
361
|
+
serviceCode: string
|
|
362
|
+
serviceName: string
|
|
363
|
+
amount: number
|
|
364
|
+
currencyCode: string
|
|
365
|
+
estimatedDays?: number
|
|
366
|
+
guaranteedDelivery?: boolean
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
export type CreateShipmentInput = {
|
|
370
|
+
orderId: string
|
|
371
|
+
origin: Address
|
|
372
|
+
destination: Address
|
|
373
|
+
packages: PackageInfo[]
|
|
374
|
+
serviceCode: string
|
|
375
|
+
credentials: Record<string, unknown>
|
|
376
|
+
labelFormat?: 'pdf' | 'zpl' | 'png'
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
export type CreateShipmentResult = {
|
|
380
|
+
shipmentId: string
|
|
381
|
+
trackingNumber: string
|
|
382
|
+
labelUrl?: string
|
|
383
|
+
labelData?: string
|
|
384
|
+
estimatedDelivery?: Date
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
export type TrackingResult = {
|
|
388
|
+
trackingNumber: string
|
|
389
|
+
status: UnifiedShipmentStatus
|
|
390
|
+
events: Array<{
|
|
391
|
+
status: UnifiedShipmentStatus
|
|
392
|
+
occurredAt: string
|
|
393
|
+
location?: string
|
|
394
|
+
}>
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
export type ShippingWebhookEvent = {
|
|
398
|
+
eventType: string
|
|
399
|
+
eventId: string
|
|
400
|
+
idempotencyKey: string
|
|
401
|
+
data: Record<string, unknown>
|
|
402
|
+
timestamp: Date
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
export interface ShippingAdapter {
|
|
406
|
+
readonly providerKey: string
|
|
407
|
+
|
|
408
|
+
calculateRates(input: {
|
|
409
|
+
origin: Address
|
|
410
|
+
destination: Address
|
|
411
|
+
packages: PackageInfo[]
|
|
412
|
+
credentials: Record<string, unknown>
|
|
413
|
+
}): Promise<ShippingRate[]>
|
|
414
|
+
|
|
415
|
+
createShipment(input: CreateShipmentInput): Promise<CreateShipmentResult>
|
|
416
|
+
|
|
417
|
+
getTracking(input: {
|
|
418
|
+
shipmentId?: string
|
|
419
|
+
trackingNumber?: string
|
|
420
|
+
credentials: Record<string, unknown>
|
|
421
|
+
}): Promise<TrackingResult>
|
|
422
|
+
|
|
423
|
+
cancelShipment(input: {
|
|
424
|
+
shipmentId: string
|
|
425
|
+
reason?: string
|
|
426
|
+
credentials: Record<string, unknown>
|
|
427
|
+
}): Promise<{ status: UnifiedShipmentStatus }>
|
|
428
|
+
|
|
429
|
+
verifyWebhook(input: {
|
|
430
|
+
rawBody: string | Buffer
|
|
431
|
+
headers: Record<string, string | string[] | undefined>
|
|
432
|
+
credentials: Record<string, unknown>
|
|
433
|
+
}): Promise<ShippingWebhookEvent>
|
|
434
|
+
|
|
435
|
+
mapStatus(carrierStatus: string): UnifiedShipmentStatus
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
// Registry functions
|
|
439
|
+
export function registerShippingAdapter(adapter: ShippingAdapter): () => void
|
|
440
|
+
export function getShippingAdapter(providerKey: string): ShippingAdapter | undefined
|
|
441
|
+
export function listShippingAdapters(): ShippingAdapter[]
|
|
442
|
+
export function clearShippingAdapters(): void
|
|
443
|
+
```
|
|
444
|
+
|
|
445
|
+
---
|
|
446
|
+
|
|
447
|
+
## 4. DataSyncAdapter (Data Sync Hub)
|
|
448
|
+
|
|
449
|
+
**Source**: `packages/core/src/modules/data_sync/lib/adapter.ts`
|
|
450
|
+
**Hub**: `data_sync` | **Category**: `data_sync` | **Package prefix**: `sync-`
|
|
451
|
+
|
|
452
|
+
```typescript
|
|
453
|
+
export interface TenantScope {
|
|
454
|
+
organizationId: string
|
|
455
|
+
tenantId: string
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
export interface FieldMapping {
|
|
459
|
+
externalField: string
|
|
460
|
+
localField: string
|
|
461
|
+
transform?: string
|
|
462
|
+
required?: boolean
|
|
463
|
+
defaultValue?: unknown
|
|
464
|
+
}
|
|
465
|
+
|
|
466
|
+
export interface DataMapping {
|
|
467
|
+
entityType: string
|
|
468
|
+
fields: FieldMapping[]
|
|
469
|
+
matchStrategy: 'externalId' | 'sku' | 'email' | 'custom'
|
|
470
|
+
matchField?: string
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
export interface StreamImportInput {
|
|
474
|
+
entityType: string
|
|
475
|
+
cursor?: string
|
|
476
|
+
batchSize: number
|
|
477
|
+
credentials: Record<string, unknown>
|
|
478
|
+
mapping: DataMapping
|
|
479
|
+
scope: TenantScope
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
export interface ImportItem {
|
|
483
|
+
externalId: string
|
|
484
|
+
data: Record<string, unknown>
|
|
485
|
+
action: 'create' | 'update' | 'skip'
|
|
486
|
+
hash?: string
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
export interface ImportBatch {
|
|
490
|
+
items: ImportItem[]
|
|
491
|
+
cursor: string
|
|
492
|
+
hasMore: boolean
|
|
493
|
+
totalEstimate?: number
|
|
494
|
+
batchIndex: number
|
|
495
|
+
}
|
|
496
|
+
|
|
497
|
+
export interface StreamExportInput {
|
|
498
|
+
entityType: string
|
|
499
|
+
cursor?: string
|
|
500
|
+
batchSize: number
|
|
501
|
+
credentials: Record<string, unknown>
|
|
502
|
+
mapping: DataMapping
|
|
503
|
+
scope: TenantScope
|
|
504
|
+
filter?: Record<string, unknown>
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
export interface ExportItemResult {
|
|
508
|
+
localId: string
|
|
509
|
+
externalId?: string
|
|
510
|
+
status: 'success' | 'error' | 'skipped'
|
|
511
|
+
error?: string
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
export interface ExportBatch {
|
|
515
|
+
results: ExportItemResult[]
|
|
516
|
+
cursor: string
|
|
517
|
+
hasMore: boolean
|
|
518
|
+
batchIndex: number
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
export interface ValidationResult {
|
|
522
|
+
ok: boolean
|
|
523
|
+
message?: string
|
|
524
|
+
details?: Record<string, unknown>
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
export interface DataSyncAdapter {
|
|
528
|
+
readonly providerKey: string
|
|
529
|
+
readonly direction: 'import' | 'export' | 'bidirectional'
|
|
530
|
+
readonly supportedEntities: string[]
|
|
531
|
+
|
|
532
|
+
streamImport?(input: StreamImportInput): AsyncIterable<ImportBatch>
|
|
533
|
+
streamExport?(input: StreamExportInput): AsyncIterable<ExportBatch>
|
|
534
|
+
getInitialCursor?(input: { entityType: string; scope: TenantScope }): Promise<string | null>
|
|
535
|
+
getMapping(input: { entityType: string; scope: TenantScope }): Promise<DataMapping>
|
|
536
|
+
validateConnection?(input: {
|
|
537
|
+
entityType: string
|
|
538
|
+
credentials: Record<string, unknown>
|
|
539
|
+
mapping: DataMapping
|
|
540
|
+
scope: TenantScope
|
|
541
|
+
}): Promise<ValidationResult>
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
// Registry functions
|
|
545
|
+
export function registerDataSyncAdapter(adapter: DataSyncAdapter): void
|
|
546
|
+
export function getDataSyncAdapter(providerKey: string): DataSyncAdapter | undefined
|
|
547
|
+
export function getAllDataSyncAdapters(): DataSyncAdapter[]
|
|
548
|
+
```
|
|
549
|
+
|
|
550
|
+
---
|
|
551
|
+
|
|
552
|
+
## 5. ChannelAdapter (Communication Channels Hub)
|
|
553
|
+
|
|
554
|
+
**Source**: SPEC-045d (spec-only, not yet implemented in code)
|
|
555
|
+
**Hub**: `communication_channels` | **Category**: `communication` | **Package prefix**: `channel-`
|
|
556
|
+
|
|
557
|
+
```typescript
|
|
558
|
+
interface ChannelAdapter {
|
|
559
|
+
readonly providerKey: string
|
|
560
|
+
readonly channelType: 'whatsapp' | 'sms' | 'email' | string
|
|
561
|
+
|
|
562
|
+
sendMessage(input: SendMessageInput): Promise<SendMessageResult>
|
|
563
|
+
verifyWebhook(input: VerifyWebhookInput): Promise<InboundMessage>
|
|
564
|
+
getStatus(input: GetMessageStatusInput): Promise<MessageStatus>
|
|
565
|
+
listSenders?(input: ListSendersInput): Promise<SenderInfo[]>
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
interface SendMessageInput {
|
|
569
|
+
channelId: string
|
|
570
|
+
recipientId: string
|
|
571
|
+
content: MessageContent
|
|
572
|
+
conversationId?: string
|
|
573
|
+
credentials: Record<string, unknown>
|
|
574
|
+
scope: TenantScope
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
interface MessageContent {
|
|
578
|
+
type: 'text' | 'template' | 'media' | 'interactive'
|
|
579
|
+
text?: string
|
|
580
|
+
templateId?: string
|
|
581
|
+
templateParams?: Record<string, string>
|
|
582
|
+
mediaUrl?: string
|
|
583
|
+
buttons?: MessageButton[]
|
|
584
|
+
}
|
|
585
|
+
|
|
586
|
+
type MessageStatus = 'sent' | 'delivered' | 'read' | 'failed' | 'unknown'
|
|
587
|
+
```
|
|
588
|
+
|
|
589
|
+
---
|
|
590
|
+
|
|
591
|
+
## 6. NotificationTransportAdapter (Notification Providers Hub)
|
|
592
|
+
|
|
593
|
+
**Source**: SPEC-045d (spec-only, not yet implemented in code)
|
|
594
|
+
**Hub**: `notification_providers` | **Category**: `communication` | **Package prefix**: `channel-`
|
|
595
|
+
|
|
596
|
+
```typescript
|
|
597
|
+
interface NotificationTransportAdapter {
|
|
598
|
+
readonly providerKey: string
|
|
599
|
+
readonly transportType: 'email' | 'sms' | 'push' | string
|
|
600
|
+
|
|
601
|
+
send(input: SendNotificationInput): Promise<SendNotificationResult>
|
|
602
|
+
getDeliveryStatus?(input: GetDeliveryStatusInput): Promise<DeliveryStatus>
|
|
603
|
+
verifyWebhook?(input: VerifyWebhookInput): Promise<DeliveryReceipt>
|
|
604
|
+
}
|
|
605
|
+
|
|
606
|
+
interface SendNotificationInput {
|
|
607
|
+
recipient: NotificationRecipient
|
|
608
|
+
subject?: string
|
|
609
|
+
body: string
|
|
610
|
+
htmlBody?: string
|
|
611
|
+
templateId?: string
|
|
612
|
+
templateData?: Record<string, unknown>
|
|
613
|
+
credentials: Record<string, unknown>
|
|
614
|
+
metadata?: Record<string, string>
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
interface NotificationRecipient {
|
|
618
|
+
email?: string
|
|
619
|
+
phone?: string
|
|
620
|
+
deviceToken?: string
|
|
621
|
+
userId?: string
|
|
622
|
+
}
|
|
623
|
+
|
|
624
|
+
interface SendNotificationResult {
|
|
625
|
+
externalId: string
|
|
626
|
+
status: 'sent' | 'queued' | 'failed'
|
|
627
|
+
error?: string
|
|
628
|
+
}
|
|
629
|
+
```
|
|
630
|
+
|
|
631
|
+
---
|
|
632
|
+
|
|
633
|
+
## 7. WebhookEndpointAdapter (Webhook Endpoints Hub)
|
|
634
|
+
|
|
635
|
+
**Source**: SPEC-045e (spec-only, delegates to SPEC-057)
|
|
636
|
+
**Hub**: `webhook_endpoints` | **Category**: `webhook` | **Package prefix**: `webhook-`
|
|
637
|
+
|
|
638
|
+
```typescript
|
|
639
|
+
interface WebhookEndpointAdapter {
|
|
640
|
+
readonly providerKey: string
|
|
641
|
+
readonly subscribedEvents: string[]
|
|
642
|
+
|
|
643
|
+
formatPayload(event: EventPayload): Promise<WebhookPayload>
|
|
644
|
+
verifyWebhook(input: VerifyWebhookInput): Promise<InboundWebhookEvent>
|
|
645
|
+
processInbound(event: InboundWebhookEvent): Promise<void>
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
interface WebhookPayload {
|
|
649
|
+
url: string
|
|
650
|
+
headers: Record<string, string>
|
|
651
|
+
body: Record<string, unknown>
|
|
652
|
+
method: 'POST' | 'PUT' | 'PATCH'
|
|
653
|
+
}
|
|
654
|
+
```
|
|
655
|
+
|
|
656
|
+
---
|
|
657
|
+
|
|
658
|
+
## 8. StorageAdapter (Storage Providers Hub)
|
|
659
|
+
|
|
660
|
+
**Source**: SPEC-045i (spec-only, not yet implemented in code)
|
|
661
|
+
**Hub**: `storage_hubs` | **Category**: `storage` | **Package prefix**: `storage-`
|
|
662
|
+
|
|
663
|
+
```typescript
|
|
664
|
+
interface StorageAdapter {
|
|
665
|
+
readonly providerKey: string
|
|
666
|
+
|
|
667
|
+
upload(input: UploadInput): Promise<UploadResult>
|
|
668
|
+
download(input: DownloadInput): Promise<ReadableStream>
|
|
669
|
+
delete(input: DeleteInput): Promise<void>
|
|
670
|
+
getSignedUrl?(input: SignedUrlInput): Promise<string>
|
|
671
|
+
list?(input: ListInput): Promise<StorageFileInfo[]>
|
|
672
|
+
exists?(input: ExistsInput): Promise<boolean>
|
|
673
|
+
}
|
|
674
|
+
```
|
|
675
|
+
|
|
676
|
+
### StorageDriver (Attachments Module Level)
|
|
677
|
+
|
|
678
|
+
Used internally by the attachments module to interface with storage backends:
|
|
679
|
+
|
|
680
|
+
```typescript
|
|
681
|
+
export type StoreFilePayload = {
|
|
682
|
+
partitionCode: string
|
|
683
|
+
orgId: string | null | undefined
|
|
684
|
+
tenantId: string | null | undefined
|
|
685
|
+
fileName: string
|
|
686
|
+
buffer: Buffer
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
export type StoredFile = {
|
|
690
|
+
storagePath: string
|
|
691
|
+
driverMeta?: Record<string, unknown> | null
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
export type ReadFileResult = {
|
|
695
|
+
buffer: Buffer
|
|
696
|
+
contentType?: string
|
|
697
|
+
}
|
|
698
|
+
|
|
699
|
+
export interface StorageDriver {
|
|
700
|
+
readonly key: string
|
|
701
|
+
store(payload: StoreFilePayload): Promise<StoredFile>
|
|
702
|
+
read(partitionCode: string, storagePath: string): Promise<ReadFileResult>
|
|
703
|
+
delete(partitionCode: string, storagePath: string): Promise<void>
|
|
704
|
+
toLocalPath(partitionCode: string, storagePath: string): Promise<{
|
|
705
|
+
filePath: string
|
|
706
|
+
cleanup: () => Promise<void>
|
|
707
|
+
}>
|
|
708
|
+
}
|
|
709
|
+
```
|
|
710
|
+
|
|
711
|
+
---
|
|
712
|
+
|
|
713
|
+
## Summary Table
|
|
714
|
+
|
|
715
|
+
| Adapter | Status | Source Location | Hub ID | Category |
|
|
716
|
+
|---------|--------|----------------|--------|----------|
|
|
717
|
+
| `GatewayAdapter` | Implemented | `packages/shared/src/modules/payment_gateways/types.ts` | `payment_gateways` | `payment` |
|
|
718
|
+
| `ShippingAdapter` | Implemented | `packages/core/src/modules/shipping_carriers/lib/adapter.ts` | `shipping_carriers` | `shipping` |
|
|
719
|
+
| `DataSyncAdapter` | Implemented | `packages/core/src/modules/data_sync/lib/adapter.ts` | `data_sync` | `data_sync` |
|
|
720
|
+
| `ChannelAdapter` | Spec-only | SPEC-045d | `communication_channels` | `communication` |
|
|
721
|
+
| `NotificationTransportAdapter` | Spec-only | SPEC-045d | `notification_providers` | `communication` |
|
|
722
|
+
| `WebhookEndpointAdapter` | Spec-only | SPEC-045e | `webhook_endpoints` | `webhook` |
|
|
723
|
+
| `StorageAdapter` | Spec-only | SPEC-045i | `storage_hubs` | `storage` |
|
|
724
|
+
|
|
725
|
+
---
|
|
726
|
+
|
|
727
|
+
## Common Patterns
|
|
728
|
+
|
|
729
|
+
### Webhook Verification Input (shared across all adapters)
|
|
730
|
+
|
|
731
|
+
```typescript
|
|
732
|
+
export interface VerifyWebhookInput {
|
|
733
|
+
rawBody: string | Buffer
|
|
734
|
+
headers: Record<string, string | string[] | undefined>
|
|
735
|
+
credentials: Record<string, unknown>
|
|
736
|
+
}
|
|
737
|
+
```
|
|
738
|
+
|
|
739
|
+
### Tenant Scope (shared across adapters that need tenant context)
|
|
740
|
+
|
|
741
|
+
```typescript
|
|
742
|
+
export interface TenantScope {
|
|
743
|
+
organizationId: string
|
|
744
|
+
tenantId: string
|
|
745
|
+
}
|
|
746
|
+
```
|
|
747
|
+
|
|
748
|
+
### DI Registration Pattern
|
|
749
|
+
|
|
750
|
+
All adapters follow the same DI registration pattern in `di.ts`:
|
|
751
|
+
|
|
752
|
+
```typescript
|
|
753
|
+
import type { AppContainer } from '@open-mercato/shared/lib/di/container'
|
|
754
|
+
import { register<Category>Adapter } from '<hub-types-path>'
|
|
755
|
+
|
|
756
|
+
export function register(container: AppContainer): void {
|
|
757
|
+
const adapter = new MyAdapter()
|
|
758
|
+
register<Category>Adapter(adapter)
|
|
759
|
+
// For gateways with versioning:
|
|
760
|
+
// registerGatewayAdapter(adapter, { version: '2025-01-01' })
|
|
761
|
+
}
|
|
762
|
+
```
|