@objectstack/connector-openapi 7.4.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.
@@ -0,0 +1,22 @@
1
+
2
+ > @objectstack/connector-openapi@7.4.0 build /home/runner/work/framework/framework/packages/connectors/connector-openapi
3
+ > tsup --config ../../../tsup.config.ts
4
+
5
+ CLI Building entry: src/index.ts
6
+ CLI Using tsconfig: tsconfig.json
7
+ CLI tsup v8.5.1
8
+ CLI Using tsup config: /home/runner/work/framework/framework/tsup.config.ts
9
+ CLI Target: es2020
10
+ CLI Cleaning output folder
11
+ ESM Build start
12
+ CJS Build start
13
+ CJS dist/index.js 8.82 KB
14
+ CJS dist/index.js.map 25.11 KB
15
+ CJS ⚡️ Build success in 94ms
16
+ ESM dist/index.mjs 7.73 KB
17
+ ESM dist/index.mjs.map 23.76 KB
18
+ ESM ⚡️ Build success in 108ms
19
+ DTS Build start
20
+ DTS ⚡️ Build success in 8511ms
21
+ DTS dist/index.d.mts 6.11 KB
22
+ DTS dist/index.d.ts 6.11 KB
package/CHANGELOG.md ADDED
@@ -0,0 +1,23 @@
1
+ # @objectstack/connector-openapi
2
+
3
+ ## 7.4.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 71d8ae1: Add `@objectstack/connector-openapi` — generate an ObjectStack connector from a declarative OpenAPI 3.x document (ADR-0023). One operation becomes one connector action; a single generic handler drives a self-contained static-auth HTTP transport (mirroring `@objectstack/connector-rest`). The generated `type: 'api'` connector registers via `engine.registerConnector(def, handlers)` with no new engine surface, and supports an `include` allowlist for trimming large specs.
8
+
9
+ ### Patch Changes
10
+
11
+ - Updated dependencies [23c7107]
12
+ - Updated dependencies [c72daad]
13
+ - Updated dependencies [f115182]
14
+ - Updated dependencies [2faf9f2]
15
+ - Updated dependencies [2faf9f2]
16
+ - Updated dependencies [2faf9f2]
17
+ - Updated dependencies [58b450b]
18
+ - Updated dependencies [82eb6cf]
19
+ - Updated dependencies [13d8653]
20
+ - Updated dependencies [ff3d006]
21
+ - Updated dependencies [5e831de]
22
+ - @objectstack/spec@7.4.0
23
+ - @objectstack/core@7.4.0
package/LICENSE ADDED
@@ -0,0 +1,93 @@
1
+ License text copyright (c) 2020 MariaDB Corporation Ab, All Rights Reserved.
2
+ "Business Source License" is a trademark of MariaDB Corporation Ab.
3
+
4
+ Parameters
5
+
6
+ Licensor: ObjectStack AI LLC
7
+ Licensed Work: ObjectStack Runtime: the BSL-licensed packages
8
+ of the ObjectStack monorepo as listed in LICENSING.md.
9
+ Copyright (c) 2026 ObjectStack AI LLC.
10
+ Additional Use Grant: You may make production use of the Licensed Work, provided
11
+ Your use does not include offering the Licensed Work to third
12
+ parties on a hosted or embedded basis in order to compete with
13
+ ObjectStack AI LLC's paid version(s) of the Licensed Work. For purposes
14
+ of this license:
15
+
16
+ A "competitive offering" is a Product that is offered to third
17
+ parties on a paid basis, including through paid support
18
+ arrangements, that significantly overlaps with the capabilities
19
+ of ObjectStack AI LLC's paid version(s) of the Licensed Work. If Your
20
+ Product is not a competitive offering when You first make it
21
+ generally available, it will not become a competitive offering
22
+ later due to ObjectStack AI LLC releasing a new version of the Licensed
23
+ Work with additional capabilities. In addition, Products that
24
+ are not provided on a paid basis are not competitive.
25
+
26
+ "Product" means software that is offered to end users to manage
27
+ in their own environments or offered as a service on a hosted
28
+ basis.
29
+
30
+ "Embedded" means including the source code or executable code
31
+ from the Licensed Work in a competitive offering. "Embedded"
32
+ also means packaging the competitive offering in such a way
33
+ that the Licensed Work must be accessed or downloaded for the
34
+ competitive offering to operate.
35
+
36
+ Hosting or using the Licensed Work(s) for internal purposes
37
+ within an organization is not considered a competitive
38
+ offering. ObjectStack AI LLC considers your organization to include all
39
+ of your affiliates under common control.
40
+
41
+ For binding interpretive guidance on using ObjectStack AI LLC products
42
+ under the Business Source License, please visit our FAQ.
43
+ (see LICENSING.md in this repository)
44
+ Change Date: Four years from the date the Licensed Work is published.
45
+ Change License: Apache License, Version 2.0
46
+
47
+ For information about alternative licensing arrangements for the Licensed Work,
48
+ please contact licensing@objectstack.dev.
49
+
50
+ Notice
51
+
52
+ Business Source License 1.1
53
+
54
+ Terms
55
+
56
+ The Licensor hereby grants you the right to copy, modify, create derivative
57
+ works, redistribute, and make non-production use of the Licensed Work. The
58
+ Licensor may make an Additional Use Grant, above, permitting limited production use.
59
+
60
+ Effective on the Change Date, or the fourth anniversary of the first publicly
61
+ available distribution of a specific version of the Licensed Work under this
62
+ License, whichever comes first, the Licensor hereby grants you rights under
63
+ the terms of the Change License, and the rights granted in the paragraph
64
+ above terminate.
65
+
66
+ If your use of the Licensed Work does not comply with the requirements
67
+ currently in effect as described in this License, you must purchase a
68
+ commercial license from the Licensor, its affiliated entities, or authorized
69
+ resellers, or you must refrain from using the Licensed Work.
70
+
71
+ All copies of the original and modified Licensed Work, and derivative works
72
+ of the Licensed Work, are subject to this License. This License applies
73
+ separately for each version of the Licensed Work and the Change Date may vary
74
+ for each version of the Licensed Work released by Licensor.
75
+
76
+ You must conspicuously display this License on each original or modified copy
77
+ of the Licensed Work. If you receive the Licensed Work in original or
78
+ modified form from a third party, the terms and conditions set forth in this
79
+ License apply to your use of that work.
80
+
81
+ Any use of the Licensed Work in violation of this License will automatically
82
+ terminate your rights under this License for the current and all other
83
+ versions of the Licensed Work.
84
+
85
+ This License does not grant you any right in any trademark or logo of
86
+ Licensor or its affiliates (provided that you may use a trademark or logo of
87
+ Licensor as expressly required by this License).
88
+
89
+ TO THE EXTENT PERMITTED BY APPLICABLE LAW, THE LICENSED WORK IS PROVIDED ON
90
+ AN "AS IS" BASIS. LICENSOR HEREBY DISCLAIMS ALL WARRANTIES AND CONDITIONS,
91
+ EXPRESS OR IMPLIED, INCLUDING (WITHOUT LIMITATION) WARRANTIES OF
92
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT, AND
93
+ TITLE.
@@ -0,0 +1,147 @@
1
+ import { Connector } from '@objectstack/spec/integration';
2
+
3
+ /**
4
+ * OpenAPI connector generator — turns a declarative OpenAPI 3.x document into a
5
+ * {@link Connector} definition + handler map (ADR-0023).
6
+ *
7
+ * Each OpenAPI operation maps to one connector action; a single generic handler
8
+ * (closing over the operation's method + path template) drives one shared HTTP
9
+ * request implementation. That transport mirrors `@objectstack/connector-rest`
10
+ * (build URL from base+path+query, apply static auth, JSON-encode the body,
11
+ * normalise the response to `{ status, ok, body }`) — kept inline so this package
12
+ * stays self-contained, depending only on `@objectstack/core` + `@objectstack/spec`
13
+ * like its sibling connectors. The output is an ordinary `type: 'api'` connector,
14
+ * registered via `engine.registerConnector(def, handlers)` exactly like a
15
+ * hand-written one — the registry, the `connector_action` node, the discovery
16
+ * route, and the Studio palette never know it came from OpenAPI.
17
+ *
18
+ * Open-source scope: **static** auth only (`none` / `api-key` / `basic` /
19
+ * `bearer`), with credentials supplied by the caller. Managed OAuth2, credential
20
+ * vaulting, and per-tenant lifecycle are the enterprise tier (ADR-0015 / 0022).
21
+ */
22
+ /** Static auth understood by the generated connector (the open-source subset). */
23
+ type RestAuth = Extract<Connector['authentication'], {
24
+ type: 'none' | 'api-key' | 'basic' | 'bearer';
25
+ }>;
26
+ /** Handler signature accepted by the connector registry (ADR-0018 §Addendum). */
27
+ type ConnectorHandler = (input: Record<string, unknown>, ctx: unknown) => Promise<Record<string, unknown>>;
28
+ /** A connector definition paired with its action handlers, ready for registerConnector(). */
29
+ interface OpenApiConnectorBundle {
30
+ def: Connector;
31
+ handlers: Record<string, ConnectorHandler>;
32
+ }
33
+ /** A free-form JSON Schema fragment (matches ConnectorAction input/outputSchema). */
34
+ type JsonSchema = Record<string, unknown>;
35
+ /** Minimal subset of an OpenAPI 3.x document consumed by the generator.
36
+ * The caller is responsible for loading and de-referencing ($ref) the doc. */
37
+ interface OpenApiDocument {
38
+ openapi?: string;
39
+ info?: {
40
+ title?: string;
41
+ description?: string;
42
+ version?: string;
43
+ };
44
+ servers?: {
45
+ url: string;
46
+ }[];
47
+ paths?: Record<string, OpenApiPathItem>;
48
+ components?: {
49
+ securitySchemes?: Record<string, OpenApiSecurityScheme>;
50
+ };
51
+ }
52
+ interface OpenApiPathItem {
53
+ [method: string]: OpenApiOperation | unknown;
54
+ }
55
+ interface OpenApiOperation {
56
+ operationId?: string;
57
+ summary?: string;
58
+ description?: string;
59
+ tags?: string[];
60
+ parameters?: OpenApiParameter[];
61
+ requestBody?: OpenApiRequestBody;
62
+ responses?: Record<string, OpenApiResponse>;
63
+ }
64
+ interface OpenApiParameter {
65
+ name: string;
66
+ in: 'path' | 'query' | 'header' | 'cookie';
67
+ required?: boolean;
68
+ description?: string;
69
+ schema?: JsonSchema;
70
+ }
71
+ interface OpenApiRequestBody {
72
+ required?: boolean;
73
+ description?: string;
74
+ content?: Record<string, {
75
+ schema?: JsonSchema;
76
+ }>;
77
+ }
78
+ interface OpenApiResponse {
79
+ description?: string;
80
+ content?: Record<string, {
81
+ schema?: JsonSchema;
82
+ }>;
83
+ }
84
+ interface OpenApiSecurityScheme {
85
+ type: 'apiKey' | 'http' | 'oauth2' | 'openIdConnect';
86
+ name?: string;
87
+ in?: 'header' | 'query' | 'cookie';
88
+ scheme?: string;
89
+ }
90
+ /** Flattened view of a single operation, passed to the `include` predicate. */
91
+ interface OperationInfo {
92
+ operationId?: string;
93
+ method: string;
94
+ path: string;
95
+ tags?: string[];
96
+ summary?: string;
97
+ description?: string;
98
+ }
99
+ /** Configuration for {@link createOpenApiConnector}. */
100
+ interface OpenApiConnectorConfig {
101
+ /** Connector machine name (snake_case). Defaults to a slug of info.title. */
102
+ name?: string;
103
+ /** Human-friendly label. Defaults to info.title (then name). */
104
+ label?: string;
105
+ /** Description. Defaults to info.description. */
106
+ description?: string;
107
+ /** Icon identifier for the Studio palette. Defaults to `globe`. */
108
+ icon?: string;
109
+ /** The parsed OpenAPI 3.x document (caller loads/derefs it). */
110
+ document: OpenApiDocument;
111
+ /** Override the base URL (else servers[0].url). */
112
+ baseUrl?: string;
113
+ /** Static auth with credentials. Defaults to `{ type: 'none' }`. */
114
+ auth?: RestAuth;
115
+ /** Headers merged into every request (request-level headers win). */
116
+ defaultHeaders?: Record<string, string>;
117
+ /** Only include operations for which this predicate returns true (allowlist). */
118
+ include?: (op: OperationInfo) => boolean;
119
+ /** Injected fetch implementation (defaults to global `fetch`). */
120
+ fetchImpl?: typeof fetch;
121
+ }
122
+ /**
123
+ * Build an OpenAPI connector definition and its handler map.
124
+ *
125
+ * @returns the `Connector` definition (`def`) and a `handlers` record keyed by
126
+ * action key, suitable for `engine.registerConnector(def, handlers)`.
127
+ */
128
+ declare function createOpenApiConnector(config: OpenApiConnectorConfig): OpenApiConnectorBundle;
129
+
130
+ /**
131
+ * Minimal surface of the automation engine this helper depends on — the
132
+ * connector registry from ADR-0018 §Addendum. Kept structural so callers need
133
+ * no runtime dependency on `@objectstack/service-automation` (mirrors
134
+ * connector-rest / connector-mcp).
135
+ */
136
+ interface ConnectorRegistrySurface {
137
+ registerConnector(def: Connector, handlers: Record<string, (input: Record<string, unknown>, ctx: unknown) => Promise<Record<string, unknown>>>): void;
138
+ unregisterConnector(name: string): void;
139
+ }
140
+ /**
141
+ * Generate an OpenAPI-backed connector and register it on the engine's connector
142
+ * registry so the baseline `connector_action` node can dispatch to the generated
143
+ * actions (ADR-0023). Returns the registered connector name.
144
+ */
145
+ declare function registerOpenApiConnector(registry: ConnectorRegistrySurface, config: OpenApiConnectorConfig): string;
146
+
147
+ export { type ConnectorRegistrySurface, type JsonSchema, type OpenApiConnectorBundle, type OpenApiConnectorConfig, type OpenApiDocument, type OpenApiOperation, type OpenApiParameter, type OpenApiPathItem, type OpenApiRequestBody, type OpenApiResponse, type OpenApiSecurityScheme, type OperationInfo, type RestAuth, createOpenApiConnector, registerOpenApiConnector };
@@ -0,0 +1,147 @@
1
+ import { Connector } from '@objectstack/spec/integration';
2
+
3
+ /**
4
+ * OpenAPI connector generator — turns a declarative OpenAPI 3.x document into a
5
+ * {@link Connector} definition + handler map (ADR-0023).
6
+ *
7
+ * Each OpenAPI operation maps to one connector action; a single generic handler
8
+ * (closing over the operation's method + path template) drives one shared HTTP
9
+ * request implementation. That transport mirrors `@objectstack/connector-rest`
10
+ * (build URL from base+path+query, apply static auth, JSON-encode the body,
11
+ * normalise the response to `{ status, ok, body }`) — kept inline so this package
12
+ * stays self-contained, depending only on `@objectstack/core` + `@objectstack/spec`
13
+ * like its sibling connectors. The output is an ordinary `type: 'api'` connector,
14
+ * registered via `engine.registerConnector(def, handlers)` exactly like a
15
+ * hand-written one — the registry, the `connector_action` node, the discovery
16
+ * route, and the Studio palette never know it came from OpenAPI.
17
+ *
18
+ * Open-source scope: **static** auth only (`none` / `api-key` / `basic` /
19
+ * `bearer`), with credentials supplied by the caller. Managed OAuth2, credential
20
+ * vaulting, and per-tenant lifecycle are the enterprise tier (ADR-0015 / 0022).
21
+ */
22
+ /** Static auth understood by the generated connector (the open-source subset). */
23
+ type RestAuth = Extract<Connector['authentication'], {
24
+ type: 'none' | 'api-key' | 'basic' | 'bearer';
25
+ }>;
26
+ /** Handler signature accepted by the connector registry (ADR-0018 §Addendum). */
27
+ type ConnectorHandler = (input: Record<string, unknown>, ctx: unknown) => Promise<Record<string, unknown>>;
28
+ /** A connector definition paired with its action handlers, ready for registerConnector(). */
29
+ interface OpenApiConnectorBundle {
30
+ def: Connector;
31
+ handlers: Record<string, ConnectorHandler>;
32
+ }
33
+ /** A free-form JSON Schema fragment (matches ConnectorAction input/outputSchema). */
34
+ type JsonSchema = Record<string, unknown>;
35
+ /** Minimal subset of an OpenAPI 3.x document consumed by the generator.
36
+ * The caller is responsible for loading and de-referencing ($ref) the doc. */
37
+ interface OpenApiDocument {
38
+ openapi?: string;
39
+ info?: {
40
+ title?: string;
41
+ description?: string;
42
+ version?: string;
43
+ };
44
+ servers?: {
45
+ url: string;
46
+ }[];
47
+ paths?: Record<string, OpenApiPathItem>;
48
+ components?: {
49
+ securitySchemes?: Record<string, OpenApiSecurityScheme>;
50
+ };
51
+ }
52
+ interface OpenApiPathItem {
53
+ [method: string]: OpenApiOperation | unknown;
54
+ }
55
+ interface OpenApiOperation {
56
+ operationId?: string;
57
+ summary?: string;
58
+ description?: string;
59
+ tags?: string[];
60
+ parameters?: OpenApiParameter[];
61
+ requestBody?: OpenApiRequestBody;
62
+ responses?: Record<string, OpenApiResponse>;
63
+ }
64
+ interface OpenApiParameter {
65
+ name: string;
66
+ in: 'path' | 'query' | 'header' | 'cookie';
67
+ required?: boolean;
68
+ description?: string;
69
+ schema?: JsonSchema;
70
+ }
71
+ interface OpenApiRequestBody {
72
+ required?: boolean;
73
+ description?: string;
74
+ content?: Record<string, {
75
+ schema?: JsonSchema;
76
+ }>;
77
+ }
78
+ interface OpenApiResponse {
79
+ description?: string;
80
+ content?: Record<string, {
81
+ schema?: JsonSchema;
82
+ }>;
83
+ }
84
+ interface OpenApiSecurityScheme {
85
+ type: 'apiKey' | 'http' | 'oauth2' | 'openIdConnect';
86
+ name?: string;
87
+ in?: 'header' | 'query' | 'cookie';
88
+ scheme?: string;
89
+ }
90
+ /** Flattened view of a single operation, passed to the `include` predicate. */
91
+ interface OperationInfo {
92
+ operationId?: string;
93
+ method: string;
94
+ path: string;
95
+ tags?: string[];
96
+ summary?: string;
97
+ description?: string;
98
+ }
99
+ /** Configuration for {@link createOpenApiConnector}. */
100
+ interface OpenApiConnectorConfig {
101
+ /** Connector machine name (snake_case). Defaults to a slug of info.title. */
102
+ name?: string;
103
+ /** Human-friendly label. Defaults to info.title (then name). */
104
+ label?: string;
105
+ /** Description. Defaults to info.description. */
106
+ description?: string;
107
+ /** Icon identifier for the Studio palette. Defaults to `globe`. */
108
+ icon?: string;
109
+ /** The parsed OpenAPI 3.x document (caller loads/derefs it). */
110
+ document: OpenApiDocument;
111
+ /** Override the base URL (else servers[0].url). */
112
+ baseUrl?: string;
113
+ /** Static auth with credentials. Defaults to `{ type: 'none' }`. */
114
+ auth?: RestAuth;
115
+ /** Headers merged into every request (request-level headers win). */
116
+ defaultHeaders?: Record<string, string>;
117
+ /** Only include operations for which this predicate returns true (allowlist). */
118
+ include?: (op: OperationInfo) => boolean;
119
+ /** Injected fetch implementation (defaults to global `fetch`). */
120
+ fetchImpl?: typeof fetch;
121
+ }
122
+ /**
123
+ * Build an OpenAPI connector definition and its handler map.
124
+ *
125
+ * @returns the `Connector` definition (`def`) and a `handlers` record keyed by
126
+ * action key, suitable for `engine.registerConnector(def, handlers)`.
127
+ */
128
+ declare function createOpenApiConnector(config: OpenApiConnectorConfig): OpenApiConnectorBundle;
129
+
130
+ /**
131
+ * Minimal surface of the automation engine this helper depends on — the
132
+ * connector registry from ADR-0018 §Addendum. Kept structural so callers need
133
+ * no runtime dependency on `@objectstack/service-automation` (mirrors
134
+ * connector-rest / connector-mcp).
135
+ */
136
+ interface ConnectorRegistrySurface {
137
+ registerConnector(def: Connector, handlers: Record<string, (input: Record<string, unknown>, ctx: unknown) => Promise<Record<string, unknown>>>): void;
138
+ unregisterConnector(name: string): void;
139
+ }
140
+ /**
141
+ * Generate an OpenAPI-backed connector and register it on the engine's connector
142
+ * registry so the baseline `connector_action` node can dispatch to the generated
143
+ * actions (ADR-0023). Returns the registered connector name.
144
+ */
145
+ declare function registerOpenApiConnector(registry: ConnectorRegistrySurface, config: OpenApiConnectorConfig): string;
146
+
147
+ export { type ConnectorRegistrySurface, type JsonSchema, type OpenApiConnectorBundle, type OpenApiConnectorConfig, type OpenApiDocument, type OpenApiOperation, type OpenApiParameter, type OpenApiPathItem, type OpenApiRequestBody, type OpenApiResponse, type OpenApiSecurityScheme, type OperationInfo, type RestAuth, createOpenApiConnector, registerOpenApiConnector };
package/dist/index.js ADDED
@@ -0,0 +1,252 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/index.ts
21
+ var index_exports = {};
22
+ __export(index_exports, {
23
+ createOpenApiConnector: () => createOpenApiConnector,
24
+ registerOpenApiConnector: () => registerOpenApiConnector
25
+ });
26
+ module.exports = __toCommonJS(index_exports);
27
+
28
+ // src/openapi-connector.ts
29
+ var HTTP_METHODS = ["get", "put", "post", "delete", "patch", "options", "head", "trace"];
30
+ function createOpenApiConnector(config) {
31
+ const { document, include } = config;
32
+ const auth = config.auth ?? { type: "none" };
33
+ const doFetch = config.fetchImpl ?? fetch;
34
+ const name = config.name ?? slug(document.info?.title ?? "openapi_connector");
35
+ const label = config.label ?? document.info?.title ?? titleize(name);
36
+ const description = config.description ?? document.info?.description;
37
+ const baseUrl = config.baseUrl ?? document.servers?.[0]?.url;
38
+ if (!baseUrl) {
39
+ throw new Error("createOpenApiConnector: no base URL \u2014 provide config.baseUrl or document.servers[0].url");
40
+ }
41
+ async function request(input) {
42
+ const method = input.method.toUpperCase();
43
+ const headers = { ...config.defaultHeaders, ...input.headers };
44
+ const query = { ...input.query };
45
+ applyAuth(auth, headers, query);
46
+ const url = buildUrl(baseUrl, input.path, query);
47
+ const hasBody = input.body !== void 0 && method !== "GET" && method !== "HEAD";
48
+ if (hasBody && headers["Content-Type"] === void 0 && headers["content-type"] === void 0) {
49
+ headers["Content-Type"] = "application/json";
50
+ }
51
+ const response = await doFetch(url, {
52
+ method,
53
+ headers,
54
+ body: hasBody ? JSON.stringify(input.body) : void 0
55
+ });
56
+ const contentType = response.headers.get("content-type") ?? "";
57
+ const parsed = contentType.includes("application/json") ? await response.json() : await response.text();
58
+ return { status: response.status, ok: response.ok, body: parsed };
59
+ }
60
+ const actions = [];
61
+ const handlers = {};
62
+ const seenKeys = /* @__PURE__ */ new Set();
63
+ for (const op of collectOperations(document)) {
64
+ if (include && !include(toInfo(op))) continue;
65
+ const key = uniqueKey(op.operationId ?? slug(`${op.method}_${op.path}`), seenKeys);
66
+ actions.push({
67
+ key,
68
+ label: op.summary ?? titleize(key),
69
+ description: op.description,
70
+ inputSchema: buildInputSchema(op),
71
+ outputSchema: buildOutputSchema(op)
72
+ });
73
+ handlers[key] = async (input) => {
74
+ const req = input;
75
+ return request({
76
+ method: op.method,
77
+ path: interpolatePath(op.path, asRecord(req.path)),
78
+ query: stringifyValues(asRecord(req.query)),
79
+ headers: stringifyValues(asRecord(req.header)),
80
+ body: req.body
81
+ });
82
+ };
83
+ }
84
+ const def = {
85
+ name,
86
+ label,
87
+ type: "api",
88
+ description,
89
+ icon: config.icon ?? "globe",
90
+ authentication: auth,
91
+ // Defaulted by ConnectorSchema; set explicitly so the literal satisfies
92
+ // the (post-parse) Connector output type (mirrors connector-rest/mcp).
93
+ status: "active",
94
+ enabled: true,
95
+ connectionTimeoutMs: 3e4,
96
+ requestTimeoutMs: 3e4,
97
+ actions
98
+ };
99
+ return { def, handlers };
100
+ }
101
+ function collectOperations(doc) {
102
+ const ops = [];
103
+ for (const [path, item] of Object.entries(doc.paths ?? {})) {
104
+ if (!item || typeof item !== "object") continue;
105
+ const record = item;
106
+ for (const method of HTTP_METHODS) {
107
+ const operation = record[method];
108
+ if (!operation || typeof operation !== "object") continue;
109
+ ops.push({ ...operation, method, path });
110
+ }
111
+ }
112
+ return ops;
113
+ }
114
+ function toInfo(op) {
115
+ return {
116
+ operationId: op.operationId,
117
+ method: op.method,
118
+ path: op.path,
119
+ tags: op.tags,
120
+ summary: op.summary,
121
+ description: op.description
122
+ };
123
+ }
124
+ function buildInputSchema(op) {
125
+ const sections = {
126
+ path: { props: {}, required: [] },
127
+ query: { props: {}, required: [] },
128
+ header: { props: {}, required: [] }
129
+ };
130
+ for (const p of op.parameters ?? []) {
131
+ if (!p || typeof p !== "object" || "$ref" in p) continue;
132
+ if (p.in !== "path" && p.in !== "query" && p.in !== "header") continue;
133
+ const sec = sections[p.in];
134
+ sec.props[p.name] = p.schema ?? (p.description ? { type: "string", description: p.description } : { type: "string" });
135
+ if (p.required) sec.required.push(p.name);
136
+ }
137
+ const properties = {};
138
+ const required = [];
139
+ for (const where of ["path", "query", "header"]) {
140
+ const sec = sections[where];
141
+ if (Object.keys(sec.props).length === 0) continue;
142
+ const schema2 = { type: "object", properties: sec.props };
143
+ if (sec.required.length) schema2.required = sec.required;
144
+ properties[where] = schema2;
145
+ if (where === "path" || sec.required.length) required.push(where);
146
+ }
147
+ const bodySchema = extractRequestBodySchema(op.requestBody);
148
+ if (bodySchema) {
149
+ properties.body = bodySchema;
150
+ if (op.requestBody && !("$ref" in op.requestBody) && op.requestBody.required) required.push("body");
151
+ }
152
+ if (Object.keys(properties).length === 0) return void 0;
153
+ const schema = { type: "object", properties };
154
+ if (required.length) schema.required = required;
155
+ return schema;
156
+ }
157
+ function buildOutputSchema(op) {
158
+ const responses = op.responses;
159
+ if (!responses) return void 0;
160
+ let code;
161
+ if (responses["200"]) code = "200";
162
+ else code = Object.keys(responses).find((c) => /^2\d\d$/.test(c));
163
+ if (!code && responses["default"]) code = "default";
164
+ if (!code) return void 0;
165
+ const resp = responses[code];
166
+ if (!resp || typeof resp !== "object" || "$ref" in resp) return void 0;
167
+ return pickJsonSchema(resp.content);
168
+ }
169
+ function extractRequestBodySchema(rb) {
170
+ if (!rb || typeof rb !== "object" || "$ref" in rb) return void 0;
171
+ return pickJsonSchema(rb.content);
172
+ }
173
+ function pickJsonSchema(content) {
174
+ if (!content) return void 0;
175
+ const chosen = content["application/json"] ?? Object.values(content)[0];
176
+ return chosen?.schema;
177
+ }
178
+ function buildUrl(baseUrl, path, query) {
179
+ const base = baseUrl.replace(/\/+$/, "");
180
+ const suffix = path ? path.startsWith("/") ? path : `/${path}` : "";
181
+ const url = new URL(base + suffix);
182
+ for (const [key, value] of Object.entries(query)) {
183
+ if (value !== void 0 && value !== null) url.searchParams.set(key, String(value));
184
+ }
185
+ return url.toString();
186
+ }
187
+ function applyAuth(auth, headers, query) {
188
+ switch (auth.type) {
189
+ case "none":
190
+ return;
191
+ case "bearer":
192
+ headers["Authorization"] = `Bearer ${auth.token}`;
193
+ return;
194
+ case "basic": {
195
+ const encoded = Buffer.from(`${auth.username}:${auth.password}`).toString("base64");
196
+ headers["Authorization"] = `Basic ${encoded}`;
197
+ return;
198
+ }
199
+ case "api-key":
200
+ if (auth.paramName) query[auth.paramName] = auth.key;
201
+ else headers[auth.headerName ?? "X-API-Key"] = auth.key;
202
+ return;
203
+ }
204
+ }
205
+ function interpolatePath(template, pathParams) {
206
+ return template.replace(/\{([^}]+)\}/g, (_match, key) => {
207
+ const value = pathParams[key];
208
+ return value === void 0 || value === null ? `{${key}}` : encodeURIComponent(String(value));
209
+ });
210
+ }
211
+ function stringifyValues(rec) {
212
+ const out = {};
213
+ for (const [k, v] of Object.entries(rec)) {
214
+ if (v === void 0 || v === null) continue;
215
+ out[k] = String(v);
216
+ }
217
+ return out;
218
+ }
219
+ function asRecord(v) {
220
+ return v && typeof v === "object" && !Array.isArray(v) ? v : {};
221
+ }
222
+ function uniqueKey(base, seen) {
223
+ let candidate = base;
224
+ if (seen.has(candidate)) {
225
+ let i = 2;
226
+ while (seen.has(`${base}_${i}`)) i++;
227
+ candidate = `${base}_${i}`;
228
+ }
229
+ seen.add(candidate);
230
+ return candidate;
231
+ }
232
+ function slug(s) {
233
+ const out = s.normalize("NFKD").replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "").toLowerCase();
234
+ if (!out) return "connector";
235
+ return /^[a-z_]/.test(out) ? out : `op_${out}`;
236
+ }
237
+ function titleize(name) {
238
+ return name.split("_").filter(Boolean).map((w) => w.charAt(0).toUpperCase() + w.slice(1)).join(" ");
239
+ }
240
+
241
+ // src/connector-openapi-plugin.ts
242
+ function registerOpenApiConnector(registry, config) {
243
+ const { def, handlers } = createOpenApiConnector(config);
244
+ registry.registerConnector(def, handlers);
245
+ return def.name;
246
+ }
247
+ // Annotate the CommonJS export names for ESM import in node:
248
+ 0 && (module.exports = {
249
+ createOpenApiConnector,
250
+ registerOpenApiConnector
251
+ });
252
+ //# sourceMappingURL=index.js.map