@proveanything/smartlinks 2.0.56 → 2.0.58

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/site.d.ts CHANGED
@@ -1,10 +1,38 @@
1
1
  declare global {
2
2
  var __SL_READY__: boolean | undefined;
3
+ var __SMARTLINKS_SITE__: SiteContext | undefined;
3
4
  }
5
+ /** The site a page is being served as. */
6
+ export interface SiteContext {
7
+ /** The hostname this request arrived on (an automatic address, a chosen name or a custom domain). */
8
+ host: string;
9
+ /** The collection the site belongs to: pass it to every SDK call. */
10
+ collectionId: string;
11
+ appId: string;
12
+ /** The release channel being served ('stable' on a live address; 'dev' etc. on a test address). */
13
+ channel: string;
14
+ /** Where search engines consolidate the site (custom domain > chosen name > automatic address). */
15
+ canonicalHost: string;
16
+ }
17
+ type HeaderSource = {
18
+ headers: Headers | Record<string, string | string[] | undefined>;
19
+ } | Headers;
20
+ /**
21
+ * On the server: the site this request is rendering. The SmartLinks site router sets it on every
22
+ * request it hands to your site's server (and drops any value a visitor sends). Null outside the
23
+ * site runtime, e.g. in local development without the router: fall back to your dev collection.
24
+ *
25
+ * @example
26
+ * // TanStack Start server function / loader
27
+ * const site = SL.site.fromRequest(getRequest())
28
+ * const products = await SL.product.list(site!.collectionId)
29
+ */
30
+ export declare function fromRequest(request: HeaderSource): SiteContext | null;
31
+ /** In the browser: the site the page is served as (the router puts it in the page). Null elsewhere. */
32
+ export declare function current(): SiteContext | null;
4
33
  /**
5
- * Tell the platform this page has finished rendering its content (data loaded, head tags set). The
6
- * platform's page renderer takes its snapshot for search engines and AI crawlers at this point;
7
- * without it, it waits for the network to go idle (capped). Call once per page, after your data
8
- * renders. Harmless anywhere else.
34
+ * @deprecated Sites are server-rendered: crawlers get the finished page from the server, so nothing
35
+ * waits for this signal any more. Kept as a harmless no-op signal for older pages.
9
36
  */
10
37
  export declare function ready(): void;
38
+ export {};
package/dist/site.js CHANGED
@@ -1,11 +1,54 @@
1
1
  // =============================================================================
2
- // site — for apps served as websites.
2
+ // site — for apps served as websites (server-rendered on the SmartLinks site runtime).
3
3
  // =============================================================================
4
+ function headerOf(source, name) {
5
+ var _a, _b;
6
+ const headers = typeof Headers !== 'undefined' && source instanceof Headers ? source : source.headers;
7
+ if (!headers)
8
+ return null;
9
+ if (typeof headers.get === 'function')
10
+ return headers.get(name);
11
+ const v = (_a = headers[name]) !== null && _a !== void 0 ? _a : headers[name.toLowerCase()];
12
+ return Array.isArray(v) ? (_b = v[0]) !== null && _b !== void 0 ? _b : null : v !== null && v !== void 0 ? v : null;
13
+ }
14
+ function parse(raw) {
15
+ try {
16
+ const v = typeof raw === 'string' ? JSON.parse(raw) : raw;
17
+ if (!v || typeof v !== 'object' || typeof v.collectionId !== 'string')
18
+ return null;
19
+ const s = v;
20
+ return {
21
+ host: String(s.host || ''),
22
+ collectionId: String(s.collectionId),
23
+ appId: String(s.appId || ''),
24
+ channel: String(s.channel || 'stable'),
25
+ canonicalHost: String(s.canonicalHost || s.host || ''),
26
+ };
27
+ }
28
+ catch (_a) {
29
+ return null;
30
+ }
31
+ }
32
+ /**
33
+ * On the server: the site this request is rendering. The SmartLinks site router sets it on every
34
+ * request it hands to your site's server (and drops any value a visitor sends). Null outside the
35
+ * site runtime, e.g. in local development without the router: fall back to your dev collection.
36
+ *
37
+ * @example
38
+ * // TanStack Start server function / loader
39
+ * const site = SL.site.fromRequest(getRequest())
40
+ * const products = await SL.product.list(site!.collectionId)
41
+ */
42
+ export function fromRequest(request) {
43
+ return parse(headerOf(request, 'x-sl-site'));
44
+ }
45
+ /** In the browser: the site the page is served as (the router puts it in the page). Null elsewhere. */
46
+ export function current() {
47
+ return parse(globalThis.__SMARTLINKS_SITE__);
48
+ }
4
49
  /**
5
- * Tell the platform this page has finished rendering its content (data loaded, head tags set). The
6
- * platform's page renderer takes its snapshot for search engines and AI crawlers at this point;
7
- * without it, it waits for the network to go idle (capped). Call once per page, after your data
8
- * renders. Harmless anywhere else.
50
+ * @deprecated Sites are server-rendered: crawlers get the finished page from the server, so nothing
51
+ * waits for this signal any more. Kept as a harmless no-op signal for older pages.
9
52
  */
