@neon/tools 0.2.0 → 0.3.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 CHANGED
@@ -24,7 +24,7 @@ const tools = createNeonTools({
24
24
  });
25
25
 
26
26
  const result = await tools.listProjects.execute({
27
- query: { limit: 10 },
27
+ limit: 10,
28
28
  });
29
29
  ```
30
30
 
@@ -43,12 +43,12 @@ Or supply the token per call:
43
43
  const tools = createNeonTools({ operations });
44
44
 
45
45
  await tools.listProjects.execute(
46
- { query: { limit: 10 } },
46
+ { limit: 10 },
47
47
  { apiKey: oauthAccessToken },
48
48
  );
49
49
  ```
50
50
 
51
- The returned record is keyed by OpenAPI operation ID. Each tool includes its generated Zod 4 `inputSchema`, snake-case `id`, title, description, safety annotations, stability metadata, and an `execute()` function. Inputs group API parameters under `path`, `query`, `headers`, and `body`.
51
+ The returned record is keyed by OpenAPI operation ID. Each tool includes its generated Zod 4 `inputSchema`, snake-case `id`, title, description, safety annotations, stability metadata, and an `execute()` function. Inputs are flat: path, query, header, and body fields sit on one object. A body that is a single object wrapper is lifted, so `create_project` takes `{ name, region_id, org_id, ... }` rather than `{ project: { name } }`. A body with several properties keeps those properties, so `create_project_branch` takes `{ project_id, branch, endpoints, annotation_value }` and `branch` is still an object. Two email-provider updates keep a `body` field because the API request is a discriminated union.
52
52
 
53
53
  `operationIds` exports every valid 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
54
 
