@veltrixsecops/app-sdk 2.2.0 → 2.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,175 @@
1
+ // src/client/inventory.ts
2
+ var INVENTORY_API = "/api/components";
3
+ async function inventoryError(res) {
4
+ const text = await res.text().catch(() => "");
5
+ if (text) {
6
+ try {
7
+ const body = JSON.parse(text);
8
+ const message = body?.error ?? body?.message;
9
+ if (message) return new Error(message);
10
+ } catch {
11
+ }
12
+ return new Error(text);
13
+ }
14
+ return new Error(`HTTP ${res.status}`);
15
+ }
16
+ function toInventoryItem(raw) {
17
+ return {
18
+ id: String(raw.id),
19
+ hostname: raw.hostname ?? "",
20
+ port: raw.port ?? void 0,
21
+ type: Array.isArray(raw.type) ? raw.type : void 0,
22
+ domains: Array.isArray(raw.domains) ? raw.domains : [],
23
+ ipRanges: Array.isArray(raw.ipRanges) ? raw.ipRanges : [],
24
+ tags: Array.isArray(raw.tags) ? raw.tags.map((tag) => ({ id: String(tag.id), name: String(tag.name) })) : [],
25
+ connectivityProviderId: raw.connectivityProviderId ?? null
26
+ };
27
+ }
28
+ async function resolveTool(name) {
29
+ const res = await authFetch("/api/tools");
30
+ if (!res.ok) throw await inventoryError(res);
31
+ const body = await res.json();
32
+ const tools = Array.isArray(body) ? body : Array.isArray(body?.data) ? body.data : [];
33
+ return tools.find((tool) => tool.name === name) ?? null;
34
+ }
35
+ async function listInventory() {
36
+ const res = await authFetch(INVENTORY_API);
37
+ if (!res.ok) throw await inventoryError(res);
38
+ const data = await res.json();
39
+ return Array.isArray(data) ? data.map(toInventoryItem) : [];
40
+ }
41
+ async function addInventoryItem(input) {
42
+ const res = await authFetch(INVENTORY_API, {
43
+ method: "POST",
44
+ headers: { "Content-Type": "application/json" },
45
+ body: JSON.stringify(input)
46
+ });
47
+ if (!res.ok) throw await inventoryError(res);
48
+ return toInventoryItem(await res.json());
49
+ }
50
+ async function updateInventoryItem(id, input) {
51
+ const res = await authFetch(`${INVENTORY_API}/${encodeURIComponent(id)}`, {
52
+ method: "PUT",
53
+ headers: { "Content-Type": "application/json" },
54
+ body: JSON.stringify(input)
55
+ });
56
+ if (!res.ok) throw await inventoryError(res);
57
+ return toInventoryItem(await res.json());
58
+ }
59
+ async function removeInventoryItem(id) {
60
+ const res = await authFetch(`${INVENTORY_API}/${encodeURIComponent(id)}`, {
61
+ method: "DELETE"
62
+ });
63
+ if (!res.ok && res.status !== 204) throw await inventoryError(res);
64
+ }
65
+
66
+ // src/client/access-servers.ts
67
+ var ACCESS_SERVERS_API = "/api/access-servers";
68
+ var CONNECTIVITY_PROVIDERS_API = "/api/connectivity-providers";
69
+ async function accessServerError(res) {
70
+ const text = await res.text().catch(() => "");
71
+ if (text) {
72
+ try {
73
+ const body = JSON.parse(text);
74
+ const message = body?.error ?? body?.message;
75
+ if (message) return new Error(message);
76
+ } catch {
77
+ }
78
+ return new Error(text);
79
+ }
80
+ return new Error(`HTTP ${res.status}`);
81
+ }
82
+ function toAccessServer(raw) {
83
+ return {
84
+ id: String(raw.id),
85
+ name: raw.name ?? "",
86
+ endpoint: raw.endpoint ?? "",
87
+ type: raw.type ?? void 0,
88
+ region: raw.region ?? null,
89
+ status: raw.status ?? void 0,
90
+ description: raw.description ?? null,
91
+ connectivityProviderId: raw.connectivityProviderId ?? null,
92
+ connectivityProvider: raw.connectivityProvider ? { id: String(raw.connectivityProvider.id), name: String(raw.connectivityProvider.name) } : null
93
+ };
94
+ }
95
+ async function listAccessServers() {
96
+ const res = await authFetch(ACCESS_SERVERS_API);
97
+ if (!res.ok) throw await accessServerError(res);
98
+ const data = await res.json();
99
+ return Array.isArray(data) ? data.map(toAccessServer) : [];
100
+ }
101
+ async function addAccessServer(input) {
102
+ const res = await authFetch(ACCESS_SERVERS_API, {
103
+ method: "POST",
104
+ headers: { "Content-Type": "application/json" },
105
+ body: JSON.stringify(input)
106
+ });
107
+ if (!res.ok) throw await accessServerError(res);
108
+ return toAccessServer(await res.json());
109
+ }
110
+ async function updateAccessServer(id, input) {
111
+ const res = await authFetch(`${ACCESS_SERVERS_API}/${encodeURIComponent(id)}`, {
112
+ method: "PUT",
113
+ headers: { "Content-Type": "application/json" },
114
+ body: JSON.stringify(input)
115
+ });
116
+ if (!res.ok) throw await accessServerError(res);
117
+ return toAccessServer(await res.json());
118
+ }
119
+ async function removeAccessServer(id) {
120
+ const res = await authFetch(`${ACCESS_SERVERS_API}/${encodeURIComponent(id)}`, {
121
+ method: "DELETE"
122
+ });
123
+ if (!res.ok && res.status !== 204) throw await accessServerError(res);
124
+ }
125
+ async function listConnectivityProviders() {
126
+ const res = await authFetch(CONNECTIVITY_PROVIDERS_API);
127
+ if (!res.ok) throw await accessServerError(res);
128
+ const body = await res.json();
129
+ const providers = Array.isArray(body) ? body : Array.isArray(body?.data) ? body.data : [];
130
+ return providers.map((provider) => ({
131
+ id: String(provider.id),
132
+ name: provider.name ?? "",
133
+ providerType: provider.providerType ?? void 0,
134
+ status: provider.status ?? void 0
135
+ }));
136
+ }
137
+
138
+ // src/client/index.ts
139
+ var HOST_RUNTIME_GLOBAL = "__VELTRIX_APP_RUNTIME__";
140
+ function getHostRuntime() {
141
+ const runtime = globalThis[HOST_RUNTIME_GLOBAL];
142
+ return runtime ?? null;
143
+ }
144
+ function requireHostRuntime() {
145
+ const runtime = getHostRuntime();
146
+ if (!runtime) {
147
+ throw new Error(
148
+ `Veltrix host runtime not found \u2014 app client bundles only run inside the Veltrix platform (missing globalThis.${HOST_RUNTIME_GLOBAL})`
149
+ );
150
+ }
151
+ return runtime;
152
+ }
153
+ function authFetch(input, init) {
154
+ const runtime = getHostRuntime();
155
+ if (runtime) return runtime.authFetch(input, init);
156
+ return fetch(input, init);
157
+ }
158
+
159
+ export {
160
+ resolveTool,
161
+ listInventory,
162
+ addInventoryItem,
163
+ updateInventoryItem,
164
+ removeInventoryItem,
165
+ listAccessServers,
166
+ addAccessServer,
167
+ updateAccessServer,
168
+ removeAccessServer,
169
+ listConnectivityProviders,
170
+ HOST_RUNTIME_GLOBAL,
171
+ getHostRuntime,
172
+ requireHostRuntime,
173
+ authFetch
174
+ };
175
+ //# sourceMappingURL=chunk-TE4UNXKW.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client/inventory.ts","../src/client/access-servers.ts","../src/client/index.ts"],"sourcesContent":["// ========================================================================\n// Inventory — the deployment targets an app can deploy configuration to.\n//\n// \"Inventory\" is the app-facing name for the platform's *components*: the\n// servers (hostname/port), domains, and IP/CIDR ranges a customer has\n// registered as deploy targets. These helpers are a typed, convenient\n// surface over the platform's components API (/api/components), enriched\n// with `domains` and `ipRanges`.\n//\n// Framework-free (no React) — safe to import from any client code. Every\n// call goes through the same `authFetch` the '/client' subpath exports, so\n// requests carry the platform's Authorization header. Non-2xx responses are\n// surfaced as thrown Errors carrying the platform's error text.\n// ========================================================================\n\nimport type { InventoryItem, InventoryItemInput } from '../types/platform'\nimport { authFetch } from './index'\n\n/** Base route for the platform's components (inventory) API. */\nconst INVENTORY_API = '/api/components'\n\n/**\n * Loosely-typed shape of a raw component as returned by the platform, before\n * it is normalized down to the {@link InventoryItem} surface.\n */\ninterface RawInventoryItem {\n id: string\n hostname?: string\n port?: string\n type?: string[]\n domains?: string[]\n ipRanges?: string[]\n tags?: Array<{ id: string; name: string }>\n connectivityProviderId?: string | null\n}\n\n/** Build an Error from a non-2xx response, preferring the platform's message. */\nasync function inventoryError(res: Response): Promise<Error> {\n const text = await res.text().catch(() => '')\n if (text) {\n try {\n const body = JSON.parse(text) as { error?: string; message?: string }\n const message = body?.error ?? body?.message\n if (message) return new Error(message)\n } catch {\n // Body was not JSON — fall through and use the raw text.\n }\n return new Error(text)\n }\n return new Error(`HTTP ${res.status}`)\n}\n\n/** Normalize a raw platform component into the typed InventoryItem surface. */\nfunction toInventoryItem(raw: RawInventoryItem): InventoryItem {\n return {\n id: String(raw.id),\n hostname: raw.hostname ?? '',\n port: raw.port ?? undefined,\n type: Array.isArray(raw.type) ? raw.type : undefined,\n domains: Array.isArray(raw.domains) ? raw.domains : [],\n ipRanges: Array.isArray(raw.ipRanges) ? raw.ipRanges : [],\n tags: Array.isArray(raw.tags)\n ? raw.tags.map((tag) => ({ id: String(tag.id), name: String(tag.name) }))\n : [],\n connectivityProviderId: raw.connectivityProviderId ?? null,\n }\n}\n\n/**\n * A platform Tool. Each installed app is upserted as a Tool keyed by its\n * manifest `name`, and inventory items (components) belong to a tool.\n */\nexport interface Tool {\n id: string\n name: string\n vendor?: string\n}\n\n/**\n * Resolve the platform Tool for an app by its manifest name (the platform\n * upserts `Tool.name === app name`). The tool id is required by the platform\n * when creating an inventory item, so call this once and pass the id as\n * `toolId` to {@link addInventoryItem}. Returns null when no tool matches.\n *\n * GET /api/tools (the endpoint is paginated — `{ data, pagination }` — or a\n * bare array; both are handled).\n */\nexport async function resolveTool(name: string): Promise<Tool | null> {\n const res = await authFetch('/api/tools')\n if (!res.ok) throw await inventoryError(res)\n const body = (await res.json()) as unknown\n const tools: Tool[] = Array.isArray(body)\n ? (body as Tool[])\n : Array.isArray((body as { data?: unknown })?.data)\n ? ((body as { data: Tool[] }).data)\n : []\n return tools.find((tool) => tool.name === name) ?? null\n}\n\n/** List the customer's inventory (deployment targets). GET /api/components */\nexport async function listInventory(): Promise<InventoryItem[]> {\n const res = await authFetch(INVENTORY_API)\n if (!res.ok) throw await inventoryError(res)\n const data = (await res.json()) as RawInventoryItem[]\n return Array.isArray(data) ? data.map(toInventoryItem) : []\n}\n\n/** Add a new inventory item (deployment target). POST /api/components */\nexport async function addInventoryItem(input: InventoryItemInput): Promise<InventoryItem> {\n const res = await authFetch(INVENTORY_API, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n })\n if (!res.ok) throw await inventoryError(res)\n return toInventoryItem((await res.json()) as RawInventoryItem)\n}\n\n/** Update an existing inventory item. PUT /api/components/:id */\nexport async function updateInventoryItem(\n id: string,\n input: InventoryItemInput,\n): Promise<InventoryItem> {\n const res = await authFetch(`${INVENTORY_API}/${encodeURIComponent(id)}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n })\n if (!res.ok) throw await inventoryError(res)\n return toInventoryItem((await res.json()) as RawInventoryItem)\n}\n\n/** Remove an inventory item. DELETE /api/components/:id */\nexport async function removeInventoryItem(id: string): Promise<void> {\n const res = await authFetch(`${INVENTORY_API}/${encodeURIComponent(id)}`, {\n method: 'DELETE',\n })\n // 204 No Content is the platform's success response for delete.\n if (!res.ok && res.status !== 204) throw await inventoryError(res)\n}\n","// ========================================================================\n// Access Servers — the Zero-Trust Access (ZTNA) gateways an app manages.\n//\n// Each Access Server is a ZTNA gateway (name + endpoint) a customer has\n// registered, optionally linked to one of their connectivity providers. These\n// helpers are a typed, convenient surface over the platform's access-servers\n// API (/api/access-servers), plus a thin reader over the connectivity\n// providers API (/api/connectivity-providers) used to populate the ZTNA link\n// picker.\n//\n// Framework-free (no React) — safe to import from any client code. Every call\n// goes through the same `authFetch` the '/client' subpath exports, so requests\n// carry the platform's Authorization header. Non-2xx responses are surfaced as\n// thrown Errors carrying the platform's error text.\n// ========================================================================\n\nimport type {\n AccessServer,\n AccessServerInput,\n ConnectivityProviderRef,\n} from '../types/platform'\nimport { authFetch } from './index'\n\n/** Base route for the platform's access-servers API. */\nconst ACCESS_SERVERS_API = '/api/access-servers'\n/** Base route for the platform's connectivity-providers API (ZTNA picker). */\nconst CONNECTIVITY_PROVIDERS_API = '/api/connectivity-providers'\n\n/**\n * Loosely-typed shape of a raw access server as returned by the platform,\n * before it is normalized down to the {@link AccessServer} surface.\n */\ninterface RawAccessServer {\n id: string\n name?: string\n endpoint?: string\n type?: string\n region?: string | null\n status?: string\n description?: string | null\n connectivityProviderId?: string | null\n connectivityProvider?: { id: string; name: string } | null\n}\n\n/**\n * Loosely-typed shape of a raw connectivity provider as returned by the\n * platform, before it is normalized to the {@link ConnectivityProviderRef}\n * picker surface.\n */\ninterface RawConnectivityProvider {\n id: string\n name?: string\n providerType?: string\n status?: string\n}\n\n/** Build an Error from a non-2xx response, preferring the platform's message. */\nasync function accessServerError(res: Response): Promise<Error> {\n const text = await res.text().catch(() => '')\n if (text) {\n try {\n const body = JSON.parse(text) as { error?: string; message?: string }\n const message = body?.error ?? body?.message\n if (message) return new Error(message)\n } catch {\n // Body was not JSON — fall through and use the raw text.\n }\n return new Error(text)\n }\n return new Error(`HTTP ${res.status}`)\n}\n\n/** Normalize a raw platform access server into the typed AccessServer surface. */\nfunction toAccessServer(raw: RawAccessServer): AccessServer {\n return {\n id: String(raw.id),\n name: raw.name ?? '',\n endpoint: raw.endpoint ?? '',\n type: raw.type ?? undefined,\n region: raw.region ?? null,\n status: raw.status ?? undefined,\n description: raw.description ?? null,\n connectivityProviderId: raw.connectivityProviderId ?? null,\n connectivityProvider: raw.connectivityProvider\n ? { id: String(raw.connectivityProvider.id), name: String(raw.connectivityProvider.name) }\n : null,\n }\n}\n\n/** List the customer's access servers (ZTNA gateways). GET /api/access-servers */\nexport async function listAccessServers(): Promise<AccessServer[]> {\n const res = await authFetch(ACCESS_SERVERS_API)\n if (!res.ok) throw await accessServerError(res)\n const data = (await res.json()) as RawAccessServer[]\n return Array.isArray(data) ? data.map(toAccessServer) : []\n}\n\n/** Add a new access server (ZTNA gateway). POST /api/access-servers */\nexport async function addAccessServer(input: AccessServerInput): Promise<AccessServer> {\n const res = await authFetch(ACCESS_SERVERS_API, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n })\n if (!res.ok) throw await accessServerError(res)\n return toAccessServer((await res.json()) as RawAccessServer)\n}\n\n/** Update an existing access server. PUT /api/access-servers/:id */\nexport async function updateAccessServer(\n id: string,\n input: AccessServerInput,\n): Promise<AccessServer> {\n const res = await authFetch(`${ACCESS_SERVERS_API}/${encodeURIComponent(id)}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n })\n if (!res.ok) throw await accessServerError(res)\n return toAccessServer((await res.json()) as RawAccessServer)\n}\n\n/** Remove an access server. DELETE /api/access-servers/:id */\nexport async function removeAccessServer(id: string): Promise<void> {\n const res = await authFetch(`${ACCESS_SERVERS_API}/${encodeURIComponent(id)}`, {\n method: 'DELETE',\n })\n // 204 No Content is the platform's success response for delete.\n if (!res.ok && res.status !== 204) throw await accessServerError(res)\n}\n\n/**\n * List the customer's ZTNA connectivity providers, used to populate the Access\n * Server link picker. GET /api/connectivity-providers (the endpoint may return\n * a bare array or a paginated `{ data, ... }` shape — both are handled).\n */\nexport async function listConnectivityProviders(): Promise<ConnectivityProviderRef[]> {\n const res = await authFetch(CONNECTIVITY_PROVIDERS_API)\n if (!res.ok) throw await accessServerError(res)\n const body = (await res.json()) as unknown\n const providers: RawConnectivityProvider[] = Array.isArray(body)\n ? (body as RawConnectivityProvider[])\n : Array.isArray((body as { data?: unknown })?.data)\n ? ((body as { data: RawConnectivityProvider[] }).data)\n : []\n return providers.map((provider) => ({\n id: String(provider.id),\n name: provider.name ?? '',\n providerType: provider.providerType ?? undefined,\n status: provider.status ?? undefined,\n }))\n}\n","// ========================================================================\n// Client runtime contract — how app client bundles talk to the host.\n//\n// App client code is packaged as a hermetic ESM bundle in which `react`,\n// `react-dom`, `react/jsx-runtime`, and every `@veltrixsecops/app-sdk`\n// subpath are compile-time shims that read the host-provided runtime from\n// `globalThis.__VELTRIX_APP_RUNTIME__`. The platform installs that global\n// (with ITS React instance, the shared AppContext, and an authenticated\n// fetch) before dynamically importing any app bundle, so app components\n// render inside the host React tree with working hooks and context.\n//\n// App authors: import from '@veltrixsecops/app-sdk/client' (and /hooks) —\n// never bundle your own copy of react. Use `authFetch` for calls to your\n// app's server routes (/api/apps/<app-id>/...): plain fetch() lacks the\n// platform's Authorization header and will receive 401s.\n// ========================================================================\n\nimport type { ComponentType, Context, LazyExoticComponent } from 'react'\nimport type { AppContextValue } from '../hooks/use-app-context'\n\nexport type { AppBrandingDeclaration } from '../types/manifest'\n\n// Inventory — typed helpers over the platform's components API (deployment\n// targets: servers, domains, IP/CIDR ranges). Framework-free; they use the\n// `authFetch` exported below internally.\nexport {\n listInventory,\n addInventoryItem,\n updateInventoryItem,\n removeInventoryItem,\n resolveTool,\n} from './inventory'\nexport type { Tool } from './inventory'\nexport type { InventoryItem, InventoryItemInput } from '../types/platform'\n\n// Access Servers — typed helpers over the platform's access-servers API (ZTNA\n// gateways) plus a reader over connectivity providers for the link picker.\n// Framework-free; they use the `authFetch` exported below internally.\nexport {\n listAccessServers,\n addAccessServer,\n updateAccessServer,\n removeAccessServer,\n listConnectivityProviders,\n} from './access-servers'\nexport type { AccessServer, AccessServerInput, ConnectivityProviderRef } from '../types/platform'\n\n/** Name of the global the platform installs before loading app bundles. */\nexport const HOST_RUNTIME_GLOBAL = '__VELTRIX_APP_RUNTIME__'\n\n/**\n * The runtime surface the platform exposes to app client bundles.\n * The react/reactDom/jsxRuntime members are the host's own module objects —\n * app bundles are compiled with shims that re-export them, guaranteeing a\n * single React instance per page.\n */\nexport interface VeltrixHostRuntime {\n /** The host's `react` module object. */\n react: unknown\n /** The host's `react-dom` module object. */\n reactDom: unknown\n /** The host's `react-dom/client` module object. */\n reactDomClient?: unknown\n /** The host's `react/jsx-runtime` module object. */\n jsxRuntime: unknown\n /** Shared app context — the host wraps app pages in its Provider. */\n AppContext: Context<AppContextValue | null>\n /** fetch() with the platform's Authorization header attached. */\n authFetch: (input: string, init?: RequestInit) => Promise<Response>\n /**\n * The SDK surface app bundles receive for `@veltrixsecops/app-sdk`,\n * `.../hooks`, and `.../client` imports (useAppContext, AppContext,\n * usePipelineStatus, authFetch, getHostRuntime, ...).\n */\n sdk: Record<string, unknown>\n /**\n * The platform's design-system components and hooks, host-owned so they\n * share the single host React instance. Keyed by the exact component/hook\n * names re-exported from `@veltrixsecops/app-sdk/ui` (Button, Input, Card,\n * DataTable, useToast, ...). Present only inside the platform.\n */\n ui?: Record<string, unknown>\n}\n\n/** Read the host runtime, or null outside the platform (tests, storybook). */\nexport function getHostRuntime(): VeltrixHostRuntime | null {\n const runtime = (globalThis as Record<string, unknown>)[HOST_RUNTIME_GLOBAL]\n return (runtime as VeltrixHostRuntime) ?? null\n}\n\n/** Read the host runtime, throwing a diagnosable error when absent. */\nexport function requireHostRuntime(): VeltrixHostRuntime {\n const runtime = getHostRuntime()\n if (!runtime) {\n throw new Error(\n 'Veltrix host runtime not found — app client bundles only run inside the ' +\n `Veltrix platform (missing globalThis.${HOST_RUNTIME_GLOBAL})`,\n )\n }\n return runtime\n}\n\n/**\n * fetch() that carries the platform's Authorization header. Required for an\n * app page to call its own server routes (/api/apps/<app-id>/...), which are\n * bearer-token protected. Falls back to plain fetch outside the platform.\n */\nexport function authFetch(input: string, init?: RequestInit): Promise<Response> {\n const runtime = getHostRuntime()\n if (runtime) return runtime.authFetch(input, init)\n return fetch(input, init)\n}\n\n/** A sidebar entry contributed by the app's client entry module. */\nexport interface AppSidebarItem {\n path: string\n label: string\n icon?: string\n}\n\n/**\n * Shape of the default export of an app's `client/index.tsx`.\n * `pages` keys must match `manifest.client.pages[].component`.\n */\nexport interface AppClientModule {\n id: string\n pages: Record<string, ComponentType | LazyExoticComponent<ComponentType>>\n sidebarItems?: AppSidebarItem[]\n}\n"],"mappings":"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","names":[]}
@@ -21,12 +21,18 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var client_exports = {};
22
22
  __export(client_exports, {
23
23
  HOST_RUNTIME_GLOBAL: () => HOST_RUNTIME_GLOBAL,
24
+ addAccessServer: () => addAccessServer,
24
25
  addInventoryItem: () => addInventoryItem,
25
26
  authFetch: () => authFetch,
26
27
  getHostRuntime: () => getHostRuntime,
28
+ listAccessServers: () => listAccessServers,
29
+ listConnectivityProviders: () => listConnectivityProviders,
27
30
  listInventory: () => listInventory,
31
+ removeAccessServer: () => removeAccessServer,
28
32
  removeInventoryItem: () => removeInventoryItem,
29
33
  requireHostRuntime: () => requireHostRuntime,
34
+ resolveTool: () => resolveTool,
35
+ updateAccessServer: () => updateAccessServer,
30
36
  updateInventoryItem: () => updateInventoryItem
31
37
  });
