@proveanything/smartlinks 1.16.7 → 1.17.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/dist/api/index.d.ts +2 -0
- package/dist/api/index.js +2 -0
- package/dist/api/integrations.d.ts +28 -0
- package/dist/api/integrations.js +82 -0
- package/dist/api/secrets.d.ts +15 -0
- package/dist/api/secrets.js +52 -0
- package/dist/docs/API_SUMMARY.md +237 -1
- package/dist/docs/integrations.md +141 -0
- package/dist/openapi.yaml +270 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/integrations.d.ts +136 -0
- package/dist/types/integrations.js +10 -0
- package/docs/API_SUMMARY.md +237 -1
- package/docs/integrations.md +141 -0
- package/openapi.yaml +270 -0
- package/package.json +2 -2
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
# Integrations
|
|
2
|
+
|
|
3
|
+
An **integration flow** is one input/output pipeline between SmartLinks and an external
|
|
4
|
+
system. There are two directions:
|
|
5
|
+
|
|
6
|
+
- **outbound** — read a SmartLinks entity (v1: a product), transform it with field
|
|
7
|
+
mappings, and send it to an external endpoint.
|
|
8
|
+
- **inbound** — fetch from an external system and write a SmartLinks entity. *(Executor is
|
|
9
|
+
outbound-first; inbound lands in a later increment.)*
|
|
10
|
+
|
|
11
|
+
Flows are triggered three ways, all converging on the same executor:
|
|
12
|
+
|
|
13
|
+
- **manual** — `integrations.runFlow(...)`, inline (returns a run summary) or enqueued.
|
|
14
|
+
- **event** — an outbound flow subscribed to an event type (e.g. `product.updated`) fires
|
|
15
|
+
automatically when that entity changes.
|
|
16
|
+
- **schedule** — a flow carrying a cron/interval `schedule` is run by the scan job. *(next)*
|
|
17
|
+
|
|
18
|
+
Credentials are **never** stored on the flow. The connection holds an opaque
|
|
19
|
+
`credentialRef` into the **sealed-secret store** (`secrets` namespace); the value is sealed
|
|
20
|
+
at rest and resolved server-side only, at execution.
|
|
21
|
+
|
|
22
|
+
---
|
|
23
|
+
|
|
24
|
+
## The flow model
|
|
25
|
+
|
|
26
|
+
```ts
|
|
27
|
+
interface IntegrationFlow {
|
|
28
|
+
id: string
|
|
29
|
+
direction: 'inbound' | 'outbound'
|
|
30
|
+
name: string
|
|
31
|
+
status: 'draft' | 'active' | 'paused' | 'error' // only 'active' flows fire on events/schedule
|
|
32
|
+
eventTypes: string[] // e.g. ['product.updated']
|
|
33
|
+
schedule: string | null // cron/interval for scheduled flows
|
|
34
|
+
sourceEntity: string | null // outbound source, v1: 'product'
|
|
35
|
+
targetEntity: string | null // inbound target
|
|
36
|
+
config: {
|
|
37
|
+
connection?: {
|
|
38
|
+
baseUrl?: string
|
|
39
|
+
sendEndpoint?: string // outbound: appended to baseUrl
|
|
40
|
+
defaultHeaders?: Record<string, string>
|
|
41
|
+
auth?: { method: 'api_key' | 'bearer' | 'basic' | ..., headerName?: string, credentialRef?: string }
|
|
42
|
+
}
|
|
43
|
+
fieldMappings?: FieldMapping[]
|
|
44
|
+
}
|
|
45
|
+
// ...run watermark/telemetry: lastRunAt, lastRunStatus, lastRunCount, totalSynced
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Field mappings (transform)
|
|
50
|
+
|
|
51
|
+
Each mapping produces one field on the target payload:
|
|
52
|
+
|
|
53
|
+
| transformType | uses | meaning |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| `direct` | `sourcePath` | copy the value at that dot-path |
|
|
56
|
+
| `static` | `transformExpression` | a constant |
|
|
57
|
+
| `template` | `transformExpression` | a Liquid template rendered against the source record |
|
|
58
|
+
| `jsonata` / `ai` | — | recognised but not yet executed; reported as a per-field error |
|
|
59
|
+
|
|
60
|
+
A single field's failure is collected and the rest continue (partial success) — it never
|
|
61
|
+
aborts the whole record.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
## Secrets (write-only)
|
|
66
|
+
|
|
67
|
+
The secret store is **write-only from the client**: you can set, rotate, list (refs +
|
|
68
|
+
masked hints + metadata) and delete — but a value never comes back over the API.
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { secrets, integrations } from '@proveanything/smartlinks'
|
|
72
|
+
|
|
73
|
+
// 1. Store the destination credential — keep the returned ref.
|
|
74
|
+
const { ref } = await secrets.set(collectionId, {
|
|
75
|
+
name: 'Acme API key',
|
|
76
|
+
purpose: 'integration',
|
|
77
|
+
value: 'sk_live_…', // sent once; never retrievable
|
|
78
|
+
})
|
|
79
|
+
|
|
80
|
+
// list shows refs + masked hints only (safe to render)
|
|
81
|
+
const { secrets: list } = await secrets.list(collectionId)
|
|
82
|
+
// → [{ ref, name: 'Acme API key', hint: '…live_1a2b', purpose, createdAt, ... }]
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
## Creating and running a flow
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
// 2. Create an outbound flow that pushes products to Acme, authed by the secret above.
|
|
91
|
+
const flow = await integrations.createFlow(collectionId, {
|
|
92
|
+
appId: 'my-integration-app',
|
|
93
|
+
direction: 'outbound',
|
|
94
|
+
name: 'Push products to Acme',
|
|
95
|
+
status: 'active',
|
|
96
|
+
eventTypes: ['product.updated'], // fire whenever a product changes
|
|
97
|
+
sourceEntity: 'product',
|
|
98
|
+
config: {
|
|
99
|
+
connection: {
|
|
100
|
+
baseUrl: 'https://api.acme.example',
|
|
101
|
+
sendEndpoint: '/v1/products',
|
|
102
|
+
auth: { method: 'api_key', headerName: 'X-API-Key', credentialRef: ref },
|
|
103
|
+
},
|
|
104
|
+
fieldMappings: [
|
|
105
|
+
{ targetPath: 'sku', sourcePath: 'sku', transformType: 'direct' },
|
|
106
|
+
{ targetPath: 'name', sourcePath: 'name', transformType: 'direct' },
|
|
107
|
+
{ targetPath: 'label', transformType: 'template', transformExpression: '{{name}} ({{sku}})' },
|
|
108
|
+
],
|
|
109
|
+
},
|
|
110
|
+
})
|
|
111
|
+
|
|
112
|
+
// 3a. Test it now against one product — inline, returns a summary.
|
|
113
|
+
const result = await integrations.runFlow(collectionId, flow.id, { entityId: 'P1045716' })
|
|
114
|
+
if (integrations.isRunSummary(result)) {
|
|
115
|
+
console.log(result) // { records: 1, sent: 1, failed: 0, status: 'success' }
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// 3b. Or enqueue on the worker (returns immediately).
|
|
119
|
+
await integrations.runFlow(collectionId, flow.id, { entityId: 'P1045716', async: true })
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
Once `status: 'active'` with `eventTypes: ['product.updated']`, editing that product in the
|
|
123
|
+
admin API fires the flow automatically — no manual run needed.
|
|
124
|
+
|
|
125
|
+
---
|
|
126
|
+
|
|
127
|
+
## Reference
|
|
128
|
+
|
|
129
|
+
| Function | HTTP |
|
|
130
|
+
|---|---|
|
|
131
|
+
| `integrations.listFlows(collectionId, query?)` | `GET /integrations/flows` |
|
|
132
|
+
| `integrations.createFlow(collectionId, input)` | `POST /integrations/flows` |
|
|
133
|
+
| `integrations.getFlow(collectionId, id)` | `GET /integrations/flows/:id` |
|
|
134
|
+
| `integrations.updateFlow(collectionId, id, input)` | `PUT /integrations/flows/:id` |
|
|
135
|
+
| `integrations.deleteFlow(collectionId, id)` | `DELETE /integrations/flows/:id` |
|
|
136
|
+
| `integrations.runFlow(collectionId, id, opts?)` | `POST /integrations/flows/:id/run` |
|
|
137
|
+
| `secrets.list(collectionId, query?)` | `GET /secrets` |
|
|
138
|
+
| `secrets.set(collectionId, input)` | `POST /secrets` |
|
|
139
|
+
| `secrets.get(collectionId, ref)` | `GET /secrets/:ref` |
|
|
140
|
+
| `secrets.rotate(collectionId, ref, input)` | `PUT /secrets/:ref` |
|
|
141
|
+
| `secrets.remove(collectionId, ref)` | `DELETE /secrets/:ref` |
|
package/openapi.yaml
CHANGED
|
@@ -22860,6 +22860,276 @@ components:
|
|
|
22860
22860
|
UploadMessage:
|
|
22861
22861
|
type: object
|
|
22862
22862
|
additionalProperties: true
|
|
22863
|
+
FieldMapping:
|
|
22864
|
+
type: object
|
|
22865
|
+
properties:
|
|
22866
|
+
targetPath:
|
|
22867
|
+
type: string
|
|
22868
|
+
sourcePath:
|
|
22869
|
+
type: string
|
|
22870
|
+
transformType:
|
|
22871
|
+
$ref: "#/components/schemas/TransformType"
|
|
22872
|
+
transformExpression:
|
|
22873
|
+
type: string
|
|
22874
|
+
required:
|
|
22875
|
+
- targetPath
|
|
22876
|
+
- transformType
|
|
22877
|
+
FlowConnectionAuth:
|
|
22878
|
+
type: object
|
|
22879
|
+
properties:
|
|
22880
|
+
method:
|
|
22881
|
+
$ref: "#/components/schemas/FlowAuthMethod"
|
|
22882
|
+
headerName:
|
|
22883
|
+
type: string
|
|
22884
|
+
credentialRef:
|
|
22885
|
+
type: string
|
|
22886
|
+
required:
|
|
22887
|
+
- method
|
|
22888
|
+
FlowConnection:
|
|
22889
|
+
type: object
|
|
22890
|
+
properties:
|
|
22891
|
+
baseUrl:
|
|
22892
|
+
type: string
|
|
22893
|
+
sendEndpoint:
|
|
22894
|
+
type: string
|
|
22895
|
+
fetchEndpoint:
|
|
22896
|
+
type: string
|
|
22897
|
+
defaultHeaders:
|
|
22898
|
+
type: object
|
|
22899
|
+
additionalProperties:
|
|
22900
|
+
type: string
|
|
22901
|
+
auth:
|
|
22902
|
+
$ref: "#/components/schemas/FlowConnectionAuth"
|
|
22903
|
+
IntegrationFlowConfig:
|
|
22904
|
+
type: object
|
|
22905
|
+
properties:
|
|
22906
|
+
connection:
|
|
22907
|
+
$ref: "#/components/schemas/FlowConnection"
|
|
22908
|
+
fieldMappings:
|
|
22909
|
+
type: array
|
|
22910
|
+
items:
|
|
22911
|
+
$ref: "#/components/schemas/FieldMapping"
|
|
22912
|
+
IntegrationFlow:
|
|
22913
|
+
type: object
|
|
22914
|
+
properties:
|
|
22915
|
+
id:
|
|
22916
|
+
type: string
|
|
22917
|
+
orgId:
|
|
22918
|
+
type: string
|
|
22919
|
+
collectionId:
|
|
22920
|
+
type: string
|
|
22921
|
+
appId:
|
|
22922
|
+
type: string
|
|
22923
|
+
direction:
|
|
22924
|
+
$ref: "#/components/schemas/FlowDirection"
|
|
22925
|
+
name:
|
|
22926
|
+
type: string
|
|
22927
|
+
status:
|
|
22928
|
+
$ref: "#/components/schemas/FlowStatus"
|
|
22929
|
+
eventTypes:
|
|
22930
|
+
type: array
|
|
22931
|
+
items:
|
|
22932
|
+
type: string
|
|
22933
|
+
schedule:
|
|
22934
|
+
type: string
|
|
22935
|
+
sourceEntity:
|
|
22936
|
+
type: string
|
|
22937
|
+
targetEntity:
|
|
22938
|
+
type: string
|
|
22939
|
+
config:
|
|
22940
|
+
$ref: "#/components/schemas/IntegrationFlowConfig"
|
|
22941
|
+
createdBy:
|
|
22942
|
+
type: string
|
|
22943
|
+
createdAt:
|
|
22944
|
+
type: string
|
|
22945
|
+
updatedAt:
|
|
22946
|
+
type: string
|
|
22947
|
+
deletedAt:
|
|
22948
|
+
type: string
|
|
22949
|
+
lastRunAt:
|
|
22950
|
+
type: string
|
|
22951
|
+
lastRunStatus:
|
|
22952
|
+
type: string
|
|
22953
|
+
lastRunError:
|
|
22954
|
+
type: string
|
|
22955
|
+
lastRunCount:
|
|
22956
|
+
type: number
|
|
22957
|
+
lastPollAt:
|
|
22958
|
+
type: string
|
|
22959
|
+
lastCursor:
|
|
22960
|
+
type: string
|
|
22961
|
+
totalSynced:
|
|
22962
|
+
type: number
|
|
22963
|
+
required:
|
|
22964
|
+
- id
|
|
22965
|
+
- orgId
|
|
22966
|
+
- collectionId
|
|
22967
|
+
- appId
|
|
22968
|
+
- direction
|
|
22969
|
+
- name
|
|
22970
|
+
- status
|
|
22971
|
+
- eventTypes
|
|
22972
|
+
- schedule
|
|
22973
|
+
- sourceEntity
|
|
22974
|
+
- targetEntity
|
|
22975
|
+
- config
|
|
22976
|
+
- createdBy
|
|
22977
|
+
- createdAt
|
|
22978
|
+
- updatedAt
|
|
22979
|
+
CreateFlowInput:
|
|
22980
|
+
type: object
|
|
22981
|
+
properties:
|
|
22982
|
+
appId:
|
|
22983
|
+
type: string
|
|
22984
|
+
direction:
|
|
22985
|
+
$ref: "#/components/schemas/FlowDirection"
|
|
22986
|
+
name:
|
|
22987
|
+
type: string
|
|
22988
|
+
status:
|
|
22989
|
+
$ref: "#/components/schemas/FlowStatus"
|
|
22990
|
+
eventTypes:
|
|
22991
|
+
type: array
|
|
22992
|
+
items:
|
|
22993
|
+
type: string
|
|
22994
|
+
schedule:
|
|
22995
|
+
type: string
|
|
22996
|
+
sourceEntity:
|
|
22997
|
+
type: string
|
|
22998
|
+
targetEntity:
|
|
22999
|
+
type: string
|
|
23000
|
+
config:
|
|
23001
|
+
$ref: "#/components/schemas/IntegrationFlowConfig"
|
|
23002
|
+
required:
|
|
23003
|
+
- appId
|
|
23004
|
+
- direction
|
|
23005
|
+
- name
|
|
23006
|
+
ListFlowsQuery:
|
|
23007
|
+
type: object
|
|
23008
|
+
properties:
|
|
23009
|
+
direction:
|
|
23010
|
+
$ref: "#/components/schemas/FlowDirection"
|
|
23011
|
+
status:
|
|
23012
|
+
$ref: "#/components/schemas/FlowStatus"
|
|
23013
|
+
appId:
|
|
23014
|
+
type: string
|
|
23015
|
+
FlowList:
|
|
23016
|
+
type: object
|
|
23017
|
+
properties:
|
|
23018
|
+
flows:
|
|
23019
|
+
type: array
|
|
23020
|
+
items:
|
|
23021
|
+
$ref: "#/components/schemas/IntegrationFlow"
|
|
23022
|
+
required:
|
|
23023
|
+
- flows
|
|
23024
|
+
RunFlowInput:
|
|
23025
|
+
type: object
|
|
23026
|
+
properties:
|
|
23027
|
+
entityId:
|
|
23028
|
+
type: string
|
|
23029
|
+
RunFlowSummary:
|
|
23030
|
+
type: object
|
|
23031
|
+
properties:
|
|
23032
|
+
flowId:
|
|
23033
|
+
type: string
|
|
23034
|
+
direction:
|
|
23035
|
+
$ref: "#/components/schemas/FlowDirection"
|
|
23036
|
+
records:
|
|
23037
|
+
type: number
|
|
23038
|
+
sent:
|
|
23039
|
+
type: number
|
|
23040
|
+
failed:
|
|
23041
|
+
type: number
|
|
23042
|
+
status:
|
|
23043
|
+
$ref: "#/components/schemas/RunStatus"
|
|
23044
|
+
required:
|
|
23045
|
+
- flowId
|
|
23046
|
+
- direction
|
|
23047
|
+
- records
|
|
23048
|
+
- sent
|
|
23049
|
+
- failed
|
|
23050
|
+
- status
|
|
23051
|
+
RunFlowEnqueued:
|
|
23052
|
+
type: object
|
|
23053
|
+
properties:
|
|
23054
|
+
enqueued:
|
|
23055
|
+
type: object
|
|
23056
|
+
additionalProperties: true
|
|
23057
|
+
flowId:
|
|
23058
|
+
type: string
|
|
23059
|
+
entityId:
|
|
23060
|
+
type: string
|
|
23061
|
+
required:
|
|
23062
|
+
- enqueued
|
|
23063
|
+
- flowId
|
|
23064
|
+
- entityId
|
|
23065
|
+
SecretMeta:
|
|
23066
|
+
type: object
|
|
23067
|
+
properties:
|
|
23068
|
+
ref:
|
|
23069
|
+
type: string
|
|
23070
|
+
name:
|
|
23071
|
+
type: string
|
|
23072
|
+
purpose:
|
|
23073
|
+
type: string
|
|
23074
|
+
hint:
|
|
23075
|
+
type: string
|
|
23076
|
+
keyVersion:
|
|
23077
|
+
type: number
|
|
23078
|
+
createdBy:
|
|
23079
|
+
type: string
|
|
23080
|
+
createdAt:
|
|
23081
|
+
type: string
|
|
23082
|
+
updatedAt:
|
|
23083
|
+
type: string
|
|
23084
|
+
rotatedAt:
|
|
23085
|
+
type: string
|
|
23086
|
+
required:
|
|
23087
|
+
- ref
|
|
23088
|
+
- name
|
|
23089
|
+
- purpose
|
|
23090
|
+
- hint
|
|
23091
|
+
- keyVersion
|
|
23092
|
+
- createdBy
|
|
23093
|
+
- createdAt
|
|
23094
|
+
- updatedAt
|
|
23095
|
+
SecretList:
|
|
23096
|
+
type: object
|
|
23097
|
+
properties:
|
|
23098
|
+
secrets:
|
|
23099
|
+
type: array
|
|
23100
|
+
items:
|
|
23101
|
+
$ref: "#/components/schemas/SecretMeta"
|
|
23102
|
+
required:
|
|
23103
|
+
- secrets
|
|
23104
|
+
SetSecretInput:
|
|
23105
|
+
type: object
|
|
23106
|
+
properties:
|
|
23107
|
+
value:
|
|
23108
|
+
type: string
|
|
23109
|
+
name:
|
|
23110
|
+
type: string
|
|
23111
|
+
purpose:
|
|
23112
|
+
type: string
|
|
23113
|
+
required:
|
|
23114
|
+
- value
|
|
23115
|
+
SetSecretResult:
|
|
23116
|
+
type: object
|
|
23117
|
+
properties:
|
|
23118
|
+
ref:
|
|
23119
|
+
type: string
|
|
23120
|
+
hint:
|
|
23121
|
+
type: string
|
|
23122
|
+
required:
|
|
23123
|
+
- ref
|
|
23124
|
+
- hint
|
|
23125
|
+
ListSecretsQuery:
|
|
23126
|
+
type: object
|
|
23127
|
+
properties:
|
|
23128
|
+
purpose:
|
|
23129
|
+
type: string
|
|
23130
|
+
RunFlowResult:
|
|
23131
|
+
type: object
|
|
23132
|
+
additionalProperties: true
|
|
22863
23133
|
AdminInteractionsQueryRequest:
|
|
22864
23134
|
type: object
|
|
22865
23135
|
properties:
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@proveanything/smartlinks",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.17.0",
|
|
4
4
|
"description": "Official JavaScript/TypeScript SDK for the Smartlinks API",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -28,7 +28,7 @@
|
|
|
28
28
|
"keywords": [
|
|
29
29
|
"smartlinks",
|
|
30
30
|
"api",
|
|
31
|
-
"authentication",
|
|
31
|
+
"authentication",
|
|
32
32
|
"traceability",
|
|
33
33
|
"blockchain",
|
|
34
34
|
"typescript",
|