@neon/tools 0.5.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -110
- package/dist/index.d.ts +24 -50
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +23 -43
- package/dist/lib/ergonomic/bind.d.ts +57 -0
- package/dist/lib/ergonomic/bind.d.ts.map +1 -0
- package/dist/lib/ergonomic/bind.js +126 -0
- package/dist/lib/ergonomic/catalog.d.ts +2601 -0
- package/dist/lib/ergonomic/catalog.d.ts.map +1 -0
- package/dist/lib/ergonomic/catalog.js +703 -0
- package/dist/lib/ergonomic/composed.d.ts +450 -0
- package/dist/lib/ergonomic/composed.d.ts.map +1 -0
- package/dist/lib/ergonomic/composed.js +186 -0
- package/dist/lib/ergonomic/ids.d.ts +7 -0
- package/dist/lib/ergonomic/ids.d.ts.map +1 -0
- package/dist/lib/ergonomic/ids.js +122 -0
- package/dist/lib/ergonomic/index.d.ts +4 -0
- package/dist/lib/ergonomic/index.d.ts.map +1 -0
- package/dist/lib/ergonomic/index.js +4 -0
- package/package.json +2 -2
- package/dist/lib/workflows.d.ts +0 -315
- package/dist/lib/workflows.d.ts.map +0 -1
- package/dist/lib/workflows.js +0 -113
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# `@neon/tools`
|
|
2
2
|
|
|
3
|
-
Agent tools for the
|
|
3
|
+
Agent tools for the `@neon/sdk` ergonomic client. Select the methods an agent needs, then use the descriptors directly or adapt them for MCP, Eve, and Mastra.
|
|
4
4
|
|
|
5
5
|
```bash
|
|
6
6
|
npm install @neon/tools
|
|
@@ -8,119 +8,88 @@ npm install @neon/tools
|
|
|
8
8
|
|
|
9
9
|
## Create tools
|
|
10
10
|
|
|
11
|
-
|
|
11
|
+
Selectors are SDK paths. The returned record is keyed by those paths. Each tool's published `id` is the last path segment, then the resource, in snake_case (`projects.list` → `list_projects`, `postgres.roles.resetPassword` → `reset_password_postgres_roles`, `postgres.connectionString` → `connection_string_postgres`). `publishedId` derives that string. `toolIds` lists every published selector.
|
|
12
12
|
|
|
13
13
|
```ts
|
|
14
|
-
import { createNeonTools } from "@neon/tools";
|
|
14
|
+
import { createNeonTools, publishedId } from "@neon/tools";
|
|
15
|
+
|
|
16
|
+
publishedId("projects.list"); // "list_projects"
|
|
17
|
+
publishedId("postgres.roles.resetPassword"); // "reset_password_postgres_roles"
|
|
15
18
|
|
|
16
19
|
const apiKey = process.env.NEON_API_KEY;
|
|
17
20
|
if (!apiKey) throw new Error("NEON_API_KEY is required");
|
|
18
21
|
|
|
19
|
-
const operations = ["listProjects", "createProject"] as const;
|
|
20
|
-
|
|
21
22
|
const tools = createNeonTools({
|
|
22
23
|
apiKey,
|
|
23
|
-
|
|
24
|
+
tools: [
|
|
25
|
+
"projects.list",
|
|
26
|
+
"projects.createAndConnect",
|
|
27
|
+
"branches.createWithCompute",
|
|
28
|
+
],
|
|
24
29
|
});
|
|
25
30
|
|
|
26
|
-
const
|
|
27
|
-
|
|
31
|
+
const listed = await tools["projects.list"].execute({ limit: 10 });
|
|
32
|
+
const created = await tools["projects.createAndConnect"].execute({
|
|
33
|
+
name: "agent-project",
|
|
34
|
+
region_id: "aws-us-east-1",
|
|
28
35
|
});
|
|
29
36
|
```
|
|
30
37
|
|
|
31
|
-
|
|
38
|
+
`limit` on a list tool caps how many items come back.
|
|
39
|
+
|
|
40
|
+
MCP and Mastra publish `tool.id` (`list_projects`), not the record key.
|
|
41
|
+
|
|
42
|
+
`apiKey` is a Bearer credential: a Neon API key or a Neon OAuth access token. A function is called on every request, which is how short-lived OAuth tokens get refreshed. A credential is required when a tool executes — at construction, on `execute()`, or from MCP `authInfo` — and an empty value is rejected rather than ignored.
|
|
32
43
|
|
|
33
44
|
```ts
|
|
34
45
|
const tools = createNeonTools({
|
|
35
46
|
apiKey: () => oauth.getAccessToken(),
|
|
36
|
-
|
|
47
|
+
tools: ["projects.list"],
|
|
37
48
|
});
|
|
38
|
-
```
|
|
39
|
-
|
|
40
|
-
Or supply the token per call:
|
|
41
|
-
|
|
42
|
-
```ts
|
|
43
|
-
const tools = createNeonTools({ operations });
|
|
44
49
|
|
|
45
|
-
await tools.
|
|
50
|
+
await tools["projects.list"].execute(
|
|
46
51
|
{ limit: 10 },
|
|
47
52
|
{ apiKey: oauthAccessToken },
|
|
48
53
|
);
|
|
49
54
|
```
|
|
50
55
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
`operationIds` exports every valid operation selector. `execute()` strictly validates the input, rejects unknown fields instead of dropping them, and returns typed, JSON-safe `{ data }`. Neon SDK errors remain typed and are thrown to the caller.
|
|
54
|
-
|
|
55
|
-
## Workflows
|
|
56
|
+
Each tool includes its Zod 4 `inputSchema`, published `id`, title, description, safety annotations, stability metadata, and `execute()`. Inputs are snake_case at the tool boundary. `execute()` strictly validates the input, rejects unknown fields, and returns typed, JSON-safe `{ data }`. Neon SDK errors remain typed and are thrown to the caller.
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
Both workflow tools poll until the resource is ready. The default deadline is five minutes (`wait.timeoutMs`). Pass `wait: { timeoutMs: 30_000 }` on `createNeonTools` or `createNeonTool` to bound that. Set it below the host's own tool-call timeout, otherwise the host gives up first. An abort `signal` on `execute` or a wait timeout stops the poll, not the create: the branch or project may already exist, and the error does not include its id. List before retrying. `metadata.method` and `metadata.path` name the first request; extra readiness GETs are not listed there. `inject.projectId` still works on `createBranchWithCompute` because its path is `/projects/{project_id}/branches`.
|
|
58
|
+
Paginated lists call `.all()` and return the item array. Do not pass a cursor; those fields are omitted from the input schema.
|
|
60
59
|
|
|
61
60
|
```ts
|
|
62
|
-
const
|
|
63
|
-
apiKey,
|
|
64
|
-
operations: ["listProjects"],
|
|
65
|
-
workflows: ["createBranchWithCompute", "createProjectAndConnect"],
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
const { data } = await tools.createBranchWithCompute.execute({
|
|
69
|
-
project_id: "project-id",
|
|
70
|
-
name: "feature-x",
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
await tools.createProjectAndConnect.execute({
|
|
74
|
-
name: "agent-project",
|
|
75
|
-
region_id: "aws-us-east-1",
|
|
76
|
-
});
|
|
61
|
+
const createBranch = createNeonTool("branches.createWithCompute", { apiKey });
|
|
77
62
|
```
|
|
78
63
|
|
|
79
|
-
|
|
64
|
+
## Writes and waiting
|
|
80
65
|
|
|
81
|
-
|
|
82
|
-
const createBranch = createNeonTool("createBranchWithCompute", { apiKey });
|
|
83
|
-
```
|
|
66
|
+
Tools run with `waitForReadiness: true`. When a mutation response includes an `operations` array, the call waits until those operations finish. The default deadline is five minutes (`wait.timeoutMs`). Pass `wait: { timeoutMs: 30_000 }` on `createNeonTools` or `createNeonTool` to bound that. Set it below the host's own tool-call timeout, otherwise the host gives up first.
|
|
84
67
|
|
|
85
|
-
|
|
68
|
+
An abort `signal` on `execute` or a wait timeout stops the poll, not the create: the branch or project may already exist, and the error does not include its id. List before retrying.
|
|
86
69
|
|
|
87
|
-
|
|
88
|
-
const tools = createNeonTools({
|
|
89
|
-
apiKey,
|
|
90
|
-
workflows: ["createBranchWithCompute"],
|
|
91
|
-
names: { createBranchWithCompute: "create_branch" },
|
|
92
|
-
});
|
|
70
|
+
`functions.deploy` can still return `pending`. Its response has no `operations` array, so the tool does not poll.
|
|
93
71
|
|
|
94
|
-
|
|
95
|
-
```
|
|
72
|
+
`metadata.method` and `metadata.path` name the first request; extra readiness GETs are not listed there.
|
|
96
73
|
|
|
97
|
-
|
|
74
|
+
These public client methods are not tools: `projects.create`, `branches.create`, `operations.waitFor`, `postgres.roles.password`, and `storage.objects.get`. Use `projects.createAndConnect` and `branches.createWithCompute` for creates that attach compute and return a connection string. Waiting is what the write tools already do.
|
|
98
75
|
|
|
99
76
|
## Optional host add-ons
|
|
100
77
|
|
|
101
|
-
None of these change the default `createNeonTools({ apiKey, operations })` path. They exist so a host can replace hand-written Management API tools without losing descriptions, call tracking, or a grant-scoped project/branch.
|
|
102
|
-
|
|
103
78
|
### Descriptions
|
|
104
79
|
|
|
105
|
-
Pass a map keyed by
|
|
80
|
+
Pass a map keyed by SDK path or the current published `id`, or a function that can append to the generated text. A key that matches neither is ignored.
|
|
106
81
|
|
|
107
82
|
```ts
|
|
108
83
|
const tools = createNeonTools({
|
|
109
84
|
apiKey,
|
|
110
|
-
|
|
85
|
+
tools: ["projects.list", "projects.delete"],
|
|
111
86
|
descriptions: {
|
|
112
|
-
|
|
87
|
+
"projects.list":
|
|
113
88
|
"List Neon projects in your account. Do not use for projects shared with you.",
|
|
114
|
-
|
|
89
|
+
delete_projects:
|
|
115
90
|
"Delete a Neon project and all its data. NEVER run autonomously; always ask the user first.",
|
|
116
91
|
},
|
|
117
92
|
});
|
|
118
|
-
|
|
119
|
-
const noticed = createNeonTools({
|
|
120
|
-
apiKey,
|
|
121
|
-
operations,
|
|
122
|
-
descriptions: (tool) => `${tool.description}\nNotice: scoped to one project.`,
|
|
123
|
-
});
|
|
124
93
|
```
|
|
125
94
|
|
|
126
95
|
### Tracking
|
|
@@ -130,9 +99,8 @@ const noticed = createNeonTools({
|
|
|
130
99
|
```ts
|
|
131
100
|
const tools = createNeonTools({
|
|
132
101
|
apiKey,
|
|
133
|
-
|
|
102
|
+
tools: ["projects.list"],
|
|
134
103
|
onExecute: async ({ id, execute }) => {
|
|
135
|
-
// record `id`, wrap in a span, then:
|
|
136
104
|
return execute();
|
|
137
105
|
},
|
|
138
106
|
});
|
|
@@ -142,38 +110,35 @@ This package does not send analytics. Mutating `event.input` does not change a g
|
|
|
142
110
|
|
|
143
111
|
### Names
|
|
144
112
|
|
|
145
|
-
`name` rewrites every published tool `id`. `names` overrides one tool first, keyed by
|
|
113
|
+
`name` rewrites every published tool `id`. `names` overrides one tool first, keyed by SDK path or the generated snake-case `id`:
|
|
146
114
|
|
|
147
115
|
```ts
|
|
148
116
|
const tools = createNeonTools({
|
|
149
117
|
apiKey,
|
|
150
|
-
|
|
151
|
-
names: {
|
|
118
|
+
tools: ["branches.createWithCompute", "projects.list"] as const,
|
|
119
|
+
names: { "branches.createWithCompute": "create_branch" },
|
|
152
120
|
name: (id) => `neon_${id}`,
|
|
153
121
|
});
|
|
154
|
-
|
|
155
|
-
tools.createProjectBranch.id; // "neon_create_branch"
|
|
156
|
-
tools.listProjects.id; // "neon_list_projects"
|
|
157
122
|
```
|
|
158
123
|
|
|
159
|
-
The record is still keyed by
|
|
124
|
+
Those tools publish as `neon_create_branch` and `neon_list_projects`. The record is still keyed by SDK path (`tools["branches.createWithCompute"]`). MCP and Mastra publish `tool.id`. Eve uses the filename as the model-facing name, so name the file after the published `id`. Duplicate or non-snake-case ids throw, and a `names` key that matches no selected tool throws.
|
|
160
125
|
|
|
161
126
|
### Project and branch injection
|
|
162
127
|
|
|
163
|
-
Tools take path parameters as `project_id` and `branch_id`. A host that already knows those values can inject them, including on `
|
|
128
|
+
Tools take path parameters as `project_id` and `branch_id`. A host that already knows those values can inject them, including on `branches.createWithCompute`. Without `omitFromSchema`, the published field becomes optional and a caller-supplied value wins. With `omitFromSchema: true`, the field is removed from the published schema and the injector is the only source:
|
|
164
129
|
|
|
165
130
|
```ts
|
|
166
131
|
const tools = createNeonTools({
|
|
167
132
|
apiKey,
|
|
168
|
-
|
|
133
|
+
tools: ["projects.get", "branches.delete"] as const,
|
|
169
134
|
inject: {
|
|
170
135
|
projectId: "project-id",
|
|
171
136
|
omitFromSchema: true,
|
|
172
137
|
},
|
|
173
138
|
});
|
|
174
139
|
|
|
175
|
-
await tools.
|
|
176
|
-
await tools.
|
|
140
|
+
await tools["projects.get"].execute({});
|
|
141
|
+
await tools["branches.delete"].execute({ branch_id: "br-id" });
|
|
177
142
|
```
|
|
178
143
|
|
|
179
144
|
Use a getter when the value is request-scoped. The getter can read the host's own `AsyncLocalStorage` (this package does not export one):
|
|
@@ -184,21 +149,21 @@ import { AsyncLocalStorage } from "node:async_hooks";
|
|
|
184
149
|
const grant = new AsyncLocalStorage<{ projectId: string }>();
|
|
185
150
|
|
|
186
151
|
const tools = createNeonTools({
|
|
187
|
-
|
|
152
|
+
tools: ["projects.get"] as const,
|
|
188
153
|
inject: {
|
|
189
154
|
projectId: () => grant.getStore()?.projectId,
|
|
190
155
|
omitFromSchema: true,
|
|
191
156
|
},
|
|
192
157
|
});
|
|
193
158
|
|
|
194
|
-
await grant.run({ projectId: "project-id" }, () =>
|
|
159
|
+
await grant.run({ projectId: "project-id" }, () =>
|
|
160
|
+
tools["projects.get"].execute({}),
|
|
161
|
+
);
|
|
195
162
|
```
|
|
196
163
|
|
|
197
|
-
Injectors only apply to tools that have that path key. `
|
|
164
|
+
Injectors only apply to tools that have that path key. `projects.list` is unchanged. Empty inject values fail closed. Invalid ids still fail the original path schema before fetch.
|
|
198
165
|
|
|
199
|
-
`
|
|
200
|
-
|
|
201
|
-
Injection reads the URL template, so it fills path `project_id` and `branch_id` only. Query and body fields with those names stay caller-supplied, including `getConnectionURI.branch_id`, `createOrgApiKey.project_id`, `createNeonAuthIntegration.project_id` / `branch_id`, `createNeonAuthNewUser.project_id`, `createNeonAuthProviderSDKKeys.project_id`, `transferNeonAuthProviderProject.project_id`, `addProjectJWKS.branch_id`, `createProjectEndpoint.branch_id`, `updateProjectEndpoint.branch_id`, and `getProjectAdvisorSecurityIssues.branch_id`. `omitFromSchema: true` does not hide those fields.
|
|
166
|
+
Injection reads the URL template, so it fills path `project_id` and `branch_id` only. Query and body fields with those names stay caller-supplied, including `postgres.connectionString`'s `branch_id`. `omitFromSchema: true` does not hide those fields.
|
|
202
167
|
|
|
203
168
|
## Request schemas
|
|
204
169
|
|
|
@@ -216,7 +181,7 @@ const body = zCreateProjectBody.parse({
|
|
|
216
181
|
});
|
|
217
182
|
```
|
|
218
183
|
|
|
219
|
-
These are the raw OpenAPI request shapes, not the
|
|
184
|
+
These are the raw OpenAPI request shapes, not the tool input. `zCreateProjectBody` still wraps fields in `project`. `projects.createAndConnect` does not.
|
|
220
185
|
|
|
221
186
|
These schemas are strict. If a newly added API field is not recognized, upgrade `@neon/tools`; use `@neon/sdk` directly until a matching tools release is available.
|
|
222
187
|
|
|
@@ -235,7 +200,7 @@ if (!apiKey) throw new Error("NEON_API_KEY is required");
|
|
|
235
200
|
const server = new McpServer({ name: "neon", version: "1.0.0" });
|
|
236
201
|
const tools = createNeonTools({
|
|
237
202
|
apiKey,
|
|
238
|
-
|
|
203
|
+
tools: ["projects.list", "projects.createAndConnect"] as const,
|
|
239
204
|
});
|
|
240
205
|
|
|
241
206
|
registerNeonTools(server, tools);
|
|
@@ -245,7 +210,7 @@ For a remote MCP server that already authenticated the client, omit `apiKey` at
|
|
|
245
210
|
|
|
246
211
|
```ts
|
|
247
212
|
const tools = createNeonTools({
|
|
248
|
-
|
|
213
|
+
tools: ["projects.list", "projects.createAndConnect"] as const,
|
|
249
214
|
});
|
|
250
215
|
registerNeonTools(server, tools);
|
|
251
216
|
```
|
|
@@ -266,8 +231,9 @@ MCP annotations are advisory; the protocol does not enforce approval. Tools expo
|
|
|
266
231
|
|
|
267
232
|
Eve requires Node.js 24 or later.
|
|
268
233
|
|
|
234
|
+
`create_and_connect_projects.ts`:
|
|
235
|
+
|
|
269
236
|
```ts
|
|
270
|
-
// agent/tools/create_project.ts
|
|
271
237
|
import { defineTool } from "eve/tools";
|
|
272
238
|
import { createNeonTool } from "@neon/tools";
|
|
273
239
|
import { toEveTool } from "@neon/tools/eve";
|
|
@@ -277,14 +243,14 @@ if (!apiKey) throw new Error("NEON_API_KEY is required");
|
|
|
277
243
|
|
|
278
244
|
export default defineTool(
|
|
279
245
|
toEveTool(
|
|
280
|
-
createNeonTool("
|
|
246
|
+
createNeonTool("projects.createAndConnect", {
|
|
281
247
|
apiKey,
|
|
282
248
|
}),
|
|
283
249
|
),
|
|
284
250
|
);
|
|
285
251
|
```
|
|
286
252
|
|
|
287
|
-
Eve uses the filename as the model-facing tool name, so name the file after the
|
|
253
|
+
Eve uses the filename as the model-facing tool name, so name the file after the published `id`. The adapter maps approval requirements to Eve's `approval` hook and forwards its abort signal.
|
|
288
254
|
|
|
289
255
|
## Mastra
|
|
290
256
|
|
|
@@ -300,19 +266,19 @@ if (!apiKey) throw new Error("NEON_API_KEY is required");
|
|
|
300
266
|
|
|
301
267
|
const neonTools = createNeonTools({
|
|
302
268
|
apiKey,
|
|
303
|
-
|
|
269
|
+
tools: ["projects.list", "projects.createAndConnect"] as const,
|
|
304
270
|
});
|
|
305
271
|
const configs = toMastraTools(neonTools);
|
|
306
272
|
|
|
307
273
|
const listProjects = createTool(configs.list_projects);
|
|
308
|
-
const createProject = createTool(configs.
|
|
274
|
+
const createProject = createTool(configs.create_and_connect_projects);
|
|
309
275
|
```
|
|
310
276
|
|
|
311
277
|
The adapter maps approval requirements to Mastra's `requireApproval` field and forwards its abort signal.
|
|
312
278
|
|
|
313
279
|
## Safety and binary data
|
|
314
280
|
|
|
315
|
-
Every non-read operation is conservatively marked as potentially destructive and requires approval. Reads that return connection credentials
|
|
281
|
+
Every non-read operation is conservatively marked as potentially destructive and requires approval. Reads that return connection credentials also require approval.
|
|
316
282
|
|
|
317
283
|
Binary request fields accept base64 strings:
|
|
318
284
|
|
|
@@ -322,10 +288,7 @@ import { createNeonTool } from "@neon/tools";
|
|
|
322
288
|
const apiKey = process.env.NEON_API_KEY;
|
|
323
289
|
if (!apiKey) throw new Error("NEON_API_KEY is required");
|
|
324
290
|
|
|
325
|
-
const deployFunction = createNeonTool(
|
|
326
|
-
"createProjectBranchFunctionDeployment",
|
|
327
|
-
{ apiKey },
|
|
328
|
-
);
|
|
291
|
+
const deployFunction = createNeonTool("functions.deploy", { apiKey });
|
|
329
292
|
|
|
330
293
|
await deployFunction.execute({
|
|
331
294
|
project_id: "project-id",
|
|
@@ -335,16 +298,4 @@ await deployFunction.execute({
|
|
|
335
298
|
});
|
|
336
299
|
```
|
|
337
300
|
|
|
338
|
-
Binary responses are JSON-safe:
|
|
339
|
-
|
|
340
|
-
```ts
|
|
341
|
-
{
|
|
342
|
-
data: {
|
|
343
|
-
base64: "aGVsbG8=",
|
|
344
|
-
contentType: "application/octet-stream",
|
|
345
|
-
size: 5,
|
|
346
|
-
},
|
|
347
|
-
}
|
|
348
|
-
```
|
|
349
|
-
|
|
350
301
|
`@neon/tools` supports Node.js 20.19 or later. Framework integrations also require the Node.js version supported by that framework.
|
package/dist/index.d.ts
CHANGED
|
@@ -1,67 +1,41 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { type NeonBearerCredential } from "./lib/auth.js";
|
|
1
|
+
import { NeonError } from "@neon/sdk";
|
|
3
2
|
import { type InjectedNeonTool, type NeonToolCustomizeOptions, type NeonToolInjectOptions, type NeonToolNameOverrides } from "./lib/customize.js";
|
|
4
|
-
import { type
|
|
5
|
-
import { type NeonOperationId, operationFactories, operationIds } from "./operations.gen.js";
|
|
3
|
+
import { type NeonToolId, type PublishedId, publishedId, type ToolClientOptions, toolFactories, toolIds } from "./lib/ergonomic/index.js";
|
|
6
4
|
export type { NeonBearerCredential } from "./lib/auth.js";
|
|
7
5
|
export type { InjectedNeonTool, NeonToolCustomizeOptions, NeonToolDescriptionOverrides, NeonToolDescriptionSource, NeonToolInjectOptions, NeonToolInjectValue, NeonToolNameOverrides, NeonToolNameSource, NeonToolOnExecute, NeonToolOnExecuteEvent, } from "./lib/customize.js";
|
|
8
6
|
export type { JsonSafe, JsonSafeBlob, NeonTool, NeonToolAnnotations, NeonToolExecutionContext, NeonToolMetadata, NeonToolResult, } from "./lib/operation.js";
|
|
9
|
-
export type {
|
|
10
|
-
export { NeonError,
|
|
11
|
-
type
|
|
12
|
-
export type NeonTools<
|
|
13
|
-
[
|
|
14
|
-
} & {
|
|
15
|
-
[Workflow in Workflows[number]]: ReturnType<WorkflowFactories[Workflow]>;
|
|
7
|
+
export type { NeonToolId, PublishedId };
|
|
8
|
+
export { NeonError, publishedId, toolIds };
|
|
9
|
+
type ToolFactories = typeof toolFactories;
|
|
10
|
+
export type NeonTools<Tools extends readonly NeonToolId[] = []> = {
|
|
11
|
+
[Tool in Tools[number]]: ReturnType<ToolFactories[Tool]>;
|
|
16
12
|
};
|
|
17
|
-
export type InjectedNeonTools<
|
|
18
|
-
[
|
|
19
|
-
} & {
|
|
20
|
-
[Workflow in Workflows[number]]: InjectedNeonTool<ReturnType<WorkflowFactories[Workflow]>, Inject>;
|
|
13
|
+
export type InjectedNeonTools<Tools extends readonly NeonToolId[], Inject> = {
|
|
14
|
+
[Tool in Tools[number]]: InjectedNeonTool<ReturnType<ToolFactories[Tool]>, Inject>;
|
|
21
15
|
};
|
|
22
16
|
type WithPublishedId<Tool> = Tool extends {
|
|
23
17
|
id: string;
|
|
24
18
|
} ? Omit<Tool, "id"> & {
|
|
25
19
|
id: string;
|
|
26
20
|
} : Tool;
|
|
27
|
-
export interface NeonToolsClientOptions extends
|
|
28
|
-
apiKey?: NeonBearerCredential;
|
|
21
|
+
export interface NeonToolsClientOptions extends ToolClientOptions, Omit<NeonToolCustomizeOptions, "name" | "names"> {
|
|
29
22
|
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
workflows: Workflows;
|
|
44
|
-
operations?: Operations;
|
|
45
|
-
} : {
|
|
46
|
-
operations: Operations;
|
|
47
|
-
workflows: Workflows;
|
|
48
|
-
});
|
|
49
|
-
type SelectedOperations<T> = T extends {
|
|
50
|
-
operations: infer O extends readonly NeonOperationId[];
|
|
51
|
-
} ? O : [];
|
|
52
|
-
type SelectedWorkflows<T> = T extends {
|
|
53
|
-
workflows: infer W extends readonly NeonWorkflowId[];
|
|
54
|
-
} ? W : [];
|
|
55
|
-
type NeonToolsFor<T, Inject> = T extends CreateNeonToolsInput ? Inject extends NeonToolInjectOptions ? InjectedNeonTools<SelectedOperations<T>, Inject, SelectedWorkflows<T>> : NeonTools<SelectedOperations<T>, SelectedWorkflows<T>> : never;
|
|
56
|
-
type NeonToolId = NeonOperationId | NeonWorkflowId;
|
|
57
|
-
type ToolForId<Id extends NeonToolId> = Id extends NeonWorkflowId ? ReturnType<WorkflowFactories[Id]> : Id extends NeonOperationId ? ReturnType<OperationFactories[Id]> : never;
|
|
58
|
-
type NamedNeonTools<Operations extends readonly NeonOperationId[], Workflows extends readonly NeonWorkflowId[], Inject> = {
|
|
59
|
-
[Operation in Operations[number]]: WithPublishedId<Inject extends NeonToolInjectOptions ? InjectedNeonTool<ReturnType<OperationFactories[Operation]>, Inject> : ReturnType<OperationFactories[Operation]>>;
|
|
60
|
-
} & {
|
|
61
|
-
[Workflow in Workflows[number]]: WithPublishedId<Inject extends NeonToolInjectOptions ? InjectedNeonTool<ReturnType<WorkflowFactories[Workflow]>, Inject> : ReturnType<WorkflowFactories[Workflow]>>;
|
|
23
|
+
type CreateNeonToolsInput = NeonToolsClientOptions & {
|
|
24
|
+
tools: readonly NeonToolId[];
|
|
25
|
+
};
|
|
26
|
+
export type CreateNeonToolsOptions<Tools extends readonly NeonToolId[] = readonly NeonToolId[]> = NeonToolsClientOptions & {
|
|
27
|
+
tools: Tools;
|
|
28
|
+
};
|
|
29
|
+
type SelectedTools<T> = T extends {
|
|
30
|
+
tools: infer S extends readonly NeonToolId[];
|
|
31
|
+
} ? S : [];
|
|
32
|
+
type NeonToolsFor<T, Inject> = T extends CreateNeonToolsInput ? Inject extends NeonToolInjectOptions ? InjectedNeonTools<SelectedTools<T>, Inject> : NeonTools<SelectedTools<T>> : never;
|
|
33
|
+
type ToolForId<Id extends NeonToolId> = ReturnType<ToolFactories[Id]>;
|
|
34
|
+
type NamedNeonTools<Tools extends readonly NeonToolId[], Inject> = {
|
|
35
|
+
[Tool in Tools[number]]: WithPublishedId<Inject extends NeonToolInjectOptions ? InjectedNeonTool<ReturnType<ToolFactories[Tool]>, Inject> : ReturnType<ToolFactories[Tool]>>;
|
|
62
36
|
};
|
|
63
37
|
type NamedNeonTool<Id extends NeonToolId, Inject> = WithPublishedId<Inject extends NeonToolInjectOptions ? InjectedNeonTool<ToolForId<Id>, Inject> : ToolForId<Id>>;
|
|
64
|
-
type NamedNeonToolsFor<T, Inject> = T extends CreateNeonToolsInput ? NamedNeonTools<
|
|
38
|
+
type NamedNeonToolsFor<T, Inject> = T extends CreateNeonToolsInput ? NamedNeonTools<SelectedTools<T>, Inject> : never;
|
|
65
39
|
export declare function createNeonTools<const T extends CreateNeonToolsInput, const Inject extends NeonToolInjectOptions | undefined = undefined>(options: T & {
|
|
66
40
|
inject?: Inject;
|
|
67
41
|
} & ({
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,49 +1,34 @@
|
|
|
1
|
-
import { missingBearerCredential, requireBearerCredential } from "./lib/auth.js";
|
|
2
1
|
import { applyToolCustomization, assertToolCustomizeOptions, hasToolCustomization } from "./lib/customize.js";
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
2
|
+
import { publishedId } from "./lib/ergonomic/bind.js";
|
|
3
|
+
import { toolFactories } from "./lib/ergonomic/catalog.js";
|
|
4
|
+
import { isNeonToolId, toolIds, unpublishedToolError } from "./lib/ergonomic/ids.js";
|
|
5
|
+
import { NeonError } from "@neon/sdk";
|
|
6
6
|
//#region src/index.ts
|
|
7
|
-
const createRawClient = (options) => createNeonClient({
|
|
8
|
-
apiKey: options.apiKey === void 0 ? missingBearerCredential : requireBearerCredential(options.apiKey),
|
|
9
|
-
...options.baseUrl === void 0 ? {} : { baseUrl: options.baseUrl },
|
|
10
|
-
...options.fetch === void 0 ? {} : { fetch: options.fetch },
|
|
11
|
-
...options.wait === void 0 ? {} : { wait: options.wait }
|
|
12
|
-
}).client;
|
|
13
|
-
const operationFactoryFor = (operationId) => {
|
|
14
|
-
const knownOperationId = operationIds.find((candidate) => candidate === operationId);
|
|
15
|
-
if (knownOperationId === void 0) throw new TypeError(`Unknown Neon operation "${operationId}".`);
|
|
16
|
-
return operationFactories[knownOperationId];
|
|
17
|
-
};
|
|
18
7
|
const assertKnownNameKeys = (names, tools) => {
|
|
19
8
|
if (names === void 0 || typeof names === "function") return;
|
|
20
9
|
const known = new Set(tools.flatMap((tool) => [tool.operationId, tool.id]));
|
|
21
10
|
const unknown = Object.keys(names).filter((key) => !known.has(key));
|
|
22
11
|
if (unknown.length > 0) throw new TypeError(`Unknown Neon tool name override: ${unknown.join(", ")}`);
|
|
23
12
|
};
|
|
24
|
-
function assertNeonTools(value,
|
|
25
|
-
if (typeof value !== "object" || value === null) throw new TypeError("Expected
|
|
26
|
-
for (const
|
|
27
|
-
for (const workflowId of workflows) if (!(workflowId in value)) throw new TypeError(`Missing Neon workflow tool "${workflowId}".`);
|
|
13
|
+
function assertNeonTools(value, tools) {
|
|
14
|
+
if (typeof value !== "object" || value === null) throw new TypeError("Expected Neon tools to be an object.");
|
|
15
|
+
for (const toolId of tools) if (!(toolId in value)) throw new TypeError(`Missing Neon tool "${toolId}".`);
|
|
28
16
|
}
|
|
17
|
+
const factoryFor = (id) => {
|
|
18
|
+
const known = toolIds.find((candidate) => candidate === id);
|
|
19
|
+
if (known === void 0) throw unpublishedToolError(id);
|
|
20
|
+
return toolFactories[known];
|
|
21
|
+
};
|
|
29
22
|
const bindTools = (options) => {
|
|
30
23
|
assertToolCustomizeOptions(options);
|
|
31
|
-
const
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
return [operationId, operationFactoryFor(operationId)(createRawClient(options))];
|
|
24
|
+
const selected = options.tools;
|
|
25
|
+
if (selected === void 0 || selected.length === 0) throw new TypeError("createNeonTools requires at least one tool");
|
|
26
|
+
const seen = /* @__PURE__ */ new Set();
|
|
27
|
+
const rawEntries = selected.map((toolId) => {
|
|
28
|
+
if (seen.has(toolId)) throw new Error(`Duplicate Neon tool "${toolId}"`);
|
|
29
|
+
seen.add(toolId);
|
|
30
|
+
return [toolId, factoryFor(toolId)(options)];
|
|
39
31
|
});
|
|
40
|
-
const selectedWorkflows = /* @__PURE__ */ new Set();
|
|
41
|
-
const workflowEntries = workflows.map((workflowId) => {
|
|
42
|
-
if (selectedWorkflows.has(workflowId)) throw new Error(`Duplicate Neon workflow "${workflowId}"`);
|
|
43
|
-
selectedWorkflows.add(workflowId);
|
|
44
|
-
return [workflowId, workflowFactoryFor(workflowId)(options)];
|
|
45
|
-
});
|
|
46
|
-
const rawEntries = [...operationEntries, ...workflowEntries];
|
|
47
32
|
assertKnownNameKeys(options.names, rawEntries.map(([, tool]) => tool));
|
|
48
33
|
const entries = rawEntries.map(([id, tool]) => {
|
|
49
34
|
return [id, hasToolCustomization(options) ? applyToolCustomization(tool, options) : tool];
|
|
@@ -55,23 +40,18 @@ const bindTools = (options) => {
|
|
|
55
40
|
publishedIds.set(tool.id, id);
|
|
56
41
|
}
|
|
57
42
|
const tools = Object.fromEntries(entries);
|
|
58
|
-
assertNeonTools(tools,
|
|
43
|
+
assertNeonTools(tools, selected);
|
|
59
44
|
return tools;
|
|
60
45
|
};
|
|
61
46
|
function createNeonTools(options) {
|
|
62
47
|
return bindTools(options);
|
|
63
48
|
}
|
|
64
49
|
function createNeonTool(id, options) {
|
|
50
|
+
if (!isNeonToolId(id)) throw unpublishedToolError(id);
|
|
65
51
|
assertToolCustomizeOptions(options);
|
|
66
|
-
|
|
67
|
-
if (isNeonWorkflowId(id)) tool = workflowFactoryFor(id)(options);
|
|
68
|
-
else {
|
|
69
|
-
const knownOperationId = operationIds.find((candidate) => candidate === id);
|
|
70
|
-
if (knownOperationId === void 0) throw new TypeError(`Unknown Neon operation or workflow "${id}".`);
|
|
71
|
-
tool = operationFactories[knownOperationId](createRawClient(options));
|
|
72
|
-
}
|
|
52
|
+
const tool = factoryFor(id)(options);
|
|
73
53
|
assertKnownNameKeys(options.names, [tool]);
|
|
74
54
|
return hasToolCustomization(options) ? applyToolCustomization(tool, options) : tool;
|
|
75
55
|
}
|
|
76
56
|
//#endregion
|
|
77
|
-
export { NeonError, createNeonTool, createNeonTools,
|
|
57
|
+
export { NeonError, createNeonTool, createNeonTools, publishedId, toolIds };
|