@@ -96,9 +96,27 @@ const tools = createNeonTools({
96
96
 
97
97
  This package does not send analytics. Mutating `event.input` does not change a grant-locked project or branch id.
98
98
 
99
+ ### Names
100
+
101
+ `name` rewrites every published tool `id`. `names` overrides one tool first, keyed by OpenAPI operation ID or the generated snake-case `id`:
102
+
103
+ ```ts
104
+ const tools = createNeonTools({
105
+ apiKey,
106
+ operations: ["createProjectBranch", "listProjects"] as const,
107
+ names: { createProjectBranch: "create_branch" },
108
+ name: (id) => `neon_${id}`,
109
+ });
110
+
111
+ tools.createProjectBranch.id; // "neon_create_branch"
112
+ tools.listProjects.id; // "neon_list_projects"
113
+ ```
114
+
115
+ The record is still keyed by operation ID (`tools.createProjectBranch`). 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.
116
+
99
117
  ### Project and branch injection
100
118
 
101
- Generated tools take OpenAPI path parameters (`path.project_id`, `path.branch_id`). A host that already knows those values can inject them. 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:
119
+ Generated tools take path parameters as `project_id` and `branch_id`. A host that already knows those values can inject them. 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:
102
120
 
103
121
  ```ts
104
122
  const tools = createNeonTools({
@@ -111,7 +129,7 @@ const tools = createNeonTools({
111
129
  });
112
130
 
113
131
  await tools.getProject.execute({});
114
- await tools.deleteProjectBranch.execute({ path: { branch_id: "br-id" } });
132
+ await tools.deleteProjectBranch.execute({ branch_id: "br-id" });
115
133
  ```
116
134
 
117
135
  Use a getter when the value is request-scoped. The getter can read the host's own `AsyncLocalStorage` (this package does not export one):
@@ -134,7 +152,9 @@ await grant.run({ projectId: "project-id" }, () => tools.getProject.execute({}))
134
152
 
135
153
  Injectors only apply to tools that have that path key. `listProjects` is unchanged. Empty inject values fail closed. Invalid ids still fail the original path schema before fetch.
136
154
 
137
- These add-ons do not flatten `{ path, query, body }` into camelCase `projectId`, do not rename tools (`get_project` is not `describe_project`), and do not add host-only behavior such as returning a connection string from `createProject`. Grant filtering, read-only filtering, and access-control notices stay in the host. `branchId` injection fills `path.branch_id` only — query/body branch selectors such as `getConnectionURI`'s `query.branch_id` are unchanged.
155
+ These add-ons do not add host-only behavior such as returning a connection string from `createProject`. Grant filtering, read-only filtering, and access-control notices stay in the host.
156
+
157
+ 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.
138
158
 
139
159
  ## Request schemas
140
160
 
@@ -152,6 +172,8 @@ const body = zCreateProjectBody.parse({
152
172
  });
153
173
  ```
154
174
 
175
+ These are the raw OpenAPI request shapes, not the flat tool input. `zCreateProjectBody` still wraps fields in `project`. The tool `create_project` does not.
176
+
155
177
  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.
156
178
 
157
179
  ## MCP
@@ -262,12 +284,10 @@ const deployFunction = createNeonTool(
262
284
  );
263
285
 
264
286
  await deployFunction.execute({
265
- path: {
266
- project_id: "project-id",
267
- branch_id: "branch-id",
268
- slug: "hello",
269
- },
270
- body: { zip: "UEsDBA==" },
287
+ project_id: "project-id",
288
+ branch_id: "branch-id",
289
+ slug: "hello",
290
+ zip: "UEsDBA==",
271
291
  });
272
292
  ```
273
293
 
package/dist/index.d.ts CHANGED
@@ -1,9 +1,9 @@
1
1
  import { type NeonConfig, NeonError } from "@neon/sdk";
2
2
  import { type NeonBearerCredential } from "./lib/auth.js";
3
- import { type InjectedNeonTool, type NeonToolCustomizeOptions, type NeonToolInjectOptions } from "./lib/customize.js";
3
+ import { type InjectedNeonTool, type NeonToolCustomizeOptions, type NeonToolInjectOptions, type NeonToolNameOverrides } from "./lib/customize.js";
4
4
  import { type NeonOperationId, operationFactories, operationIds } from "./operations.gen.js";
5
5
  export type { NeonBearerCredential } from "./lib/auth.js";
6
- export type { InjectedNeonTool, NeonToolCustomizeOptions, NeonToolDescriptionOverrides, NeonToolDescriptionSource, NeonToolInjectOptions, NeonToolInjectValue, NeonToolOnExecute, NeonToolOnExecuteEvent, } from "./lib/customize.js";
6
+ export type { InjectedNeonTool, NeonToolCustomizeOptions, NeonToolDescriptionOverrides, NeonToolDescriptionSource, NeonToolInjectOptions, NeonToolInjectValue, NeonToolNameOverrides, NeonToolNameSource, NeonToolOnExecute, NeonToolOnExecuteEvent, } from "./lib/customize.js";
7
7
  export type { JsonSafe, JsonSafeBlob, NeonTool, NeonToolAnnotations, NeonToolExecutionContext, NeonToolMetadata, NeonToolResult, } from "./lib/operation.js";
8
8
  export type { NeonOperationId };
9
9
  export { NeonError, operationIds };
@@ -14,15 +14,42 @@ export type NeonTools<Operations extends readonly NeonOperationId[]> = {
14
14
  export type InjectedNeonTools<Operations extends readonly NeonOperationId[], Inject> = {
15
15
  [Operation in Operations[number]]: InjectedNeonTool<ReturnType<OperationFactories[Operation]>, Inject>;
16
16
  };
17
- export interface NeonToolsClientOptions extends Pick<NeonConfig, "baseUrl" | "fetch">, NeonToolCustomizeOptions {
17
+ type WithPublishedId<Tool> = Tool extends {
18
+ id: string;
19
+ } ? Omit<Tool, "id"> & {
20
+ id: string;
21
+ } : Tool;
22
+ export interface NeonToolsClientOptions extends Pick<NeonConfig, "baseUrl" | "fetch">, Omit<NeonToolCustomizeOptions, "name" | "names"> {
18
23
  apiKey?: NeonBearerCredential;
19
24
  }
20
25
  export interface CreateNeonToolsOptions<Operations extends readonly NeonOperationId[]> extends NeonToolsClientOptions {
21
26
  operations: Operations;
22
27
  }
23
- export declare const createNeonTools: <const Operations extends readonly NeonOperationId[], const Inject extends NeonToolInjectOptions | undefined = undefined>(options: CreateNeonToolsOptions<Operations> & {
28
+ type NamedNeonTools<Operations extends readonly NeonOperationId[], Inject> = {
29
+ [Operation in Operations[number]]: WithPublishedId<Inject extends NeonToolInjectOptions ? InjectedNeonTool<ReturnType<OperationFactories[Operation]>, Inject> : ReturnType<OperationFactories[Operation]>>;
30
+ };
31
+ type NamedNeonTool<Operation extends NeonOperationId, Inject> = WithPublishedId<Inject extends NeonToolInjectOptions ? InjectedNeonTool<ReturnType<OperationFactories[Operation]>, Inject> : ReturnType<OperationFactories[Operation]>>;
32
+ export declare function createNeonTools<const Operations extends readonly NeonOperationId[], const Inject extends NeonToolInjectOptions | undefined = undefined>(options: CreateNeonToolsOptions<Operations> & {
33
+ inject?: Inject;
34
+ } & ({
35
+ name: (id: string) => string;
36
+ names?: NeonToolNameOverrides;
37
+ } | {
38
+ names: NeonToolNameOverrides;
39
+ name?: (id: string) => string;
40
+ })): NamedNeonTools<Operations, Inject>;
41
+ export declare function createNeonTools<const Operations extends readonly NeonOperationId[], const Inject extends NeonToolInjectOptions | undefined = undefined>(options: CreateNeonToolsOptions<Operations> & {
42
+ inject?: Inject;
43
+ }): Inject extends NeonToolInjectOptions ? InjectedNeonTools<Operations, Inject> : NeonTools<Operations>;
44
+ export declare function createNeonTool<const Operation extends NeonOperationId, const Inject extends NeonToolInjectOptions | undefined = undefined>(operationId: Operation, options: NeonToolsClientOptions & {
24
45
  inject?: Inject;
25
- }) => Inject extends NeonToolInjectOptions ? InjectedNeonTools<Operations, Inject> : NeonTools<Operations>;
46
+ } & ({
47
+ name: (id: string) => string;
48
+ names?: NeonToolNameOverrides;
49
+ } | {
50
+ names: NeonToolNameOverrides;
51
+ name?: (id: string) => string;
52
+ })): NamedNeonTool<Operation, Inject>;
26
53
  export declare function createNeonTool<const Operation extends NeonOperationId, const Inject extends NeonToolInjectOptions | undefined = undefined>(operationId: Operation, options: NeonToolsClientOptions & {
27
54
  inject?: Inject;
28
55
  }): Inject extends NeonToolInjectOptions ? InjectedNeonTool<ReturnType<OperationFactories[Operation]>, Inject> : ReturnType<OperationFactories[Operation]>;
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAoB,KAAK,UAAU,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACzE,OAAO,EAEN,KAAK,oBAAoB,EAEzB,MAAM,eAAe,CAAC;AACvB,OAAO,EAIN,KAAK,gBAAgB,EACrB,KAAK,wBAAwB,EAC7B,KAAK,qBAAqB,EAC1B,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACN,KAAK,eAAe,EACpB,kBAAkB,EAClB,YAAY,EACZ,MAAM,qBAAqB,CAAC;AAE7B,YAAY,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AAC1D,YAAY,EACX,gBAAgB,EAChB,wBAAwB,EACxB,4BAA4B,EAC5B,yBAAyB,EACzB,qBAAqB,EACrB,mBAAmB,EACnB,iBAAiB,EACjB,sBAAsB,GACtB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACX,QAAQ,EACR,YAAY,EACZ,QAAQ,EACR,mBAAmB,EACnB,wBAAwB,EACxB,gBAAgB,EAChB,cAAc,GACd,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EAAE,eAAe,EAAE,CAAC;AAChC,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;AAEnC,KAAK,kBAAkB,GAAG,OAAO,kBAAkB,CAAC;AAEpD,MAAM,MAAM,SAAS,CAAC,UAAU,SAAS,SAAS,eAAe,EAAE,IAAI;KACrE,SAAS,IAAI,UAAU,CAAC,MAAM,CAAC,GAAG,UAAU,CAC5C,kBAAkB,CAAC,SAAS,CAAC,CAC7B;CACD,CAAC;AAEF,MAAM,MAAM,iBAAiB,CAC5B,UAAU,SAAS,SAAS,eAAe,EAAE,EAC7C,MAAM,IACH;KACF,SAAS,IAAI,UAAU,CAAC,MAAM,CAAC,GAAG,gBAAgB,CAClD,UAAU,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,EACzC,MAAM,CACN;CACD,CAAC;AAEF,MAAM,WAAW,sBAChB,SAAQ,IAAI,CAAC,UAAU,EAAE,SAAS,GAAG,OAAO,CAAC,EAC5C,wBAAwB;IACzB,MAAM,CAAC,EAAE,oBAAoB,CAAC;CAC9B;AAED,MAAM,WAAW,sBAAsB,CACtC,UAAU,SAAS,SAAS,eAAe,EAAE,CAC5C,SAAQ,sBAAsB;IAC/B,UAAU,EAAE,UAAU,CAAC;CACvB;AAiED,eAAO,MAAM,eAAe,GAC3B,KAAK,CAAC,UAAU,SAAS,SAAS,eAAe,EAAE,EACnD,KAAK,CAAC,MAAM,SAAS,qBAAqB,GAAG,SAAS,GAAG,SAAS,EAElE,SAAS,sBAAsB,CAAC,UAAU,CAAC,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,KAC/D,MAAM,SAAS,qBAAqB,GACpC,iBAAiB,CAAC,UAAU,EAAE,MAAM,CAAC,GACrC,SAAS,CAAC,UAAU,CAGE,CAAC;AAE1B,wBAAgB,cAAc,CAC7B,KAAK,CAAC,SAAS,SAAS,eAAe,EACvC,KAAK,CAAC,MAAM,SAAS,qBAAqB,GAAG,SAAS,GAAG,SAAS,EAElE,WAAW,EAAE,SAAS,EACtB,OAAO,EAAE,sBAAsB,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACnD,MAAM,SAAS,qBAAqB,GACpC,gBAAgB,CAAC,UAAU,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,EAAE,MAAM,CAAC,GACnE,UAAU,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC,CAS3C"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -13,6 +13,12 @@ const operationFactoryFor = (operationId) => {
13
13
  if (knownOperationId === void 0) throw new TypeError(`Unknown Neon operation "${operationId}".`);
14
14
  return operationFactories[knownOperationId];
15
15
  };
16
+ const assertKnownNameKeys = (names, tools) => {
17
+ if (names === void 0 || typeof names === "function") return;
18
+ const known = new Set(tools.flatMap((tool) => [tool.operationId, tool.id]));
19
+ const unknown = Object.keys(names).filter((key) => !known.has(key));
20
+ if (unknown.length > 0) throw new TypeError(`Unknown Neon tool name override: ${unknown.join(", ")}`);
21
+ };
16
22
  function assertNeonTools(value, operations) {
17
23
  if (typeof value !== "object" || value === null) throw new TypeError("Expected generated Neon tools to be an object.");
18
24
  for (const operationId of operations) if (!(operationId in value)) throw new TypeError(`Missing generated Neon tool "${operationId}".`);
@@ -26,18 +32,30 @@ const bindTools = (options) => {
26
32
  return [operationId, operationFactoryFor(operationId)];
27
33
  });
28
34
  const client = createRawClient(options);
29
- const entries = selectedFactories.map(([operationId, factory]) => {
30
- const tool = factory(client);
35
+ const rawEntries = selectedFactories.map(([operationId, factory]) => {
36
+ return [operationId, factory(client)];
37
+ });
38
+ assertKnownNameKeys(options.names, rawEntries.map(([, tool]) => tool));
39
+ const entries = rawEntries.map(([operationId, tool]) => {
31
40
  return [operationId, hasToolCustomization(options) ? applyToolCustomization(tool, options) : tool];
32
41
  });
42
+ const publishedIds = /* @__PURE__ */ new Map();
43
+ for (const [operationId, tool] of entries) {
44
+ const previous = publishedIds.get(tool.id);
45
+ if (previous !== void 0) throw new Error(`Duplicate Neon tool id "${tool.id}" for ${previous}, ${operationId}`);
46
+ publishedIds.set(tool.id, operationId);
47
+ }
33
48
  const tools = Object.fromEntries(entries);
34
49
  assertNeonTools(tools, options.operations);
35
50
  return tools;
36
51
  };
37
- const createNeonTools = (options) => bindTools(options);
52
+ function createNeonTools(options) {
53
+ return bindTools(options);
54
+ }
38
55
  function createNeonTool(operationId, options) {
39
56
  assertToolCustomizeOptions(options);
40
57
  const tool = operationFactoryFor(operationId)(createRawClient(options));
58
+ assertKnownNameKeys(options.names, [tool]);
41
59
  return hasToolCustomization(options) ? applyToolCustomization(tool, options) : tool;
42
60
  }
43
61
  //#endregion
@@ -13,6 +13,8 @@ export interface NeonToolDescriptionSource {
13
13
  description: string;
14
14
  }
15
15
  export type NeonToolDescriptionOverrides = Readonly<Record<string, string>> | ((tool: NeonToolDescriptionSource) => string);
16
+ export type NeonToolNameSource = Pick<NeonToolDescriptionSource, "operationId" | "id">;
17
+ export type NeonToolNameOverrides = Readonly<Record<string, string>> | ((tool: NeonToolNameSource) => string);
16
18
  export interface NeonToolOnExecuteEvent<Output = unknown> {
17
19
  operationId: string;
18
20
  id: string;
@@ -22,31 +24,29 @@ export interface NeonToolOnExecuteEvent<Output = unknown> {
22
24
  export type NeonToolOnExecute = <Output>(event: NeonToolOnExecuteEvent<Output>) => Promise<NeonToolResult<Output>>;
23
25
  export interface NeonToolCustomizeOptions {
24
26
  descriptions?: NeonToolDescriptionOverrides;
27
+ names?: NeonToolNameOverrides;
28
+ name?: (id: string) => string;
25
29
  onExecute?: NeonToolOnExecute;
26
30
  inject?: NeonToolInjectOptions;
27
31
  }
28
32
  type InjectedPathKey<Inject> = ("projectId" extends keyof Inject ? Inject["projectId"] extends undefined ? never : "project_id" : never) | ("branchId" extends keyof Inject ? Inject["branchId"] extends undefined ? never : "branch_id" : never);
29
- type OptionalInjectedPath<Path, Keys extends string> = [
30
- keyof Omit<Path, Keys>
31
- ] extends [never] ? {
32
- path?: Omit<Path, Keys> & Partial<Pick<Path, Extract<Keys, keyof Path>>>;
33
- } : {
34
- path: Omit<Path, Keys> & Partial<Pick<Path, Extract<Keys, keyof Path>>>;
35
- };
36
- type ApplyInjectToInput<Input, Inject> = [InjectedPathKey<Inject>] extends [
37
- never
38
- ] ? Input : Input extends {
39
- path: infer Path;
40
- } ? Inject extends {
33
+ type RequiredKeys<Input> = {
34
+ [Key in keyof Input]-?: object extends Pick<Input, Key> ? never : Key;
35
+ }[keyof Input];
36
+ type InjectedRequiredKey<Input, Inject> = Extract<InjectedPathKey<Inject>, RequiredKeys<Input>>;
37
+ type ApplyInjectToInput<Input, Inject> = [
38
+ InjectedRequiredKey<Input, Inject>
39
+ ] extends [never] ? Input : Inject extends {
41
40
  omitFromSchema: true;
42
- } ? [keyof Omit<Path, InjectedPathKey<Inject>>] extends [never] ? Omit<Input, "path"> : Omit<Input, "path"> & {
43
- path: Omit<Path, InjectedPathKey<Inject>>;
44
- } : Omit<Input, "path"> & OptionalInjectedPath<Path, InjectedPathKey<Inject>> : Input;
41
+ } ? Omit<Input, InjectedRequiredKey<Input, Inject>> : Omit<Input, InjectedRequiredKey<Input, Inject>> & Partial<Pick<Input, Extract<InjectedRequiredKey<Input, Inject>, keyof Input>>>;
45
42
  export type InjectedNeonTool<Tool, Inject> = Tool extends NeonTool<infer Schema, string, infer Output> ? Omit<Tool, "execute"> & {
46
43
  execute(input: ApplyInjectToInput<z.input<Schema>, Inject>, context?: NeonToolExecutionContext): Promise<NeonToolResult<Output>>;
47
44
  } : Tool;
45
+ export declare const pathTemplateParams: (path: string) => Set<string>;
48
46
  export declare const assertToolCustomizeOptions: (options: NeonToolCustomizeOptions) => void;
49
47
  export declare const hasToolCustomization: (options: NeonToolCustomizeOptions) => boolean;
50
- export declare const applyToolCustomization: <Tool extends NeonTool>(tool: Tool, options: NeonToolCustomizeOptions) => Tool;
48
+ export declare const applyToolCustomization: <Tool extends NeonTool>(tool: Tool, options: NeonToolCustomizeOptions) => Omit<Tool, "id"> & {
49
+ id: string;
50
+ };
51
51
  export {};
52
52
  //# sourceMappingURL=customize.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"customize.d.ts","sourceRoot":"","sources":["../../src/lib/customize.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC;AACzB,OAAO,KAAK,EACX,QAAQ,EACR,wBAAwB,EACxB,cAAc,EACd,MAAM,gBAAgB,CAAC;AAExB,MAAM,MAAM,mBAAmB,GAC5B,MAAM,GACN,CAAC,MAAM,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC,CAAC;AAE5D,MAAM,WAAW,qBAAqB;IACrC,SAAS,CAAC,EAAE,mBAAmB,CAAC;IAChC,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,cAAc,CAAC,EAAE,OAAO,CAAC;CACzB;AAED,MAAM,WAAW,yBAAyB;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,4BAA4B,GACrC,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAChC,CAAC,CAAC,IAAI,EAAE,yBAAyB,KAAK,MAAM,CAAC,CAAC;AAEjD,MAAM,WAAW,sBAAsB,CAAC,MAAM,GAAG,OAAO;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,OAAO,CAAC;IACf,OAAO,EAAE,MAAM,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;CAC/C;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,MAAM,EACtC,KAAK,EAAE,sBAAsB,CAAC,MAAM,CAAC,KACjC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;AAErC,MAAM,WAAW,wBAAwB;IACxC,YAAY,CAAC,EAAE,4BAA4B,CAAC;IAC5C,SAAS,CAAC,EAAE,iBAAiB,CAAC;IAC9B,MAAM,CAAC,EAAE,qBAAqB,CAAC;CAC/B;AAED,KAAK,eAAe,CAAC,MAAM,IACxB,CAAC,WAAW,SAAS,MAAM,MAAM,GAC/B,MAAM,CAAC,WAAW,CAAC,SAAS,SAAS,GACpC,KAAK,GACL,YAAY,GACb,KAAK,CAAC,GACR,CAAC,UAAU,SAAS,MAAM,MAAM,GAC9B,MAAM,CAAC,UAAU,CAAC,SAAS,SAAS,GACnC,KAAK,GACL,WAAW,GACZ,KAAK,CAAC,CAAC;AAEZ,KAAK,oBAAoB,CAAC,IAAI,EAAE,IAAI,SAAS,MAAM,IAAI;IACtD,MAAM,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC;CACtB,SAAS,CAAC,KAAK,CAAC,GACd;IACA,IAAI,CAAC,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GACtB,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC;CAChD,GACA;IACA,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,IAAI,CAAC,GACrB,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC,CAAC;CAChD,CAAC;AAEJ,KAAK,kBAAkB,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,SAAS;IAC1E,KAAK;CACL,GACE,KAAK,GACL,KAAK,SAAS;IAAE,IAAI,EAAE,MAAM,IAAI,CAAA;CAAE,GACjC,MAAM,SAAS;IAAE,cAAc,EAAE,IAAI,CAAA;CAAE,GACtC,CAAC,MAAM,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,GAC1D,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,GACnB,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG;IACtB,IAAI,EAAE,IAAI,CAAC,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC;CAC1C,GACD,IAAI,CAAC,KAAK,EAAE,MAAM,CAAC,GACnB,oBAAoB,CAAC,IAAI,EAAE,eAAe,CAAC,MAAM,CAAC,CAAC,GACpD,KAAK,CAAC;AAEV,MAAM,MAAM,gBAAgB,CAAC,IAAI,EAAE,MAAM,IACxC,IAAI,SAAS,QAAQ,CAAC,MAAM,MAAM,EAAE,MAAM,EAAE,MAAM,MAAM,CAAC,GACtD,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,GAAG;IACxB,OAAO,CACN,KAAK,EAAE,kBAAkB,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,EAClD,OAAO,CAAC,EAAE,wBAAwB,GAChC,OAAO,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC;CACnC,GACA,IAAI,CAAC;AAeT,eAAO,MAAM,0BAA0B,GACtC,SAAS,wBAAwB,KAC/B,IAEF,CAAC;AAEF,eAAO,MAAM,oBAAoB,GAChC,SAAS,wBAAwB,KAC/B,OAGkC,CAAC;AAEtC,eAAO,MAAM,sBAAsB,GAAI,IAAI,SAAS,QAAQ,EAC3D,MAAM,IAAI,EACV,SAAS,wBAAwB,KAC/B,IAsBF,CAAC"}
1
+ {"version":3,"file":"customize.d.ts","sourceRoot":"","sources":["../../src/lib/customize.ts"],"names":[],"mappings":"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"}
@@ -1,24 +1,51 @@
1
1
  import * as z from "zod";
2
2
  //#region src/lib/customize.ts
3
+ const PATH_INJECT = [["projectId", "project_id"], ["branchId", "branch_id"]];
4
+ const PUBLISHED_ID = /^[a-z][a-z0-9_]*$/;
3
5
  const missingInjectMessage = (name) => `A ${name} inject value is required`;
4
6
  const isPlainObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
7
+ const pathTemplateParams = (path) => new Set([...path.matchAll(/\{([^{}]+)\}/g)].map((match) => match[1]));
5
8
  const assertToolCustomizeOptions = (options) => {
6
9
  resolveInject(options.inject);
10
+ if (options.name !== void 0 && typeof options.name !== "function") throw new TypeError("Neon tool name transforms must be functions");
11
+ if (options.names !== void 0 && typeof options.names !== "function" && (typeof options.names !== "object" || options.names === null || Array.isArray(options.names))) throw new TypeError("Neon tool name overrides must be a map or a function");
7
12
  };
8
- const hasToolCustomization = (options) => options.descriptions !== void 0 || options.onExecute !== void 0 || resolveInject(options.inject).hasAny;
13
+ const hasToolCustomization = (options) => options.descriptions !== void 0 || options.names !== void 0 || options.name !== void 0 || options.onExecute !== void 0 || resolveInject(options.inject).hasAny;
9
14
  const applyToolCustomization = (tool, options) => {
10
15
  const inject = resolveInject(options.inject);
16
+ const id = publishedId(tool, options);
11
17
  const description = applyDescription(tool, options.descriptions);
12
- const inputSchema = publishInputSchema(tool.inputSchema, inject);
18
+ const inputSchema = publishInputSchema(tool.inputSchema, inject, pathTemplateParams(tool.metadata.path));
13
19
  const wrapExecute = options.onExecute !== void 0 || inject.hasAny;
14
- if (description === tool.description && inputSchema === tool.inputSchema && !wrapExecute) return tool;
15
20
  return {
16
21
  ...tool,
22
+ id,
17
23
  description,
18
24
  inputSchema,
19
- execute: wrapExecute ? wrapToolExecute(tool, options.onExecute, inject) : tool.execute
25
+ execute: wrapExecute ? wrapToolExecute({
26
+ ...tool,
27
+ id
28
+ }, options.onExecute, inject) : tool.execute
20
29
  };
21
30
  };
31
+ function publishedId(tool, options) {
32
+ let id = tool.id;
33
+ if (options.names !== void 0) {
34
+ if (typeof options.names === "function") {
35
+ id = options.names({
36
+ operationId: tool.operationId,
37
+ id: tool.id
38
+ });
39
+ if (typeof id !== "string") throw new TypeError(`Neon tool name overrides must return a string for ${tool.operationId}`);
40
+ } else {
41
+ const override = options.names[tool.operationId] ?? options.names[tool.id];
42
+ if (override !== void 0) id = override;
43
+ }
44
+ }
45
+ if (options.name !== void 0) id = options.name(id);
46
+ if (typeof id !== "string" || !PUBLISHED_ID.test(id)) throw new TypeError(`Neon tool id must match ${PUBLISHED_ID} for ${tool.operationId}: received ${JSON.stringify(id)}`);
47
+ return id;
48
+ }
22
49
  function resolveInject(inject) {
23
50
  if (inject === void 0) return {
24
51
  omitFromSchema: false,
@@ -64,10 +91,10 @@ function applyDescription(tool, descriptions) {
64
91
  }
65
92
  function wrapToolExecute(tool, onExecute, inject) {
66
93
  const originalExecute = tool.execute.bind(tool);
67
- const availableKeys = pathKeys(tool.inputSchema);
94
+ const availableKeys = pathTemplateParams(tool.metadata.path);
68
95
  const mode = inject.omitFromSchema ? "override" : "fill";
69
96
  return async (input, context) => {
70
- const run = async () => originalExecute(mergePathPatch(input, await resolveInjectedPath(input, inject, availableKeys, mode), mode), context);
97
+ const run = async () => originalExecute(mergeFields(input, await resolveInjectedFields(input, inject, availableKeys, mode), mode), context);
71
98
  if (onExecute === void 0) return run();
72
99
  return onExecute({
73
100
  operationId: tool.operationId,
@@ -77,10 +104,10 @@ function wrapToolExecute(tool, onExecute, inject) {
77
104
  });
78
105
  };
79
106
  }
80
- async function resolveInjectedPath(input, inject, availableKeys, mode) {
81
- const present = isPlainObject(input) && isPlainObject(input.path) ? input.path : void 0;
107
+ async function resolveInjectedFields(input, inject, availableKeys, mode) {
108
+ const present = isPlainObject(input) ? input : void 0;
82
109
  const patch = {};
83
- for (const [name, pathKey] of [["projectId", "project_id"], ["branchId", "branch_id"]]) {
110
+ for (const [name, pathKey] of PATH_INJECT) {
84
111
  if (!availableKeys.has(pathKey)) continue;
85
112
  const injector = inject[name];
86
113
  if (injector === void 0) continue;
@@ -95,78 +122,37 @@ async function resolveInjectedPath(input, inject, availableKeys, mode) {
95
122
  }
96
123
  return patch;
97
124
  }
98
- function mergePathPatch(input, patch, mode) {
125
+ function mergeFields(input, patch, mode) {
99
126
  if (Object.keys(patch).length === 0) return input === void 0 ? {} : input;
100
- if (input === void 0) return { path: patch };
127
+ if (input === void 0) return patch;
101
128
  if (!isPlainObject(input)) return input;
102
- const path = input.path;
103
- if (path === void 0) return {
104
- ...input,
105
- path: patch
106
- };
107
- if (!isPlainObject(path)) return input;
108
- const nextPath = { ...path };
109
- for (const [key, value] of Object.entries(patch)) if (mode === "override" || nextPath[key] === void 0) nextPath[key] = value;
110
- return {
111
- ...input,
112
- path: nextPath
113
- };
129
+ const next = { ...input };
130
+ for (const [key, value] of Object.entries(patch)) if (mode === "override" || next[key] === void 0) next[key] = value;
131
+ return next;
114
132
  }
115
133
  function cloneInput(input) {
116
134
  if (!isPlainObject(input)) return input;
117
- if (!isPlainObject(input.path)) return { ...input };
118
- return {
119
- ...input,
120
- path: { ...input.path }
121
- };
135
+ return { ...input };
122
136
  }
123
137
  function objectShape(schema) {
124
138
  if (schema instanceof z.ZodOptional) return objectShape(schema.unwrap());
125
139
  if (schema instanceof z.ZodObject) return schema.shape;
126
140
  }
127
- function pathKeys(schema) {
128
- const shape = objectShape(schema);
129
- if (shape?.path === void 0) return /* @__PURE__ */ new Set();
130
- const pathShape = objectShape(shape.path);
131
- if (pathShape === void 0) return /* @__PURE__ */ new Set();
132
- return new Set(Object.keys(pathShape));
133
- }
134
- function publishInputSchema(schema, inject) {
141
+ function publishInputSchema(schema, inject, pathKeys) {
135
142
  if (!inject.hasAny) return schema;
136
- const available = pathKeys(schema);
137
- const modes = {};
138
- if (inject.projectId !== void 0 && available.has("project_id")) modes.project_id = inject.omitFromSchema ? "omit" : "optional";
139
- if (inject.branchId !== void 0 && available.has("branch_id")) modes.branch_id = inject.omitFromSchema ? "omit" : "optional";
140
- if (modes.project_id === void 0 && modes.branch_id === void 0) return schema;
141
- return rewritePathSchema(schema, modes);
142
- }
143
- function rewritePathSchema(schema, modes) {
144
- if (!(schema instanceof z.ZodObject)) return schema;
145
- const shape = schema.shape;
146
- if (shape.path === void 0) return schema;
147
- let pathSchema = shape.path;
148
- if (shape.path instanceof z.ZodOptional) pathSchema = shape.path.unwrap();
149
- const pathWasOptional = shape.path instanceof z.ZodOptional;
150
- if (!(pathSchema instanceof z.ZodObject)) return schema;
151
- const pathShape = { ...pathSchema.shape };
143
+ const shape = objectShape(schema);
144
+ if (shape === void 0) return schema;
145
+ const nextShape = { ...shape };
152
146
  let changed = false;
153
- for (const key of ["project_id", "branch_id"]) {
154
- const mode = modes[key];
155
- if (mode === void 0 || pathShape[key] === void 0) continue;
147
+ for (const [name, pathKey] of PATH_INJECT) {
148
+ if (inject[name] === void 0 || !pathKeys.has(pathKey)) continue;
149
+ if (nextShape[pathKey] === void 0) continue;
156
150
  changed = true;
157
- if (mode === "omit") delete pathShape[key];
158
- else pathShape[key] = pathShape[key].optional();
151
+ if (inject.omitFromSchema) delete nextShape[pathKey];
152
+ else nextShape[pathKey] = nextShape[pathKey].optional();
159
153
  }
160
154
  if (!changed) return schema;
161
- const restShape = { ...shape };
162
- const remaining = Object.keys(pathShape);
163
- if (remaining.length === 0) {
164
- delete restShape.path;
165
- return Object.keys(restShape).length === 0 ? z.strictObject({}) : z.strictObject(restShape);
166
- }
167
- const nextPath = z.strictObject(pathShape);
168
- restShape.path = pathWasOptional || remaining.every((key) => pathShape[key] instanceof z.ZodOptional) ? nextPath.optional() : nextPath;
169
- return z.strictObject(restShape);
155
+ return Object.keys(nextShape).length === 0 ? z.strictObject({}) : z.strictObject(nextShape);
170
156
  }
171
157
  //#endregion
172
- export { applyToolCustomization, assertToolCustomizeOptions, hasToolCustomization };
158
+ export { applyToolCustomization, assertToolCustomizeOptions, hasToolCustomization, pathTemplateParams };
@@ -0,0 +1,5 @@
1
+ export declare function optionalGroup<Value extends Record<string, unknown>>(value: Value, required: true): Value;
2
+ export declare function optionalGroup<Value extends Record<string, unknown>>(value: Value, required: false): Value | undefined;
3
+ export declare function decodeBinaryFields(body: Record<string, unknown>, fields: readonly string[], decode: (value: string) => Blob): Record<string, unknown>;
4
+ export declare function decodeBinaryFields(body: Record<string, unknown> | undefined, fields: readonly string[], decode: (value: string) => Blob): Record<string, unknown> | undefined;
5
+ //# sourceMappingURL=envelope.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../../src/lib/envelope.ts"],"names":[],"mappings":"AAYA,wBAAgB,aAAa,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,IAAI,GACZ,KAAK,CAAC;AACT,wBAAgB,aAAa,CAAC,KAAK,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClE,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,KAAK,GACb,KAAK,GAAG,SAAS,CAAC;AAYrB,wBAAgB,kBAAkB,CACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC3B,wBAAgB,kBAAkB,CACjC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,EACzC,MAAM,EAAE,SAAS,MAAM,EAAE,EACzB,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,GAC7B,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC"}
@@ -0,0 +1,22 @@
1
+ //#region src/lib/envelope.ts
2
+ const defined = (value) => {
3
+ const next = {};
4
+ for (const [key, child] of Object.entries(value)) if (child !== void 0) next[key] = child;
5
+ return next;
6
+ };
7
+ function optionalGroup(value, required) {
8
+ const next = defined(value);
9
+ if (!required && Object.keys(next).length === 0) return;
10
+ return next;
11
+ }
12
+ function decodeBinaryFields(body, fields, decode) {
13
+ if (body === void 0) return;
14
+ const next = { ...body };
15
+ for (const field of fields) {
16
+ const value = next[field];
17
+ if (typeof value === "string") next[field] = decode(value);
18
+ }
19
+ return next;
20
+ }
21
+ //#endregion
22
+ export { decodeBinaryFields, optionalGroup };