@infracraft/pulumi 0.1.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.
Potentially problematic release.
This version of @infracraft/pulumi might be problematic. Click here for more details.
- package/dist/chunk-BVYJZCqc.cjs +44 -0
- package/dist/chunk-OPjESj5l.mjs +9 -0
- package/dist/git-guard.cjs +62 -0
- package/dist/git-guard.cjs.map +1 -0
- package/dist/git-guard.d.cts +13 -0
- package/dist/git-guard.d.cts.map +1 -0
- package/dist/git-guard.d.mts +13 -0
- package/dist/git-guard.d.mts.map +1 -0
- package/dist/git-guard.mjs +56 -0
- package/dist/git-guard.mjs.map +1 -0
- package/dist/hash.cjs +40 -0
- package/dist/hash.cjs.map +1 -0
- package/dist/hash.d.cts +10 -0
- package/dist/hash.d.cts.map +1 -0
- package/dist/hash.d.mts +10 -0
- package/dist/hash.d.mts.map +1 -0
- package/dist/hash.mjs +36 -0
- package/dist/hash.mjs.map +1 -0
- package/dist/neon/branch.cjs +113 -0
- package/dist/neon/branch.cjs.map +1 -0
- package/dist/neon/branch.d.cts +40 -0
- package/dist/neon/branch.d.cts.map +1 -0
- package/dist/neon/branch.d.mts +40 -0
- package/dist/neon/branch.d.mts.map +1 -0
- package/dist/neon/branch.mjs +111 -0
- package/dist/neon/branch.mjs.map +1 -0
- package/dist/neon/client.cjs +85 -0
- package/dist/neon/client.cjs.map +1 -0
- package/dist/neon/client.d.cts +59 -0
- package/dist/neon/client.d.cts.map +1 -0
- package/dist/neon/client.d.mts +59 -0
- package/dist/neon/client.d.mts.map +1 -0
- package/dist/neon/client.mjs +84 -0
- package/dist/neon/client.mjs.map +1 -0
- package/dist/neon/database.cjs +117 -0
- package/dist/neon/database.cjs.map +1 -0
- package/dist/neon/database.d.cts +48 -0
- package/dist/neon/database.d.cts.map +1 -0
- package/dist/neon/database.d.mts +48 -0
- package/dist/neon/database.d.mts.map +1 -0
- package/dist/neon/database.mjs +115 -0
- package/dist/neon/database.mjs.map +1 -0
- package/dist/neon/endpoint.cjs +167 -0
- package/dist/neon/endpoint.cjs.map +1 -0
- package/dist/neon/endpoint.d.cts +57 -0
- package/dist/neon/endpoint.d.cts.map +1 -0
- package/dist/neon/endpoint.d.mts +57 -0
- package/dist/neon/endpoint.d.mts.map +1 -0
- package/dist/neon/endpoint.mjs +165 -0
- package/dist/neon/endpoint.mjs.map +1 -0
- package/dist/neon/index.cjs +14 -0
- package/dist/neon/index.d.cts +7 -0
- package/dist/neon/index.d.mts +7 -0
- package/dist/neon/index.mjs +8 -0
- package/dist/neon/project.cjs +120 -0
- package/dist/neon/project.cjs.map +1 -0
- package/dist/neon/project.d.cts +52 -0
- package/dist/neon/project.d.cts.map +1 -0
- package/dist/neon/project.d.mts +52 -0
- package/dist/neon/project.d.mts.map +1 -0
- package/dist/neon/project.mjs +118 -0
- package/dist/neon/project.mjs.map +1 -0
- package/dist/neon/role.cjs +135 -0
- package/dist/neon/role.cjs.map +1 -0
- package/dist/neon/role.d.cts +49 -0
- package/dist/neon/role.d.cts.map +1 -0
- package/dist/neon/role.d.mts +49 -0
- package/dist/neon/role.d.mts.map +1 -0
- package/dist/neon/role.mjs +133 -0
- package/dist/neon/role.mjs.map +1 -0
- package/dist/railway/client.cjs +59 -0
- package/dist/railway/client.cjs.map +1 -0
- package/dist/railway/client.d.cts +39 -0
- package/dist/railway/client.d.cts.map +1 -0
- package/dist/railway/client.d.mts +39 -0
- package/dist/railway/client.d.mts.map +1 -0
- package/dist/railway/client.mjs +58 -0
- package/dist/railway/client.mjs.map +1 -0
- package/dist/railway/deploy.cjs +40 -0
- package/dist/railway/deploy.cjs.map +1 -0
- package/dist/railway/deploy.d.cts +47 -0
- package/dist/railway/deploy.d.cts.map +1 -0
- package/dist/railway/deploy.d.mts +47 -0
- package/dist/railway/deploy.d.mts.map +1 -0
- package/dist/railway/deploy.mjs +37 -0
- package/dist/railway/deploy.mjs.map +1 -0
- package/dist/railway/domain.cjs +236 -0
- package/dist/railway/domain.cjs.map +1 -0
- package/dist/railway/domain.d.cts +52 -0
- package/dist/railway/domain.d.cts.map +1 -0
- package/dist/railway/domain.d.mts +52 -0
- package/dist/railway/domain.d.mts.map +1 -0
- package/dist/railway/domain.mjs +234 -0
- package/dist/railway/domain.mjs.map +1 -0
- package/dist/railway/index.cjs +16 -0
- package/dist/railway/index.d.cts +8 -0
- package/dist/railway/index.d.mts +8 -0
- package/dist/railway/index.mjs +9 -0
- package/dist/railway/project.cjs +231 -0
- package/dist/railway/project.cjs.map +1 -0
- package/dist/railway/project.d.cts +52 -0
- package/dist/railway/project.d.cts.map +1 -0
- package/dist/railway/project.d.mts +52 -0
- package/dist/railway/project.d.mts.map +1 -0
- package/dist/railway/project.mjs +229 -0
- package/dist/railway/project.mjs.map +1 -0
- package/dist/railway/service.cjs +268 -0
- package/dist/railway/service.cjs.map +1 -0
- package/dist/railway/service.d.cts +88 -0
- package/dist/railway/service.d.cts.map +1 -0
- package/dist/railway/service.d.mts +88 -0
- package/dist/railway/service.d.mts.map +1 -0
- package/dist/railway/service.mjs +266 -0
- package/dist/railway/service.mjs.map +1 -0
- package/dist/railway/variable.cjs +149 -0
- package/dist/railway/variable.cjs.map +1 -0
- package/dist/railway/variable.d.cts +52 -0
- package/dist/railway/variable.d.cts.map +1 -0
- package/dist/railway/variable.d.mts +52 -0
- package/dist/railway/variable.d.mts.map +1 -0
- package/dist/railway/variable.mjs +147 -0
- package/dist/railway/variable.mjs.map +1 -0
- package/dist/railway/volume.cjs +179 -0
- package/dist/railway/volume.cjs.map +1 -0
- package/dist/railway/volume.d.cts +52 -0
- package/dist/railway/volume.d.cts.map +1 -0
- package/dist/railway/volume.d.mts +52 -0
- package/dist/railway/volume.d.mts.map +1 -0
- package/dist/railway/volume.mjs +177 -0
- package/dist/railway/volume.mjs.map +1 -0
- package/dist/vercel/deploy.cjs +65 -0
- package/dist/vercel/deploy.cjs.map +1 -0
- package/dist/vercel/deploy.d.cts +54 -0
- package/dist/vercel/deploy.d.cts.map +1 -0
- package/dist/vercel/deploy.d.mts +54 -0
- package/dist/vercel/deploy.d.mts.map +1 -0
- package/dist/vercel/deploy.mjs +61 -0
- package/dist/vercel/deploy.mjs.map +1 -0
- package/dist/vercel/index.cjs +6 -0
- package/dist/vercel/index.d.cts +3 -0
- package/dist/vercel/index.d.mts +3 -0
- package/dist/vercel/index.mjs +4 -0
- package/dist/vercel/variable.cjs +280 -0
- package/dist/vercel/variable.cjs.map +1 -0
- package/dist/vercel/variable.d.cts +55 -0
- package/dist/vercel/variable.d.cts.map +1 -0
- package/dist/vercel/variable.d.mts +55 -0
- package/dist/vercel/variable.d.mts.map +1 -0
- package/dist/vercel/variable.mjs +278 -0
- package/dist/vercel/variable.mjs.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { t as __name } from "../chunk-OPjESj5l.mjs";
|
|
2
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
3
|
+
|
|
4
|
+
//#region src/neon/database.d.ts
|
|
5
|
+
/** Resolved inputs for the Neon database dynamic provider. */
|
|
6
|
+
interface NeonDatabaseInputs {
|
|
7
|
+
/** Neon API key. */
|
|
8
|
+
apiKey: string;
|
|
9
|
+
/** Neon project ID. */
|
|
10
|
+
projectId: string;
|
|
11
|
+
/** Branch ID the database belongs to. */
|
|
12
|
+
branchId: string;
|
|
13
|
+
/** Database name (e.g. `"neondb"`). */
|
|
14
|
+
name: string;
|
|
15
|
+
/** Owner role name (e.g. `"neondb_owner"`). */
|
|
16
|
+
ownerName: string;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Manages a Neon database with adopt-or-create semantics.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* new NeonDatabase("neon-database", {
|
|
24
|
+
* apiKey: config.requireSecret("neonApiKey"),
|
|
25
|
+
* projectId: "quiet-forest-69719462",
|
|
26
|
+
* branchId: branch.id,
|
|
27
|
+
* name: "neondb",
|
|
28
|
+
* ownerName: "neondb_owner",
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
declare class NeonDatabase extends pulumi.dynamic.Resource {
|
|
33
|
+
/**
|
|
34
|
+
* @param name Pulumi resource name
|
|
35
|
+
* @param args Database configuration inputs
|
|
36
|
+
* @param opts Standard Pulumi resource options
|
|
37
|
+
*/
|
|
38
|
+
constructor(name: string, args: {
|
|
39
|
+
/** Neon API key. */apiKey: pulumi.Input<string>; /** Neon project ID. */
|
|
40
|
+
projectId: pulumi.Input<string>; /** Branch ID the database belongs to. */
|
|
41
|
+
branchId: pulumi.Input<string>; /** Database name. */
|
|
42
|
+
name: pulumi.Input<string>; /** Owner role name. */
|
|
43
|
+
ownerName: pulumi.Input<string>;
|
|
44
|
+
}, opts?: pulumi.CustomResourceOptions);
|
|
45
|
+
}
|
|
46
|
+
//#endregion
|
|
47
|
+
export { NeonDatabase, NeonDatabaseInputs };
|
|
48
|
+
//# sourceMappingURL=database.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.d.mts","names":[],"sources":["../../src/neon/database.ts"],"mappings":";;;;;UAIiB,kBAAA;;EAEhB,MAAA;EAFkC;EAKlC,SAAA;EALkC;EAQlC,QAAA;EAHA;EAMA,IAAA;EAAA;EAGA,SAAA;AAAA;AAAS;AA6KV;;;;;;;;;;;;;AA7KU,cA6KG,YAAA,SAAqB,MAAA,CAAO,OAAA,CAAQ,QAAA;EAAA;;;;;cAO/C,IAAA,UACA,IAAA;IAKC,oBAHA,MAAA,EAAQ,MAAA,CAAO,KAAA,UAGG;IAAlB,SAAA,EAAW,MAAA,CAAO,KAAA,UAGR;IAAV,QAAA,EAAU,MAAA,CAAO,KAAA,UAGjB;IAAA,IAAA,EAAM,MAAA,CAAO,KAAA,UAAA;IAGb,SAAA,EAAW,MAAA,CAAO,KAAA;EAAA,GAEnB,IAAA,GAAO,MAAA,CAAO,qBAAA;AAAA"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { t as __name } from "../chunk-OPjESj5l.mjs";
|
|
2
|
+
import { NeonClient } from "./client.mjs";
|
|
3
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
4
|
+
|
|
5
|
+
//#region src/neon/database.ts
|
|
6
|
+
/**
|
|
7
|
+
* Finds an existing database by name on a branch.
|
|
8
|
+
*
|
|
9
|
+
* @param client Authenticated Neon API client
|
|
10
|
+
* @param projectId Neon project ID
|
|
11
|
+
* @param branchId Branch ID to search within
|
|
12
|
+
* @param name Exact database name to match
|
|
13
|
+
* @returns `true` if found, `false` otherwise
|
|
14
|
+
*/
|
|
15
|
+
async function findDatabaseByName(client, projectId, branchId, name) {
|
|
16
|
+
return (await client.get(`/projects/${projectId}/branches/${branchId}/databases`)).databases.some((d) => d.name === name);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Dynamic provider implementing CRUD for Neon databases.
|
|
20
|
+
*
|
|
21
|
+
* Uses adopt-or-create on `create()`: checks if the database already exists
|
|
22
|
+
* before creating a new one.
|
|
23
|
+
*/
|
|
24
|
+
var NeonDatabaseProvider = class {
|
|
25
|
+
/**
|
|
26
|
+
* Creates or adopts a Neon database by name.
|
|
27
|
+
*
|
|
28
|
+
* @param inputs Resolved database configuration
|
|
29
|
+
* @returns Composite ID `{branchId}/{databaseName}` as the resource ID
|
|
30
|
+
*/
|
|
31
|
+
async create(inputs) {
|
|
32
|
+
const client = new NeonClient(inputs.apiKey);
|
|
33
|
+
if (await findDatabaseByName(client, inputs.projectId, inputs.branchId, inputs.name)) pulumi.log.info(`Adopting existing Neon database "${inputs.name}"`);
|
|
34
|
+
else await client.post(`/projects/${inputs.projectId}/branches/${inputs.branchId}/databases`, { database: {
|
|
35
|
+
name: inputs.name,
|
|
36
|
+
owner_name: inputs.ownerName
|
|
37
|
+
} });
|
|
38
|
+
return {
|
|
39
|
+
id: `${inputs.branchId}/${inputs.name}`,
|
|
40
|
+
outs: inputs
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Reads current state for `pulumi refresh`.
|
|
45
|
+
*
|
|
46
|
+
* @param id Current composite database ID
|
|
47
|
+
* @param props Last known persisted state
|
|
48
|
+
* @returns Refreshed resource ID and properties
|
|
49
|
+
* @throws {Error} If the database no longer exists
|
|
50
|
+
*/
|
|
51
|
+
async read(id, props) {
|
|
52
|
+
const result = await new NeonClient(props.apiKey).get(`/projects/${props.projectId}/branches/${props.branchId}/databases/${props.name}`);
|
|
53
|
+
return {
|
|
54
|
+
id,
|
|
55
|
+
props: {
|
|
56
|
+
...props,
|
|
57
|
+
ownerName: result.database.owner_name
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Deletes the Neon database. Silently succeeds if already deleted.
|
|
63
|
+
*/
|
|
64
|
+
async delete(_id, props) {
|
|
65
|
+
const client = new NeonClient(props.apiKey);
|
|
66
|
+
try {
|
|
67
|
+
await client.delete(`/projects/${props.projectId}/branches/${props.branchId}/databases/${props.name}`);
|
|
68
|
+
} catch {
|
|
69
|
+
pulumi.log.warn(`Failed to delete Neon database "${props.name}" (may already be deleted)`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Compares old and new inputs. All fields trigger replacement
|
|
74
|
+
* since databases cannot be renamed or moved.
|
|
75
|
+
*/
|
|
76
|
+
async diff(_id, olds, news) {
|
|
77
|
+
const replaces = [];
|
|
78
|
+
if (olds.projectId !== news.projectId) replaces.push("projectId");
|
|
79
|
+
if (olds.branchId !== news.branchId) replaces.push("branchId");
|
|
80
|
+
if (olds.name !== news.name) replaces.push("name");
|
|
81
|
+
return {
|
|
82
|
+
changes: replaces.length > 0 || olds.ownerName !== news.ownerName,
|
|
83
|
+
replaces,
|
|
84
|
+
deleteBeforeReplace: true
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Manages a Neon database with adopt-or-create semantics.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```typescript
|
|
93
|
+
* new NeonDatabase("neon-database", {
|
|
94
|
+
* apiKey: config.requireSecret("neonApiKey"),
|
|
95
|
+
* projectId: "quiet-forest-69719462",
|
|
96
|
+
* branchId: branch.id,
|
|
97
|
+
* name: "neondb",
|
|
98
|
+
* ownerName: "neondb_owner",
|
|
99
|
+
* });
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
var NeonDatabase = class extends pulumi.dynamic.Resource {
|
|
103
|
+
/**
|
|
104
|
+
* @param name Pulumi resource name
|
|
105
|
+
* @param args Database configuration inputs
|
|
106
|
+
* @param opts Standard Pulumi resource options
|
|
107
|
+
*/
|
|
108
|
+
constructor(name, args, opts) {
|
|
109
|
+
super(new NeonDatabaseProvider(), name, { ...args }, opts);
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
//#endregion
|
|
114
|
+
export { NeonDatabase };
|
|
115
|
+
//# sourceMappingURL=database.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.mjs","names":[],"sources":["../../src/neon/database.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\nimport { NeonClient } from \"./client.js\";\n\n/** Resolved inputs for the Neon database dynamic provider. */\nexport interface NeonDatabaseInputs {\n\t/** Neon API key. */\n\tapiKey: string;\n\n\t/** Neon project ID. */\n\tprojectId: string;\n\n\t/** Branch ID the database belongs to. */\n\tbranchId: string;\n\n\t/** Database name (e.g. `\"neondb\"`). */\n\tname: string;\n\n\t/** Owner role name (e.g. `\"neondb_owner\"`). */\n\townerName: string;\n}\n\n/** Persisted state for the Neon database. */\ninterface NeonDatabaseOutputs extends NeonDatabaseInputs {}\n\n/** Neon API response for a database. */\ninterface DatabaseResponse {\n\tdatabase: {\n\t\tid: number;\n\t\tname: string;\n\t\towner_name: string;\n\t\tbranch_id: string;\n\t};\n}\n\n/** Neon API response for listing databases. */\ninterface DatabaseListResponse {\n\tdatabases: Array<{\n\t\tid: number;\n\t\tname: string;\n\t\towner_name: string;\n\t}>;\n}\n\n/**\n * Finds an existing database by name on a branch.\n *\n * @param client Authenticated Neon API client\n * @param projectId Neon project ID\n * @param branchId Branch ID to search within\n * @param name Exact database name to match\n * @returns `true` if found, `false` otherwise\n */\nasync function findDatabaseByName(\n\tclient: NeonClient,\n\tprojectId: string,\n\tbranchId: string,\n\tname: string,\n): Promise<boolean> {\n\tconst result = await client.get<DatabaseListResponse>(\n\t\t`/projects/${projectId}/branches/${branchId}/databases`,\n\t);\n\n\treturn result.databases.some((d) => d.name === name);\n}\n\n/**\n * Dynamic provider implementing CRUD for Neon databases.\n *\n * Uses adopt-or-create on `create()`: checks if the database already exists\n * before creating a new one.\n */\nclass NeonDatabaseProvider implements pulumi.dynamic.ResourceProvider {\n\t/**\n\t * Creates or adopts a Neon database by name.\n\t *\n\t * @param inputs Resolved database configuration\n\t * @returns Composite ID `{branchId}/{databaseName}` as the resource ID\n\t */\n\tasync create(\n\t\tinputs: NeonDatabaseInputs,\n\t): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new NeonClient(inputs.apiKey);\n\n\t\tconst exists = await findDatabaseByName(\n\t\t\tclient,\n\t\t\tinputs.projectId,\n\t\t\tinputs.branchId,\n\t\t\tinputs.name,\n\t\t);\n\n\t\tif (exists) {\n\t\t\tpulumi.log.info(`Adopting existing Neon database \"${inputs.name}\"`);\n\t\t} else {\n\t\t\tawait client.post(\n\t\t\t\t`/projects/${inputs.projectId}/branches/${inputs.branchId}/databases`,\n\t\t\t\t{ database: { name: inputs.name, owner_name: inputs.ownerName } },\n\t\t\t);\n\t\t}\n\n\t\treturn {\n\t\t\tid: `${inputs.branchId}/${inputs.name}`,\n\t\t\touts: inputs,\n\t\t};\n\t}\n\n\t/**\n\t * Reads current state for `pulumi refresh`.\n\t *\n\t * @param id Current composite database ID\n\t * @param props Last known persisted state\n\t * @returns Refreshed resource ID and properties\n\t * @throws {Error} If the database no longer exists\n\t */\n\tasync read(\n\t\tid: string,\n\t\tprops: NeonDatabaseOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new NeonClient(props.apiKey);\n\n\t\tconst result = await client.get<DatabaseResponse>(\n\t\t\t`/projects/${props.projectId}/branches/${props.branchId}/databases/${props.name}`,\n\t\t);\n\n\t\treturn {\n\t\t\tid,\n\t\t\tprops: { ...props, ownerName: result.database.owner_name },\n\t\t};\n\t}\n\n\t/**\n\t * Deletes the Neon database. Silently succeeds if already deleted.\n\t */\n\tasync delete(_id: string, props: NeonDatabaseOutputs): Promise<void> {\n\t\tconst client = new NeonClient(props.apiKey);\n\n\t\ttry {\n\t\t\tawait client.delete(\n\t\t\t\t`/projects/${props.projectId}/branches/${props.branchId}/databases/${props.name}`,\n\t\t\t);\n\t\t} catch {\n\t\t\tpulumi.log.warn(\n\t\t\t\t`Failed to delete Neon database \"${props.name}\" (may already be deleted)`,\n\t\t\t);\n\t\t}\n\t}\n\n\t/**\n\t * Compares old and new inputs. All fields trigger replacement\n\t * since databases cannot be renamed or moved.\n\t */\n\tasync diff(\n\t\t_id: string,\n\t\tolds: NeonDatabaseOutputs,\n\t\tnews: NeonDatabaseInputs,\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\tif (olds.name !== news.name) {\n\t\t\treplaces.push(\"name\");\n\t\t}\n\n\t\treturn {\n\t\t\tchanges: replaces.length > 0 || olds.ownerName !== news.ownerName,\n\t\t\treplaces,\n\t\t\tdeleteBeforeReplace: true,\n\t\t};\n\t}\n}\n\n/**\n * Manages a Neon database with adopt-or-create semantics.\n *\n * @example\n * ```typescript\n * new NeonDatabase(\"neon-database\", {\n * apiKey: config.requireSecret(\"neonApiKey\"),\n * projectId: \"quiet-forest-69719462\",\n * branchId: branch.id,\n * name: \"neondb\",\n * ownerName: \"neondb_owner\",\n * });\n * ```\n */\nexport class NeonDatabase extends pulumi.dynamic.Resource {\n\t/**\n\t * @param name Pulumi resource name\n\t * @param args Database configuration inputs\n\t * @param opts Standard Pulumi resource options\n\t */\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\t/** Neon API key. */\n\t\t\tapiKey: pulumi.Input<string>;\n\n\t\t\t/** Neon project ID. */\n\t\t\tprojectId: pulumi.Input<string>;\n\n\t\t\t/** Branch ID the database belongs to. */\n\t\t\tbranchId: pulumi.Input<string>;\n\n\t\t\t/** Database name. */\n\t\t\tname: pulumi.Input<string>;\n\n\t\t\t/** Owner role name. */\n\t\t\townerName: pulumi.Input<string>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(new NeonDatabaseProvider(), name, { ...args }, opts);\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;AAoDA,eAAe,mBACd,QACA,WACA,UACA,MACmB;CAKnB,QAAO,MAJc,OAAO,IAC3B,aAAa,UAAU,YAAY,SAAS,WAC7C,GAEc,UAAU,MAAM,MAAM,EAAE,SAAS,IAAI;AACpD;;;;;;;AAQA,IAAM,uBAAN,MAAsE;;;;;;;CAOrE,MAAM,OACL,QACuC;EACvC,MAAM,SAAS,IAAI,WAAW,OAAO,MAAM;EAS3C,IAAI,MAPiB,mBACpB,QACA,OAAO,WACP,OAAO,UACP,OAAO,IACR,GAGC,OAAO,IAAI,KAAK,oCAAoC,OAAO,KAAK,EAAE;OAElE,MAAM,OAAO,KACZ,aAAa,OAAO,UAAU,YAAY,OAAO,SAAS,aAC1D,EAAE,UAAU;GAAE,MAAM,OAAO;GAAM,YAAY,OAAO;EAAU,EAAE,CACjE;EAGD,OAAO;GACN,IAAI,GAAG,OAAO,SAAS,GAAG,OAAO;GACjC,MAAM;EACP;CACD;;;;;;;;;CAUA,MAAM,KACL,IACA,OACqC;EAGrC,MAAM,SAAS,MAAM,IAFF,WAAW,MAAM,MAEV,EAAE,IAC3B,aAAa,MAAM,UAAU,YAAY,MAAM,SAAS,aAAa,MAAM,MAC5E;EAEA,OAAO;GACN;GACA,OAAO;IAAE,GAAG;IAAO,WAAW,OAAO,SAAS;GAAW;EAC1D;CACD;;;;CAKA,MAAM,OAAO,KAAa,OAA2C;EACpE,MAAM,SAAS,IAAI,WAAW,MAAM,MAAM;EAE1C,IAAI;GACH,MAAM,OAAO,OACZ,aAAa,MAAM,UAAU,YAAY,MAAM,SAAS,aAAa,MAAM,MAC5E;EACD,QAAQ;GACP,OAAO,IAAI,KACV,mCAAmC,MAAM,KAAK,2BAC/C;EACD;CACD;;;;;CAMA,MAAM,KACL,KACA,MACA,MACqC;EACrC,MAAM,WAAqB,CAAC;EAE5B,IAAI,KAAK,cAAc,KAAK,WAC3B,SAAS,KAAK,WAAW;EAG1B,IAAI,KAAK,aAAa,KAAK,UAC1B,SAAS,KAAK,UAAU;EAGzB,IAAI,KAAK,SAAS,KAAK,MACtB,SAAS,KAAK,MAAM;EAGrB,OAAO;GACN,SAAS,SAAS,SAAS,KAAK,KAAK,cAAc,KAAK;GACxD;GACA,qBAAqB;EACtB;CACD;AACD;;;;;;;;;;;;;;;AAgBA,IAAa,eAAb,cAAkC,OAAO,QAAQ,SAAS;;;;;;CAMzD,YACC,MACA,MAgBA,MACC;EACD,MAAM,IAAI,qBAAqB,GAAG,MAAM,EAAE,GAAG,KAAK,GAAG,IAAI;CAC1D;AACD"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_chunk = require('../chunk-BVYJZCqc.cjs');
|
|
3
|
+
const require_neon_client = require('./client.cjs');
|
|
4
|
+
let _pulumi_pulumi = require("@pulumi/pulumi");
|
|
5
|
+
_pulumi_pulumi = require_chunk.__toESM(_pulumi_pulumi, 1);
|
|
6
|
+
|
|
7
|
+
//#region src/neon/endpoint.ts
|
|
8
|
+
/**
|
|
9
|
+
* Finds an existing read-write endpoint for a branch.
|
|
10
|
+
*
|
|
11
|
+
* @param client Authenticated Neon API client
|
|
12
|
+
* @param projectId Neon project ID
|
|
13
|
+
* @param branchId Branch ID to search within
|
|
14
|
+
* @returns The endpoint ID and host if found, `undefined` otherwise
|
|
15
|
+
*/
|
|
16
|
+
async function findEndpointByBranch(client, projectId, branchId) {
|
|
17
|
+
const match = (await client.get(`/projects/${projectId}/branches/${branchId}/endpoints`)).endpoints.find((e) => e.type === "read_write");
|
|
18
|
+
return match ? {
|
|
19
|
+
id: match.id,
|
|
20
|
+
host: match.host
|
|
21
|
+
} : void 0;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Dynamic provider implementing CRUD for Neon compute endpoints.
|
|
25
|
+
*
|
|
26
|
+
* Uses adopt-or-create on `create()`: finds an existing read-write endpoint
|
|
27
|
+
* on the target branch before creating a new one.
|
|
28
|
+
*/
|
|
29
|
+
var NeonEndpointProvider = class {
|
|
30
|
+
/**
|
|
31
|
+
* Creates or adopts a Neon endpoint on the target branch.
|
|
32
|
+
*
|
|
33
|
+
* @param inputs Resolved endpoint configuration
|
|
34
|
+
* @returns The Neon endpoint ID as the resource ID
|
|
35
|
+
*/
|
|
36
|
+
async create(inputs) {
|
|
37
|
+
const client = new require_neon_client.NeonClient(inputs.apiKey);
|
|
38
|
+
const existing = await findEndpointByBranch(client, inputs.projectId, inputs.branchId);
|
|
39
|
+
if (existing) {
|
|
40
|
+
_pulumi_pulumi.log.info(`Adopting existing Neon endpoint (${existing.id})`);
|
|
41
|
+
await client.patch(`/projects/${inputs.projectId}/endpoints/${existing.id}`, { endpoint: {
|
|
42
|
+
autoscaling_limit_min_cu: inputs.minCu,
|
|
43
|
+
autoscaling_limit_max_cu: inputs.maxCu,
|
|
44
|
+
suspend_timeout_seconds: inputs.suspendTimeout
|
|
45
|
+
} });
|
|
46
|
+
return {
|
|
47
|
+
id: existing.id,
|
|
48
|
+
outs: {
|
|
49
|
+
...inputs,
|
|
50
|
+
host: existing.host
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const result = await client.post(`/projects/${inputs.projectId}/branches/${inputs.branchId}/endpoints`, { endpoint: {
|
|
55
|
+
type: "read_write",
|
|
56
|
+
autoscaling_limit_min_cu: inputs.minCu,
|
|
57
|
+
autoscaling_limit_max_cu: inputs.maxCu,
|
|
58
|
+
suspend_timeout_seconds: inputs.suspendTimeout
|
|
59
|
+
} });
|
|
60
|
+
return {
|
|
61
|
+
id: result.endpoint.id,
|
|
62
|
+
outs: {
|
|
63
|
+
...inputs,
|
|
64
|
+
host: result.endpoint.host
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Updates endpoint compute settings in place.
|
|
70
|
+
*
|
|
71
|
+
* @param id Current Neon endpoint ID
|
|
72
|
+
* @param _olds Previous persisted state
|
|
73
|
+
* @param news New desired configuration
|
|
74
|
+
* @returns Updated outputs with current host
|
|
75
|
+
*/
|
|
76
|
+
async update(id, _olds, news) {
|
|
77
|
+
const result = await new require_neon_client.NeonClient(news.apiKey).patch(`/projects/${news.projectId}/endpoints/${id}`, { endpoint: {
|
|
78
|
+
autoscaling_limit_min_cu: news.minCu,
|
|
79
|
+
autoscaling_limit_max_cu: news.maxCu,
|
|
80
|
+
suspend_timeout_seconds: news.suspendTimeout
|
|
81
|
+
} });
|
|
82
|
+
return { outs: {
|
|
83
|
+
...news,
|
|
84
|
+
host: result.endpoint.host
|
|
85
|
+
} };
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Reads current state for `pulumi refresh`.
|
|
89
|
+
*
|
|
90
|
+
* @param id Current Neon endpoint ID
|
|
91
|
+
* @param props Last known persisted state
|
|
92
|
+
* @returns Refreshed resource ID and properties
|
|
93
|
+
* @throws {Error} If the endpoint no longer exists
|
|
94
|
+
*/
|
|
95
|
+
async read(id, props) {
|
|
96
|
+
const result = await new require_neon_client.NeonClient(props.apiKey).get(`/projects/${props.projectId}/endpoints/${id}`);
|
|
97
|
+
return {
|
|
98
|
+
id: result.endpoint.id,
|
|
99
|
+
props: {
|
|
100
|
+
...props,
|
|
101
|
+
host: result.endpoint.host,
|
|
102
|
+
minCu: result.endpoint.autoscaling_limit_min_cu,
|
|
103
|
+
maxCu: result.endpoint.autoscaling_limit_max_cu,
|
|
104
|
+
suspendTimeout: result.endpoint.suspend_timeout_seconds
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Deletes the Neon endpoint. Silently succeeds if already deleted.
|
|
110
|
+
*/
|
|
111
|
+
async delete(id, props) {
|
|
112
|
+
const client = new require_neon_client.NeonClient(props.apiKey);
|
|
113
|
+
try {
|
|
114
|
+
await client.delete(`/projects/${props.projectId}/endpoints/${id}`);
|
|
115
|
+
} catch {
|
|
116
|
+
_pulumi_pulumi.log.warn(`Failed to delete Neon endpoint (may already be deleted)`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Compares old and new inputs. Changing `projectId` or `branchId` triggers replacement.
|
|
121
|
+
*/
|
|
122
|
+
async diff(_id, olds, news) {
|
|
123
|
+
const replaces = [];
|
|
124
|
+
if (olds.projectId !== news.projectId) replaces.push("projectId");
|
|
125
|
+
if (olds.branchId !== news.branchId) replaces.push("branchId");
|
|
126
|
+
return {
|
|
127
|
+
changes: replaces.length > 0 || olds.minCu !== news.minCu || olds.maxCu !== news.maxCu || olds.suspendTimeout !== news.suspendTimeout,
|
|
128
|
+
replaces,
|
|
129
|
+
deleteBeforeReplace: true
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Manages a Neon compute endpoint with adopt-or-create semantics.
|
|
135
|
+
* Exposes `host` as an output for connection string composition.
|
|
136
|
+
*
|
|
137
|
+
* @example
|
|
138
|
+
* ```typescript
|
|
139
|
+
* const endpoint = new NeonEndpoint("neon-endpoint-production", {
|
|
140
|
+
* apiKey: config.requireSecret("neonApiKey"),
|
|
141
|
+
* projectId: "quiet-forest-69719462",
|
|
142
|
+
* branchId: branch.id,
|
|
143
|
+
* minCu: 0.25,
|
|
144
|
+
* maxCu: 2,
|
|
145
|
+
* suspendTimeout: 0,
|
|
146
|
+
* });
|
|
147
|
+
*
|
|
148
|
+
* const host = endpoint.host;
|
|
149
|
+
* ```
|
|
150
|
+
*/
|
|
151
|
+
var NeonEndpoint = class extends _pulumi_pulumi.dynamic.Resource {
|
|
152
|
+
/**
|
|
153
|
+
* @param name Pulumi resource name
|
|
154
|
+
* @param args Endpoint configuration inputs
|
|
155
|
+
* @param opts Standard Pulumi resource options
|
|
156
|
+
*/
|
|
157
|
+
constructor(name, args, opts) {
|
|
158
|
+
super(new NeonEndpointProvider(), name, {
|
|
159
|
+
...args,
|
|
160
|
+
host: void 0
|
|
161
|
+
}, opts);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
|
|
165
|
+
//#endregion
|
|
166
|
+
exports.NeonEndpoint = NeonEndpoint;
|
|
167
|
+
//# sourceMappingURL=endpoint.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoint.cjs","names":["NeonClient","pulumi"],"sources":["../../src/neon/endpoint.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\nimport { NeonClient } from \"./client.js\";\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 *\n * @param client Authenticated Neon API client\n * @param projectId Neon project ID\n * @param branchId Branch ID to search within\n * @returns The endpoint ID and host if found, `undefined` otherwise\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 NeonEndpointProvider implements pulumi.dynamic.ResourceProvider {\n\t/**\n\t * Creates or adopts a Neon endpoint on the target branch.\n\t *\n\t * @param inputs Resolved endpoint configuration\n\t * @returns The Neon endpoint ID as the resource ID\n\t */\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\t/**\n\t * Updates endpoint compute settings in place.\n\t *\n\t * @param id Current Neon endpoint ID\n\t * @param _olds Previous persisted state\n\t * @param news New desired configuration\n\t * @returns Updated outputs with current host\n\t */\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\t/**\n\t * Reads current state for `pulumi refresh`.\n\t *\n\t * @param id Current Neon endpoint ID\n\t * @param props Last known persisted state\n\t * @returns Refreshed resource ID and properties\n\t * @throws {Error} If the endpoint no longer exists\n\t */\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\t/**\n\t * Deletes the Neon endpoint. Silently succeeds if already deleted.\n\t */\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\t/**\n\t * Compares old and new inputs. Changing `projectId` or `branchId` triggers replacement.\n\t */\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/**\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(\"neon-endpoint-production\", {\n * apiKey: config.requireSecret(\"neonApiKey\"),\n * projectId: \"quiet-forest-69719462\",\n * branchId: branch.id,\n * minCu: 0.25,\n * maxCu: 2,\n * suspendTimeout: 0,\n * });\n *\n * const host = endpoint.host;\n * ```\n */\nexport class NeonEndpoint extends pulumi.dynamic.Resource {\n\t/** Endpoint hostname for connection strings. */\n\tpublic declare readonly host: pulumi.Output<string>;\n\n\t/**\n\t * @param name Pulumi resource name\n\t * @param args Endpoint configuration inputs\n\t * @param opts Standard Pulumi resource options\n\t */\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\t/** Neon API key. */\n\t\t\tapiKey: pulumi.Input<string>;\n\n\t\t\t/** Neon project ID. */\n\t\t\tprojectId: pulumi.Input<string>;\n\n\t\t\t/** Branch ID to attach the endpoint to. */\n\t\t\tbranchId: pulumi.Input<string>;\n\n\t\t\t/** Minimum compute units. */\n\t\t\tminCu: pulumi.Input<number>;\n\n\t\t\t/** Maximum compute units. */\n\t\t\tmaxCu: pulumi.Input<number>;\n\n\t\t\t/** Seconds of inactivity before suspending. */\n\t\t\tsuspendTimeout: pulumi.Input<number>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(new NeonEndpointProvider(), name, { ...args, host: undefined }, opts);\n\t}\n}\n"],"mappings":";;;;;;;;;;;;;;;AA4DA,eAAe,qBACd,QACA,WACA,UACoD;CAKpD,MAAM,SAAQ,MAJO,OAAO,IAC3B,aAAa,UAAU,YAAY,SAAS,WAC7C,GAEqB,UAAU,MAAM,MAAM,EAAE,SAAS,YAAY;CAElE,OAAO,QAAQ;EAAE,IAAI,MAAM;EAAI,MAAM,MAAM;CAAK,IAAI;AACrD;;;;;;;AAQA,IAAM,uBAAN,MAAsE;;;;;;;CAOrE,MAAM,OACL,QACuC;EACvC,MAAM,SAAS,IAAIA,+BAAW,OAAO,MAAM;EAE3C,MAAM,WAAW,MAAM,qBACtB,QACA,OAAO,WACP,OAAO,QACR;EAEA,IAAI,UAAU;GACb,eAAO,IAAI,KAAK,oCAAoC,SAAS,GAAG,EAAE;GAElE,MAAM,OAAO,MACZ,aAAa,OAAO,UAAU,aAAa,SAAS,MACpD,EACC,UAAU;IACT,0BAA0B,OAAO;IACjC,0BAA0B,OAAO;IACjC,yBAAyB,OAAO;GACjC,EACD,CACD;GAEA,OAAO;IACN,IAAI,SAAS;IACb,MAAM;KAAE,GAAG;KAAQ,MAAM,SAAS;IAAK;GACxC;EACD;EAEA,MAAM,SAAS,MAAM,OAAO,KAC3B,aAAa,OAAO,UAAU,YAAY,OAAO,SAAS,aAC1D,EACC,UAAU;GACT,MAAM;GACN,0BAA0B,OAAO;GACjC,0BAA0B,OAAO;GACjC,yBAAyB,OAAO;EACjC,EACD,CACD;EAEA,OAAO;GACN,IAAI,OAAO,SAAS;GACpB,MAAM;IAAE,GAAG;IAAQ,MAAM,OAAO,SAAS;GAAK;EAC/C;CACD;;;;;;;;;CAUA,MAAM,OACL,IACA,OACA,MACuC;EAGvC,MAAM,SAAS,MAAM,IAFFA,+BAAW,KAAK,MAET,EAAE,MAC3B,aAAa,KAAK,UAAU,aAAa,MACzC,EACC,UAAU;GACT,0BAA0B,KAAK;GAC/B,0BAA0B,KAAK;GAC/B,yBAAyB,KAAK;EAC/B,EACD,CACD;EAEA,OAAO,EAAE,MAAM;GAAE,GAAG;GAAM,MAAM,OAAO,SAAS;EAAK,EAAE;CACxD;;;;;;;;;CAUA,MAAM,KACL,IACA,OACqC;EAGrC,MAAM,SAAS,MAAM,IAFFA,+BAAW,MAAM,MAEV,EAAE,IAC3B,aAAa,MAAM,UAAU,aAAa,IAC3C;EAEA,OAAO;GACN,IAAI,OAAO,SAAS;GACpB,OAAO;IACN,GAAG;IACH,MAAM,OAAO,SAAS;IACtB,OAAO,OAAO,SAAS;IACvB,OAAO,OAAO,SAAS;IACvB,gBAAgB,OAAO,SAAS;GACjC;EACD;CACD;;;;CAKA,MAAM,OAAO,IAAY,OAA2C;EACnE,MAAM,SAAS,IAAIA,+BAAW,MAAM,MAAM;EAE1C,IAAI;GACH,MAAM,OAAO,OAAO,aAAa,MAAM,UAAU,aAAa,IAAI;EACnE,QAAQ;GACP,eAAO,IAAI,KACV,yDACD;EACD;CACD;;;;CAKA,MAAM,KACL,KACA,MACA,MACqC;EACrC,MAAM,WAAqB,CAAC;EAE5B,IAAI,KAAK,cAAc,KAAK,WAC3B,SAAS,KAAK,WAAW;EAG1B,IAAI,KAAK,aAAa,KAAK,UAC1B,SAAS,KAAK,UAAU;EASzB,OAAO;GAAE,SALR,SAAS,SAAS,KAClB,KAAK,UAAU,KAAK,SACpB,KAAK,UAAU,KAAK,SACpB,KAAK,mBAAmB,KAAK;GAEA;GAAU,qBAAqB;EAAK;CACnE;AACD;;;;;;;;;;;;;;;;;;;AAoBA,IAAa,eAAb,cAAkCC,eAAO,QAAQ,SAAS;;;;;;CASzD,YACC,MACA,MAmBA,MACC;EACD,MAAM,IAAI,qBAAqB,GAAG,MAAM;GAAE,GAAG;GAAM,MAAM;EAAU,GAAG,IAAI;CAC3E;AACD"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { t as __name } from "../chunk-OPjESj5l.cjs";
|
|
2
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
3
|
+
|
|
4
|
+
//#region src/neon/endpoint.d.ts
|
|
5
|
+
/** Resolved inputs for the Neon endpoint dynamic provider. */
|
|
6
|
+
interface NeonEndpointInputs {
|
|
7
|
+
/** Neon API key. */
|
|
8
|
+
apiKey: string;
|
|
9
|
+
/** Neon project ID. */
|
|
10
|
+
projectId: string;
|
|
11
|
+
/** Branch ID to attach the endpoint to. */
|
|
12
|
+
branchId: string;
|
|
13
|
+
/** Minimum compute units (e.g. `0.25`). */
|
|
14
|
+
minCu: number;
|
|
15
|
+
/** Maximum compute units (e.g. `2`). */
|
|
16
|
+
maxCu: number;
|
|
17
|
+
/** Seconds of inactivity before suspending. `0` means use global default. */
|
|
18
|
+
suspendTimeout: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Manages a Neon compute endpoint with adopt-or-create semantics.
|
|
22
|
+
* Exposes `host` as an output for connection string composition.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const endpoint = new NeonEndpoint("neon-endpoint-production", {
|
|
27
|
+
* apiKey: config.requireSecret("neonApiKey"),
|
|
28
|
+
* projectId: "quiet-forest-69719462",
|
|
29
|
+
* branchId: branch.id,
|
|
30
|
+
* minCu: 0.25,
|
|
31
|
+
* maxCu: 2,
|
|
32
|
+
* suspendTimeout: 0,
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* const host = endpoint.host;
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
declare class NeonEndpoint extends pulumi.dynamic.Resource {
|
|
39
|
+
/** Endpoint hostname for connection strings. */
|
|
40
|
+
readonly host: pulumi.Output<string>;
|
|
41
|
+
/**
|
|
42
|
+
* @param name Pulumi resource name
|
|
43
|
+
* @param args Endpoint configuration inputs
|
|
44
|
+
* @param opts Standard Pulumi resource options
|
|
45
|
+
*/
|
|
46
|
+
constructor(name: string, args: {
|
|
47
|
+
/** Neon API key. */apiKey: pulumi.Input<string>; /** Neon project ID. */
|
|
48
|
+
projectId: pulumi.Input<string>; /** Branch ID to attach the endpoint to. */
|
|
49
|
+
branchId: pulumi.Input<string>; /** Minimum compute units. */
|
|
50
|
+
minCu: pulumi.Input<number>; /** Maximum compute units. */
|
|
51
|
+
maxCu: pulumi.Input<number>; /** Seconds of inactivity before suspending. */
|
|
52
|
+
suspendTimeout: pulumi.Input<number>;
|
|
53
|
+
}, opts?: pulumi.CustomResourceOptions);
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { NeonEndpoint, NeonEndpointInputs };
|
|
57
|
+
//# sourceMappingURL=endpoint.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoint.d.cts","names":[],"sources":["../../src/neon/endpoint.ts"],"mappings":";;;;;UAIiB,kBAAA;;EAEhB,MAAA;EAFkC;EAKlC,SAAA;EALkC;EAQlC,QAAA;EAHA;EAMA,KAAA;EAAA;EAGA,KAAA;EAGA;EAAA,cAAA;AAAA;AA2OD;;;;;;;;;;;;;;;;;;AAAA,cAAa,YAAA,SAAqB,MAAA,CAAO,OAAA,CAAQ,QAAA;EAEX;EAAA,SAAb,IAAA,EAAM,MAAA,CAAO,MAAA;EAQpC;;;;;cAAA,IAAA,UACA,IAAA;IAKmB,oBAHlB,MAAA,EAAQ,MAAA,CAAO,KAAA,UAML;IAHV,SAAA,EAAW,MAAA,CAAO,KAAA,UAMlB;IAHA,QAAA,EAAU,MAAA,CAAO,KAAA,UAGH;IAAd,KAAA,EAAO,MAAA,CAAO,KAAA,UAGP;IAAP,KAAA,EAAO,MAAA,CAAO,KAAA,UAGd;IAAA,cAAA,EAAgB,MAAA,CAAO,KAAA;EAAA,GAExB,IAAA,GAAO,MAAA,CAAO,qBAAA;AAAA"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { t as __name } from "../chunk-OPjESj5l.mjs";
|
|
2
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
3
|
+
|
|
4
|
+
//#region src/neon/endpoint.d.ts
|
|
5
|
+
/** Resolved inputs for the Neon endpoint dynamic provider. */
|
|
6
|
+
interface NeonEndpointInputs {
|
|
7
|
+
/** Neon API key. */
|
|
8
|
+
apiKey: string;
|
|
9
|
+
/** Neon project ID. */
|
|
10
|
+
projectId: string;
|
|
11
|
+
/** Branch ID to attach the endpoint to. */
|
|
12
|
+
branchId: string;
|
|
13
|
+
/** Minimum compute units (e.g. `0.25`). */
|
|
14
|
+
minCu: number;
|
|
15
|
+
/** Maximum compute units (e.g. `2`). */
|
|
16
|
+
maxCu: number;
|
|
17
|
+
/** Seconds of inactivity before suspending. `0` means use global default. */
|
|
18
|
+
suspendTimeout: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Manages a Neon compute endpoint with adopt-or-create semantics.
|
|
22
|
+
* Exposes `host` as an output for connection string composition.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const endpoint = new NeonEndpoint("neon-endpoint-production", {
|
|
27
|
+
* apiKey: config.requireSecret("neonApiKey"),
|
|
28
|
+
* projectId: "quiet-forest-69719462",
|
|
29
|
+
* branchId: branch.id,
|
|
30
|
+
* minCu: 0.25,
|
|
31
|
+
* maxCu: 2,
|
|
32
|
+
* suspendTimeout: 0,
|
|
33
|
+
* });
|
|
34
|
+
*
|
|
35
|
+
* const host = endpoint.host;
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
declare class NeonEndpoint extends pulumi.dynamic.Resource {
|
|
39
|
+
/** Endpoint hostname for connection strings. */
|
|
40
|
+
readonly host: pulumi.Output<string>;
|
|
41
|
+
/**
|
|
42
|
+
* @param name Pulumi resource name
|
|
43
|
+
* @param args Endpoint configuration inputs
|
|
44
|
+
* @param opts Standard Pulumi resource options
|
|
45
|
+
*/
|
|
46
|
+
constructor(name: string, args: {
|
|
47
|
+
/** Neon API key. */apiKey: pulumi.Input<string>; /** Neon project ID. */
|
|
48
|
+
projectId: pulumi.Input<string>; /** Branch ID to attach the endpoint to. */
|
|
49
|
+
branchId: pulumi.Input<string>; /** Minimum compute units. */
|
|
50
|
+
minCu: pulumi.Input<number>; /** Maximum compute units. */
|
|
51
|
+
maxCu: pulumi.Input<number>; /** Seconds of inactivity before suspending. */
|
|
52
|
+
suspendTimeout: pulumi.Input<number>;
|
|
53
|
+
}, opts?: pulumi.CustomResourceOptions);
|
|
54
|
+
}
|
|
55
|
+
//#endregion
|
|
56
|
+
export { NeonEndpoint, NeonEndpointInputs };
|
|
57
|
+
//# sourceMappingURL=endpoint.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoint.d.mts","names":[],"sources":["../../src/neon/endpoint.ts"],"mappings":";;;;;UAIiB,kBAAA;;EAEhB,MAAA;EAFkC;EAKlC,SAAA;EALkC;EAQlC,QAAA;EAHA;EAMA,KAAA;EAAA;EAGA,KAAA;EAGA;EAAA,cAAA;AAAA;AA2OD;;;;;;;;;;;;;;;;;;AAAA,cAAa,YAAA,SAAqB,MAAA,CAAO,OAAA,CAAQ,QAAA;EAEX;EAAA,SAAb,IAAA,EAAM,MAAA,CAAO,MAAA;EAQpC;;;;;cAAA,IAAA,UACA,IAAA;IAKmB,oBAHlB,MAAA,EAAQ,MAAA,CAAO,KAAA,UAML;IAHV,SAAA,EAAW,MAAA,CAAO,KAAA,UAMlB;IAHA,QAAA,EAAU,MAAA,CAAO,KAAA,UAGH;IAAd,KAAA,EAAO,MAAA,CAAO,KAAA,UAGP;IAAP,KAAA,EAAO,MAAA,CAAO,KAAA,UAGd;IAAA,cAAA,EAAgB,MAAA,CAAO,KAAA;EAAA,GAExB,IAAA,GAAO,MAAA,CAAO,qBAAA;AAAA"}
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
import { t as __name } from "../chunk-OPjESj5l.mjs";
|
|
2
|
+
import { NeonClient } from "./client.mjs";
|
|
3
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
4
|
+
|
|
5
|
+
//#region src/neon/endpoint.ts
|
|
6
|
+
/**
|
|
7
|
+
* Finds an existing read-write endpoint for a branch.
|
|
8
|
+
*
|
|
9
|
+
* @param client Authenticated Neon API client
|
|
10
|
+
* @param projectId Neon project ID
|
|
11
|
+
* @param branchId Branch ID to search within
|
|
12
|
+
* @returns The endpoint ID and host if found, `undefined` otherwise
|
|
13
|
+
*/
|
|
14
|
+
async function findEndpointByBranch(client, projectId, branchId) {
|
|
15
|
+
const match = (await client.get(`/projects/${projectId}/branches/${branchId}/endpoints`)).endpoints.find((e) => e.type === "read_write");
|
|
16
|
+
return match ? {
|
|
17
|
+
id: match.id,
|
|
18
|
+
host: match.host
|
|
19
|
+
} : void 0;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Dynamic provider implementing CRUD for Neon compute endpoints.
|
|
23
|
+
*
|
|
24
|
+
* Uses adopt-or-create on `create()`: finds an existing read-write endpoint
|
|
25
|
+
* on the target branch before creating a new one.
|
|
26
|
+
*/
|
|
27
|
+
var NeonEndpointProvider = class {
|
|
28
|
+
/**
|
|
29
|
+
* Creates or adopts a Neon endpoint on the target branch.
|
|
30
|
+
*
|
|
31
|
+
* @param inputs Resolved endpoint configuration
|
|
32
|
+
* @returns The Neon endpoint ID as the resource ID
|
|
33
|
+
*/
|
|
34
|
+
async create(inputs) {
|
|
35
|
+
const client = new NeonClient(inputs.apiKey);
|
|
36
|
+
const existing = await findEndpointByBranch(client, inputs.projectId, inputs.branchId);
|
|
37
|
+
if (existing) {
|
|
38
|
+
pulumi.log.info(`Adopting existing Neon endpoint (${existing.id})`);
|
|
39
|
+
await client.patch(`/projects/${inputs.projectId}/endpoints/${existing.id}`, { endpoint: {
|
|
40
|
+
autoscaling_limit_min_cu: inputs.minCu,
|
|
41
|
+
autoscaling_limit_max_cu: inputs.maxCu,
|
|
42
|
+
suspend_timeout_seconds: inputs.suspendTimeout
|
|
43
|
+
} });
|
|
44
|
+
return {
|
|
45
|
+
id: existing.id,
|
|
46
|
+
outs: {
|
|
47
|
+
...inputs,
|
|
48
|
+
host: existing.host
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
const result = await client.post(`/projects/${inputs.projectId}/branches/${inputs.branchId}/endpoints`, { endpoint: {
|
|
53
|
+
type: "read_write",
|
|
54
|
+
autoscaling_limit_min_cu: inputs.minCu,
|
|
55
|
+
autoscaling_limit_max_cu: inputs.maxCu,
|
|
56
|
+
suspend_timeout_seconds: inputs.suspendTimeout
|
|
57
|
+
} });
|
|
58
|
+
return {
|
|
59
|
+
id: result.endpoint.id,
|
|
60
|
+
outs: {
|
|
61
|
+
...inputs,
|
|
62
|
+
host: result.endpoint.host
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Updates endpoint compute settings in place.
|
|
68
|
+
*
|
|
69
|
+
* @param id Current Neon endpoint ID
|
|
70
|
+
* @param _olds Previous persisted state
|
|
71
|
+
* @param news New desired configuration
|
|
72
|
+
* @returns Updated outputs with current host
|
|
73
|
+
*/
|
|
74
|
+
async update(id, _olds, news) {
|
|
75
|
+
const result = await new NeonClient(news.apiKey).patch(`/projects/${news.projectId}/endpoints/${id}`, { endpoint: {
|
|
76
|
+
autoscaling_limit_min_cu: news.minCu,
|
|
77
|
+
autoscaling_limit_max_cu: news.maxCu,
|
|
78
|
+
suspend_timeout_seconds: news.suspendTimeout
|
|
79
|
+
} });
|
|
80
|
+
return { outs: {
|
|
81
|
+
...news,
|
|
82
|
+
host: result.endpoint.host
|
|
83
|
+
} };
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Reads current state for `pulumi refresh`.
|
|
87
|
+
*
|
|
88
|
+
* @param id Current Neon endpoint ID
|
|
89
|
+
* @param props Last known persisted state
|
|
90
|
+
* @returns Refreshed resource ID and properties
|
|
91
|
+
* @throws {Error} If the endpoint no longer exists
|
|
92
|
+
*/
|
|
93
|
+
async read(id, props) {
|
|
94
|
+
const result = await new NeonClient(props.apiKey).get(`/projects/${props.projectId}/endpoints/${id}`);
|
|
95
|
+
return {
|
|
96
|
+
id: result.endpoint.id,
|
|
97
|
+
props: {
|
|
98
|
+
...props,
|
|
99
|
+
host: result.endpoint.host,
|
|
100
|
+
minCu: result.endpoint.autoscaling_limit_min_cu,
|
|
101
|
+
maxCu: result.endpoint.autoscaling_limit_max_cu,
|
|
102
|
+
suspendTimeout: result.endpoint.suspend_timeout_seconds
|
|
103
|
+
}
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Deletes the Neon endpoint. Silently succeeds if already deleted.
|
|
108
|
+
*/
|
|
109
|
+
async delete(id, props) {
|
|
110
|
+
const client = new NeonClient(props.apiKey);
|
|
111
|
+
try {
|
|
112
|
+
await client.delete(`/projects/${props.projectId}/endpoints/${id}`);
|
|
113
|
+
} catch {
|
|
114
|
+
pulumi.log.warn(`Failed to delete Neon endpoint (may already be deleted)`);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Compares old and new inputs. Changing `projectId` or `branchId` triggers replacement.
|
|
119
|
+
*/
|
|
120
|
+
async diff(_id, olds, news) {
|
|
121
|
+
const replaces = [];
|
|
122
|
+
if (olds.projectId !== news.projectId) replaces.push("projectId");
|
|
123
|
+
if (olds.branchId !== news.branchId) replaces.push("branchId");
|
|
124
|
+
return {
|
|
125
|
+
changes: replaces.length > 0 || olds.minCu !== news.minCu || olds.maxCu !== news.maxCu || olds.suspendTimeout !== news.suspendTimeout,
|
|
126
|
+
replaces,
|
|
127
|
+
deleteBeforeReplace: true
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
/**
|
|
132
|
+
* Manages a Neon compute endpoint with adopt-or-create semantics.
|
|
133
|
+
* Exposes `host` as an output for connection string composition.
|
|
134
|
+
*
|
|
135
|
+
* @example
|
|
136
|
+
* ```typescript
|
|
137
|
+
* const endpoint = new NeonEndpoint("neon-endpoint-production", {
|
|
138
|
+
* apiKey: config.requireSecret("neonApiKey"),
|
|
139
|
+
* projectId: "quiet-forest-69719462",
|
|
140
|
+
* branchId: branch.id,
|
|
141
|
+
* minCu: 0.25,
|
|
142
|
+
* maxCu: 2,
|
|
143
|
+
* suspendTimeout: 0,
|
|
144
|
+
* });
|
|
145
|
+
*
|
|
146
|
+
* const host = endpoint.host;
|
|
147
|
+
* ```
|
|
148
|
+
*/
|
|
149
|
+
var NeonEndpoint = class extends pulumi.dynamic.Resource {
|
|
150
|
+
/**
|
|
151
|
+
* @param name Pulumi resource name
|
|
152
|
+
* @param args Endpoint configuration inputs
|
|
153
|
+
* @param opts Standard Pulumi resource options
|
|
154
|
+
*/
|
|
155
|
+
constructor(name, args, opts) {
|
|
156
|
+
super(new NeonEndpointProvider(), name, {
|
|
157
|
+
...args,
|
|
158
|
+
host: void 0
|
|
159
|
+
}, opts);
|
|
160
|
+
}
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
//#endregion
|
|
164
|
+
export { NeonEndpoint };
|
|
165
|
+
//# sourceMappingURL=endpoint.mjs.map
|