@open-mercato/cli 0.6.6-develop.6377.1.d26fed7324 → 0.6.6-develop.6382.1.4b9b9091ab
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/.turbo/turbo-build.log +2 -2
- package/dist/agentic/guides/core.md +3 -38
- package/dist/agentic/guides/module-system.md +130 -0
- package/dist/agentic/shared/AGENTS.md.template +4 -12
- package/dist/lib/generators/index.js +2 -0
- package/dist/lib/generators/index.js.map +2 -2
- package/dist/lib/generators/module-facts-generate.js +52 -0
- package/dist/lib/generators/module-facts-generate.js.map +7 -0
- package/dist/lib/generators/module-facts.js +734 -0
- package/dist/lib/generators/module-facts.js.map +7 -0
- package/dist/mercato.js +3 -1
- package/dist/mercato.js.map +2 -2
- package/package.json +5 -5
- package/src/__tests__/mercato.test.ts +5 -0
- package/src/lib/generators/__tests__/module-facts.auth-source.test.ts +83 -0
- package/src/lib/generators/__tests__/module-facts.bc-guard.test.ts +56 -0
- package/src/lib/generators/__tests__/module-facts.customers.fixture.test.ts +69 -0
- package/src/lib/generators/__tests__/module-facts.malformed.test.ts +76 -0
- package/src/lib/generators/index.ts +1 -0
- package/src/lib/generators/module-facts-generate.ts +68 -0
- package/src/lib/generators/module-facts.ts +958 -0
- package/src/mercato.ts +2 -0
- package/dist/agentic/guides/core.auth.md +0 -101
- package/dist/agentic/guides/core.catalog.md +0 -79
- package/dist/agentic/guides/core.currencies.md +0 -43
- package/dist/agentic/guides/core.customer_accounts.md +0 -129
- package/dist/agentic/guides/core.customers.md +0 -138
- package/dist/agentic/guides/core.data_sync.md +0 -107
- package/dist/agentic/guides/core.integrations.md +0 -113
- package/dist/agentic/guides/core.sales.md +0 -104
- package/dist/agentic/guides/core.workflows.md +0 -152
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
# Integrations Module — Standalone App Guide
|
|
2
|
-
|
|
3
|
-
The integrations module provides the foundation for all external connectors (payment gateways, shipping carriers, data sync providers, etc.). It offers three shared mechanisms: **Integration Registry**, **Credentials API**, and **Operation Logs**.
|
|
4
|
-
|
|
5
|
-
## Creating an Integration Provider
|
|
6
|
-
|
|
7
|
-
Create a new module in your app for each provider:
|
|
8
|
-
|
|
9
|
-
1. Create `src/modules/<provider_id>/` with standard module files
|
|
10
|
-
2. Add `integration.ts` at the module root exporting an `IntegrationDefinition`:
|
|
11
|
-
|
|
12
|
-
```typescript
|
|
13
|
-
import type { IntegrationDefinition } from '@open-mercato/shared/modules/integrations/types'
|
|
14
|
-
|
|
15
|
-
export const integration: IntegrationDefinition = {
|
|
16
|
-
id: 'my_provider',
|
|
17
|
-
name: 'My Provider',
|
|
18
|
-
description: 'Integration with My Provider',
|
|
19
|
-
category: 'payment',
|
|
20
|
-
credentials: {
|
|
21
|
-
fields: [
|
|
22
|
-
{ key: 'apiKey', label: 'API Key', type: 'password', required: true },
|
|
23
|
-
{ key: 'environment', label: 'Environment', type: 'select', options: ['sandbox', 'production'] },
|
|
24
|
-
],
|
|
25
|
-
},
|
|
26
|
-
healthCheck: { service: 'myProviderHealthCheck' }, // optional
|
|
27
|
-
apiVersions: ['v1', 'v2'], // optional
|
|
28
|
-
}
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
3. Register the health check service in `di.ts` (if declared)
|
|
32
|
-
4. Run `yarn generate` to auto-discover the integration
|
|
33
|
-
|
|
34
|
-
## Key Services (DI)
|
|
35
|
-
|
|
36
|
-
| Service | Purpose |
|
|
37
|
-
|---------|---------|
|
|
38
|
-
| `integrationCredentialsService` | Encrypted credential CRUD with bundle fallthrough |
|
|
39
|
-
| `integrationStateService` | Enable/disable, API version, reauth, health state |
|
|
40
|
-
| `integrationLogService` | Structured logging with scoped loggers |
|
|
41
|
-
| `integrationHealthService` | Resolves and runs provider health checks |
|
|
42
|
-
|
|
43
|
-
## Credential Resolution
|
|
44
|
-
|
|
45
|
-
1. Direct credentials for the integration ID
|
|
46
|
-
2. If `bundleId` is set, fallback to bundle's credentials
|
|
47
|
-
3. Returns `null` if neither exists
|
|
48
|
-
|
|
49
|
-
## Bundle Integrations
|
|
50
|
-
|
|
51
|
-
For platform connectors with multiple integrations (e.g., an ERP with products + orders sync):
|
|
52
|
-
|
|
53
|
-
```typescript
|
|
54
|
-
export const bundle: IntegrationBundle = {
|
|
55
|
-
id: 'my_erp',
|
|
56
|
-
name: 'My ERP',
|
|
57
|
-
integrations: ['my_erp_products', 'my_erp_orders'],
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
- Set `bundleId` on each child integration
|
|
62
|
-
- Bundle credentials are shared via fallthrough
|
|
63
|
-
|
|
64
|
-
## Events
|
|
65
|
-
|
|
66
|
-
| Event | When |
|
|
67
|
-
|-------|------|
|
|
68
|
-
| `integrations.credentials.updated` | Credentials saved |
|
|
69
|
-
| `integrations.state.updated` | Integration enabled/disabled |
|
|
70
|
-
| `integrations.version.changed` | API version changed |
|
|
71
|
-
| `integrations.log.created` | Log entry written |
|
|
72
|
-
|
|
73
|
-
## Extending the Integration Detail Page
|
|
74
|
-
|
|
75
|
-
Provider modules can add tabs, cards, or sections to the integration detail page:
|
|
76
|
-
|
|
77
|
-
```typescript
|
|
78
|
-
// integration.ts
|
|
79
|
-
import { buildIntegrationDetailWidgetSpotId } from '@open-mercato/shared/modules/integrations/types'
|
|
80
|
-
|
|
81
|
-
export const integration = {
|
|
82
|
-
id: 'my_provider',
|
|
83
|
-
detailPage: {
|
|
84
|
-
widgetSpotId: buildIntegrationDetailWidgetSpotId('my_provider'),
|
|
85
|
-
},
|
|
86
|
-
} satisfies IntegrationDefinition
|
|
87
|
-
```
|
|
88
|
-
|
|
89
|
-
Register widgets for that spot in `widgets/injection-table.ts`. Use `placement.kind: 'tab'` for additional tabs, `'group'` for card panels, `'stack'` for inline sections.
|
|
90
|
-
|
|
91
|
-
## UMES Extension Points
|
|
92
|
-
|
|
93
|
-
Integration providers can leverage the full extension system:
|
|
94
|
-
|
|
95
|
-
| Extension | Use Case |
|
|
96
|
-
|-----------|----------|
|
|
97
|
-
| **Widget Injection** | Inject status badges, config panels into other modules |
|
|
98
|
-
| **Event Subscribers** | React to integration events for side-effects |
|
|
99
|
-
| **Entity Extensions** | Link provider data to core entities (e.g., external IDs) |
|
|
100
|
-
| **Response Enrichers** | Attach provider data to API responses |
|
|
101
|
-
| **API Interceptors** | Intercept routes with before/after hooks |
|
|
102
|
-
| **Notifications** | In-app alerts on integration events |
|
|
103
|
-
| **DOM Event Bridge** | Real-time updates via SSE (`clientBroadcast: true`) |
|
|
104
|
-
|
|
105
|
-
## Provider-Owned Env Preconfiguration
|
|
106
|
-
|
|
107
|
-
If your provider needs credentials or settings after a fresh install:
|
|
108
|
-
|
|
109
|
-
- Read env vars in a provider-local helper (e.g., `lib/preset.ts`)
|
|
110
|
-
- Apply from your module's `setup.ts` for automatic tenant bootstrap
|
|
111
|
-
- Expose a CLI command for rerunning the bootstrap
|
|
112
|
-
- Use provider-prefixed env names (e.g., `OM_INTEGRATION_MYPROVIDER_*`)
|
|
113
|
-
- Persist through normal integration services — never special-case in core
|
|
@@ -1,104 +0,0 @@
|
|
|
1
|
-
# Sales Module — Standalone App Guide
|
|
2
|
-
|
|
3
|
-
Use the sales module for orders, quotes, invoices, shipments, and payments. This module has the most complex business logic in the system.
|
|
4
|
-
|
|
5
|
-
## Document Flow
|
|
6
|
-
|
|
7
|
-
```
|
|
8
|
-
Quote → Order → Invoice
|
|
9
|
-
↓
|
|
10
|
-
Shipments + Payments
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
- Quotes convert to orders — do not create orders without a source quote (unless configured)
|
|
14
|
-
- Orders track shipments and payments independently
|
|
15
|
-
- Each entity has its own status workflow — do not skip states
|
|
16
|
-
- Returns create line-level adjustments and update `returned_quantity`
|
|
17
|
-
|
|
18
|
-
## Pricing Calculations
|
|
19
|
-
|
|
20
|
-
Always use the sales calculation service — never inline price math:
|
|
21
|
-
|
|
22
|
-
```typescript
|
|
23
|
-
const calcService = container.resolve('salesCalculationService')
|
|
24
|
-
```
|
|
25
|
-
|
|
26
|
-
- Dispatches `sales.line.calculate.*` and `sales.document.calculate.*` events
|
|
27
|
-
- For catalog pricing: use `selectBestPrice` from the catalog module
|
|
28
|
-
- Register custom line/totals calculators or override via DI
|
|
29
|
-
|
|
30
|
-
## Channel Scoping
|
|
31
|
-
|
|
32
|
-
All sales documents are scoped to channels. Channel selection affects:
|
|
33
|
-
- Available pricing tiers
|
|
34
|
-
- Document numbering sequences
|
|
35
|
-
- Visibility in admin UI
|
|
36
|
-
|
|
37
|
-
## Data Model
|
|
38
|
-
|
|
39
|
-
### Core Entities
|
|
40
|
-
| Entity | Purpose | Key Constraint |
|
|
41
|
-
|--------|---------|---------------|
|
|
42
|
-
| **Sales Orders** | Confirmed customer orders | MUST have a channel and at least one line |
|
|
43
|
-
| **Sales Quotes** | Proposed orders | MUST track conversion status |
|
|
44
|
-
| **Order/Quote Lines** | Individual items | MUST reference valid products |
|
|
45
|
-
| **Adjustments** | Discounts/surcharges | MUST use registered `AdjustmentKind` |
|
|
46
|
-
|
|
47
|
-
### Fulfillment
|
|
48
|
-
| Entity | Purpose |
|
|
49
|
-
|--------|---------|
|
|
50
|
-
| **Shipments** | Delivery tracking with status workflow |
|
|
51
|
-
| **Payments** | Payment recording with status workflow |
|
|
52
|
-
| **Returns** | Order returns with line selection and automatic adjustments |
|
|
53
|
-
|
|
54
|
-
### Configuration (do not modify directly)
|
|
55
|
-
Channels, statuses, payment/shipping methods, price kinds, adjustment kinds, and document numbers — configure via admin UI or `setup.ts` hooks.
|
|
56
|
-
|
|
57
|
-
## Subscribing to Sales Events
|
|
58
|
-
|
|
59
|
-
```typescript
|
|
60
|
-
// src/modules/<your_module>/subscribers/order-created.ts
|
|
61
|
-
export const metadata = {
|
|
62
|
-
event: 'sales.order.created',
|
|
63
|
-
persistent: true,
|
|
64
|
-
id: 'your-module-order-created',
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
export default async function handler(payload, ctx) {
|
|
68
|
-
// React to new orders
|
|
69
|
-
}
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
Key events: `sales.order.created` / `updated` / `deleted`, `sales.quote.created` / `updated`, `sales.payment.created`, `sales.shipment.created`
|
|
73
|
-
|
|
74
|
-
## Extending Sales UI
|
|
75
|
-
|
|
76
|
-
Widget injection spots:
|
|
77
|
-
|
|
78
|
-
**Order & Quote detail page:**
|
|
79
|
-
- `sales.document.detail.order:details` — order detail page sections
|
|
80
|
-
- `sales.document.detail.quote:details` — quote detail page sections
|
|
81
|
-
- `sales.document.detail.order:tabs` — order detail page tabs
|
|
82
|
-
- `sales.document.detail.quote:tabs` — quote detail page tabs
|
|
83
|
-
- `detail:sales.order:stage-bar` — order stage bar (empty, ready for extension)
|
|
84
|
-
- `detail:sales.quote:stage-bar` — quote stage bar (empty, ready for extension)
|
|
85
|
-
- `detail:sales.order:closure` — order closure section (empty, ready for extension)
|
|
86
|
-
- `detail:sales.quote:closure` — quote closure section (empty, ready for extension)
|
|
87
|
-
|
|
88
|
-
**Order list:**
|
|
89
|
-
- `data-table:sales.orders:columns` — order list columns
|
|
90
|
-
- `data-table:sales.orders:row-actions` — order row actions
|
|
91
|
-
|
|
92
|
-
**Order form:**
|
|
93
|
-
- `crud-form:sales.sales_order:fields` — order detail form
|
|
94
|
-
|
|
95
|
-
**Payments:**
|
|
96
|
-
- `data-table:sales.payments:columns` — payment list columns
|
|
97
|
-
|
|
98
|
-
**Payment methods:**
|
|
99
|
-
- `crud-form:sales.payment_method:fields` — payment method form fields
|
|
100
|
-
- `crud-form:sales.sales_payment_method:fields` — sales payment method form fields
|
|
101
|
-
|
|
102
|
-
## Frontend Pages
|
|
103
|
-
|
|
104
|
-
- `frontend/quote/` — public-facing quote view for customer acceptance
|
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
# Workflows Module — Standalone App Guide
|
|
2
|
-
|
|
3
|
-
Use the workflows module for business process automation: defining step-based workflows, executing instances, handling user tasks, and triggering workflows from domain events.
|
|
4
|
-
|
|
5
|
-
## Using Workflows in Your App
|
|
6
|
-
|
|
7
|
-
The workflow engine is provided by `@open-mercato/core`. Your standalone app can:
|
|
8
|
-
|
|
9
|
-
1. **Create workflow definitions** via the visual editor at `/backend/workflows`
|
|
10
|
-
2. **Trigger workflows** from domain events emitted by your modules
|
|
11
|
-
3. **Subscribe to workflow events** for side effects in your modules
|
|
12
|
-
4. **Inject UI widgets** into workflow pages or inject workflow widgets into your pages
|
|
13
|
-
5. **Define user tasks** that require human approval or data entry
|
|
14
|
-
|
|
15
|
-
## Starting Workflows Programmatically
|
|
16
|
-
|
|
17
|
-
Resolve the workflow executor via DI — never import lib functions directly:
|
|
18
|
-
|
|
19
|
-
```typescript
|
|
20
|
-
// In your module's DI-aware context (API route, subscriber, worker)
|
|
21
|
-
const executor = container.resolve('workflowExecutor')
|
|
22
|
-
|
|
23
|
-
await executor.startWorkflow({
|
|
24
|
-
workflowId: 'order-approval', // matches a WorkflowDefinition.workflowId
|
|
25
|
-
context: {
|
|
26
|
-
orderId: order.id,
|
|
27
|
-
orderTotal: order.totalGross,
|
|
28
|
-
customerName: order.customerName,
|
|
29
|
-
},
|
|
30
|
-
organizationId,
|
|
31
|
-
tenantId,
|
|
32
|
-
})
|
|
33
|
-
```
|
|
34
|
-
|
|
35
|
-
## Event Triggers
|
|
36
|
-
|
|
37
|
-
Configure automatic workflow starts from your module's domain events:
|
|
38
|
-
|
|
39
|
-
1. Create a workflow definition with a `triggers[]` entry in the visual editor or via API
|
|
40
|
-
2. The workflow engine's wildcard subscriber evaluates all non-internal events
|
|
41
|
-
3. Use `filterConditions` to narrow which events match (e.g., only orders above a threshold)
|
|
42
|
-
4. Use `contextMapping` to extract event payload fields into workflow context variables
|
|
43
|
-
5. Use `debounceMs` and `maxConcurrentInstances` to prevent trigger storms
|
|
44
|
-
|
|
45
|
-
Excluded event prefixes (never trigger workflows): `query_index`, `search`, `workflows`, `cache`, `queue`.
|
|
46
|
-
|
|
47
|
-
## Subscribing to Workflow Events
|
|
48
|
-
|
|
49
|
-
React to workflow lifecycle events in your module:
|
|
50
|
-
|
|
51
|
-
```typescript
|
|
52
|
-
// src/modules/<your_module>/subscribers/workflow-completed.ts
|
|
53
|
-
export const metadata = {
|
|
54
|
-
event: 'workflows.instance.completed',
|
|
55
|
-
persistent: true,
|
|
56
|
-
id: 'your-module-workflow-completed',
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
export default async function handler(payload, ctx) {
|
|
60
|
-
// payload.resourceId = instance ID
|
|
61
|
-
// payload.workflowId = definition ID
|
|
62
|
-
// payload.context = workflow context variables
|
|
63
|
-
}
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
Key workflow events your module can subscribe to:
|
|
67
|
-
|
|
68
|
-
| Event | When it fires |
|
|
69
|
-
|-------|--------------|
|
|
70
|
-
| `workflows.instance.created` | New workflow instance started |
|
|
71
|
-
| `workflows.instance.completed` | Workflow finished successfully |
|
|
72
|
-
| `workflows.instance.failed` | Workflow failed |
|
|
73
|
-
| `workflows.instance.cancelled` | Workflow was cancelled |
|
|
74
|
-
| `workflows.task.created` | User task assigned |
|
|
75
|
-
| `workflows.task.completed` | User task completed |
|
|
76
|
-
| `workflows.step.completed` | Individual step finished |
|
|
77
|
-
|
|
78
|
-
## Step Types
|
|
79
|
-
|
|
80
|
-
| Step type | Use case |
|
|
81
|
-
|-----------|----------|
|
|
82
|
-
| `START` | Entry point — every definition has exactly one |
|
|
83
|
-
| `END` | Terminal step — marks workflow as COMPLETED |
|
|
84
|
-
| `USER_TASK` | Human approval or data entry — pauses until task completion |
|
|
85
|
-
| `AUTOMATED` | Executes transition activities immediately and advances |
|
|
86
|
-
| `SUB_WORKFLOW` | Invokes a nested workflow definition |
|
|
87
|
-
| `WAIT_FOR_SIGNAL` | Pauses for an external signal (e.g., payment confirmed) |
|
|
88
|
-
| `WAIT_FOR_TIMER` | Pauses for a configured duration |
|
|
89
|
-
| `PARALLEL_FORK` / `PARALLEL_JOIN` | Splits/merges parallel execution paths |
|
|
90
|
-
|
|
91
|
-
## Activity Types
|
|
92
|
-
|
|
93
|
-
Activities execute on transitions between steps:
|
|
94
|
-
|
|
95
|
-
| Activity type | Use case |
|
|
96
|
-
|---------------|----------|
|
|
97
|
-
| `SEND_EMAIL` | Send templated email |
|
|
98
|
-
| `CALL_API` | Call an internal API endpoint |
|
|
99
|
-
| `CALL_WEBHOOK` | Call an external HTTP endpoint |
|
|
100
|
-
| `UPDATE_ENTITY` | Mutate an entity via the command bus |
|
|
101
|
-
| `EMIT_EVENT` | Emit a domain event |
|
|
102
|
-
| `EXECUTE_FUNCTION` | Run a registered custom function |
|
|
103
|
-
| `WAIT` | Delay execution for a configured duration |
|
|
104
|
-
|
|
105
|
-
Use `{{context.*}}`, `{{workflow.*}}`, `{{env.*}}`, `{{now}}` for variable interpolation in activity config — never hardcode values.
|
|
106
|
-
|
|
107
|
-
## Sending Signals
|
|
108
|
-
|
|
109
|
-
Resume a workflow waiting for an external signal:
|
|
110
|
-
|
|
111
|
-
```typescript
|
|
112
|
-
const executor = container.resolve('workflowExecutor')
|
|
113
|
-
|
|
114
|
-
await executor.sendSignal({
|
|
115
|
-
instanceId: workflowInstanceId,
|
|
116
|
-
signalName: 'payment_confirmed',
|
|
117
|
-
payload: { transactionId: '...' },
|
|
118
|
-
organizationId,
|
|
119
|
-
tenantId,
|
|
120
|
-
})
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
## Widget Injection
|
|
124
|
-
|
|
125
|
-
Inject workflow-related UI into your module's pages, or inject your module's widgets into workflow pages:
|
|
126
|
-
|
|
127
|
-
```typescript
|
|
128
|
-
// src/modules/<your_module>/widgets/injection-table.ts
|
|
129
|
-
export const widgetInjections = {
|
|
130
|
-
// Inject into workflow task detail page
|
|
131
|
-
'workflows.task.detail:after': {
|
|
132
|
-
widgetId: 'your-module-task-context',
|
|
133
|
-
priority: 50,
|
|
134
|
-
},
|
|
135
|
-
}
|
|
136
|
-
```
|
|
137
|
-
|
|
138
|
-
## Compensation (Saga Pattern)
|
|
139
|
-
|
|
140
|
-
When a workflow step fails, compensation activities execute in reverse order to undo previous steps. This follows the saga pattern:
|
|
141
|
-
|
|
142
|
-
- **Sync activities** execute inline and advance immediately
|
|
143
|
-
- **Async activities** enqueue to the `workflow-activities` queue; workflow pauses until completion
|
|
144
|
-
- On failure, compensation runs in reverse — keep activity handlers **idempotent** (check state before mutating)
|
|
145
|
-
|
|
146
|
-
## Key Rules
|
|
147
|
-
|
|
148
|
-
- MUST resolve services via DI (`container.resolve('workflowExecutor')`) — never import lib functions directly
|
|
149
|
-
- MUST use `workflowExecutor.startWorkflow()` to create instances — never insert rows directly
|
|
150
|
-
- MUST keep activity handlers idempotent — they may be retried on failure
|
|
151
|
-
- MUST scope all queries by `organization_id` — workflow data is tenant-scoped
|
|
152
|
-
- MUST NOT couple your module to workflow internals — use event triggers and signals for integration
|