@infracraft/pulumi 1.6.3 → 1.6.4

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.
@@ -40,7 +40,8 @@ var NeonEndpointResourceProvider = class {
40
40
  }
41
41
  };
42
42
  }
43
- const result = await client.post(`/projects/${inputs.projectId}/branches/${inputs.branchId}/endpoints`, { endpoint: {
43
+ const result = await client.post(`/projects/${inputs.projectId}/endpoints`, { endpoint: {
44
+ branch_id: inputs.branchId,
44
45
  type: "read_write",
45
46
  autoscaling_limit_min_cu: inputs.minCu,
46
47
  autoscaling_limit_max_cu: inputs.maxCu,
@@ -1 +1 @@
1
- {"version":3,"file":"endpoint.cjs","names":["NeonClient","pulumi"],"sources":["../../src/neon/endpoint.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\nimport type { NeonBranch } from \"./branch\";\nimport { NeonClient } from \"./client\";\nimport type { NeonProject } from \"./project\";\nimport type { NeonProvider } from \"./provider\";\n\n/** Resolved inputs for the Neon endpoint dynamic provider. */\nexport interface NeonEndpointInputs {\n\t/** Neon API key. */\n\tapiKey: string;\n\n\t/** Neon project ID. */\n\tprojectId: string;\n\n\t/** Branch ID to attach the endpoint to. */\n\tbranchId: string;\n\n\t/** Minimum compute units (e.g. `0.25`). */\n\tminCu: number;\n\n\t/** Maximum compute units (e.g. `2`). */\n\tmaxCu: number;\n\n\t/** Seconds of inactivity before suspending. `0` means use global default. */\n\tsuspendTimeout: number;\n}\n\n/** Persisted state for the Neon endpoint. */\ninterface NeonEndpointOutputs extends NeonEndpointInputs {\n\t/** Endpoint hostname (e.g. `\"ep-delicate-union-ah0ekn7n.us-east-1.aws.neon.tech\"`). */\n\thost: string;\n}\n\n/** Neon API response for an endpoint. */\ninterface EndpointResponse {\n\tendpoint: {\n\t\tid: string;\n\t\thost: string;\n\t\tbranch_id: string;\n\t\tautoscaling_limit_min_cu: number;\n\t\tautoscaling_limit_max_cu: number;\n\t\tsuspend_timeout_seconds: number;\n\t};\n}\n\n/** Neon API response for listing endpoints. */\ninterface EndpointListResponse {\n\tendpoints: Array<{\n\t\tid: string;\n\t\thost: string;\n\t\tbranch_id: string;\n\t\ttype: string;\n\t}>;\n}\n\n/**\n * Finds an existing read-write endpoint for a branch.\n */\nasync function findEndpointByBranch(\n\tclient: NeonClient,\n\tprojectId: string,\n\tbranchId: string,\n): Promise<{ id: string; host: string } | undefined> {\n\tconst result = await client.get<EndpointListResponse>(\n\t\t`/projects/${projectId}/branches/${branchId}/endpoints`,\n\t);\n\n\tconst match = result.endpoints.find((e) => e.type === \"read_write\");\n\n\treturn match ? { id: match.id, host: match.host } : undefined;\n}\n\n/**\n * Dynamic provider implementing CRUD for Neon compute endpoints.\n *\n * Uses adopt-or-create on `create()`: finds an existing read-write endpoint\n * on the target branch before creating a new one.\n */\nclass NeonEndpointResourceProvider implements pulumi.dynamic.ResourceProvider {\n\tasync create(\n\t\tinputs: NeonEndpointInputs,\n\t): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new NeonClient(inputs.apiKey);\n\n\t\tconst existing = await findEndpointByBranch(\n\t\t\tclient,\n\t\t\tinputs.projectId,\n\t\t\tinputs.branchId,\n\t\t);\n\n\t\tif (existing) {\n\t\t\tpulumi.log.info(`Adopting existing Neon endpoint (${existing.id})`);\n\n\t\t\tawait client.patch(\n\t\t\t\t`/projects/${inputs.projectId}/endpoints/${existing.id}`,\n\t\t\t\t{\n\t\t\t\t\tendpoint: {\n\t\t\t\t\t\tautoscaling_limit_min_cu: inputs.minCu,\n\t\t\t\t\t\tautoscaling_limit_max_cu: inputs.maxCu,\n\t\t\t\t\t\tsuspend_timeout_seconds: inputs.suspendTimeout,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tid: existing.id,\n\t\t\t\touts: { ...inputs, host: existing.host },\n\t\t\t};\n\t\t}\n\n\t\tconst result = await client.post<EndpointResponse>(\n\t\t\t`/projects/${inputs.projectId}/branches/${inputs.branchId}/endpoints`,\n\t\t\t{\n\t\t\t\tendpoint: {\n\t\t\t\t\ttype: \"read_write\",\n\t\t\t\t\tautoscaling_limit_min_cu: inputs.minCu,\n\t\t\t\t\tautoscaling_limit_max_cu: inputs.maxCu,\n\t\t\t\t\tsuspend_timeout_seconds: inputs.suspendTimeout,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\treturn {\n\t\t\tid: result.endpoint.id,\n\t\t\touts: { ...inputs, host: result.endpoint.host },\n\t\t};\n\t}\n\n\tasync update(\n\t\tid: string,\n\t\t_olds: NeonEndpointOutputs,\n\t\tnews: NeonEndpointInputs,\n\t): Promise<pulumi.dynamic.UpdateResult> {\n\t\tconst client = new NeonClient(news.apiKey);\n\n\t\tconst result = await client.patch<EndpointResponse>(\n\t\t\t`/projects/${news.projectId}/endpoints/${id}`,\n\t\t\t{\n\t\t\t\tendpoint: {\n\t\t\t\t\tautoscaling_limit_min_cu: news.minCu,\n\t\t\t\t\tautoscaling_limit_max_cu: news.maxCu,\n\t\t\t\t\tsuspend_timeout_seconds: news.suspendTimeout,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\treturn { outs: { ...news, host: result.endpoint.host } };\n\t}\n\n\tasync read(\n\t\tid: string,\n\t\tprops: NeonEndpointOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new NeonClient(props.apiKey);\n\n\t\tconst result = await client.get<EndpointResponse>(\n\t\t\t`/projects/${props.projectId}/endpoints/${id}`,\n\t\t);\n\n\t\treturn {\n\t\t\tid: result.endpoint.id,\n\t\t\tprops: {\n\t\t\t\t...props,\n\t\t\t\thost: result.endpoint.host,\n\t\t\t\tminCu: result.endpoint.autoscaling_limit_min_cu,\n\t\t\t\tmaxCu: result.endpoint.autoscaling_limit_max_cu,\n\t\t\t\tsuspendTimeout: result.endpoint.suspend_timeout_seconds,\n\t\t\t},\n\t\t};\n\t}\n\n\tasync delete(id: string, props: NeonEndpointOutputs): Promise<void> {\n\t\tconst client = new NeonClient(props.apiKey);\n\n\t\ttry {\n\t\t\tawait client.delete(`/projects/${props.projectId}/endpoints/${id}`);\n\t\t} catch {\n\t\t\tpulumi.log.warn(\n\t\t\t\t`Failed to delete Neon endpoint (may already be deleted)`,\n\t\t\t);\n\t\t}\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: NeonEndpointOutputs,\n\t\tnews: NeonEndpointInputs,\n\t): Promise<pulumi.dynamic.DiffResult> {\n\t\tconst replaces: string[] = [];\n\n\t\tif (olds.projectId !== news.projectId) {\n\t\t\treplaces.push(\"projectId\");\n\t\t}\n\n\t\tif (olds.branchId !== news.branchId) {\n\t\t\treplaces.push(\"branchId\");\n\t\t}\n\n\t\tconst hasChanges =\n\t\t\treplaces.length > 0 ||\n\t\t\tolds.minCu !== news.minCu ||\n\t\t\tolds.maxCu !== news.maxCu ||\n\t\t\tolds.suspendTimeout !== news.suspendTimeout;\n\n\t\treturn { changes: hasChanges, replaces, deleteBeforeReplace: true };\n\t}\n}\n\n/** Internal dynamic resource — not part of the public API. */\nclass NeonEndpointResource extends pulumi.dynamic.Resource {\n\tpublic declare readonly host: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\tapiKey: pulumi.Input<string>;\n\t\t\tprojectId: pulumi.Input<string>;\n\t\t\tbranchId: pulumi.Input<string>;\n\t\t\tminCu: pulumi.Input<number>;\n\t\t\tmaxCu: pulumi.Input<number>;\n\t\t\tsuspendTimeout: pulumi.Input<number>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(\n\t\t\tnew NeonEndpointResourceProvider(),\n\t\t\tname,\n\t\t\t{ ...args, host: undefined },\n\t\t\topts,\n\t\t);\n\t}\n}\n\n/** Options type for NeonEndpoint — replaces Pulumi's native `provider` field. */\ntype NeonEndpointOptions = Omit<pulumi.ComponentResourceOptions, \"provider\"> & {\n\t/** Neon authentication context. */\n\tprovider: NeonProvider;\n\n\t/** Neon project context. */\n\tproject: NeonProject;\n\n\t/** Neon branch context. */\n\tbranch: NeonBranch;\n};\n\n/** Args for NeonEndpoint. */\nexport interface NeonEndpointArgs {\n\t/** Minimum compute units. */\n\tminCu: pulumi.Input<number>;\n\n\t/** Maximum compute units. */\n\tmaxCu: pulumi.Input<number>;\n\n\t/** Seconds of inactivity before suspending. */\n\tsuspendTimeout: pulumi.Input<number>;\n}\n\n/**\n * Manages a Neon compute endpoint with adopt-or-create semantics.\n * Exposes `host` as an output for connection string composition.\n *\n * @example\n * ```typescript\n * const endpoint = new NeonEndpoint(\"production\", {\n * minCu: 0.25,\n * maxCu: 1,\n * suspendTimeout: 0,\n * }, { provider, project, branch });\n * ```\n */\nexport class NeonEndpoint extends pulumi.ComponentResource {\n\t/** Endpoint hostname for connection strings. */\n\tpublic readonly host: pulumi.Output<string>;\n\n\tconstructor(name: string, args: NeonEndpointArgs, opts: NeonEndpointOptions) {\n\t\tconst { provider, project, branch, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:neon:Endpoint\", name, {}, pulumiOpts);\n\n\t\tconst resource = new NeonEndpointResource(\n\t\t\t`${name}-resource`,\n\t\t\t{\n\t\t\t\tapiKey: provider.apiKey,\n\t\t\t\tprojectId: project.id,\n\t\t\t\tbranchId: branch.id,\n\t\t\t\t...args,\n\t\t\t},\n\t\t\t{ parent: this },\n\t\t);\n\n\t\tthis.host = resource.host;\n\n\t\tthis.registerOutputs({ host: this.host });\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"endpoint.cjs","names":["NeonClient","pulumi"],"sources":["../../src/neon/endpoint.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\nimport type { NeonBranch } from \"./branch\";\nimport { NeonClient } from \"./client\";\nimport type { NeonProject } from \"./project\";\nimport type { NeonProvider } from \"./provider\";\n\n/** Resolved inputs for the Neon endpoint dynamic provider. */\nexport interface NeonEndpointInputs {\n\t/** Neon API key. */\n\tapiKey: string;\n\n\t/** Neon project ID. */\n\tprojectId: string;\n\n\t/** Branch ID to attach the endpoint to. */\n\tbranchId: string;\n\n\t/** Minimum compute units (e.g. `0.25`). */\n\tminCu: number;\n\n\t/** Maximum compute units (e.g. `2`). */\n\tmaxCu: number;\n\n\t/** Seconds of inactivity before suspending. `0` means use global default. */\n\tsuspendTimeout: number;\n}\n\n/** Persisted state for the Neon endpoint. */\ninterface NeonEndpointOutputs extends NeonEndpointInputs {\n\t/** Endpoint hostname (e.g. `\"ep-delicate-union-ah0ekn7n.us-east-1.aws.neon.tech\"`). */\n\thost: string;\n}\n\n/** Neon API response for an endpoint. */\ninterface EndpointResponse {\n\tendpoint: {\n\t\tid: string;\n\t\thost: string;\n\t\tbranch_id: string;\n\t\tautoscaling_limit_min_cu: number;\n\t\tautoscaling_limit_max_cu: number;\n\t\tsuspend_timeout_seconds: number;\n\t};\n}\n\n/** Neon API response for listing endpoints. */\ninterface EndpointListResponse {\n\tendpoints: Array<{\n\t\tid: string;\n\t\thost: string;\n\t\tbranch_id: string;\n\t\ttype: string;\n\t}>;\n}\n\n/**\n * Finds an existing read-write endpoint for a branch.\n */\nasync function findEndpointByBranch(\n\tclient: NeonClient,\n\tprojectId: string,\n\tbranchId: string,\n): Promise<{ id: string; host: string } | undefined> {\n\tconst result = await client.get<EndpointListResponse>(\n\t\t`/projects/${projectId}/branches/${branchId}/endpoints`,\n\t);\n\n\tconst match = result.endpoints.find((e) => e.type === \"read_write\");\n\n\treturn match ? { id: match.id, host: match.host } : undefined;\n}\n\n/**\n * Dynamic provider implementing CRUD for Neon compute endpoints.\n *\n * Uses adopt-or-create on `create()`: finds an existing read-write endpoint\n * on the target branch before creating a new one.\n */\nclass NeonEndpointResourceProvider implements pulumi.dynamic.ResourceProvider {\n\tasync create(\n\t\tinputs: NeonEndpointInputs,\n\t): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new NeonClient(inputs.apiKey);\n\n\t\tconst existing = await findEndpointByBranch(\n\t\t\tclient,\n\t\t\tinputs.projectId,\n\t\t\tinputs.branchId,\n\t\t);\n\n\t\tif (existing) {\n\t\t\tpulumi.log.info(`Adopting existing Neon endpoint (${existing.id})`);\n\n\t\t\tawait client.patch(\n\t\t\t\t`/projects/${inputs.projectId}/endpoints/${existing.id}`,\n\t\t\t\t{\n\t\t\t\t\tendpoint: {\n\t\t\t\t\t\tautoscaling_limit_min_cu: inputs.minCu,\n\t\t\t\t\t\tautoscaling_limit_max_cu: inputs.maxCu,\n\t\t\t\t\t\tsuspend_timeout_seconds: inputs.suspendTimeout,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tid: existing.id,\n\t\t\t\touts: { ...inputs, host: existing.host },\n\t\t\t};\n\t\t}\n\n\t\t// Create the compute endpoint via the project-level endpoints collection with\n\t\t// branch_id in the body. The branch-scoped path (/branches/{id}/endpoints) is\n\t\t// GET-only and returns 405 on POST.\n\t\tconst result = await client.post<EndpointResponse>(\n\t\t\t`/projects/${inputs.projectId}/endpoints`,\n\t\t\t{\n\t\t\t\tendpoint: {\n\t\t\t\t\tbranch_id: inputs.branchId,\n\t\t\t\t\ttype: \"read_write\",\n\t\t\t\t\tautoscaling_limit_min_cu: inputs.minCu,\n\t\t\t\t\tautoscaling_limit_max_cu: inputs.maxCu,\n\t\t\t\t\tsuspend_timeout_seconds: inputs.suspendTimeout,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\treturn {\n\t\t\tid: result.endpoint.id,\n\t\t\touts: { ...inputs, host: result.endpoint.host },\n\t\t};\n\t}\n\n\tasync update(\n\t\tid: string,\n\t\t_olds: NeonEndpointOutputs,\n\t\tnews: NeonEndpointInputs,\n\t): Promise<pulumi.dynamic.UpdateResult> {\n\t\tconst client = new NeonClient(news.apiKey);\n\n\t\tconst result = await client.patch<EndpointResponse>(\n\t\t\t`/projects/${news.projectId}/endpoints/${id}`,\n\t\t\t{\n\t\t\t\tendpoint: {\n\t\t\t\t\tautoscaling_limit_min_cu: news.minCu,\n\t\t\t\t\tautoscaling_limit_max_cu: news.maxCu,\n\t\t\t\t\tsuspend_timeout_seconds: news.suspendTimeout,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\treturn { outs: { ...news, host: result.endpoint.host } };\n\t}\n\n\tasync read(\n\t\tid: string,\n\t\tprops: NeonEndpointOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new NeonClient(props.apiKey);\n\n\t\tconst result = await client.get<EndpointResponse>(\n\t\t\t`/projects/${props.projectId}/endpoints/${id}`,\n\t\t);\n\n\t\treturn {\n\t\t\tid: result.endpoint.id,\n\t\t\tprops: {\n\t\t\t\t...props,\n\t\t\t\thost: result.endpoint.host,\n\t\t\t\tminCu: result.endpoint.autoscaling_limit_min_cu,\n\t\t\t\tmaxCu: result.endpoint.autoscaling_limit_max_cu,\n\t\t\t\tsuspendTimeout: result.endpoint.suspend_timeout_seconds,\n\t\t\t},\n\t\t};\n\t}\n\n\tasync delete(id: string, props: NeonEndpointOutputs): Promise<void> {\n\t\tconst client = new NeonClient(props.apiKey);\n\n\t\ttry {\n\t\t\tawait client.delete(`/projects/${props.projectId}/endpoints/${id}`);\n\t\t} catch {\n\t\t\tpulumi.log.warn(\n\t\t\t\t`Failed to delete Neon endpoint (may already be deleted)`,\n\t\t\t);\n\t\t}\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: NeonEndpointOutputs,\n\t\tnews: NeonEndpointInputs,\n\t): Promise<pulumi.dynamic.DiffResult> {\n\t\tconst replaces: string[] = [];\n\n\t\tif (olds.projectId !== news.projectId) {\n\t\t\treplaces.push(\"projectId\");\n\t\t}\n\n\t\tif (olds.branchId !== news.branchId) {\n\t\t\treplaces.push(\"branchId\");\n\t\t}\n\n\t\tconst hasChanges =\n\t\t\treplaces.length > 0 ||\n\t\t\tolds.minCu !== news.minCu ||\n\t\t\tolds.maxCu !== news.maxCu ||\n\t\t\tolds.suspendTimeout !== news.suspendTimeout;\n\n\t\treturn { changes: hasChanges, replaces, deleteBeforeReplace: true };\n\t}\n}\n\n/** Internal dynamic resource — not part of the public API. */\nclass NeonEndpointResource extends pulumi.dynamic.Resource {\n\tpublic declare readonly host: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\tapiKey: pulumi.Input<string>;\n\t\t\tprojectId: pulumi.Input<string>;\n\t\t\tbranchId: pulumi.Input<string>;\n\t\t\tminCu: pulumi.Input<number>;\n\t\t\tmaxCu: pulumi.Input<number>;\n\t\t\tsuspendTimeout: pulumi.Input<number>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(\n\t\t\tnew NeonEndpointResourceProvider(),\n\t\t\tname,\n\t\t\t{ ...args, host: undefined },\n\t\t\topts,\n\t\t);\n\t}\n}\n\n/** Options type for NeonEndpoint — replaces Pulumi's native `provider` field. */\ntype NeonEndpointOptions = Omit<pulumi.ComponentResourceOptions, \"provider\"> & {\n\t/** Neon authentication context. */\n\tprovider: NeonProvider;\n\n\t/** Neon project context. */\n\tproject: NeonProject;\n\n\t/** Neon branch context. */\n\tbranch: NeonBranch;\n};\n\n/** Args for NeonEndpoint. */\nexport interface NeonEndpointArgs {\n\t/** Minimum compute units. */\n\tminCu: pulumi.Input<number>;\n\n\t/** Maximum compute units. */\n\tmaxCu: pulumi.Input<number>;\n\n\t/** Seconds of inactivity before suspending. */\n\tsuspendTimeout: pulumi.Input<number>;\n}\n\n/**\n * Manages a Neon compute endpoint with adopt-or-create semantics.\n * Exposes `host` as an output for connection string composition.\n *\n * @example\n * ```typescript\n * const endpoint = new NeonEndpoint(\"production\", {\n * minCu: 0.25,\n * maxCu: 1,\n * suspendTimeout: 0,\n * }, { provider, project, branch });\n * ```\n */\nexport class NeonEndpoint extends pulumi.ComponentResource {\n\t/** Endpoint hostname for connection strings. */\n\tpublic readonly host: pulumi.Output<string>;\n\n\tconstructor(name: string, args: NeonEndpointArgs, opts: NeonEndpointOptions) {\n\t\tconst { provider, project, branch, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:neon:Endpoint\", name, {}, pulumiOpts);\n\n\t\tconst resource = new NeonEndpointResource(\n\t\t\t`${name}-resource`,\n\t\t\t{\n\t\t\t\tapiKey: provider.apiKey,\n\t\t\t\tprojectId: project.id,\n\t\t\t\tbranchId: branch.id,\n\t\t\t\t...args,\n\t\t\t},\n\t\t\t{ parent: this },\n\t\t);\n\n\t\tthis.host = resource.host;\n\n\t\tthis.registerOutputs({ host: this.host });\n\t}\n}\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"endpoint.d.cts","names":[],"sources":["../../src/neon/endpoint.ts"],"mappings":";;;;;;;;UAOiB,kBAAA;;EAEhB,MAAA;EAFkC;EAKlC,SAAA;EALkC;EAQlC,QAAA;EAHA;EAMA,KAAA;EAAA;EAGA,KAAA;EAGA;EAAA,cAAA;AAAA;AACA;AAAA,KAiNI,mBAAA,GAAsB,IAAA,CAAK,MAAA,CAAO,wBAAA;qCAEtC,QAAA,EAAU,YAAA,EAFgB;EAK1B,OAAA,EAAS,WAAA,EAAA;EAGT,MAAA,EAAQ,UAAA;AAAA;;UAIQ,gBAAA;EAZe;EAc/B,KAAA,EAAO,MAAA,CAAO,KAAA;EAZd;EAeA,KAAA,EAAO,MAAA,CAAO,KAAA;EAZd;EAeA,cAAA,EAAgB,MAAA,CAAO,KAAA;AAAA;;;AAZL;AAInB;;;;;;;;;;cAwBa,YAAA,SAAqB,MAAA,CAAO,iBAAA;EAnBxC;EAAA,SAqBgB,IAAA,EAAM,MAAA,CAAO,MAAA;cAEjB,IAAA,UAAc,IAAA,EAAM,gBAAA,EAAkB,IAAA,EAAM,mBAAA;AAAA"}
1
+ {"version":3,"file":"endpoint.d.cts","names":[],"sources":["../../src/neon/endpoint.ts"],"mappings":";;;;;;;;UAOiB,kBAAA;;EAEhB,MAAA;EAFkC;EAKlC,SAAA;EALkC;EAQlC,QAAA;EAHA;EAMA,KAAA;EAAA;EAGA,KAAA;EAGA;EAAA,cAAA;AAAA;AACA;AAAA,KAqNI,mBAAA,GAAsB,IAAA,CAAK,MAAA,CAAO,wBAAA;qCAEtC,QAAA,EAAU,YAAA,EAFgB;EAK1B,OAAA,EAAS,WAAA,EAAA;EAGT,MAAA,EAAQ,UAAA;AAAA;;UAIQ,gBAAA;EAZe;EAc/B,KAAA,EAAO,MAAA,CAAO,KAAA;EAZd;EAeA,KAAA,EAAO,MAAA,CAAO,KAAA;EAZd;EAeA,cAAA,EAAgB,MAAA,CAAO,KAAA;AAAA;;;AAZL;AAInB;;;;;;;;;;cAwBa,YAAA,SAAqB,MAAA,CAAO,iBAAA;EAnBxC;EAAA,SAqBgB,IAAA,EAAM,MAAA,CAAO,MAAA;cAEjB,IAAA,UAAc,IAAA,EAAM,gBAAA,EAAkB,IAAA,EAAM,mBAAA;AAAA"}
@@ -1 +1 @@
1
- {"version":3,"file":"endpoint.d.mts","names":[],"sources":["../../src/neon/endpoint.ts"],"mappings":";;;;;;;;UAOiB,kBAAA;;EAEhB,MAAA;EAFkC;EAKlC,SAAA;EALkC;EAQlC,QAAA;EAHA;EAMA,KAAA;EAAA;EAGA,KAAA;EAGA;EAAA,cAAA;AAAA;AACA;AAAA,KAiNI,mBAAA,GAAsB,IAAA,CAAK,MAAA,CAAO,wBAAA;qCAEtC,QAAA,EAAU,YAAA,EAFgB;EAK1B,OAAA,EAAS,WAAA,EAAA;EAGT,MAAA,EAAQ,UAAA;AAAA;;UAIQ,gBAAA;EAZe;EAc/B,KAAA,EAAO,MAAA,CAAO,KAAA;EAZd;EAeA,KAAA,EAAO,MAAA,CAAO,KAAA;EAZd;EAeA,cAAA,EAAgB,MAAA,CAAO,KAAA;AAAA;;;AAZL;AAInB;;;;;;;;;;cAwBa,YAAA,SAAqB,MAAA,CAAO,iBAAA;EAnBxC;EAAA,SAqBgB,IAAA,EAAM,MAAA,CAAO,MAAA;cAEjB,IAAA,UAAc,IAAA,EAAM,gBAAA,EAAkB,IAAA,EAAM,mBAAA;AAAA"}
1
+ {"version":3,"file":"endpoint.d.mts","names":[],"sources":["../../src/neon/endpoint.ts"],"mappings":";;;;;;;;UAOiB,kBAAA;;EAEhB,MAAA;EAFkC;EAKlC,SAAA;EALkC;EAQlC,QAAA;EAHA;EAMA,KAAA;EAAA;EAGA,KAAA;EAGA;EAAA,cAAA;AAAA;AACA;AAAA,KAqNI,mBAAA,GAAsB,IAAA,CAAK,MAAA,CAAO,wBAAA;qCAEtC,QAAA,EAAU,YAAA,EAFgB;EAK1B,OAAA,EAAS,WAAA,EAAA;EAGT,MAAA,EAAQ,UAAA;AAAA;;UAIQ,gBAAA;EAZe;EAc/B,KAAA,EAAO,MAAA,CAAO,KAAA;EAZd;EAeA,KAAA,EAAO,MAAA,CAAO,KAAA;EAZd;EAeA,cAAA,EAAgB,MAAA,CAAO,KAAA;AAAA;;;AAZL;AAInB;;;;;;;;;;cAwBa,YAAA,SAAqB,MAAA,CAAO,iBAAA;EAnBxC;EAAA,SAqBgB,IAAA,EAAM,MAAA,CAAO,MAAA;cAEjB,IAAA,UAAc,IAAA,EAAM,gBAAA,EAAkB,IAAA,EAAM,mBAAA;AAAA"}
@@ -38,7 +38,8 @@ var NeonEndpointResourceProvider = class {
38
38
  }
39
39
  };
40
40
  }
41
- const result = await client.post(`/projects/${inputs.projectId}/branches/${inputs.branchId}/endpoints`, { endpoint: {
41
+ const result = await client.post(`/projects/${inputs.projectId}/endpoints`, { endpoint: {
42
+ branch_id: inputs.branchId,
42
43
  type: "read_write",
43
44
  autoscaling_limit_min_cu: inputs.minCu,
44
45
  autoscaling_limit_max_cu: inputs.maxCu,
@@ -1 +1 @@
1
- {"version":3,"file":"endpoint.mjs","names":[],"sources":["../../src/neon/endpoint.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\nimport type { NeonBranch } from \"./branch\";\nimport { NeonClient } from \"./client\";\nimport type { NeonProject } from \"./project\";\nimport type { NeonProvider } from \"./provider\";\n\n/** Resolved inputs for the Neon endpoint dynamic provider. */\nexport interface NeonEndpointInputs {\n\t/** Neon API key. */\n\tapiKey: string;\n\n\t/** Neon project ID. */\n\tprojectId: string;\n\n\t/** Branch ID to attach the endpoint to. */\n\tbranchId: string;\n\n\t/** Minimum compute units (e.g. `0.25`). */\n\tminCu: number;\n\n\t/** Maximum compute units (e.g. `2`). */\n\tmaxCu: number;\n\n\t/** Seconds of inactivity before suspending. `0` means use global default. */\n\tsuspendTimeout: number;\n}\n\n/** Persisted state for the Neon endpoint. */\ninterface NeonEndpointOutputs extends NeonEndpointInputs {\n\t/** Endpoint hostname (e.g. `\"ep-delicate-union-ah0ekn7n.us-east-1.aws.neon.tech\"`). */\n\thost: string;\n}\n\n/** Neon API response for an endpoint. */\ninterface EndpointResponse {\n\tendpoint: {\n\t\tid: string;\n\t\thost: string;\n\t\tbranch_id: string;\n\t\tautoscaling_limit_min_cu: number;\n\t\tautoscaling_limit_max_cu: number;\n\t\tsuspend_timeout_seconds: number;\n\t};\n}\n\n/** Neon API response for listing endpoints. */\ninterface EndpointListResponse {\n\tendpoints: Array<{\n\t\tid: string;\n\t\thost: string;\n\t\tbranch_id: string;\n\t\ttype: string;\n\t}>;\n}\n\n/**\n * Finds an existing read-write endpoint for a branch.\n */\nasync function findEndpointByBranch(\n\tclient: NeonClient,\n\tprojectId: string,\n\tbranchId: string,\n): Promise<{ id: string; host: string } | undefined> {\n\tconst result = await client.get<EndpointListResponse>(\n\t\t`/projects/${projectId}/branches/${branchId}/endpoints`,\n\t);\n\n\tconst match = result.endpoints.find((e) => e.type === \"read_write\");\n\n\treturn match ? { id: match.id, host: match.host } : undefined;\n}\n\n/**\n * Dynamic provider implementing CRUD for Neon compute endpoints.\n *\n * Uses adopt-or-create on `create()`: finds an existing read-write endpoint\n * on the target branch before creating a new one.\n */\nclass NeonEndpointResourceProvider implements pulumi.dynamic.ResourceProvider {\n\tasync create(\n\t\tinputs: NeonEndpointInputs,\n\t): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new NeonClient(inputs.apiKey);\n\n\t\tconst existing = await findEndpointByBranch(\n\t\t\tclient,\n\t\t\tinputs.projectId,\n\t\t\tinputs.branchId,\n\t\t);\n\n\t\tif (existing) {\n\t\t\tpulumi.log.info(`Adopting existing Neon endpoint (${existing.id})`);\n\n\t\t\tawait client.patch(\n\t\t\t\t`/projects/${inputs.projectId}/endpoints/${existing.id}`,\n\t\t\t\t{\n\t\t\t\t\tendpoint: {\n\t\t\t\t\t\tautoscaling_limit_min_cu: inputs.minCu,\n\t\t\t\t\t\tautoscaling_limit_max_cu: inputs.maxCu,\n\t\t\t\t\t\tsuspend_timeout_seconds: inputs.suspendTimeout,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tid: existing.id,\n\t\t\t\touts: { ...inputs, host: existing.host },\n\t\t\t};\n\t\t}\n\n\t\tconst result = await client.post<EndpointResponse>(\n\t\t\t`/projects/${inputs.projectId}/branches/${inputs.branchId}/endpoints`,\n\t\t\t{\n\t\t\t\tendpoint: {\n\t\t\t\t\ttype: \"read_write\",\n\t\t\t\t\tautoscaling_limit_min_cu: inputs.minCu,\n\t\t\t\t\tautoscaling_limit_max_cu: inputs.maxCu,\n\t\t\t\t\tsuspend_timeout_seconds: inputs.suspendTimeout,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\treturn {\n\t\t\tid: result.endpoint.id,\n\t\t\touts: { ...inputs, host: result.endpoint.host },\n\t\t};\n\t}\n\n\tasync update(\n\t\tid: string,\n\t\t_olds: NeonEndpointOutputs,\n\t\tnews: NeonEndpointInputs,\n\t): Promise<pulumi.dynamic.UpdateResult> {\n\t\tconst client = new NeonClient(news.apiKey);\n\n\t\tconst result = await client.patch<EndpointResponse>(\n\t\t\t`/projects/${news.projectId}/endpoints/${id}`,\n\t\t\t{\n\t\t\t\tendpoint: {\n\t\t\t\t\tautoscaling_limit_min_cu: news.minCu,\n\t\t\t\t\tautoscaling_limit_max_cu: news.maxCu,\n\t\t\t\t\tsuspend_timeout_seconds: news.suspendTimeout,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\treturn { outs: { ...news, host: result.endpoint.host } };\n\t}\n\n\tasync read(\n\t\tid: string,\n\t\tprops: NeonEndpointOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new NeonClient(props.apiKey);\n\n\t\tconst result = await client.get<EndpointResponse>(\n\t\t\t`/projects/${props.projectId}/endpoints/${id}`,\n\t\t);\n\n\t\treturn {\n\t\t\tid: result.endpoint.id,\n\t\t\tprops: {\n\t\t\t\t...props,\n\t\t\t\thost: result.endpoint.host,\n\t\t\t\tminCu: result.endpoint.autoscaling_limit_min_cu,\n\t\t\t\tmaxCu: result.endpoint.autoscaling_limit_max_cu,\n\t\t\t\tsuspendTimeout: result.endpoint.suspend_timeout_seconds,\n\t\t\t},\n\t\t};\n\t}\n\n\tasync delete(id: string, props: NeonEndpointOutputs): Promise<void> {\n\t\tconst client = new NeonClient(props.apiKey);\n\n\t\ttry {\n\t\t\tawait client.delete(`/projects/${props.projectId}/endpoints/${id}`);\n\t\t} catch {\n\t\t\tpulumi.log.warn(\n\t\t\t\t`Failed to delete Neon endpoint (may already be deleted)`,\n\t\t\t);\n\t\t}\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: NeonEndpointOutputs,\n\t\tnews: NeonEndpointInputs,\n\t): Promise<pulumi.dynamic.DiffResult> {\n\t\tconst replaces: string[] = [];\n\n\t\tif (olds.projectId !== news.projectId) {\n\t\t\treplaces.push(\"projectId\");\n\t\t}\n\n\t\tif (olds.branchId !== news.branchId) {\n\t\t\treplaces.push(\"branchId\");\n\t\t}\n\n\t\tconst hasChanges =\n\t\t\treplaces.length > 0 ||\n\t\t\tolds.minCu !== news.minCu ||\n\t\t\tolds.maxCu !== news.maxCu ||\n\t\t\tolds.suspendTimeout !== news.suspendTimeout;\n\n\t\treturn { changes: hasChanges, replaces, deleteBeforeReplace: true };\n\t}\n}\n\n/** Internal dynamic resource — not part of the public API. */\nclass NeonEndpointResource extends pulumi.dynamic.Resource {\n\tpublic declare readonly host: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\tapiKey: pulumi.Input<string>;\n\t\t\tprojectId: pulumi.Input<string>;\n\t\t\tbranchId: pulumi.Input<string>;\n\t\t\tminCu: pulumi.Input<number>;\n\t\t\tmaxCu: pulumi.Input<number>;\n\t\t\tsuspendTimeout: pulumi.Input<number>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(\n\t\t\tnew NeonEndpointResourceProvider(),\n\t\t\tname,\n\t\t\t{ ...args, host: undefined },\n\t\t\topts,\n\t\t);\n\t}\n}\n\n/** Options type for NeonEndpoint — replaces Pulumi's native `provider` field. */\ntype NeonEndpointOptions = Omit<pulumi.ComponentResourceOptions, \"provider\"> & {\n\t/** Neon authentication context. */\n\tprovider: NeonProvider;\n\n\t/** Neon project context. */\n\tproject: NeonProject;\n\n\t/** Neon branch context. */\n\tbranch: NeonBranch;\n};\n\n/** Args for NeonEndpoint. */\nexport interface NeonEndpointArgs {\n\t/** Minimum compute units. */\n\tminCu: pulumi.Input<number>;\n\n\t/** Maximum compute units. */\n\tmaxCu: pulumi.Input<number>;\n\n\t/** Seconds of inactivity before suspending. */\n\tsuspendTimeout: pulumi.Input<number>;\n}\n\n/**\n * Manages a Neon compute endpoint with adopt-or-create semantics.\n * Exposes `host` as an output for connection string composition.\n *\n * @example\n * ```typescript\n * const endpoint = new NeonEndpoint(\"production\", {\n * minCu: 0.25,\n * maxCu: 1,\n * suspendTimeout: 0,\n * }, { provider, project, branch });\n * ```\n */\nexport class NeonEndpoint extends pulumi.ComponentResource {\n\t/** Endpoint hostname for connection strings. */\n\tpublic readonly host: pulumi.Output<string>;\n\n\tconstructor(name: string, args: NeonEndpointArgs, opts: NeonEndpointOptions) {\n\t\tconst { provider, project, branch, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:neon:Endpoint\", name, {}, pulumiOpts);\n\n\t\tconst resource = new NeonEndpointResource(\n\t\t\t`${name}-resource`,\n\t\t\t{\n\t\t\t\tapiKey: provider.apiKey,\n\t\t\t\tprojectId: project.id,\n\t\t\t\tbranchId: branch.id,\n\t\t\t\t...args,\n\t\t\t},\n\t\t\t{ parent: this },\n\t\t);\n\n\t\tthis.host = resource.host;\n\n\t\tthis.registerOutputs({ host: this.host });\n\t}\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"endpoint.mjs","names":[],"sources":["../../src/neon/endpoint.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\nimport type { NeonBranch } from \"./branch\";\nimport { NeonClient } from \"./client\";\nimport type { NeonProject } from \"./project\";\nimport type { NeonProvider } from \"./provider\";\n\n/** Resolved inputs for the Neon endpoint dynamic provider. */\nexport interface NeonEndpointInputs {\n\t/** Neon API key. */\n\tapiKey: string;\n\n\t/** Neon project ID. */\n\tprojectId: string;\n\n\t/** Branch ID to attach the endpoint to. */\n\tbranchId: string;\n\n\t/** Minimum compute units (e.g. `0.25`). */\n\tminCu: number;\n\n\t/** Maximum compute units (e.g. `2`). */\n\tmaxCu: number;\n\n\t/** Seconds of inactivity before suspending. `0` means use global default. */\n\tsuspendTimeout: number;\n}\n\n/** Persisted state for the Neon endpoint. */\ninterface NeonEndpointOutputs extends NeonEndpointInputs {\n\t/** Endpoint hostname (e.g. `\"ep-delicate-union-ah0ekn7n.us-east-1.aws.neon.tech\"`). */\n\thost: string;\n}\n\n/** Neon API response for an endpoint. */\ninterface EndpointResponse {\n\tendpoint: {\n\t\tid: string;\n\t\thost: string;\n\t\tbranch_id: string;\n\t\tautoscaling_limit_min_cu: number;\n\t\tautoscaling_limit_max_cu: number;\n\t\tsuspend_timeout_seconds: number;\n\t};\n}\n\n/** Neon API response for listing endpoints. */\ninterface EndpointListResponse {\n\tendpoints: Array<{\n\t\tid: string;\n\t\thost: string;\n\t\tbranch_id: string;\n\t\ttype: string;\n\t}>;\n}\n\n/**\n * Finds an existing read-write endpoint for a branch.\n */\nasync function findEndpointByBranch(\n\tclient: NeonClient,\n\tprojectId: string,\n\tbranchId: string,\n): Promise<{ id: string; host: string } | undefined> {\n\tconst result = await client.get<EndpointListResponse>(\n\t\t`/projects/${projectId}/branches/${branchId}/endpoints`,\n\t);\n\n\tconst match = result.endpoints.find((e) => e.type === \"read_write\");\n\n\treturn match ? { id: match.id, host: match.host } : undefined;\n}\n\n/**\n * Dynamic provider implementing CRUD for Neon compute endpoints.\n *\n * Uses adopt-or-create on `create()`: finds an existing read-write endpoint\n * on the target branch before creating a new one.\n */\nclass NeonEndpointResourceProvider implements pulumi.dynamic.ResourceProvider {\n\tasync create(\n\t\tinputs: NeonEndpointInputs,\n\t): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new NeonClient(inputs.apiKey);\n\n\t\tconst existing = await findEndpointByBranch(\n\t\t\tclient,\n\t\t\tinputs.projectId,\n\t\t\tinputs.branchId,\n\t\t);\n\n\t\tif (existing) {\n\t\t\tpulumi.log.info(`Adopting existing Neon endpoint (${existing.id})`);\n\n\t\t\tawait client.patch(\n\t\t\t\t`/projects/${inputs.projectId}/endpoints/${existing.id}`,\n\t\t\t\t{\n\t\t\t\t\tendpoint: {\n\t\t\t\t\t\tautoscaling_limit_min_cu: inputs.minCu,\n\t\t\t\t\t\tautoscaling_limit_max_cu: inputs.maxCu,\n\t\t\t\t\t\tsuspend_timeout_seconds: inputs.suspendTimeout,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t);\n\n\t\t\treturn {\n\t\t\t\tid: existing.id,\n\t\t\t\touts: { ...inputs, host: existing.host },\n\t\t\t};\n\t\t}\n\n\t\t// Create the compute endpoint via the project-level endpoints collection with\n\t\t// branch_id in the body. The branch-scoped path (/branches/{id}/endpoints) is\n\t\t// GET-only and returns 405 on POST.\n\t\tconst result = await client.post<EndpointResponse>(\n\t\t\t`/projects/${inputs.projectId}/endpoints`,\n\t\t\t{\n\t\t\t\tendpoint: {\n\t\t\t\t\tbranch_id: inputs.branchId,\n\t\t\t\t\ttype: \"read_write\",\n\t\t\t\t\tautoscaling_limit_min_cu: inputs.minCu,\n\t\t\t\t\tautoscaling_limit_max_cu: inputs.maxCu,\n\t\t\t\t\tsuspend_timeout_seconds: inputs.suspendTimeout,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\treturn {\n\t\t\tid: result.endpoint.id,\n\t\t\touts: { ...inputs, host: result.endpoint.host },\n\t\t};\n\t}\n\n\tasync update(\n\t\tid: string,\n\t\t_olds: NeonEndpointOutputs,\n\t\tnews: NeonEndpointInputs,\n\t): Promise<pulumi.dynamic.UpdateResult> {\n\t\tconst client = new NeonClient(news.apiKey);\n\n\t\tconst result = await client.patch<EndpointResponse>(\n\t\t\t`/projects/${news.projectId}/endpoints/${id}`,\n\t\t\t{\n\t\t\t\tendpoint: {\n\t\t\t\t\tautoscaling_limit_min_cu: news.minCu,\n\t\t\t\t\tautoscaling_limit_max_cu: news.maxCu,\n\t\t\t\t\tsuspend_timeout_seconds: news.suspendTimeout,\n\t\t\t\t},\n\t\t\t},\n\t\t);\n\n\t\treturn { outs: { ...news, host: result.endpoint.host } };\n\t}\n\n\tasync read(\n\t\tid: string,\n\t\tprops: NeonEndpointOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new NeonClient(props.apiKey);\n\n\t\tconst result = await client.get<EndpointResponse>(\n\t\t\t`/projects/${props.projectId}/endpoints/${id}`,\n\t\t);\n\n\t\treturn {\n\t\t\tid: result.endpoint.id,\n\t\t\tprops: {\n\t\t\t\t...props,\n\t\t\t\thost: result.endpoint.host,\n\t\t\t\tminCu: result.endpoint.autoscaling_limit_min_cu,\n\t\t\t\tmaxCu: result.endpoint.autoscaling_limit_max_cu,\n\t\t\t\tsuspendTimeout: result.endpoint.suspend_timeout_seconds,\n\t\t\t},\n\t\t};\n\t}\n\n\tasync delete(id: string, props: NeonEndpointOutputs): Promise<void> {\n\t\tconst client = new NeonClient(props.apiKey);\n\n\t\ttry {\n\t\t\tawait client.delete(`/projects/${props.projectId}/endpoints/${id}`);\n\t\t} catch {\n\t\t\tpulumi.log.warn(\n\t\t\t\t`Failed to delete Neon endpoint (may already be deleted)`,\n\t\t\t);\n\t\t}\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: NeonEndpointOutputs,\n\t\tnews: NeonEndpointInputs,\n\t): Promise<pulumi.dynamic.DiffResult> {\n\t\tconst replaces: string[] = [];\n\n\t\tif (olds.projectId !== news.projectId) {\n\t\t\treplaces.push(\"projectId\");\n\t\t}\n\n\t\tif (olds.branchId !== news.branchId) {\n\t\t\treplaces.push(\"branchId\");\n\t\t}\n\n\t\tconst hasChanges =\n\t\t\treplaces.length > 0 ||\n\t\t\tolds.minCu !== news.minCu ||\n\t\t\tolds.maxCu !== news.maxCu ||\n\t\t\tolds.suspendTimeout !== news.suspendTimeout;\n\n\t\treturn { changes: hasChanges, replaces, deleteBeforeReplace: true };\n\t}\n}\n\n/** Internal dynamic resource — not part of the public API. */\nclass NeonEndpointResource extends pulumi.dynamic.Resource {\n\tpublic declare readonly host: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\tapiKey: pulumi.Input<string>;\n\t\t\tprojectId: pulumi.Input<string>;\n\t\t\tbranchId: pulumi.Input<string>;\n\t\t\tminCu: pulumi.Input<number>;\n\t\t\tmaxCu: pulumi.Input<number>;\n\t\t\tsuspendTimeout: pulumi.Input<number>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(\n\t\t\tnew NeonEndpointResourceProvider(),\n\t\t\tname,\n\t\t\t{ ...args, host: undefined },\n\t\t\topts,\n\t\t);\n\t}\n}\n\n/** Options type for NeonEndpoint — replaces Pulumi's native `provider` field. */\ntype NeonEndpointOptions = Omit<pulumi.ComponentResourceOptions, \"provider\"> & {\n\t/** Neon authentication context. */\n\tprovider: NeonProvider;\n\n\t/** Neon project context. */\n\tproject: NeonProject;\n\n\t/** Neon branch context. */\n\tbranch: NeonBranch;\n};\n\n/** Args for NeonEndpoint. */\nexport interface NeonEndpointArgs {\n\t/** Minimum compute units. */\n\tminCu: pulumi.Input<number>;\n\n\t/** Maximum compute units. */\n\tmaxCu: pulumi.Input<number>;\n\n\t/** Seconds of inactivity before suspending. */\n\tsuspendTimeout: pulumi.Input<number>;\n}\n\n/**\n * Manages a Neon compute endpoint with adopt-or-create semantics.\n * Exposes `host` as an output for connection string composition.\n *\n * @example\n * ```typescript\n * const endpoint = new NeonEndpoint(\"production\", {\n * minCu: 0.25,\n * maxCu: 1,\n * suspendTimeout: 0,\n * }, { provider, project, branch });\n * ```\n */\nexport class NeonEndpoint extends pulumi.ComponentResource {\n\t/** Endpoint hostname for connection strings. */\n\tpublic readonly host: pulumi.Output<string>;\n\n\tconstructor(name: string, args: NeonEndpointArgs, opts: NeonEndpointOptions) {\n\t\tconst { provider, project, branch, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:neon:Endpoint\", name, {}, pulumiOpts);\n\n\t\tconst resource = new NeonEndpointResource(\n\t\t\t`${name}-resource`,\n\t\t\t{\n\t\t\t\tapiKey: provider.apiKey,\n\t\t\t\tprojectId: project.id,\n\t\t\t\tbranchId: branch.id,\n\t\t\t\t...args,\n\t\t\t},\n\t\t\t{ parent: this },\n\t\t);\n\n\t\tthis.host = resource.host;\n\n\t\tthis.registerOutputs({ host: this.host });\n\t}\n}\n"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@infracraft/pulumi",
3
- "version": "1.6.3",
3
+ "version": "1.6.4",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "repository": {