32
38
  module.exports = __toCommonJS(client_exports);
@@ -58,6 +64,13 @@ function toInventoryItem(raw) {
58
64
  connectivityProviderId: raw.connectivityProviderId ?? null
59
65
  };
60
66
  }
67
+ async function resolveTool(name) {
68
+ const res = await authFetch("/api/tools");
69
+ if (!res.ok) throw await inventoryError(res);
70
+ const body = await res.json();
71
+ const tools = Array.isArray(body) ? body : Array.isArray(body?.data) ? body.data : [];
72
+ return tools.find((tool) => tool.name === name) ?? null;
73
+ }
61
74
  async function listInventory() {
62
75
  const res = await authFetch(INVENTORY_API);
63
76
  if (!res.ok) throw await inventoryError(res);
@@ -89,6 +102,78 @@ async function removeInventoryItem(id) {
89
102
  if (!res.ok && res.status !== 204) throw await inventoryError(res);
90
103
  }
91
104
 
105
+ // src/client/access-servers.ts
106
+ var ACCESS_SERVERS_API = "/api/access-servers";
107
+ var CONNECTIVITY_PROVIDERS_API = "/api/connectivity-providers";
108
+ async function accessServerError(res) {
109
+ const text = await res.text().catch(() => "");
110
+ if (text) {
111
+ try {
112
+ const body = JSON.parse(text);
113
+ const message = body?.error ?? body?.message;
114
+ if (message) return new Error(message);
115
+ } catch {
116
+ }
117
+ return new Error(text);
118
+ }
119
+ return new Error(`HTTP ${res.status}`);
120
+ }
121
+ function toAccessServer(raw) {
122
+ return {
123
+ id: String(raw.id),
124
+ name: raw.name ?? "",
125
+ endpoint: raw.endpoint ?? "",
126
+ type: raw.type ?? void 0,
127
+ region: raw.region ?? null,
128
+ status: raw.status ?? void 0,
129
+ description: raw.description ?? null,
130
+ connectivityProviderId: raw.connectivityProviderId ?? null,
131
+ connectivityProvider: raw.connectivityProvider ? { id: String(raw.connectivityProvider.id), name: String(raw.connectivityProvider.name) } : null
132
+ };
133
+ }
134
+ async function listAccessServers() {
135
+ const res = await authFetch(ACCESS_SERVERS_API);
136
+ if (!res.ok) throw await accessServerError(res);
137
+ const data = await res.json();
138
+ return Array.isArray(data) ? data.map(toAccessServer) : [];
139
+ }
140
+ async function addAccessServer(input) {
141
+ const res = await authFetch(ACCESS_SERVERS_API, {
142
+ method: "POST",
143
+ headers: { "Content-Type": "application/json" },
144
+ body: JSON.stringify(input)
145
+ });
146
+ if (!res.ok) throw await accessServerError(res);
147
+ return toAccessServer(await res.json());
148
+ }
149
+ async function updateAccessServer(id, input) {
150
+ const res = await authFetch(`${ACCESS_SERVERS_API}/${encodeURIComponent(id)}`, {
151
+ method: "PUT",
152
+ headers: { "Content-Type": "application/json" },
153
+ body: JSON.stringify(input)
154
+ });
155
+ if (!res.ok) throw await accessServerError(res);
156
+ return toAccessServer(await res.json());
157
+ }
158
+ async function removeAccessServer(id) {
159
+ const res = await authFetch(`${ACCESS_SERVERS_API}/${encodeURIComponent(id)}`, {
160
+ method: "DELETE"
161
+ });
162
+ if (!res.ok && res.status !== 204) throw await accessServerError(res);
163
+ }
164
+ async function listConnectivityProviders() {
165
+ const res = await authFetch(CONNECTIVITY_PROVIDERS_API);
166
+ if (!res.ok) throw await accessServerError(res);
167
+ const body = await res.json();
168
+ const providers = Array.isArray(body) ? body : Array.isArray(body?.data) ? body.data : [];
169
+ return providers.map((provider) => ({
170
+ id: String(provider.id),
171
+ name: provider.name ?? "",
172
+ providerType: provider.providerType ?? void 0,
173
+ status: provider.status ?? void 0
174
+ }));
175
+ }
176
+
92
177
  // src/client/index.ts
93
178
  var HOST_RUNTIME_GLOBAL = "__VELTRIX_APP_RUNTIME__";
94
179
  function getHostRuntime() {
@@ -112,12 +197,18 @@ function authFetch(input, init) {
112
197
  // Annotate the CommonJS export names for ESM import in node:
113
198
  0 && (module.exports = {
114
199
  HOST_RUNTIME_GLOBAL,
200
+ addAccessServer,
115
201
  addInventoryItem,
116
202
  authFetch,
117
203
  getHostRuntime,
204
+ listAccessServers,
205
+ listConnectivityProviders,
118
206
  listInventory,
207
+ removeAccessServer,
119
208
  removeInventoryItem,
120
209
  requireHostRuntime,
210
+ resolveTool,
211
+ updateAccessServer,
121
212
  updateInventoryItem
122
213
  });
123
214
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/client/index.ts","../../src/client/inventory.ts"],"sourcesContent":["// ========================================================================\n// Client runtime contract — how app client bundles talk to the host.\n//\n// App client code is packaged as a hermetic ESM bundle in which `react`,\n// `react-dom`, `react/jsx-runtime`, and every `@veltrixsecops/app-sdk`\n// subpath are compile-time shims that read the host-provided runtime from\n// `globalThis.__VELTRIX_APP_RUNTIME__`. The platform installs that global\n// (with ITS React instance, the shared AppContext, and an authenticated\n// fetch) before dynamically importing any app bundle, so app components\n// render inside the host React tree with working hooks and context.\n//\n// App authors: import from '@veltrixsecops/app-sdk/client' (and /hooks) —\n// never bundle your own copy of react. Use `authFetch` for calls to your\n// app's server routes (/api/apps/<app-id>/...): plain fetch() lacks the\n// platform's Authorization header and will receive 401s.\n// ========================================================================\n\nimport type { ComponentType, Context, LazyExoticComponent } from 'react'\nimport type { AppContextValue } from '../hooks/use-app-context'\n\nexport type { AppBrandingDeclaration } from '../types/manifest'\n\n// Inventory — typed helpers over the platform's components API (deployment\n// targets: servers, domains, IP/CIDR ranges). Framework-free; they use the\n// `authFetch` exported below internally.\nexport {\n listInventory,\n addInventoryItem,\n updateInventoryItem,\n removeInventoryItem,\n} from './inventory'\nexport type { InventoryItem, InventoryItemInput } from '../types/platform'\n\n/** Name of the global the platform installs before loading app bundles. */\nexport const HOST_RUNTIME_GLOBAL = '__VELTRIX_APP_RUNTIME__'\n\n/**\n * The runtime surface the platform exposes to app client bundles.\n * The react/reactDom/jsxRuntime members are the host's own module objects —\n * app bundles are compiled with shims that re-export them, guaranteeing a\n * single React instance per page.\n */\nexport interface VeltrixHostRuntime {\n /** The host's `react` module object. */\n react: unknown\n /** The host's `react-dom` module object. */\n reactDom: unknown\n /** The host's `react-dom/client` module object. */\n reactDomClient?: unknown\n /** The host's `react/jsx-runtime` module object. */\n jsxRuntime: unknown\n /** Shared app context — the host wraps app pages in its Provider. */\n AppContext: Context<AppContextValue | null>\n /** fetch() with the platform's Authorization header attached. */\n authFetch: (input: string, init?: RequestInit) => Promise<Response>\n /**\n * The SDK surface app bundles receive for `@veltrixsecops/app-sdk`,\n * `.../hooks`, and `.../client` imports (useAppContext, AppContext,\n * usePipelineStatus, authFetch, getHostRuntime, ...).\n */\n sdk: Record<string, unknown>\n /**\n * The platform's design-system components and hooks, host-owned so they\n * share the single host React instance. Keyed by the exact component/hook\n * names re-exported from `@veltrixsecops/app-sdk/ui` (Button, Input, Card,\n * DataTable, useToast, ...). Present only inside the platform.\n */\n ui?: Record<string, unknown>\n}\n\n/** Read the host runtime, or null outside the platform (tests, storybook). */\nexport function getHostRuntime(): VeltrixHostRuntime | null {\n const runtime = (globalThis as Record<string, unknown>)[HOST_RUNTIME_GLOBAL]\n return (runtime as VeltrixHostRuntime) ?? null\n}\n\n/** Read the host runtime, throwing a diagnosable error when absent. */\nexport function requireHostRuntime(): VeltrixHostRuntime {\n const runtime = getHostRuntime()\n if (!runtime) {\n throw new Error(\n 'Veltrix host runtime not found — app client bundles only run inside the ' +\n `Veltrix platform (missing globalThis.${HOST_RUNTIME_GLOBAL})`,\n )\n }\n return runtime\n}\n\n/**\n * fetch() that carries the platform's Authorization header. Required for an\n * app page to call its own server routes (/api/apps/<app-id>/...), which are\n * bearer-token protected. Falls back to plain fetch outside the platform.\n */\nexport function authFetch(input: string, init?: RequestInit): Promise<Response> {\n const runtime = getHostRuntime()\n if (runtime) return runtime.authFetch(input, init)\n return fetch(input, init)\n}\n\n/** A sidebar entry contributed by the app's client entry module. */\nexport interface AppSidebarItem {\n path: string\n label: string\n icon?: string\n}\n\n/**\n * Shape of the default export of an app's `client/index.tsx`.\n * `pages` keys must match `manifest.client.pages[].component`.\n */\nexport interface AppClientModule {\n id: string\n pages: Record<string, ComponentType | LazyExoticComponent<ComponentType>>\n sidebarItems?: AppSidebarItem[]\n}\n","// ========================================================================\n// Inventory — the deployment targets an app can deploy configuration to.\n//\n// \"Inventory\" is the app-facing name for the platform's *components*: the\n// servers (hostname/port), domains, and IP/CIDR ranges a customer has\n// registered as deploy targets. These helpers are a typed, convenient\n// surface over the platform's components API (/api/components), enriched\n// with `domains` and `ipRanges`.\n//\n// Framework-free (no React) — safe to import from any client code. Every\n// call goes through the same `authFetch` the '/client' subpath exports, so\n// requests carry the platform's Authorization header. Non-2xx responses are\n// surfaced as thrown Errors carrying the platform's error text.\n// ========================================================================\n\nimport type { InventoryItem, InventoryItemInput } from '../types/platform'\nimport { authFetch } from './index'\n\n/** Base route for the platform's components (inventory) API. */\nconst INVENTORY_API = '/api/components'\n\n/**\n * Loosely-typed shape of a raw component as returned by the platform, before\n * it is normalized down to the {@link InventoryItem} surface.\n */\ninterface RawInventoryItem {\n id: string\n hostname?: string\n port?: string\n type?: string[]\n domains?: string[]\n ipRanges?: string[]\n tags?: Array<{ id: string; name: string }>\n connectivityProviderId?: string | null\n}\n\n/** Build an Error from a non-2xx response, preferring the platform's message. */\nasync function inventoryError(res: Response): Promise<Error> {\n const text = await res.text().catch(() => '')\n if (text) {\n try {\n const body = JSON.parse(text) as { error?: string; message?: string }\n const message = body?.error ?? body?.message\n if (message) return new Error(message)\n } catch {\n // Body was not JSON — fall through and use the raw text.\n }\n return new Error(text)\n }\n return new Error(`HTTP ${res.status}`)\n}\n\n/** Normalize a raw platform component into the typed InventoryItem surface. */\nfunction toInventoryItem(raw: RawInventoryItem): InventoryItem {\n return {\n id: String(raw.id),\n hostname: raw.hostname ?? '',\n port: raw.port ?? undefined,\n type: Array.isArray(raw.type) ? raw.type : undefined,\n domains: Array.isArray(raw.domains) ? raw.domains : [],\n ipRanges: Array.isArray(raw.ipRanges) ? raw.ipRanges : [],\n tags: Array.isArray(raw.tags)\n ? raw.tags.map((tag) => ({ id: String(tag.id), name: String(tag.name) }))\n : [],\n connectivityProviderId: raw.connectivityProviderId ?? null,\n }\n}\n\n/** List the customer's inventory (deployment targets). GET /api/components */\nexport async function listInventory(): Promise<InventoryItem[]> {\n const res = await authFetch(INVENTORY_API)\n if (!res.ok) throw await inventoryError(res)\n const data = (await res.json()) as RawInventoryItem[]\n return Array.isArray(data) ? data.map(toInventoryItem) : []\n}\n\n/** Add a new inventory item (deployment target). POST /api/components */\nexport async function addInventoryItem(input: InventoryItemInput): Promise<InventoryItem> {\n const res = await authFetch(INVENTORY_API, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n })\n if (!res.ok) throw await inventoryError(res)\n return toInventoryItem((await res.json()) as RawInventoryItem)\n}\n\n/** Update an existing inventory item. PUT /api/components/:id */\nexport async function updateInventoryItem(\n id: string,\n input: InventoryItemInput,\n): Promise<InventoryItem> {\n const res = await authFetch(`${INVENTORY_API}/${encodeURIComponent(id)}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n })\n if (!res.ok) throw await inventoryError(res)\n return toInventoryItem((await res.json()) as RawInventoryItem)\n}\n\n/** Remove an inventory item. DELETE /api/components/:id */\nexport async function removeInventoryItem(id: string): Promise<void> {\n const res = await authFetch(`${INVENTORY_API}/${encodeURIComponent(id)}`, {\n method: 'DELETE',\n })\n // 204 No Content is the platform's success response for delete.\n if (!res.ok && res.status !== 204) throw await inventoryError(res)\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/client/index.ts","../../src/client/inventory.ts","../../src/client/access-servers.ts"],"sourcesContent":["// ========================================================================\n// Client runtime contract — how app client bundles talk to the host.\n//\n// App client code is packaged as a hermetic ESM bundle in which `react`,\n// `react-dom`, `react/jsx-runtime`, and every `@veltrixsecops/app-sdk`\n// subpath are compile-time shims that read the host-provided runtime from\n// `globalThis.__VELTRIX_APP_RUNTIME__`. The platform installs that global\n// (with ITS React instance, the shared AppContext, and an authenticated\n// fetch) before dynamically importing any app bundle, so app components\n// render inside the host React tree with working hooks and context.\n//\n// App authors: import from '@veltrixsecops/app-sdk/client' (and /hooks) —\n// never bundle your own copy of react. Use `authFetch` for calls to your\n// app's server routes (/api/apps/<app-id>/...): plain fetch() lacks the\n// platform's Authorization header and will receive 401s.\n// ========================================================================\n\nimport type { ComponentType, Context, LazyExoticComponent } from 'react'\nimport type { AppContextValue } from '../hooks/use-app-context'\n\nexport type { AppBrandingDeclaration } from '../types/manifest'\n\n// Inventory — typed helpers over the platform's components API (deployment\n// targets: servers, domains, IP/CIDR ranges). Framework-free; they use the\n// `authFetch` exported below internally.\nexport {\n listInventory,\n addInventoryItem,\n updateInventoryItem,\n removeInventoryItem,\n resolveTool,\n} from './inventory'\nexport type { Tool } from './inventory'\nexport type { InventoryItem, InventoryItemInput } from '../types/platform'\n\n// Access Servers — typed helpers over the platform's access-servers API (ZTNA\n// gateways) plus a reader over connectivity providers for the link picker.\n// Framework-free; they use the `authFetch` exported below internally.\nexport {\n listAccessServers,\n addAccessServer,\n updateAccessServer,\n removeAccessServer,\n listConnectivityProviders,\n} from './access-servers'\nexport type { AccessServer, AccessServerInput, ConnectivityProviderRef } from '../types/platform'\n\n/** Name of the global the platform installs before loading app bundles. */\nexport const HOST_RUNTIME_GLOBAL = '__VELTRIX_APP_RUNTIME__'\n\n/**\n * The runtime surface the platform exposes to app client bundles.\n * The react/reactDom/jsxRuntime members are the host's own module objects —\n * app bundles are compiled with shims that re-export them, guaranteeing a\n * single React instance per page.\n */\nexport interface VeltrixHostRuntime {\n /** The host's `react` module object. */\n react: unknown\n /** The host's `react-dom` module object. */\n reactDom: unknown\n /** The host's `react-dom/client` module object. */\n reactDomClient?: unknown\n /** The host's `react/jsx-runtime` module object. */\n jsxRuntime: unknown\n /** Shared app context — the host wraps app pages in its Provider. */\n AppContext: Context<AppContextValue | null>\n /** fetch() with the platform's Authorization header attached. */\n authFetch: (input: string, init?: RequestInit) => Promise<Response>\n /**\n * The SDK surface app bundles receive for `@veltrixsecops/app-sdk`,\n * `.../hooks`, and `.../client` imports (useAppContext, AppContext,\n * usePipelineStatus, authFetch, getHostRuntime, ...).\n */\n sdk: Record<string, unknown>\n /**\n * The platform's design-system components and hooks, host-owned so they\n * share the single host React instance. Keyed by the exact component/hook\n * names re-exported from `@veltrixsecops/app-sdk/ui` (Button, Input, Card,\n * DataTable, useToast, ...). Present only inside the platform.\n */\n ui?: Record<string, unknown>\n}\n\n/** Read the host runtime, or null outside the platform (tests, storybook). */\nexport function getHostRuntime(): VeltrixHostRuntime | null {\n const runtime = (globalThis as Record<string, unknown>)[HOST_RUNTIME_GLOBAL]\n return (runtime as VeltrixHostRuntime) ?? null\n}\n\n/** Read the host runtime, throwing a diagnosable error when absent. */\nexport function requireHostRuntime(): VeltrixHostRuntime {\n const runtime = getHostRuntime()\n if (!runtime) {\n throw new Error(\n 'Veltrix host runtime not found — app client bundles only run inside the ' +\n `Veltrix platform (missing globalThis.${HOST_RUNTIME_GLOBAL})`,\n )\n }\n return runtime\n}\n\n/**\n * fetch() that carries the platform's Authorization header. Required for an\n * app page to call its own server routes (/api/apps/<app-id>/...), which are\n * bearer-token protected. Falls back to plain fetch outside the platform.\n */\nexport function authFetch(input: string, init?: RequestInit): Promise<Response> {\n const runtime = getHostRuntime()\n if (runtime) return runtime.authFetch(input, init)\n return fetch(input, init)\n}\n\n/** A sidebar entry contributed by the app's client entry module. */\nexport interface AppSidebarItem {\n path: string\n label: string\n icon?: string\n}\n\n/**\n * Shape of the default export of an app's `client/index.tsx`.\n * `pages` keys must match `manifest.client.pages[].component`.\n */\nexport interface AppClientModule {\n id: string\n pages: Record<string, ComponentType | LazyExoticComponent<ComponentType>>\n sidebarItems?: AppSidebarItem[]\n}\n","// ========================================================================\n// Inventory — the deployment targets an app can deploy configuration to.\n//\n// \"Inventory\" is the app-facing name for the platform's *components*: the\n// servers (hostname/port), domains, and IP/CIDR ranges a customer has\n// registered as deploy targets. These helpers are a typed, convenient\n// surface over the platform's components API (/api/components), enriched\n// with `domains` and `ipRanges`.\n//\n// Framework-free (no React) — safe to import from any client code. Every\n// call goes through the same `authFetch` the '/client' subpath exports, so\n// requests carry the platform's Authorization header. Non-2xx responses are\n// surfaced as thrown Errors carrying the platform's error text.\n// ========================================================================\n\nimport type { InventoryItem, InventoryItemInput } from '../types/platform'\nimport { authFetch } from './index'\n\n/** Base route for the platform's components (inventory) API. */\nconst INVENTORY_API = '/api/components'\n\n/**\n * Loosely-typed shape of a raw component as returned by the platform, before\n * it is normalized down to the {@link InventoryItem} surface.\n */\ninterface RawInventoryItem {\n id: string\n hostname?: string\n port?: string\n type?: string[]\n domains?: string[]\n ipRanges?: string[]\n tags?: Array<{ id: string; name: string }>\n connectivityProviderId?: string | null\n}\n\n/** Build an Error from a non-2xx response, preferring the platform's message. */\nasync function inventoryError(res: Response): Promise<Error> {\n const text = await res.text().catch(() => '')\n if (text) {\n try {\n const body = JSON.parse(text) as { error?: string; message?: string }\n const message = body?.error ?? body?.message\n if (message) return new Error(message)\n } catch {\n // Body was not JSON — fall through and use the raw text.\n }\n return new Error(text)\n }\n return new Error(`HTTP ${res.status}`)\n}\n\n/** Normalize a raw platform component into the typed InventoryItem surface. */\nfunction toInventoryItem(raw: RawInventoryItem): InventoryItem {\n return {\n id: String(raw.id),\n hostname: raw.hostname ?? '',\n port: raw.port ?? undefined,\n type: Array.isArray(raw.type) ? raw.type : undefined,\n domains: Array.isArray(raw.domains) ? raw.domains : [],\n ipRanges: Array.isArray(raw.ipRanges) ? raw.ipRanges : [],\n tags: Array.isArray(raw.tags)\n ? raw.tags.map((tag) => ({ id: String(tag.id), name: String(tag.name) }))\n : [],\n connectivityProviderId: raw.connectivityProviderId ?? null,\n }\n}\n\n/**\n * A platform Tool. Each installed app is upserted as a Tool keyed by its\n * manifest `name`, and inventory items (components) belong to a tool.\n */\nexport interface Tool {\n id: string\n name: string\n vendor?: string\n}\n\n/**\n * Resolve the platform Tool for an app by its manifest name (the platform\n * upserts `Tool.name === app name`). The tool id is required by the platform\n * when creating an inventory item, so call this once and pass the id as\n * `toolId` to {@link addInventoryItem}. Returns null when no tool matches.\n *\n * GET /api/tools (the endpoint is paginated — `{ data, pagination }` — or a\n * bare array; both are handled).\n */\nexport async function resolveTool(name: string): Promise<Tool | null> {\n const res = await authFetch('/api/tools')\n if (!res.ok) throw await inventoryError(res)\n const body = (await res.json()) as unknown\n const tools: Tool[] = Array.isArray(body)\n ? (body as Tool[])\n : Array.isArray((body as { data?: unknown })?.data)\n ? ((body as { data: Tool[] }).data)\n : []\n return tools.find((tool) => tool.name === name) ?? null\n}\n\n/** List the customer's inventory (deployment targets). GET /api/components */\nexport async function listInventory(): Promise<InventoryItem[]> {\n const res = await authFetch(INVENTORY_API)\n if (!res.ok) throw await inventoryError(res)\n const data = (await res.json()) as RawInventoryItem[]\n return Array.isArray(data) ? data.map(toInventoryItem) : []\n}\n\n/** Add a new inventory item (deployment target). POST /api/components */\nexport async function addInventoryItem(input: InventoryItemInput): Promise<InventoryItem> {\n const res = await authFetch(INVENTORY_API, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n })\n if (!res.ok) throw await inventoryError(res)\n return toInventoryItem((await res.json()) as RawInventoryItem)\n}\n\n/** Update an existing inventory item. PUT /api/components/:id */\nexport async function updateInventoryItem(\n id: string,\n input: InventoryItemInput,\n): Promise<InventoryItem> {\n const res = await authFetch(`${INVENTORY_API}/${encodeURIComponent(id)}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n })\n if (!res.ok) throw await inventoryError(res)\n return toInventoryItem((await res.json()) as RawInventoryItem)\n}\n\n/** Remove an inventory item. DELETE /api/components/:id */\nexport async function removeInventoryItem(id: string): Promise<void> {\n const res = await authFetch(`${INVENTORY_API}/${encodeURIComponent(id)}`, {\n method: 'DELETE',\n })\n // 204 No Content is the platform's success response for delete.\n if (!res.ok && res.status !== 204) throw await inventoryError(res)\n}\n","// ========================================================================\n// Access Servers — the Zero-Trust Access (ZTNA) gateways an app manages.\n//\n// Each Access Server is a ZTNA gateway (name + endpoint) a customer has\n// registered, optionally linked to one of their connectivity providers. These\n// helpers are a typed, convenient surface over the platform's access-servers\n// API (/api/access-servers), plus a thin reader over the connectivity\n// providers API (/api/connectivity-providers) used to populate the ZTNA link\n// picker.\n//\n// Framework-free (no React) — safe to import from any client code. Every call\n// goes through the same `authFetch` the '/client' subpath exports, so requests\n// carry the platform's Authorization header. Non-2xx responses are surfaced as\n// thrown Errors carrying the platform's error text.\n// ========================================================================\n\nimport type {\n AccessServer,\n AccessServerInput,\n ConnectivityProviderRef,\n} from '../types/platform'\nimport { authFetch } from './index'\n\n/** Base route for the platform's access-servers API. */\nconst ACCESS_SERVERS_API = '/api/access-servers'\n/** Base route for the platform's connectivity-providers API (ZTNA picker). */\nconst CONNECTIVITY_PROVIDERS_API = '/api/connectivity-providers'\n\n/**\n * Loosely-typed shape of a raw access server as returned by the platform,\n * before it is normalized down to the {@link AccessServer} surface.\n */\ninterface RawAccessServer {\n id: string\n name?: string\n endpoint?: string\n type?: string\n region?: string | null\n status?: string\n description?: string | null\n connectivityProviderId?: string | null\n connectivityProvider?: { id: string; name: string } | null\n}\n\n/**\n * Loosely-typed shape of a raw connectivity provider as returned by the\n * platform, before it is normalized to the {@link ConnectivityProviderRef}\n * picker surface.\n */\ninterface RawConnectivityProvider {\n id: string\n name?: string\n providerType?: string\n status?: string\n}\n\n/** Build an Error from a non-2xx response, preferring the platform's message. */\nasync function accessServerError(res: Response): Promise<Error> {\n const text = await res.text().catch(() => '')\n if (text) {\n try {\n const body = JSON.parse(text) as { error?: string; message?: string }\n const message = body?.error ?? body?.message\n if (message) return new Error(message)\n } catch {\n // Body was not JSON — fall through and use the raw text.\n }\n return new Error(text)\n }\n return new Error(`HTTP ${res.status}`)\n}\n\n/** Normalize a raw platform access server into the typed AccessServer surface. */\nfunction toAccessServer(raw: RawAccessServer): AccessServer {\n return {\n id: String(raw.id),\n name: raw.name ?? '',\n endpoint: raw.endpoint ?? '',\n type: raw.type ?? undefined,\n region: raw.region ?? null,\n status: raw.status ?? undefined,\n description: raw.description ?? null,\n connectivityProviderId: raw.connectivityProviderId ?? null,\n connectivityProvider: raw.connectivityProvider\n ? { id: String(raw.connectivityProvider.id), name: String(raw.connectivityProvider.name) }\n : null,\n }\n}\n\n/** List the customer's access servers (ZTNA gateways). GET /api/access-servers */\nexport async function listAccessServers(): Promise<AccessServer[]> {\n const res = await authFetch(ACCESS_SERVERS_API)\n if (!res.ok) throw await accessServerError(res)\n const data = (await res.json()) as RawAccessServer[]\n return Array.isArray(data) ? data.map(toAccessServer) : []\n}\n\n/** Add a new access server (ZTNA gateway). POST /api/access-servers */\nexport async function addAccessServer(input: AccessServerInput): Promise<AccessServer> {\n const res = await authFetch(ACCESS_SERVERS_API, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n })\n if (!res.ok) throw await accessServerError(res)\n return toAccessServer((await res.json()) as RawAccessServer)\n}\n\n/** Update an existing access server. PUT /api/access-servers/:id */\nexport async function updateAccessServer(\n id: string,\n input: AccessServerInput,\n): Promise<AccessServer> {\n const res = await authFetch(`${ACCESS_SERVERS_API}/${encodeURIComponent(id)}`, {\n method: 'PUT',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(input),\n })\n if (!res.ok) throw await accessServerError(res)\n return toAccessServer((await res.json()) as RawAccessServer)\n}\n\n/** Remove an access server. DELETE /api/access-servers/:id */\nexport async function removeAccessServer(id: string): Promise<void> {\n const res = await authFetch(`${ACCESS_SERVERS_API}/${encodeURIComponent(id)}`, {\n method: 'DELETE',\n })\n // 204 No Content is the platform's success response for delete.\n if (!res.ok && res.status !== 204) throw await accessServerError(res)\n}\n\n/**\n * List the customer's ZTNA connectivity providers, used to populate the Access\n * Server link picker. GET /api/connectivity-providers (the endpoint may return\n * a bare array or a paginated `{ data, ... }` shape — both are handled).\n */\nexport async function listConnectivityProviders(): Promise<ConnectivityProviderRef[]> {\n const res = await authFetch(CONNECTIVITY_PROVIDERS_API)\n if (!res.ok) throw await accessServerError(res)\n const body = (await res.json()) as unknown\n const providers: RawConnectivityProvider[] = Array.isArray(body)\n ? (body as RawConnectivityProvider[])\n : Array.isArray((body as { data?: unknown })?.data)\n ? ((body as { data: RawConnectivityProvider[] }).data)\n : []\n return providers.map((provider) => ({\n id: String(provider.id),\n name: provider.name ?? '',\n providerType: provider.providerType ?? undefined,\n status: provider.status ?? undefined,\n }))\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACmBA,IAAM,gBAAgB;AAkBtB,eAAe,eAAe,KAA+B;AAC3D,QAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC5C,MAAI,MAAM;AACR,QAAI;AACF,YAAM,OAAO,KAAK,MAAM,IAAI;AAC5B,YAAM,UAAU,MAAM,SAAS,MAAM;AACrC,UAAI,QAAS,QAAO,IAAI,MAAM,OAAO;AAAA,IACvC,QAAQ;AAAA,IAER;AACA,WAAO,IAAI,MAAM,IAAI;AAAA,EACvB;AACA,SAAO,IAAI,MAAM,QAAQ,IAAI,MAAM,EAAE;AACvC;AAGA,SAAS,gBAAgB,KAAsC;AAC7D,SAAO;AAAA,IACL,IAAI,OAAO,IAAI,EAAE;AAAA,IACjB,UAAU,IAAI,YAAY;AAAA,IAC1B,MAAM,IAAI,QAAQ;AAAA,IAClB,MAAM,MAAM,QAAQ,IAAI,IAAI,IAAI,IAAI,OAAO;AAAA,IAC3C,SAAS,MAAM,QAAQ,IAAI,OAAO,IAAI,IAAI,UAAU,CAAC;AAAA,IACrD,UAAU,MAAM,QAAQ,IAAI,QAAQ,IAAI,IAAI,WAAW,CAAC;AAAA,IACxD,MAAM,MAAM,QAAQ,IAAI,IAAI,IACxB,IAAI,KAAK,IAAI,CAAC,SAAS,EAAE,IAAI,OAAO,IAAI,EAAE,GAAG,MAAM,OAAO,IAAI,IAAI,EAAE,EAAE,IACtE,CAAC;AAAA,IACL,wBAAwB,IAAI,0BAA0B;AAAA,EACxD;AACF;AAqBA,eAAsB,YAAY,MAAoC;AACpE,QAAM,MAAM,MAAM,UAAU,YAAY;AACxC,MAAI,CAAC,IAAI,GAAI,OAAM,MAAM,eAAe,GAAG;AAC3C,QAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,QAAM,QAAgB,MAAM,QAAQ,IAAI,IACnC,OACD,MAAM,QAAS,MAA6B,IAAI,IAC5C,KAA0B,OAC5B,CAAC;AACP,SAAO,MAAM,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,KAAK;AACrD;AAGA,eAAsB,gBAA0C;AAC9D,QAAM,MAAM,MAAM,UAAU,aAAa;AACzC,MAAI,CAAC,IAAI,GAAI,OAAM,MAAM,eAAe,GAAG;AAC3C,QAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,SAAO,MAAM,QAAQ,IAAI,IAAI,KAAK,IAAI,eAAe,IAAI,CAAC;AAC5D;AAGA,eAAsB,iBAAiB,OAAmD;AACxF,QAAM,MAAM,MAAM,UAAU,eAAe;AAAA,IACzC,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,KAAK;AAAA,EAC5B,CAAC;AACD,MAAI,CAAC,IAAI,GAAI,OAAM,MAAM,eAAe,GAAG;AAC3C,SAAO,gBAAiB,MAAM,IAAI,KAAK,CAAsB;AAC/D;AAGA,eAAsB,oBACpB,IACA,OACwB;AACxB,QAAM,MAAM,MAAM,UAAU,GAAG,aAAa,IAAI,mBAAmB,EAAE,CAAC,IAAI;AAAA,IACxE,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,KAAK;AAAA,EAC5B,CAAC;AACD,MAAI,CAAC,IAAI,GAAI,OAAM,MAAM,eAAe,GAAG;AAC3C,SAAO,gBAAiB,MAAM,IAAI,KAAK,CAAsB;AAC/D;AAGA,eAAsB,oBAAoB,IAA2B;AACnE,QAAM,MAAM,MAAM,UAAU,GAAG,aAAa,IAAI,mBAAmB,EAAE,CAAC,IAAI;AAAA,IACxE,QAAQ;AAAA,EACV,CAAC;AAED,MAAI,CAAC,IAAI,MAAM,IAAI,WAAW,IAAK,OAAM,MAAM,eAAe,GAAG;AACnE;;;ACnHA,IAAM,qBAAqB;AAE3B,IAAM,6BAA6B;AA+BnC,eAAe,kBAAkB,KAA+B;AAC9D,QAAM,OAAO,MAAM,IAAI,KAAK,EAAE,MAAM,MAAM,EAAE;AAC5C,MAAI,MAAM;AACR,QAAI;AACF,YAAM,OAAO,KAAK,MAAM,IAAI;AAC5B,YAAM,UAAU,MAAM,SAAS,MAAM;AACrC,UAAI,QAAS,QAAO,IAAI,MAAM,OAAO;AAAA,IACvC,QAAQ;AAAA,IAER;AACA,WAAO,IAAI,MAAM,IAAI;AAAA,EACvB;AACA,SAAO,IAAI,MAAM,QAAQ,IAAI,MAAM,EAAE;AACvC;AAGA,SAAS,eAAe,KAAoC;AAC1D,SAAO;AAAA,IACL,IAAI,OAAO,IAAI,EAAE;AAAA,IACjB,MAAM,IAAI,QAAQ;AAAA,IAClB,UAAU,IAAI,YAAY;AAAA,IAC1B,MAAM,IAAI,QAAQ;AAAA,IAClB,QAAQ,IAAI,UAAU;AAAA,IACtB,QAAQ,IAAI,UAAU;AAAA,IACtB,aAAa,IAAI,eAAe;AAAA,IAChC,wBAAwB,IAAI,0BAA0B;AAAA,IACtD,sBAAsB,IAAI,uBACtB,EAAE,IAAI,OAAO,IAAI,qBAAqB,EAAE,GAAG,MAAM,OAAO,IAAI,qBAAqB,IAAI,EAAE,IACvF;AAAA,EACN;AACF;AAGA,eAAsB,oBAA6C;AACjE,QAAM,MAAM,MAAM,UAAU,kBAAkB;AAC9C,MAAI,CAAC,IAAI,GAAI,OAAM,MAAM,kBAAkB,GAAG;AAC9C,QAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,SAAO,MAAM,QAAQ,IAAI,IAAI,KAAK,IAAI,cAAc,IAAI,CAAC;AAC3D;AAGA,eAAsB,gBAAgB,OAAiD;AACrF,QAAM,MAAM,MAAM,UAAU,oBAAoB;AAAA,IAC9C,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,KAAK;AAAA,EAC5B,CAAC;AACD,MAAI,CAAC,IAAI,GAAI,OAAM,MAAM,kBAAkB,GAAG;AAC9C,SAAO,eAAgB,MAAM,IAAI,KAAK,CAAqB;AAC7D;AAGA,eAAsB,mBACpB,IACA,OACuB;AACvB,QAAM,MAAM,MAAM,UAAU,GAAG,kBAAkB,IAAI,mBAAmB,EAAE,CAAC,IAAI;AAAA,IAC7E,QAAQ;AAAA,IACR,SAAS,EAAE,gBAAgB,mBAAmB;AAAA,IAC9C,MAAM,KAAK,UAAU,KAAK;AAAA,EAC5B,CAAC;AACD,MAAI,CAAC,IAAI,GAAI,OAAM,MAAM,kBAAkB,GAAG;AAC9C,SAAO,eAAgB,MAAM,IAAI,KAAK,CAAqB;AAC7D;AAGA,eAAsB,mBAAmB,IAA2B;AAClE,QAAM,MAAM,MAAM,UAAU,GAAG,kBAAkB,IAAI,mBAAmB,EAAE,CAAC,IAAI;AAAA,IAC7E,QAAQ;AAAA,EACV,CAAC;AAED,MAAI,CAAC,IAAI,MAAM,IAAI,WAAW,IAAK,OAAM,MAAM,kBAAkB,GAAG;AACtE;AAOA,eAAsB,4BAAgE;AACpF,QAAM,MAAM,MAAM,UAAU,0BAA0B;AACtD,MAAI,CAAC,IAAI,GAAI,OAAM,MAAM,kBAAkB,GAAG;AAC9C,QAAM,OAAQ,MAAM,IAAI,KAAK;AAC7B,QAAM,YAAuC,MAAM,QAAQ,IAAI,IAC1D,OACD,MAAM,QAAS,MAA6B,IAAI,IAC5C,KAA6C,OAC/C,CAAC;AACP,SAAO,UAAU,IAAI,CAAC,cAAc;AAAA,IAClC,IAAI,OAAO,SAAS,EAAE;AAAA,IACtB,MAAM,SAAS,QAAQ;AAAA,IACvB,cAAc,SAAS,gBAAgB;AAAA,IACvC,QAAQ,SAAS,UAAU;AAAA,EAC7B,EAAE;AACJ;;;AFvGO,IAAM,sBAAsB;AAqC5B,SAAS,iBAA4C;AAC1D,QAAM,UAAW,WAAuC,mBAAmB;AAC3E,SAAQ,WAAkC;AAC5C;AAGO,SAAS,qBAAyC;AACvD,QAAM,UAAU,eAAe;AAC/B,MAAI,CAAC,SAAS;AACZ,UAAM,IAAI;AAAA,MACR,qHAC0C,mBAAmB;AAAA,IAC/D;AAAA,EACF;AACA,SAAO;AACT;AAOO,SAAS,UAAU,OAAe,MAAuC;AAC9E,QAAM,UAAU,eAAe;AAC/B,MAAI,QAAS,QAAO,QAAQ,UAAU,OAAO,IAAI;AACjD,SAAO,MAAM,OAAO,IAAI;AAC1B;","names":[]}
@@ -1,7 +1,26 @@
1
1
  import { ComponentType, LazyExoticComponent, Context } from 'react';
2
- import { y as InventoryItemInput, I as InventoryItem, b as AppContextValue } from '../use-app-context-Dh1S28Cv.cjs';
3
- export { A as AppBrandingDeclaration } from '../use-app-context-Dh1S28Cv.cjs';
2
+ import { D as InventoryItemInput, I as InventoryItem, f as AccessServerInput, e as AccessServer, y as ConnectivityProviderRef, b as AppContextValue } from '../use-app-context-Df_dfcOm.cjs';
3
+ export { A as AppBrandingDeclaration } from '../use-app-context-Df_dfcOm.cjs';
4
4
 
5
+ /**
6
+ * A platform Tool. Each installed app is upserted as a Tool keyed by its
7
+ * manifest `name`, and inventory items (components) belong to a tool.
8
+ */
9
+ interface Tool {
10
+ id: string;
11
+ name: string;
12
+ vendor?: string;
13
+ }
14
+ /**
15
+ * Resolve the platform Tool for an app by its manifest name (the platform
16
+ * upserts `Tool.name === app name`). The tool id is required by the platform
17
+ * when creating an inventory item, so call this once and pass the id as
18
+ * `toolId` to {@link addInventoryItem}. Returns null when no tool matches.
19
+ *
20
+ * GET /api/tools (the endpoint is paginated — `{ data, pagination }` — or a
21
+ * bare array; both are handled).
22
+ */
23
+ declare function resolveTool(name: string): Promise<Tool | null>;
5
24
  /** List the customer's inventory (deployment targets). GET /api/components */
6
25
  declare function listInventory(): Promise<InventoryItem[]>;
7
26
  /** Add a new inventory item (deployment target). POST /api/components */
@@ -11,6 +30,21 @@ declare function updateInventoryItem(id: string, input: InventoryItemInput): Pro
11
30
  /** Remove an inventory item. DELETE /api/components/:id */
12
31
  declare function removeInventoryItem(id: string): Promise<void>;
13
32
 
33
+ /** List the customer's access servers (ZTNA gateways). GET /api/access-servers */
34
+ declare function listAccessServers(): Promise<AccessServer[]>;
35
+ /** Add a new access server (ZTNA gateway). POST /api/access-servers */
36
+ declare function addAccessServer(input: AccessServerInput): Promise<AccessServer>;
37
+ /** Update an existing access server. PUT /api/access-servers/:id */
38
+ declare function updateAccessServer(id: string, input: AccessServerInput): Promise<AccessServer>;
39
+ /** Remove an access server. DELETE /api/access-servers/:id */
40
+ declare function removeAccessServer(id: string): Promise<void>;
41
+ /**
42
+ * List the customer's ZTNA connectivity providers, used to populate the Access
43
+ * Server link picker. GET /api/connectivity-providers (the endpoint may return
44
+ * a bare array or a paginated `{ data, ... }` shape — both are handled).
45
+ */
46
+ declare function listConnectivityProviders(): Promise<ConnectivityProviderRef[]>;
47
+
14
48
  /** Name of the global the platform installs before loading app bundles. */
15
49
  declare const HOST_RUNTIME_GLOBAL = "__VELTRIX_APP_RUNTIME__";
16
50
  /**
@@ -72,4 +106,4 @@ interface AppClientModule {
72
106
  sidebarItems?: AppSidebarItem[];
73
107
  }
74
108
 
75
- export { type AppClientModule, type AppSidebarItem, HOST_RUNTIME_GLOBAL, InventoryItem, InventoryItemInput, type VeltrixHostRuntime, addInventoryItem, authFetch, getHostRuntime, listInventory, removeInventoryItem, requireHostRuntime, updateInventoryItem };
109
+ export { AccessServer, AccessServerInput, type AppClientModule, type AppSidebarItem, ConnectivityProviderRef, HOST_RUNTIME_GLOBAL, InventoryItem, InventoryItemInput, type Tool, type VeltrixHostRuntime, addAccessServer, addInventoryItem, authFetch, getHostRuntime, listAccessServers, listConnectivityProviders, listInventory, removeAccessServer, removeInventoryItem, requireHostRuntime, resolveTool, updateAccessServer, updateInventoryItem };
@@ -1,7 +1,26 @@
1
1
  import { ComponentType, LazyExoticComponent, Context } from 'react';
2
- import { y as InventoryItemInput, I as InventoryItem, b as AppContextValue } from '../use-app-context-Dh1S28Cv.js';
3
- export { A as AppBrandingDeclaration } from '../use-app-context-Dh1S28Cv.js';
2
+ import { D as InventoryItemInput, I as InventoryItem, f as AccessServerInput, e as AccessServer, y as ConnectivityProviderRef, b as AppContextValue } from '../use-app-context-Df_dfcOm.js';
3
+ export { A as AppBrandingDeclaration } from '../use-app-context-Df_dfcOm.js';
4
4
 
5
+ /**
6
+ * A platform Tool. Each installed app is upserted as a Tool keyed by its
7
+ * manifest `name`, and inventory items (components) belong to a tool.
8
+ */
9
+ interface Tool {
10
+ id: string;
11
+ name: string;
12
+ vendor?: string;
13
+ }
14
+ /**
15
+ * Resolve the platform Tool for an app by its manifest name (the platform
16
+ * upserts `Tool.name === app name`). The tool id is required by the platform
17
+ * when creating an inventory item, so call this once and pass the id as
18
+ * `toolId` to {@link addInventoryItem}. Returns null when no tool matches.
19
+ *
20
+ * GET /api/tools (the endpoint is paginated — `{ data, pagination }` — or a
21
+ * bare array; both are handled).
22
+ */
23
+ declare function resolveTool(name: string): Promise<Tool | null>;
5
24
  /** List the customer's inventory (deployment targets). GET /api/components */
6
25
  declare function listInventory(): Promise<InventoryItem[]>;
7
26
  /** Add a new inventory item (deployment target). POST /api/components */
@@ -11,6 +30,21 @@ declare function updateInventoryItem(id: string, input: InventoryItemInput): Pro
11
30
  /** Remove an inventory item. DELETE /api/components/:id */
12
31
  declare function removeInventoryItem(id: string): Promise<void>;
13
32
 
33
+ /** List the customer's access servers (ZTNA gateways). GET /api/access-servers */
34
+ declare function listAccessServers(): Promise<AccessServer[]>;
35
+ /** Add a new access server (ZTNA gateway). POST /api/access-servers */
36
+ declare function addAccessServer(input: AccessServerInput): Promise<AccessServer>;
37
+ /** Update an existing access server. PUT /api/access-servers/:id */
38
+ declare function updateAccessServer(id: string, input: AccessServerInput): Promise<AccessServer>;
39
+ /** Remove an access server. DELETE /api/access-servers/:id */
40
+ declare function removeAccessServer(id: string): Promise<void>;
41
+ /**
42
+ * List the customer's ZTNA connectivity providers, used to populate the Access
43
+ * Server link picker. GET /api/connectivity-providers (the endpoint may return
44
+ * a bare array or a paginated `{ data, ... }` shape — both are handled).
45
+ */
46
+ declare function listConnectivityProviders(): Promise<ConnectivityProviderRef[]>;
47
+
14
48
  /** Name of the global the platform installs before loading app bundles. */
15
49
  declare const HOST_RUNTIME_GLOBAL = "__VELTRIX_APP_RUNTIME__";
16
50
  /**
@@ -72,4 +106,4 @@ interface AppClientModule {
72
106
  sidebarItems?: AppSidebarItem[];
73
107
  }
74
108
 
75
- export { type AppClientModule, type AppSidebarItem, HOST_RUNTIME_GLOBAL, InventoryItem, InventoryItemInput, type VeltrixHostRuntime, addInventoryItem, authFetch, getHostRuntime, listInventory, removeInventoryItem, requireHostRuntime, updateInventoryItem };
109
+ export { AccessServer, AccessServerInput, type AppClientModule, type AppSidebarItem, ConnectivityProviderRef, HOST_RUNTIME_GLOBAL, InventoryItem, InventoryItemInput, type Tool, type VeltrixHostRuntime, addAccessServer, addInventoryItem, authFetch, getHostRuntime, listAccessServers, listConnectivityProviders, listInventory, removeAccessServer, removeInventoryItem, requireHostRuntime, resolveTool, updateAccessServer, updateInventoryItem };
@@ -1,21 +1,33 @@
1
1
  import {
2
2
  HOST_RUNTIME_GLOBAL,
3
+ addAccessServer,
3
4
  addInventoryItem,
4
5
  authFetch,
5
6
  getHostRuntime,
7
+ listAccessServers,
8
+ listConnectivityProviders,
6
9
  listInventory,
10
+ removeAccessServer,
7
11
  removeInventoryItem,
8
12
  requireHostRuntime,
13
+ resolveTool,
14
+ updateAccessServer,
9
15
  updateInventoryItem
10
- } from "../chunk-MMWEXHPU.js";
16
+ } from "../chunk-TE4UNXKW.js";
11
17
  export {
12
18
  HOST_RUNTIME_GLOBAL,
19
+ addAccessServer,
13
20
  addInventoryItem,
14
21
  authFetch,
15
22
  getHostRuntime,
23
+ listAccessServers,
24
+ listConnectivityProviders,
16
25
  listInventory,
26
+ removeAccessServer,
17
27
  removeInventoryItem,
18
28
  requireHostRuntime,
29
+ resolveTool,
30
+ updateAccessServer,
19
31
  updateInventoryItem
20
32
  };
21
33
  //# sourceMappingURL=index.js.map