10
53
  export function ready() {
11
54
  if (typeof globalThis === 'undefined')
@@ -827,8 +827,194 @@ export interface AppManifest {
827
827
  * provider). Validated by `smartlinks-headless`. @see AppHeadlessDeclaration
828
828
  */
829
829
  headless?: AppHeadlessDeclaration;
830
+ /**
831
+ * This app is an integration CONNECTOR for one external provider (Syndigo, OneWorldSync, …): the
832
+ * integrations console lists it, draws its connect form and settings, and the integration engine
833
+ * calls its server functions to test, describe, sample, shape, serialize, send and fetch. The
834
+ * customer's mapping is NOT the connector's job: core maps between the connector's provider-neutral
835
+ * documents and SmartLinks (docs/connectors.md).
836
+ * @see AppConnectorDeclaration · docs/connectors.md
837
+ */
838
+ connector?: AppConnectorDeclaration;
830
839
  [key: string]: any;
831
840
  }
841
+ /** One field of a connector's "Connect" form. */
842
+ export interface ConnectorConnectionField {
843
+ /** Key in the installation's connection settings (non-secret fields) — `name` for a secret too. */
844
+ name: string;
845
+ label: string;
846
+ description?: string;
847
+ /** Store the value as this app's SECRET of this name (sealed, write-only; the function reads it with
848
+ * `ctx.secrets.get(secret)`), never in the settings. Declare `secrets:<name>` on the functions. */
849
+ secret?: string;
850
+ required?: boolean;
851
+ /** Input hint for the form. Default 'text'. */
852
+ type?: 'text' | 'url' | 'select' | 'number' | 'boolean';
853
+ options?: Array<{
854
+ value: string;
855
+ label: string;
856
+ }>;
857
+ placeholder?: string;
858
+ }
859
+ /** A ready-made flow a connector offers ("Products → Syndigo"). */
860
+ export interface ConnectorPreset {
861
+ id: string;
862
+ title: string;
863
+ description?: string;
864
+ direction: 'inbound' | 'outbound';
865
+ /** SmartLinks entity: outbound source / inbound target. */
866
+ entity: string;
867
+ /** Defaults for the flow (event types, schedule, mapping, settings…). */
868
+ flow?: Record<string, unknown>;
869
+ }
870
+ /** A panel the connector contributes to the integrations console (e.g. an API explorer). */
871
+ export interface ConnectorPanel {
872
+ id: string;
873
+ title: string;
874
+ /** Exported component name in the app's widgets bundle (manifest `widgets.files`). */
875
+ component: string;
876
+ }
877
+ /**
878
+ * The connector contract. Every function named here is one of this app's server functions
879
+ * (manifest `functions.definitions`); the engine calls it with collection authority, capped by the
880
+ * capabilities the function declares. A connector fills in only what it needs.
881
+ *
882
+ * A connector is an ADAPTER: it talks to the provider and converts between the provider's format and
883
+ * a clean, provider-neutral document. Each customer's mapping, routing and rules live in core.
884
+ */
885
+ export interface AppConnectorDeclaration {
886
+ /** Stable provider key, e.g. 'syndigo', 'oneworldsync'. */
887
+ provider: string;
888
+ /** Display name of the provider ("1WorldSync"). Defaults to the app name. */
889
+ title?: string;
890
+ directions: Array<'inbound' | 'outbound'>;
891
+ /** SmartLinks entities it maps, e.g. ['product']. */
892
+ entities: string[];
893
+ /** The console's "Connect" form. */
894
+ connection?: {
895
+ fields: ConnectorConnectionField[];
896
+ };
897
+ /** Per-installation settings: a JSON Schema the console renders as a form. */
898
+ settings?: Record<string, unknown>;
899
+ /** Ready-made flows; a preset's `flow.config.fieldMappings` is a suggested mapping the customer can edit. */
900
+ presets?: ConnectorPreset[];
901
+ /** Names of this app's server functions implementing each step. */
902
+ functions: {
903
+ /** → ConnectorTestResult. */
904
+ testConnection?: string;
905
+ /** → ConnectorTargetSchema: the provider's fields for THIS customer (the mapper's right-hand side). */
906
+ describeTarget?: string;
907
+ /** → ConnectorRecords: real records for the mapper, the AI assistant and dry runs (inbound). */
908
+ sample?: string;
909
+ /**
910
+ * Inbound: (ConnectorShapeInput) → ConnectorShapeResult. Provider records → provider-neutral
911
+ * documents, the same for every customer (no customer mapping). Deterministic — no AI, network or
912
+ * clock. Omit to hand core the provider records as they are.
913
+ */
914
+ shape?: string;
915
+ /**
916
+ * Outbound: (ConnectorSerializeInput) → ConnectorSerializeResult. Documents core has mapped to this
917
+ * provider's fields (`describeTarget` paths) → the provider's wire format (an envelope, a batch).
918
+ * Deterministic. Omit to send the mapped documents as they are.
919
+ */
920
+ serialize?: string;
921
+ /** (ConnectorSendInput) → ConnectorSendResult. Omit to use a generic transport (HTTP, Event Hub). */
922
+ send?: string;
923
+ /** (ConnectorFetchInput) → ConnectorRecords: inbound pull, one page per call. */
924
+ fetch?: string;
925
+ };
926
+ panels?: ConnectorPanel[];
927
+ /** Path (under the app's public files) of a guide the AI mapping assistant reads. */
928
+ aiGuide?: string;
929
+ }
930
+ /**
931
+ * What every connector function receives about the installation it serves. The engine assembles it
932
+ * from the connector app's config on the collection (`connector.connection` / `connector.settings`)
933
+ * with the flow's `config.connector.settings` layered on top.
934
+ */
935
+ export interface ConnectorInstallation {
936
+ collectionId: string;
937
+ /** The connector app. */
938
+ appId: string;
939
+ /** The flow being run / configured, when there is one. */
940
+ flowId?: string | null;
941
+ /** Non-secret connection fields (secrets are read with ctx.secrets.get). */
942
+ connection: Record<string, unknown>;
943
+ /** Installation settings, overridden per flow. */
944
+ settings: Record<string, unknown>;
945
+ }
946
+ export interface ConnectorTestResult {
947
+ ok: boolean;
948
+ /** Shown to the admin: "Connected as …" or what's wrong. */
949
+ message: string;
950
+ }
951
+ export interface ConnectorTargetField {
952
+ /** Path in the provider payload, e.g. 'attributes.brandName'. */
953
+ path: string;
954
+ label?: string;
955
+ type?: 'string' | 'number' | 'boolean' | 'date' | 'object' | 'array';
956
+ required?: boolean;
957
+ description?: string;
958
+ /** Allowed values, when the provider fixes them. */
959
+ enum?: string[];
960
+ }
961
+ export interface ConnectorTargetSchema {
962
+ fields: ConnectorTargetField[];
963
+ }
964
+ export interface ConnectorRecords {
965
+ records: Array<Record<string, unknown>>;
966
+ /** Inbound paging: pass back to the next fetch; absent when there's no more. */
967
+ nextCursor?: string | null;
968
+ }
969
+ /** Inbound: provider records, as fetch / sample returned them. */
970
+ export interface ConnectorShapeInput {
971
+ installation: ConnectorInstallation;
972
+ records: Array<Record<string, unknown>>;
973
+ }
974
+ export interface ConnectorShapeResult {
975
+ /** One provider-neutral document per record, in the same order (null = skip it, with a reason). */
976
+ documents: Array<Record<string, unknown> | null>;
977
+ skipped?: Array<{
978
+ index: number;
979
+ reason: string;
980
+ }>;
981
+ }
982
+ /**
983
+ * Outbound: documents core has mapped to this provider's fields (keyed by `describeTarget` paths).
984
+ * A deleted SmartLinks entity arrives as `{ id, _deleted: true }`.
985
+ */
986
+ export interface ConnectorSerializeInput {
987
+ installation: ConnectorInstallation;
988
+ documents: Array<Record<string, unknown>>;
989
+ /** The event that triggered the run, e.g. 'product.updated' (absent for manual / scheduled runs). */
990
+ eventType?: string;
991
+ }
992
+ export interface ConnectorSerializeResult {
993
+ /** One provider payload per document, in the same order (null = skip it, with a reason). */
994
+ payloads: Array<unknown | null>;
995
+ skipped?: Array<{
996
+ index: number;
997
+ reason: string;
998
+ }>;
999
+ }
1000
+ export interface ConnectorSendInput {
1001
+ installation: ConnectorInstallation;
1002
+ payloads: unknown[];
1003
+ }
1004
+ export interface ConnectorSendResult {
1005
+ results: Array<{
1006
+ index: number;
1007
+ ok: boolean;
1008
+ status?: number;
1009
+ error?: string;
1010
+ externalId?: string;
1011
+ }>;
1012
+ }
1013
+ export interface ConnectorFetchInput {
1014
+ installation: ConnectorInstallation;
1015
+ cursor?: string | null;
1016
+ limit?: number;
1017
+ }
832
1018
  /**
833
1019
  * One app entry in the collection widgets response.
834
1020
  */
@@ -29,9 +29,20 @@ export interface FlowConnection {
29
29
  defaultHeaders?: Record<string, string>;
30
30
  auth?: FlowConnectionAuth;
31
31
  }
32
+ /** A flow driven by a connector app (docs/connectors.md). */
33
+ export interface FlowConnectorRef {
34
+ /** The connector app (manifest `connector` block), installed on the collection. */
35
+ appId: string;
36
+ /** The preset the flow was created from, if any. */
37
+ preset?: string;
38
+ /** Per-flow settings, layered over the installation's. */
39
+ settings?: Record<string, unknown>;
40
+ }
32
41
  export interface IntegrationFlowConfig {
33
42
  connection?: FlowConnection;
34
43
  fieldMappings?: FieldMapping[];
44
+ /** Run this flow through a connector app's functions instead of the built-in mapper/transport. */
45
+ connector?: FlowConnectorRef;
35
46
  [key: string]: any;
36
47
  }
37
48
  export interface IntegrationFlow {
@@ -95,12 +106,43 @@ export interface RunFlowSummary {
95
106
  flowId: string;
96
107
  direction: FlowDirection;
97
108
  records: number;
98
- sent: number;
109
+ /** Outbound: records delivered. */
110
+ sent?: number;
99
111
  failed: number;
112
+ /** Inbound: products created / updated, and records the connector skipped. */
113
+ created?: number;
114
+ updated?: number;
115
+ skipped?: number;
100
116
  status: RunStatus;
101
117
  /** Id of the persisted run row (deep-link into its detail). */
102
118
  runId?: string;
103
119
  }
120
+ /** One installed connector app, as the integrations console sees it. */
121
+ export interface InstalledConnector {
122
+ appId: string;
123
+ name: string;
124
+ /** The release channel installed on this collection. */
125
+ channel: string;
126
+ version: string | null;
127
+ connector: import('./appManifest.js').AppConnectorDeclaration;
128
+ /** Non-secret Connect-form values + installation settings. */
129
+ installation: {
130
+ connection: Record<string, unknown>;
131
+ settings: Record<string, unknown>;
132
+ };
133
+ /** Each secret the Connect form declares: whether it is set (+ masked hint). Never a value. */
134
+ secrets: Record<string, {
135
+ set: boolean;
136
+ hint?: string | null;
137
+ }>;
138
+ }
139
+ export interface SaveConnectorInstallationInput {
140
+ /** Non-secret fields only; secret fields are set with `secrets.put` for the connector's appId. */
141
+ connection?: Record<string, unknown>;
142
+ settings?: Record<string, unknown>;
143
+ }
144
+ /** Steps the console may run directly (send and fetch only run inside a flow; shape/serialize as dry runs). */
145
+ export type ConnectorConsoleStep = 'testConnection' | 'describeTarget' | 'sample' | 'shape' | 'serialize';
104
146
  export type RunTrigger = 'manual' | 'event' | 'schedule' | 'test';
105
147
  export type FlowRunStatus = 'running' | 'success' | 'partial' | 'failed' | 'skipped';
106
148
  export type FlowRunItemStatus = 'sent' | 'failed' | 'skipped';
@@ -1,6 +1,6 @@
1
1
  # Smartlinks API Summary
2
2
 
3
- Version: 2.0.56 | Generated: 2026-10-12T20:58:59.335Z
3
+ Version: 2.0.58 | Generated: 2026-10-13T14:08:01.791Z
4
4
 
5
5
  This is a concise summary of all available API functions and types.
6
6
 
@@ -65,6 +65,7 @@ For detailed guides on specific features:
65
65
  - **[Analytics Metadata Conventions](analytics-metadata-conventions.md)** - Standard recommended keys and conventions for analytics metadata fields
66
66
  - **[Loyalty: Points, Members & Earning Rules](loyalty.md)** - Loyalty schemes, automatic point earning via interaction rules, member balances, transaction history, and manual adjustments
67
67
  - **[Integrations](integrations.md)** - Inbound/outbound integration flows + the sealed-secret store; triggers (manual/event/schedule), field mappings, and the Syndigo/Event Hub outbound path
68
+ - **[Connectors](connectors.md)** - Connector apps (adapters for one external provider): a manifest `connector` block + server functions (testConnection/describeTarget/sample/fetch/shape/serialize/send); core does the mapping
68
69
  - **[AI Tools & Skills](ai-tools-and-skills.md)** - The AI capability catalog: skills apps invoke by name (e.g. research.brand), the tools the AI reaches for (web fetch/screenshot/brand assets/image gen), the agent loop, and how apps discover them
69
70
  - **[Deep Link Discovery](deep-link-discovery.md)** - Registering and discovering navigable app states for portal menus and AI orchestration
70
71
  - **[AI Guide Template](ai-guide-template.md)** - A sample for an app on how to build an AI setup guide
@@ -2853,10 +2854,173 @@ interface AppManifest {
2853
2854
  realtime?: { channels: RealtimeChannelDeclaration[] };
2854
2855
  data?: AppDataDeclaration;
2855
2856
  headless?: AppHeadlessDeclaration;
2857
+ connector?: AppConnectorDeclaration;
2856
2858
  [key: string]: any;
2857
2859
  }
2858
2860
  ```
2859
2861
 
2862
+ **ConnectorConnectionField** (interface)
2863
+ ```typescript
2864
+ interface ConnectorConnectionField {
2865
+ name: string
2866
+ label: string
2867
+ description?: string
2868
+ secret?: string
2869
+ required?: boolean
2870
+ type?: 'text' | 'url' | 'select' | 'number' | 'boolean'
2871
+ options?: Array<{ value: string; label: string }>
2872
+ placeholder?: string
2873
+ }
2874
+ ```
2875
+
2876
+ **ConnectorPreset** (interface)
2877
+ ```typescript
2878
+ interface ConnectorPreset {
2879
+ id: string
2880
+ title: string
2881
+ description?: string
2882
+ direction: 'inbound' | 'outbound'
2883
+ entity: string
2884
+ flow?: Record<string, unknown>
2885
+ }
2886
+ ```
2887
+
2888
+ **ConnectorPanel** (interface)
2889
+ ```typescript
2890
+ interface ConnectorPanel {
2891
+ id: string
2892
+ title: string
2893
+ component: string
2894
+ }
2895
+ ```
2896
+
2897
+ **AppConnectorDeclaration** (interface)
2898
+ ```typescript
2899
+ interface AppConnectorDeclaration {
2900
+ provider: string
2901
+ title?: string
2902
+ directions: Array<'inbound' | 'outbound'>
2903
+ entities: string[]
2904
+ connection?: { fields: ConnectorConnectionField[] }
2905
+ settings?: Record<string, unknown>
2906
+ presets?: ConnectorPreset[]
2907
+ functions: {
2908
+ testConnection?: string
2909
+ describeTarget?: string
2910
+ sample?: string
2911
+ shape?: string
2912
+ serialize?: string
2913
+ send?: string
2914
+ fetch?: string
2915
+ }
2916
+ panels?: ConnectorPanel[]
2917
+ aiGuide?: string
2918
+ }
2919
+ ```
2920
+
2921
+ **ConnectorInstallation** (interface)
2922
+ ```typescript
2923
+ interface ConnectorInstallation {
2924
+ collectionId: string
2925
+ appId: string
2926
+ flowId?: string | null
2927
+ connection: Record<string, unknown>
2928
+ settings: Record<string, unknown>
2929
+ }
2930
+ ```
2931
+
2932
+ **ConnectorTestResult** (interface)
2933
+ ```typescript
2934
+ interface ConnectorTestResult {
2935
+ ok: boolean
2936
+ message: string
2937
+ }
2938
+ ```
2939
+
2940
+ **ConnectorTargetField** (interface)
2941
+ ```typescript
2942
+ interface ConnectorTargetField {
2943
+ path: string
2944
+ label?: string
2945
+ type?: 'string' | 'number' | 'boolean' | 'date' | 'object' | 'array'
2946
+ required?: boolean
2947
+ description?: string
2948
+ enum?: string[]
2949
+ }
2950
+ ```
2951
+
2952
+ **ConnectorTargetSchema** (interface)
2953
+ ```typescript
2954
+ interface ConnectorTargetSchema {
2955
+ fields: ConnectorTargetField[]
2956
+ }
2957
+ ```
2958
+
2959
+ **ConnectorRecords** (interface)
2960
+ ```typescript
2961
+ interface ConnectorRecords {
2962
+ records: Array<Record<string, unknown>>
2963
+ nextCursor?: string | null
2964
+ }
2965
+ ```
2966
+
2967
+ **ConnectorShapeInput** (interface)
2968
+ ```typescript
2969
+ interface ConnectorShapeInput {
2970
+ installation: ConnectorInstallation
2971
+ records: Array<Record<string, unknown>>
2972
+ }
2973
+ ```
2974
+
2975
+ **ConnectorShapeResult** (interface)
2976
+ ```typescript
2977
+ interface ConnectorShapeResult {
2978
+ documents: Array<Record<string, unknown> | null>
2979
+ skipped?: Array<{ index: number; reason: string }>
2980
+ }
2981
+ ```
2982
+
2983
+ **ConnectorSerializeInput** (interface)
2984
+ ```typescript
2985
+ interface ConnectorSerializeInput {
2986
+ installation: ConnectorInstallation
2987
+ documents: Array<Record<string, unknown>>
2988
+ eventType?: string
2989
+ }
2990
+ ```
2991
+
2992
+ **ConnectorSerializeResult** (interface)
2993
+ ```typescript
2994
+ interface ConnectorSerializeResult {
2995
+ payloads: Array<unknown | null>
2996
+ skipped?: Array<{ index: number; reason: string }>
2997
+ }
2998
+ ```
2999
+
3000
+ **ConnectorSendInput** (interface)
3001
+ ```typescript
3002
+ interface ConnectorSendInput {
3003
+ installation: ConnectorInstallation
3004
+ payloads: unknown[]
3005
+ }
3006
+ ```
3007
+
3008
+ **ConnectorSendResult** (interface)
3009
+ ```typescript
3010
+ interface ConnectorSendResult {
3011
+ results: Array<{ index: number; ok: boolean; status?: number; error?: string; externalId?: string }>
3012
+ }
3013
+ ```
3014
+
3015
+ **ConnectorFetchInput** (interface)
3016
+ ```typescript
3017
+ interface ConnectorFetchInput {
3018
+ installation: ConnectorInstallation
3019
+ cursor?: string | null
3020
+ limit?: number
3021
+ }
3022
+ ```
3023
+
2860
3024
  **CollectionAppWidget** (interface)
2861
3025
  ```typescript
2862
3026
  interface CollectionAppWidget {
@@ -6899,11 +7063,21 @@ interface FlowConnection {
6899
7063
  }
6900
7064
  ```
6901
7065
 
7066
+ **FlowConnectorRef** (interface)
7067
+ ```typescript
7068
+ interface FlowConnectorRef {
7069
+ appId: string
7070
+ preset?: string
7071
+ settings?: Record<string, unknown>
7072
+ }
7073
+ ```
7074
+
6902
7075
  **IntegrationFlowConfig** (interface)
6903
7076
  ```typescript
6904
7077
  interface IntegrationFlowConfig {
6905
7078
  connection?: FlowConnection
6906
7079
  fieldMappings?: FieldMapping[]
7080
+ connector?: FlowConnectorRef
6907
7081
  [key: string]: any
6908
7082
  }
6909
7083
  ```
@@ -6982,13 +7156,37 @@ interface RunFlowSummary {
6982
7156
  flowId: string
6983
7157
  direction: FlowDirection
6984
7158
  records: number
6985
- sent: number
7159
+ sent?: number
6986
7160
  failed: number
7161
+ created?: number
7162
+ updated?: number
7163
+ skipped?: number
6987
7164
  status: RunStatus
6988
7165
  runId?: string
6989
7166
  }
6990
7167
  ```
6991
7168
 
7169
+ **InstalledConnector** (interface)
7170
+ ```typescript
7171
+ interface InstalledConnector {
7172
+ appId: string
7173
+ name: string
7174
+ channel: string
7175
+ version: string | null
7176
+ connector: import('./appManifest').AppConnectorDeclaration
7177
+ installation: { connection: Record<string, unknown>; settings: Record<string, unknown> }
7178
+ secrets: Record<string, { set: boolean; hint?: string | null }>
7179
+ }
7180
+ ```
7181
+
7182
+ **SaveConnectorInstallationInput** (interface)
7183
+ ```typescript
7184
+ interface SaveConnectorInstallationInput {
7185
+ connection?: Record<string, unknown>
7186
+ settings?: Record<string, unknown>
7187
+ }
7188
+ ```
7189
+
6992
7190
  **CapturedRequest** (interface)
6993
7191
  ```typescript
6994
7192
  interface CapturedRequest {
@@ -7193,6 +7391,8 @@ interface RecordTypesResponse {
7193
7391
 
7194
7392
  **UpdateFlowInput** = `Partial<Omit<CreateFlowInput, 'direction'>> & {`
7195
7393
 
7394
+ **ConnectorConsoleStep** = `'testConnection' | 'describeTarget' | 'sample' | 'shape' | 'serialize'`
7395
+
7196
7396
  **RunTrigger** = `'manual' | 'event' | 'schedule' | 'test'`
7197
7397
 
7198
7398
  **FlowRunStatus** = `'running' | 'success' | 'partial' | 'failed' | 'skipped'`
@@ -11507,6 +11707,20 @@ Enable enhanced logging. POST /integrations/logging/:connectionId (omit ttlMinut
11507
11707
  **cancelLogging**(collectionId: string, connectionId: string) → `Promise<`
11508
11708
  Cancel enhanced logging now. DELETE /integrations/logging/:connectionId
11509
11709
 
11710
+ **listConnectors**(collectionId: string) → `Promise<`
11711
+ The collection's installed connector apps. GET /integrations/connectors
11712
+
11713
+ **saveConnectorInstallation**(collectionId: string,
11714
+ appId: string,
11715
+ input: SaveConnectorInstallationInput) → `Promise<`
11716
+ Save a connector's non-secret Connect-form values and/or settings. PUT /integrations/connectors/:appId/installation
11717
+
11718
+ **runConnectorStep**(collectionId: string,
11719
+ appId: string,
11720
+ step: ConnectorConsoleStep,
11721
+ input: Record<string, unknown> & { flowId?: string } = {}) → `Promise<T>`
11722
+ Run a connector step from the console: `testConnection` → ConnectorTestResult, `describeTarget` → ConnectorTargetSchema, `sample` → ConnectorRecords, and dry runs of `shape` ({ records }) → ConnectorShapeResult and `serialize` ({ documents }) → ConnectorSerializeResult. The server adds the installation; pass `flowId` to layer that flow's settings. POST /integrations/connectors/:appId/steps/:step
11723
+
11510
11724
  ### interactions
11511
11725
 
11512
11726
  **query**(collectionId: string,
@@ -436,6 +436,13 @@ this is just the manifest shape.
436
436
  | `definitions[].authority` | string | `caller` \| `collection` — whose authority it runs as |
437
437
  | `definitions[].capabilities` | string[] | Least-privilege grants (`sl:<res>:<read\|write>`, `network[:<host>]`, `secrets:<ref>`) |
438
438
 
439
+ #### `connector`
440
+
441
+ Marks the app as an integration **connector** for one external provider: the integrations console
442
+ lists it and draws its connect form and settings, and the integration engine calls its server
443
+ functions (`testConnection`, `describeTarget`, `sample`, `fetch`, `shape`, `serialize`, `send`). It adapts the provider's format; core does each customer's mapping. The full
444
+ contract is in the **[Connectors guide](connectors.md)**.
445
+
439
446
  ---
440
447
 
441
448
  ## `app.admin.json`