@infracraft/pulumi 1.5.2 → 1.6.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/neon/branch.cjs +27 -6
- package/dist/neon/branch.cjs.map +1 -1
- package/dist/neon/branch.d.cts +35 -2
- package/dist/neon/branch.d.cts.map +1 -1
- package/dist/neon/branch.d.mts +35 -2
- package/dist/neon/branch.d.mts.map +1 -1
- package/dist/neon/branch.mjs +27 -7
- package/dist/neon/branch.mjs.map +1 -1
- package/dist/railway/environment.cjs +58 -11
- package/dist/railway/environment.cjs.map +1 -1
- package/dist/railway/environment.d.cts +57 -4
- package/dist/railway/environment.d.cts.map +1 -1
- package/dist/railway/environment.d.mts +57 -4
- package/dist/railway/environment.d.mts.map +1 -1
- package/dist/railway/environment.mjs +58 -12
- package/dist/railway/environment.mjs.map +1 -1
- package/dist/vercel/index.cjs +6 -0
- package/dist/vercel/index.d.cts +4 -1
- package/dist/vercel/index.d.mts +4 -1
- package/dist/vercel/index.mjs +4 -1
- package/dist/vercel/integration.cjs +94 -0
- package/dist/vercel/integration.cjs.map +1 -0
- package/dist/vercel/integration.d.cts +72 -0
- package/dist/vercel/integration.d.cts.map +1 -0
- package/dist/vercel/integration.d.mts +72 -0
- package/dist/vercel/integration.d.mts.map +1 -0
- package/dist/vercel/integration.mjs +91 -0
- package/dist/vercel/integration.mjs.map +1 -0
- package/dist/vercel/marketplace-resource.cjs +126 -0
- package/dist/vercel/marketplace-resource.cjs.map +1 -0
- package/dist/vercel/marketplace-resource.d.cts +114 -0
- package/dist/vercel/marketplace-resource.d.cts.map +1 -0
- package/dist/vercel/marketplace-resource.d.mts +114 -0
- package/dist/vercel/marketplace-resource.d.mts.map +1 -0
- package/dist/vercel/marketplace-resource.mjs +123 -0
- package/dist/vercel/marketplace-resource.mjs.map +1 -0
- package/dist/vercel/resource-connection.cjs +107 -0
- package/dist/vercel/resource-connection.cjs.map +1 -0
- package/dist/vercel/resource-connection.d.cts +93 -0
- package/dist/vercel/resource-connection.d.cts.map +1 -0
- package/dist/vercel/resource-connection.d.mts +93 -0
- package/dist/vercel/resource-connection.d.mts.map +1 -0
- package/dist/vercel/resource-connection.mjs +104 -0
- package/dist/vercel/resource-connection.mjs.map +1 -0
- package/package.json +1 -1
package/dist/neon/branch.cjs
CHANGED
|
@@ -15,17 +15,28 @@ async function findBranchByName(client, projectId, name) {
|
|
|
15
15
|
* Dynamic provider implementing CRUD for Neon branches.
|
|
16
16
|
*
|
|
17
17
|
* Uses adopt-or-create on `create()`: finds an existing branch by name
|
|
18
|
-
* before creating a new one.
|
|
18
|
+
* before creating a new one. When `parentName` is supplied, resolves it
|
|
19
|
+
* to a `parent_id` and includes it in the POST body.
|
|
19
20
|
*/
|
|
21
|
+
/** @internal Exported only for unit testing; not part of the public API surface. */
|
|
20
22
|
var NeonBranchResourceProvider = class {
|
|
21
23
|
async create(inputs) {
|
|
22
24
|
const client = new require_neon_client.NeonClient(inputs.apiKey);
|
|
23
25
|
let branchId = await findBranchByName(client, inputs.projectId, inputs.name);
|
|
24
|
-
if (branchId) _pulumi_pulumi.log.
|
|
25
|
-
else
|
|
26
|
+
if (branchId) if (inputs.parentName) _pulumi_pulumi.log.warn(`Adopting existing Neon branch "${inputs.name}" — parentName "${inputs.parentName}" is ignored for adopted branches (existing lineage preserved).`);
|
|
27
|
+
else _pulumi_pulumi.log.info(`Adopting existing Neon branch "${inputs.name}" (${branchId})`);
|
|
28
|
+
else {
|
|
29
|
+
const body = { branch: { name: inputs.name } };
|
|
30
|
+
if (inputs.parentName) {
|
|
31
|
+
const parentId = await findBranchByName(client, inputs.projectId, inputs.parentName);
|
|
32
|
+
if (!parentId) throw new Error(`Neon parent branch "${inputs.parentName}" not found in project ${inputs.projectId}`);
|
|
33
|
+
body.branch.parent_id = parentId;
|
|
34
|
+
}
|
|
35
|
+
branchId = (await client.post(`/projects/${inputs.projectId}/branches`, body)).branch.id;
|
|
36
|
+
}
|
|
26
37
|
return {
|
|
27
38
|
id: branchId,
|
|
28
|
-
outs: inputs
|
|
39
|
+
outs: { ...inputs }
|
|
29
40
|
};
|
|
30
41
|
}
|
|
31
42
|
async read(id, props) {
|
|
@@ -49,6 +60,7 @@ var NeonBranchResourceProvider = class {
|
|
|
49
60
|
async diff(_id, olds, news) {
|
|
50
61
|
const replaces = [];
|
|
51
62
|
if (olds.projectId !== news.projectId) replaces.push("projectId");
|
|
63
|
+
if (olds.parentName !== news.parentName) replaces.push("parentName");
|
|
52
64
|
return {
|
|
53
65
|
changes: replaces.length > 0 || olds.name !== news.name,
|
|
54
66
|
replaces,
|
|
@@ -67,9 +79,16 @@ var NeonBranchResource = class extends _pulumi_pulumi.dynamic.Resource {
|
|
|
67
79
|
*
|
|
68
80
|
* @example
|
|
69
81
|
* ```typescript
|
|
70
|
-
*
|
|
82
|
+
* // Root branch (Neon default parent)
|
|
83
|
+
* const production = new NeonBranch("production", {
|
|
71
84
|
* name: "production",
|
|
72
85
|
* }, { provider, project });
|
|
86
|
+
*
|
|
87
|
+
* // Copy-on-write branch from production
|
|
88
|
+
* const staging = new NeonBranch("staging", {
|
|
89
|
+
* name: "staging",
|
|
90
|
+
* parent: "production",
|
|
91
|
+
* }, { provider, project });
|
|
73
92
|
* ```
|
|
74
93
|
*/
|
|
75
94
|
var NeonBranch = class extends _pulumi_pulumi.ComponentResource {
|
|
@@ -79,7 +98,8 @@ var NeonBranch = class extends _pulumi_pulumi.ComponentResource {
|
|
|
79
98
|
const resource = new NeonBranchResource(`${name}-resource`, {
|
|
80
99
|
apiKey: provider.apiKey,
|
|
81
100
|
projectId: project.id,
|
|
82
|
-
name: args.name
|
|
101
|
+
name: args.name,
|
|
102
|
+
parentName: args.parent
|
|
83
103
|
}, { parent: this });
|
|
84
104
|
this.id = resource.id;
|
|
85
105
|
this.registerOutputs({ id: this.id });
|
|
@@ -88,4 +108,5 @@ var NeonBranch = class extends _pulumi_pulumi.ComponentResource {
|
|
|
88
108
|
|
|
89
109
|
//#endregion
|
|
90
110
|
exports.NeonBranch = NeonBranch;
|
|
111
|
+
exports.NeonBranchResourceProvider = NeonBranchResourceProvider;
|
|
91
112
|
//# sourceMappingURL=branch.cjs.map
|
package/dist/neon/branch.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"branch.cjs","names":["NeonClient","pulumi"],"sources":["../../src/neon/branch.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\nimport { NeonClient } from \"./client\";\nimport type { NeonProject } from \"./project\";\nimport type { NeonProvider } from \"./provider\";\n\n/** Resolved inputs for the Neon branch dynamic provider. */\nexport interface NeonBranchInputs {\n\t/** Neon API key. */\n\tapiKey: string;\n\n\t/** Neon project ID (e.g. `\"quiet-forest-69719462\"`). */\n\tprojectId: string;\n\n\t/** Branch display name (e.g. `\"production\"`, `\"development\"`). */\n\tname: string;\n}\n\n/** Persisted state for the Neon branch. */\ninterface NeonBranchOutputs extends NeonBranchInputs {}\n\n/** Neon API response for a branch. */\ninterface BranchResponse {\n\tbranch: {\n\t\tid: string;\n\t\tname: string;\n\t\tproject_id: string;\n\t};\n}\n\n/** Neon API response for branch creation. */\ninterface BranchCreateResponse {\n\tbranch: {\n\t\tid: string;\n\t\tname: string;\n\t\tproject_id: string;\n\t};\n}\n\n/** Neon API response for listing branches. */\ninterface BranchListResponse {\n\tbranches: Array<{\n\t\tid: string;\n\t\tname: string;\n\t}>;\n}\n\n/**\n * Finds an existing Neon branch by name within a project.\n */\nasync function findBranchByName(\n\tclient: NeonClient,\n\tprojectId: string,\n\tname: string,\n): Promise<string | undefined> {\n\tconst result = await client.get<BranchListResponse>(\n\t\t`/projects/${projectId}/branches`,\n\t);\n\n\tconst match = result.branches.find((b) => b.name === name);\n\n\treturn match?.id;\n}\n\n/**\n * Dynamic provider implementing CRUD for Neon branches.\n *\n * Uses adopt-or-create on `create()`: finds an existing branch by name\n * before creating a new one.\n */\
|
|
1
|
+
{"version":3,"file":"branch.cjs","names":["NeonClient","pulumi"],"sources":["../../src/neon/branch.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\nimport { NeonClient } from \"./client\";\nimport type { NeonProject } from \"./project\";\nimport type { NeonProvider } from \"./provider\";\n\n/** Resolved inputs for the Neon branch dynamic provider. */\nexport interface NeonBranchInputs {\n\t/** Neon API key. */\n\tapiKey: string;\n\n\t/** Neon project ID (e.g. `\"quiet-forest-69719462\"`). */\n\tprojectId: string;\n\n\t/** Branch display name (e.g. `\"production\"`, `\"development\"`). */\n\tname: string;\n\n\t/**\n\t * Parent branch NAME. Resolved to `parent_id` inside `create()` via\n\t * `findBranchByName`. Omit for project-root branches.\n\t */\n\tparentName?: string;\n}\n\n/** Persisted state for the Neon branch. */\ninterface NeonBranchOutputs extends NeonBranchInputs {}\n\n/** Neon API response for a branch. */\ninterface BranchResponse {\n\tbranch: {\n\t\tid: string;\n\t\tname: string;\n\t\tproject_id: string;\n\t};\n}\n\n/** Neon API response for branch creation. */\ninterface BranchCreateResponse {\n\tbranch: {\n\t\tid: string;\n\t\tname: string;\n\t\tproject_id: string;\n\t};\n}\n\n/** Neon API response for listing branches. */\ninterface BranchListResponse {\n\tbranches: Array<{\n\t\tid: string;\n\t\tname: string;\n\t}>;\n}\n\n/**\n * Finds an existing Neon branch by name within a project.\n */\nasync function findBranchByName(\n\tclient: NeonClient,\n\tprojectId: string,\n\tname: string,\n): Promise<string | undefined> {\n\tconst result = await client.get<BranchListResponse>(\n\t\t`/projects/${projectId}/branches`,\n\t);\n\n\tconst match = result.branches.find((b) => b.name === name);\n\n\treturn match?.id;\n}\n\n/**\n * Dynamic provider implementing CRUD for Neon branches.\n *\n * Uses adopt-or-create on `create()`: finds an existing branch by name\n * before creating a new one. When `parentName` is supplied, resolves it\n * to a `parent_id` and includes it in the POST body.\n */\n/** @internal Exported only for unit testing; not part of the public API surface. */\nexport class NeonBranchResourceProvider\n\timplements pulumi.dynamic.ResourceProvider\n{\n\tasync create(inputs: NeonBranchInputs): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new NeonClient(inputs.apiKey);\n\n\t\tlet branchId = await findBranchByName(\n\t\t\tclient,\n\t\t\tinputs.projectId,\n\t\t\tinputs.name,\n\t\t);\n\n\t\tif (branchId) {\n\t\t\tif (inputs.parentName) {\n\t\t\t\tpulumi.log.warn(\n\t\t\t\t\t`Adopting existing Neon branch \"${inputs.name}\" — parentName \"${inputs.parentName}\" is ignored for adopted branches (existing lineage preserved).`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tpulumi.log.info(\n\t\t\t\t\t`Adopting existing Neon branch \"${inputs.name}\" (${branchId})`,\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tconst body: { branch: { name: string; parent_id?: string } } = {\n\t\t\t\tbranch: { name: inputs.name },\n\t\t\t};\n\n\t\t\tif (inputs.parentName) {\n\t\t\t\tconst parentId = await findBranchByName(\n\t\t\t\t\tclient,\n\t\t\t\t\tinputs.projectId,\n\t\t\t\t\tinputs.parentName,\n\t\t\t\t);\n\n\t\t\t\tif (!parentId) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Neon parent branch \"${inputs.parentName}\" not found in project ${inputs.projectId}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tbody.branch.parent_id = parentId;\n\t\t\t}\n\n\t\t\tconst result = await client.post<BranchCreateResponse>(\n\t\t\t\t`/projects/${inputs.projectId}/branches`,\n\t\t\t\tbody,\n\t\t\t);\n\n\t\t\tbranchId = result.branch.id;\n\t\t}\n\n\t\treturn { id: branchId, outs: { ...inputs } };\n\t}\n\n\tasync read(\n\t\tid: string,\n\t\tprops: NeonBranchOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new NeonClient(props.apiKey);\n\n\t\tconst result = await client.get<BranchResponse>(\n\t\t\t`/projects/${props.projectId}/branches/${id}`,\n\t\t);\n\n\t\t// parentName is preserved from prior state (props): the Neon API does not expose\n\t\t// a branch's parent on GET /branches/:id, so it cannot be re-derived here.\n\t\treturn {\n\t\t\tid: result.branch.id,\n\t\t\tprops: { ...props, name: result.branch.name },\n\t\t};\n\t}\n\n\tasync delete(id: string, props: NeonBranchOutputs): Promise<void> {\n\t\tconst client = new NeonClient(props.apiKey);\n\n\t\ttry {\n\t\t\tawait client.delete(`/projects/${props.projectId}/branches/${id}`);\n\t\t} catch {\n\t\t\tpulumi.log.warn(`Failed to delete Neon branch (may already be deleted)`);\n\t\t}\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: NeonBranchOutputs,\n\t\tnews: NeonBranchInputs,\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.parentName !== news.parentName) {\n\t\t\treplaces.push(\"parentName\");\n\t\t}\n\n\t\treturn {\n\t\t\tchanges: replaces.length > 0 || olds.name !== news.name,\n\t\t\treplaces,\n\t\t\tdeleteBeforeReplace: true,\n\t\t};\n\t}\n}\n\n/** Internal dynamic resource — not part of the public API. */\nclass NeonBranchResource extends pulumi.dynamic.Resource {\n\tpublic declare readonly branchId: 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\tname: pulumi.Input<string>;\n\t\t\t/** Name of the parent branch; omit for project-root branches. */\n\t\t\tparentName?: pulumi.Input<string>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(new NeonBranchResourceProvider(), name, { ...args }, opts);\n\t}\n}\n\n/** Options type for NeonBranch — replaces Pulumi's native `provider` field. */\ntype NeonBranchOptions = Omit<pulumi.ComponentResourceOptions, \"provider\"> & {\n\t/** Neon authentication context. */\n\tprovider: NeonProvider;\n\n\t/** Neon project context. */\n\tproject: NeonProject;\n};\n\n/** Args for NeonBranch. */\nexport interface NeonBranchArgs {\n\t/** Branch display name. */\n\tname: pulumi.Input<string>;\n\n\t/**\n\t * Name of the parent branch to branch from (copy-on-write). Omit to\n\t * branch from the project root (Neon default branch).\n\t */\n\tparent?: pulumi.Input<string>;\n}\n\n/**\n * Manages a Neon branch with adopt-or-create semantics.\n *\n * @example\n * ```typescript\n * // Root branch (Neon default parent)\n * const production = new NeonBranch(\"production\", {\n * name: \"production\",\n * }, { provider, project });\n *\n * // Copy-on-write branch from production\n * const staging = new NeonBranch(\"staging\", {\n * name: \"staging\",\n * parent: \"production\",\n * }, { provider, project });\n * ```\n */\nexport class NeonBranch extends pulumi.ComponentResource {\n\t/** Neon branch ID. */\n\tpublic readonly id: pulumi.Output<string>;\n\n\tconstructor(name: string, args: NeonBranchArgs, opts: NeonBranchOptions) {\n\t\tconst { provider, project, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:neon:Branch\", name, {}, pulumiOpts);\n\n\t\tconst resource = new NeonBranchResource(\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\tname: args.name,\n\t\t\t\tparentName: args.parent,\n\t\t\t},\n\t\t\t{ parent: this },\n\t\t);\n\n\t\tthis.id = resource.id;\n\n\t\tthis.registerOutputs({ id: this.id });\n\t}\n}\n"],"mappings":";;;;;;;;;;AAuDA,eAAe,iBACd,QACA,WACA,MAC8B;CAO9B,QAFc,MAJO,OAAO,IAC3B,aAAa,UAAU,UACxB,GAEqB,SAAS,MAAM,MAAM,EAAE,SAAS,IAE1C,GAAG;AACf;;;;;;;;;AAUA,IAAa,6BAAb,MAEA;CACC,MAAM,OAAO,QAAgE;EAC5E,MAAM,SAAS,IAAIA,+BAAW,OAAO,MAAM;EAE3C,IAAI,WAAW,MAAM,iBACpB,QACA,OAAO,WACP,OAAO,IACR;EAEA,IAAI,UACH,IAAI,OAAO,YACV,eAAO,IAAI,KACV,kCAAkC,OAAO,KAAK,kBAAkB,OAAO,WAAW,gEACnF;OAEA,eAAO,IAAI,KACV,kCAAkC,OAAO,KAAK,KAAK,SAAS,EAC7D;OAEK;GACN,MAAM,OAAyD,EAC9D,QAAQ,EAAE,MAAM,OAAO,KAAK,EAC7B;GAEA,IAAI,OAAO,YAAY;IACtB,MAAM,WAAW,MAAM,iBACtB,QACA,OAAO,WACP,OAAO,UACR;IAEA,IAAI,CAAC,UACJ,MAAM,IAAI,MACT,uBAAuB,OAAO,WAAW,yBAAyB,OAAO,WAC1E;IAGD,KAAK,OAAO,YAAY;GACzB;GAOA,YAAW,MALU,OAAO,KAC3B,aAAa,OAAO,UAAU,YAC9B,IACD,GAEkB,OAAO;EAC1B;EAEA,OAAO;GAAE,IAAI;GAAU,MAAM,EAAE,GAAG,OAAO;EAAE;CAC5C;CAEA,MAAM,KACL,IACA,OACqC;EAGrC,MAAM,SAAS,MAAM,IAFFA,+BAAW,MAAM,MAEV,EAAE,IAC3B,aAAa,MAAM,UAAU,YAAY,IAC1C;EAIA,OAAO;GACN,IAAI,OAAO,OAAO;GAClB,OAAO;IAAE,GAAG;IAAO,MAAM,OAAO,OAAO;GAAK;EAC7C;CACD;CAEA,MAAM,OAAO,IAAY,OAAyC;EACjE,MAAM,SAAS,IAAIA,+BAAW,MAAM,MAAM;EAE1C,IAAI;GACH,MAAM,OAAO,OAAO,aAAa,MAAM,UAAU,YAAY,IAAI;EAClE,QAAQ;GACP,eAAO,IAAI,KAAK,uDAAuD;EACxE;CACD;CAEA,MAAM,KACL,KACA,MACA,MACqC;EACrC,MAAM,WAAqB,CAAC;EAE5B,IAAI,KAAK,cAAc,KAAK,WAC3B,SAAS,KAAK,WAAW;EAG1B,IAAI,KAAK,eAAe,KAAK,YAC5B,SAAS,KAAK,YAAY;EAG3B,OAAO;GACN,SAAS,SAAS,SAAS,KAAK,KAAK,SAAS,KAAK;GACnD;GACA,qBAAqB;EACtB;CACD;AACD;;AAGA,IAAM,qBAAN,cAAiCC,eAAO,QAAQ,SAAS;CAGxD,YACC,MACA,MAOA,MACC;EACD,MAAM,IAAI,2BAA2B,GAAG,MAAM,EAAE,GAAG,KAAK,GAAG,IAAI;CAChE;AACD;;;;;;;;;;;;;;;;;;AAwCA,IAAa,aAAb,cAAgCA,eAAO,kBAAkB;CAIxD,YAAY,MAAc,MAAsB,MAAyB;EACxE,MAAM,EAAE,UAAU,SAAS,GAAG,eAAe;EAE7C,MAAM,0BAA0B,MAAM,CAAC,GAAG,UAAU;EAEpD,MAAM,WAAW,IAAI,mBACpB,GAAG,KAAK,YACR;GACC,QAAQ,SAAS;GACjB,WAAW,QAAQ;GACnB,MAAM,KAAK;GACX,YAAY,KAAK;EAClB,GACA,EAAE,QAAQ,KAAK,CAChB;EAEA,KAAK,KAAK,SAAS;EAEnB,KAAK,gBAAgB,EAAE,IAAI,KAAK,GAAG,CAAC;CACrC;AACD"}
|
package/dist/neon/branch.d.cts
CHANGED
|
@@ -12,6 +12,27 @@ interface NeonBranchInputs {
|
|
|
12
12
|
projectId: string;
|
|
13
13
|
/** Branch display name (e.g. `"production"`, `"development"`). */
|
|
14
14
|
name: string;
|
|
15
|
+
/**
|
|
16
|
+
* Parent branch NAME. Resolved to `parent_id` inside `create()` via
|
|
17
|
+
* `findBranchByName`. Omit for project-root branches.
|
|
18
|
+
*/
|
|
19
|
+
parentName?: string;
|
|
20
|
+
}
|
|
21
|
+
/** Persisted state for the Neon branch. */
|
|
22
|
+
interface NeonBranchOutputs extends NeonBranchInputs {}
|
|
23
|
+
/**
|
|
24
|
+
* Dynamic provider implementing CRUD for Neon branches.
|
|
25
|
+
*
|
|
26
|
+
* Uses adopt-or-create on `create()`: finds an existing branch by name
|
|
27
|
+
* before creating a new one. When `parentName` is supplied, resolves it
|
|
28
|
+
* to a `parent_id` and includes it in the POST body.
|
|
29
|
+
*/
|
|
30
|
+
/** @internal Exported only for unit testing; not part of the public API surface. */
|
|
31
|
+
declare class NeonBranchResourceProvider implements pulumi.dynamic.ResourceProvider {
|
|
32
|
+
create(inputs: NeonBranchInputs): Promise<pulumi.dynamic.CreateResult>;
|
|
33
|
+
read(id: string, props: NeonBranchOutputs): Promise<pulumi.dynamic.ReadResult>;
|
|
34
|
+
delete(id: string, props: NeonBranchOutputs): Promise<void>;
|
|
35
|
+
diff(_id: string, olds: NeonBranchOutputs, news: NeonBranchInputs): Promise<pulumi.dynamic.DiffResult>;
|
|
15
36
|
}
|
|
16
37
|
/** Options type for NeonBranch — replaces Pulumi's native `provider` field. */
|
|
17
38
|
type NeonBranchOptions = Omit<pulumi.ComponentResourceOptions, "provider"> & {
|
|
@@ -22,15 +43,27 @@ type NeonBranchOptions = Omit<pulumi.ComponentResourceOptions, "provider"> & {
|
|
|
22
43
|
interface NeonBranchArgs {
|
|
23
44
|
/** Branch display name. */
|
|
24
45
|
name: pulumi.Input<string>;
|
|
46
|
+
/**
|
|
47
|
+
* Name of the parent branch to branch from (copy-on-write). Omit to
|
|
48
|
+
* branch from the project root (Neon default branch).
|
|
49
|
+
*/
|
|
50
|
+
parent?: pulumi.Input<string>;
|
|
25
51
|
}
|
|
26
52
|
/**
|
|
27
53
|
* Manages a Neon branch with adopt-or-create semantics.
|
|
28
54
|
*
|
|
29
55
|
* @example
|
|
30
56
|
* ```typescript
|
|
31
|
-
*
|
|
57
|
+
* // Root branch (Neon default parent)
|
|
58
|
+
* const production = new NeonBranch("production", {
|
|
32
59
|
* name: "production",
|
|
33
60
|
* }, { provider, project });
|
|
61
|
+
*
|
|
62
|
+
* // Copy-on-write branch from production
|
|
63
|
+
* const staging = new NeonBranch("staging", {
|
|
64
|
+
* name: "staging",
|
|
65
|
+
* parent: "production",
|
|
66
|
+
* }, { provider, project });
|
|
34
67
|
* ```
|
|
35
68
|
*/
|
|
36
69
|
declare class NeonBranch extends pulumi.ComponentResource {
|
|
@@ -39,5 +72,5 @@ declare class NeonBranch extends pulumi.ComponentResource {
|
|
|
39
72
|
constructor(name: string, args: NeonBranchArgs, opts: NeonBranchOptions);
|
|
40
73
|
}
|
|
41
74
|
//#endregion
|
|
42
|
-
export { NeonBranch, NeonBranchArgs, NeonBranchInputs };
|
|
75
|
+
export { NeonBranch, NeonBranchArgs, NeonBranchInputs, NeonBranchResourceProvider };
|
|
43
76
|
//# sourceMappingURL=branch.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"branch.d.cts","names":[],"sources":["../../src/neon/branch.ts"],"mappings":";;;;;;;UAMiB,gBAAA;;EAEhB,MAAA;EAFgC;EAKhC,SAAA;EALgC;EAQhC,IAAA;AAAA;;
|
|
1
|
+
{"version":3,"file":"branch.d.cts","names":[],"sources":["../../src/neon/branch.ts"],"mappings":";;;;;;;UAMiB,gBAAA;;EAEhB,MAAA;EAFgC;EAKhC,SAAA;EALgC;EAQhC,IAAA;EAHA;;;;EASA,UAAA;AAAA;;UAIS,iBAAA,SAA0B,gBAAgB;AAAA;AAqDpD;;;;;;;cAAa,0BAAA,YACD,MAAA,CAAO,OAAA,CAAQ,gBAAA;EAEpB,MAAA,CAAO,MAAA,EAAQ,gBAAA,GAAmB,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,YAAA;EAmDzD,IAAA,CACL,EAAA,UACA,KAAA,EAAO,iBAAA,GACL,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;EAepB,MAAA,CAAO,EAAA,UAAY,KAAA,EAAO,iBAAA,GAAoB,OAAA;EAU9C,IAAA,CACL,GAAA,UACA,IAAA,EAAM,iBAAA,EACN,IAAA,EAAM,gBAAA,GACJ,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;AAAA;;KAuCtB,iBAAA,GAAoB,IAAA,CAAK,MAAA,CAAO,wBAAA;EA5HzB,mCA8HX,QAAA,EAAU,YAAA,EA9HgC;EAiI1C,OAAA,EAAS,WAAA;AAAA;;UAIO,cAAA;EAnIK;EAqIrB,IAAA,EAAM,MAAA,CAAO,KAAA;EArI2B;;;;EA2IxC,MAAA,GAAS,MAAA,CAAO,KAAK;AAAA;;;;;;;;;;;;;;;;;;cAoBT,UAAA,SAAmB,MAAA,CAAO,iBAAA;EA5E3B;EAAA,SA8EK,EAAA,EAAI,MAAA,CAAO,MAAA;cAEf,IAAA,UAAc,IAAA,EAAM,cAAA,EAAgB,IAAA,EAAM,iBAAA;AAAA"}
|
package/dist/neon/branch.d.mts
CHANGED
|
@@ -12,6 +12,27 @@ interface NeonBranchInputs {
|
|
|
12
12
|
projectId: string;
|
|
13
13
|
/** Branch display name (e.g. `"production"`, `"development"`). */
|
|
14
14
|
name: string;
|
|
15
|
+
/**
|
|
16
|
+
* Parent branch NAME. Resolved to `parent_id` inside `create()` via
|
|
17
|
+
* `findBranchByName`. Omit for project-root branches.
|
|
18
|
+
*/
|
|
19
|
+
parentName?: string;
|
|
20
|
+
}
|
|
21
|
+
/** Persisted state for the Neon branch. */
|
|
22
|
+
interface NeonBranchOutputs extends NeonBranchInputs {}
|
|
23
|
+
/**
|
|
24
|
+
* Dynamic provider implementing CRUD for Neon branches.
|
|
25
|
+
*
|
|
26
|
+
* Uses adopt-or-create on `create()`: finds an existing branch by name
|
|
27
|
+
* before creating a new one. When `parentName` is supplied, resolves it
|
|
28
|
+
* to a `parent_id` and includes it in the POST body.
|
|
29
|
+
*/
|
|
30
|
+
/** @internal Exported only for unit testing; not part of the public API surface. */
|
|
31
|
+
declare class NeonBranchResourceProvider implements pulumi.dynamic.ResourceProvider {
|
|
32
|
+
create(inputs: NeonBranchInputs): Promise<pulumi.dynamic.CreateResult>;
|
|
33
|
+
read(id: string, props: NeonBranchOutputs): Promise<pulumi.dynamic.ReadResult>;
|
|
34
|
+
delete(id: string, props: NeonBranchOutputs): Promise<void>;
|
|
35
|
+
diff(_id: string, olds: NeonBranchOutputs, news: NeonBranchInputs): Promise<pulumi.dynamic.DiffResult>;
|
|
15
36
|
}
|
|
16
37
|
/** Options type for NeonBranch — replaces Pulumi's native `provider` field. */
|
|
17
38
|
type NeonBranchOptions = Omit<pulumi.ComponentResourceOptions, "provider"> & {
|
|
@@ -22,15 +43,27 @@ type NeonBranchOptions = Omit<pulumi.ComponentResourceOptions, "provider"> & {
|
|
|
22
43
|
interface NeonBranchArgs {
|
|
23
44
|
/** Branch display name. */
|
|
24
45
|
name: pulumi.Input<string>;
|
|
46
|
+
/**
|
|
47
|
+
* Name of the parent branch to branch from (copy-on-write). Omit to
|
|
48
|
+
* branch from the project root (Neon default branch).
|
|
49
|
+
*/
|
|
50
|
+
parent?: pulumi.Input<string>;
|
|
25
51
|
}
|
|
26
52
|
/**
|
|
27
53
|
* Manages a Neon branch with adopt-or-create semantics.
|
|
28
54
|
*
|
|
29
55
|
* @example
|
|
30
56
|
* ```typescript
|
|
31
|
-
*
|
|
57
|
+
* // Root branch (Neon default parent)
|
|
58
|
+
* const production = new NeonBranch("production", {
|
|
32
59
|
* name: "production",
|
|
33
60
|
* }, { provider, project });
|
|
61
|
+
*
|
|
62
|
+
* // Copy-on-write branch from production
|
|
63
|
+
* const staging = new NeonBranch("staging", {
|
|
64
|
+
* name: "staging",
|
|
65
|
+
* parent: "production",
|
|
66
|
+
* }, { provider, project });
|
|
34
67
|
* ```
|
|
35
68
|
*/
|
|
36
69
|
declare class NeonBranch extends pulumi.ComponentResource {
|
|
@@ -39,5 +72,5 @@ declare class NeonBranch extends pulumi.ComponentResource {
|
|
|
39
72
|
constructor(name: string, args: NeonBranchArgs, opts: NeonBranchOptions);
|
|
40
73
|
}
|
|
41
74
|
//#endregion
|
|
42
|
-
export { NeonBranch, NeonBranchArgs, NeonBranchInputs };
|
|
75
|
+
export { NeonBranch, NeonBranchArgs, NeonBranchInputs, NeonBranchResourceProvider };
|
|
43
76
|
//# sourceMappingURL=branch.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"branch.d.mts","names":[],"sources":["../../src/neon/branch.ts"],"mappings":";;;;;;;UAMiB,gBAAA;;EAEhB,MAAA;EAFgC;EAKhC,SAAA;EALgC;EAQhC,IAAA;AAAA;;
|
|
1
|
+
{"version":3,"file":"branch.d.mts","names":[],"sources":["../../src/neon/branch.ts"],"mappings":";;;;;;;UAMiB,gBAAA;;EAEhB,MAAA;EAFgC;EAKhC,SAAA;EALgC;EAQhC,IAAA;EAHA;;;;EASA,UAAA;AAAA;;UAIS,iBAAA,SAA0B,gBAAgB;AAAA;AAqDpD;;;;;;;cAAa,0BAAA,YACD,MAAA,CAAO,OAAA,CAAQ,gBAAA;EAEpB,MAAA,CAAO,MAAA,EAAQ,gBAAA,GAAmB,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,YAAA;EAmDzD,IAAA,CACL,EAAA,UACA,KAAA,EAAO,iBAAA,GACL,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;EAepB,MAAA,CAAO,EAAA,UAAY,KAAA,EAAO,iBAAA,GAAoB,OAAA;EAU9C,IAAA,CACL,GAAA,UACA,IAAA,EAAM,iBAAA,EACN,IAAA,EAAM,gBAAA,GACJ,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;AAAA;;KAuCtB,iBAAA,GAAoB,IAAA,CAAK,MAAA,CAAO,wBAAA;EA5HzB,mCA8HX,QAAA,EAAU,YAAA,EA9HgC;EAiI1C,OAAA,EAAS,WAAA;AAAA;;UAIO,cAAA;EAnIK;EAqIrB,IAAA,EAAM,MAAA,CAAO,KAAA;EArI2B;;;;EA2IxC,MAAA,GAAS,MAAA,CAAO,KAAK;AAAA;;;;;;;;;;;;;;;;;;cAoBT,UAAA,SAAmB,MAAA,CAAO,iBAAA;EA5E3B;EAAA,SA8EK,EAAA,EAAI,MAAA,CAAO,MAAA;cAEf,IAAA,UAAc,IAAA,EAAM,cAAA,EAAgB,IAAA,EAAM,iBAAA;AAAA"}
|
package/dist/neon/branch.mjs
CHANGED
|
@@ -13,17 +13,28 @@ async function findBranchByName(client, projectId, name) {
|
|
|
13
13
|
* Dynamic provider implementing CRUD for Neon branches.
|
|
14
14
|
*
|
|
15
15
|
* Uses adopt-or-create on `create()`: finds an existing branch by name
|
|
16
|
-
* before creating a new one.
|
|
16
|
+
* before creating a new one. When `parentName` is supplied, resolves it
|
|
17
|
+
* to a `parent_id` and includes it in the POST body.
|
|
17
18
|
*/
|
|
19
|
+
/** @internal Exported only for unit testing; not part of the public API surface. */
|
|
18
20
|
var NeonBranchResourceProvider = class {
|
|
19
21
|
async create(inputs) {
|
|
20
22
|
const client = new NeonClient(inputs.apiKey);
|
|
21
23
|
let branchId = await findBranchByName(client, inputs.projectId, inputs.name);
|
|
22
|
-
if (branchId) pulumi.log.
|
|
23
|
-
else
|
|
24
|
+
if (branchId) if (inputs.parentName) pulumi.log.warn(`Adopting existing Neon branch "${inputs.name}" — parentName "${inputs.parentName}" is ignored for adopted branches (existing lineage preserved).`);
|
|
25
|
+
else pulumi.log.info(`Adopting existing Neon branch "${inputs.name}" (${branchId})`);
|
|
26
|
+
else {
|
|
27
|
+
const body = { branch: { name: inputs.name } };
|
|
28
|
+
if (inputs.parentName) {
|
|
29
|
+
const parentId = await findBranchByName(client, inputs.projectId, inputs.parentName);
|
|
30
|
+
if (!parentId) throw new Error(`Neon parent branch "${inputs.parentName}" not found in project ${inputs.projectId}`);
|
|
31
|
+
body.branch.parent_id = parentId;
|
|
32
|
+
}
|
|
33
|
+
branchId = (await client.post(`/projects/${inputs.projectId}/branches`, body)).branch.id;
|
|
34
|
+
}
|
|
24
35
|
return {
|
|
25
36
|
id: branchId,
|
|
26
|
-
outs: inputs
|
|
37
|
+
outs: { ...inputs }
|
|
27
38
|
};
|
|
28
39
|
}
|
|
29
40
|
async read(id, props) {
|
|
@@ -47,6 +58,7 @@ var NeonBranchResourceProvider = class {
|
|
|
47
58
|
async diff(_id, olds, news) {
|
|
48
59
|
const replaces = [];
|
|
49
60
|
if (olds.projectId !== news.projectId) replaces.push("projectId");
|
|
61
|
+
if (olds.parentName !== news.parentName) replaces.push("parentName");
|
|
50
62
|
return {
|
|
51
63
|
changes: replaces.length > 0 || olds.name !== news.name,
|
|
52
64
|
replaces,
|
|
@@ -65,9 +77,16 @@ var NeonBranchResource = class extends pulumi.dynamic.Resource {
|
|
|
65
77
|
*
|
|
66
78
|
* @example
|
|
67
79
|
* ```typescript
|
|
68
|
-
*
|
|
80
|
+
* // Root branch (Neon default parent)
|
|
81
|
+
* const production = new NeonBranch("production", {
|
|
69
82
|
* name: "production",
|
|
70
83
|
* }, { provider, project });
|
|
84
|
+
*
|
|
85
|
+
* // Copy-on-write branch from production
|
|
86
|
+
* const staging = new NeonBranch("staging", {
|
|
87
|
+
* name: "staging",
|
|
88
|
+
* parent: "production",
|
|
89
|
+
* }, { provider, project });
|
|
71
90
|
* ```
|
|
72
91
|
*/
|
|
73
92
|
var NeonBranch = class extends pulumi.ComponentResource {
|
|
@@ -77,7 +96,8 @@ var NeonBranch = class extends pulumi.ComponentResource {
|
|
|
77
96
|
const resource = new NeonBranchResource(`${name}-resource`, {
|
|
78
97
|
apiKey: provider.apiKey,
|
|
79
98
|
projectId: project.id,
|
|
80
|
-
name: args.name
|
|
99
|
+
name: args.name,
|
|
100
|
+
parentName: args.parent
|
|
81
101
|
}, { parent: this });
|
|
82
102
|
this.id = resource.id;
|
|
83
103
|
this.registerOutputs({ id: this.id });
|
|
@@ -85,5 +105,5 @@ var NeonBranch = class extends pulumi.ComponentResource {
|
|
|
85
105
|
};
|
|
86
106
|
|
|
87
107
|
//#endregion
|
|
88
|
-
export { NeonBranch };
|
|
108
|
+
export { NeonBranch, NeonBranchResourceProvider };
|
|
89
109
|
//# sourceMappingURL=branch.mjs.map
|
package/dist/neon/branch.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"branch.mjs","names":[],"sources":["../../src/neon/branch.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\nimport { NeonClient } from \"./client\";\nimport type { NeonProject } from \"./project\";\nimport type { NeonProvider } from \"./provider\";\n\n/** Resolved inputs for the Neon branch dynamic provider. */\nexport interface NeonBranchInputs {\n\t/** Neon API key. */\n\tapiKey: string;\n\n\t/** Neon project ID (e.g. `\"quiet-forest-69719462\"`). */\n\tprojectId: string;\n\n\t/** Branch display name (e.g. `\"production\"`, `\"development\"`). */\n\tname: string;\n}\n\n/** Persisted state for the Neon branch. */\ninterface NeonBranchOutputs extends NeonBranchInputs {}\n\n/** Neon API response for a branch. */\ninterface BranchResponse {\n\tbranch: {\n\t\tid: string;\n\t\tname: string;\n\t\tproject_id: string;\n\t};\n}\n\n/** Neon API response for branch creation. */\ninterface BranchCreateResponse {\n\tbranch: {\n\t\tid: string;\n\t\tname: string;\n\t\tproject_id: string;\n\t};\n}\n\n/** Neon API response for listing branches. */\ninterface BranchListResponse {\n\tbranches: Array<{\n\t\tid: string;\n\t\tname: string;\n\t}>;\n}\n\n/**\n * Finds an existing Neon branch by name within a project.\n */\nasync function findBranchByName(\n\tclient: NeonClient,\n\tprojectId: string,\n\tname: string,\n): Promise<string | undefined> {\n\tconst result = await client.get<BranchListResponse>(\n\t\t`/projects/${projectId}/branches`,\n\t);\n\n\tconst match = result.branches.find((b) => b.name === name);\n\n\treturn match?.id;\n}\n\n/**\n * Dynamic provider implementing CRUD for Neon branches.\n *\n * Uses adopt-or-create on `create()`: finds an existing branch by name\n * before creating a new one.\n */\
|
|
1
|
+
{"version":3,"file":"branch.mjs","names":[],"sources":["../../src/neon/branch.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\nimport { NeonClient } from \"./client\";\nimport type { NeonProject } from \"./project\";\nimport type { NeonProvider } from \"./provider\";\n\n/** Resolved inputs for the Neon branch dynamic provider. */\nexport interface NeonBranchInputs {\n\t/** Neon API key. */\n\tapiKey: string;\n\n\t/** Neon project ID (e.g. `\"quiet-forest-69719462\"`). */\n\tprojectId: string;\n\n\t/** Branch display name (e.g. `\"production\"`, `\"development\"`). */\n\tname: string;\n\n\t/**\n\t * Parent branch NAME. Resolved to `parent_id` inside `create()` via\n\t * `findBranchByName`. Omit for project-root branches.\n\t */\n\tparentName?: string;\n}\n\n/** Persisted state for the Neon branch. */\ninterface NeonBranchOutputs extends NeonBranchInputs {}\n\n/** Neon API response for a branch. */\ninterface BranchResponse {\n\tbranch: {\n\t\tid: string;\n\t\tname: string;\n\t\tproject_id: string;\n\t};\n}\n\n/** Neon API response for branch creation. */\ninterface BranchCreateResponse {\n\tbranch: {\n\t\tid: string;\n\t\tname: string;\n\t\tproject_id: string;\n\t};\n}\n\n/** Neon API response for listing branches. */\ninterface BranchListResponse {\n\tbranches: Array<{\n\t\tid: string;\n\t\tname: string;\n\t}>;\n}\n\n/**\n * Finds an existing Neon branch by name within a project.\n */\nasync function findBranchByName(\n\tclient: NeonClient,\n\tprojectId: string,\n\tname: string,\n): Promise<string | undefined> {\n\tconst result = await client.get<BranchListResponse>(\n\t\t`/projects/${projectId}/branches`,\n\t);\n\n\tconst match = result.branches.find((b) => b.name === name);\n\n\treturn match?.id;\n}\n\n/**\n * Dynamic provider implementing CRUD for Neon branches.\n *\n * Uses adopt-or-create on `create()`: finds an existing branch by name\n * before creating a new one. When `parentName` is supplied, resolves it\n * to a `parent_id` and includes it in the POST body.\n */\n/** @internal Exported only for unit testing; not part of the public API surface. */\nexport class NeonBranchResourceProvider\n\timplements pulumi.dynamic.ResourceProvider\n{\n\tasync create(inputs: NeonBranchInputs): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new NeonClient(inputs.apiKey);\n\n\t\tlet branchId = await findBranchByName(\n\t\t\tclient,\n\t\t\tinputs.projectId,\n\t\t\tinputs.name,\n\t\t);\n\n\t\tif (branchId) {\n\t\t\tif (inputs.parentName) {\n\t\t\t\tpulumi.log.warn(\n\t\t\t\t\t`Adopting existing Neon branch \"${inputs.name}\" — parentName \"${inputs.parentName}\" is ignored for adopted branches (existing lineage preserved).`,\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tpulumi.log.info(\n\t\t\t\t\t`Adopting existing Neon branch \"${inputs.name}\" (${branchId})`,\n\t\t\t\t);\n\t\t\t}\n\t\t} else {\n\t\t\tconst body: { branch: { name: string; parent_id?: string } } = {\n\t\t\t\tbranch: { name: inputs.name },\n\t\t\t};\n\n\t\t\tif (inputs.parentName) {\n\t\t\t\tconst parentId = await findBranchByName(\n\t\t\t\t\tclient,\n\t\t\t\t\tinputs.projectId,\n\t\t\t\t\tinputs.parentName,\n\t\t\t\t);\n\n\t\t\t\tif (!parentId) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Neon parent branch \"${inputs.parentName}\" not found in project ${inputs.projectId}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tbody.branch.parent_id = parentId;\n\t\t\t}\n\n\t\t\tconst result = await client.post<BranchCreateResponse>(\n\t\t\t\t`/projects/${inputs.projectId}/branches`,\n\t\t\t\tbody,\n\t\t\t);\n\n\t\t\tbranchId = result.branch.id;\n\t\t}\n\n\t\treturn { id: branchId, outs: { ...inputs } };\n\t}\n\n\tasync read(\n\t\tid: string,\n\t\tprops: NeonBranchOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new NeonClient(props.apiKey);\n\n\t\tconst result = await client.get<BranchResponse>(\n\t\t\t`/projects/${props.projectId}/branches/${id}`,\n\t\t);\n\n\t\t// parentName is preserved from prior state (props): the Neon API does not expose\n\t\t// a branch's parent on GET /branches/:id, so it cannot be re-derived here.\n\t\treturn {\n\t\t\tid: result.branch.id,\n\t\t\tprops: { ...props, name: result.branch.name },\n\t\t};\n\t}\n\n\tasync delete(id: string, props: NeonBranchOutputs): Promise<void> {\n\t\tconst client = new NeonClient(props.apiKey);\n\n\t\ttry {\n\t\t\tawait client.delete(`/projects/${props.projectId}/branches/${id}`);\n\t\t} catch {\n\t\t\tpulumi.log.warn(`Failed to delete Neon branch (may already be deleted)`);\n\t\t}\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: NeonBranchOutputs,\n\t\tnews: NeonBranchInputs,\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.parentName !== news.parentName) {\n\t\t\treplaces.push(\"parentName\");\n\t\t}\n\n\t\treturn {\n\t\t\tchanges: replaces.length > 0 || olds.name !== news.name,\n\t\t\treplaces,\n\t\t\tdeleteBeforeReplace: true,\n\t\t};\n\t}\n}\n\n/** Internal dynamic resource — not part of the public API. */\nclass NeonBranchResource extends pulumi.dynamic.Resource {\n\tpublic declare readonly branchId: 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\tname: pulumi.Input<string>;\n\t\t\t/** Name of the parent branch; omit for project-root branches. */\n\t\t\tparentName?: pulumi.Input<string>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(new NeonBranchResourceProvider(), name, { ...args }, opts);\n\t}\n}\n\n/** Options type for NeonBranch — replaces Pulumi's native `provider` field. */\ntype NeonBranchOptions = Omit<pulumi.ComponentResourceOptions, \"provider\"> & {\n\t/** Neon authentication context. */\n\tprovider: NeonProvider;\n\n\t/** Neon project context. */\n\tproject: NeonProject;\n};\n\n/** Args for NeonBranch. */\nexport interface NeonBranchArgs {\n\t/** Branch display name. */\n\tname: pulumi.Input<string>;\n\n\t/**\n\t * Name of the parent branch to branch from (copy-on-write). Omit to\n\t * branch from the project root (Neon default branch).\n\t */\n\tparent?: pulumi.Input<string>;\n}\n\n/**\n * Manages a Neon branch with adopt-or-create semantics.\n *\n * @example\n * ```typescript\n * // Root branch (Neon default parent)\n * const production = new NeonBranch(\"production\", {\n * name: \"production\",\n * }, { provider, project });\n *\n * // Copy-on-write branch from production\n * const staging = new NeonBranch(\"staging\", {\n * name: \"staging\",\n * parent: \"production\",\n * }, { provider, project });\n * ```\n */\nexport class NeonBranch extends pulumi.ComponentResource {\n\t/** Neon branch ID. */\n\tpublic readonly id: pulumi.Output<string>;\n\n\tconstructor(name: string, args: NeonBranchArgs, opts: NeonBranchOptions) {\n\t\tconst { provider, project, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:neon:Branch\", name, {}, pulumiOpts);\n\n\t\tconst resource = new NeonBranchResource(\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\tname: args.name,\n\t\t\t\tparentName: args.parent,\n\t\t\t},\n\t\t\t{ parent: this },\n\t\t);\n\n\t\tthis.id = resource.id;\n\n\t\tthis.registerOutputs({ id: this.id });\n\t}\n}\n"],"mappings":";;;;;;;;AAuDA,eAAe,iBACd,QACA,WACA,MAC8B;CAO9B,QAFc,MAJO,OAAO,IAC3B,aAAa,UAAU,UACxB,GAEqB,SAAS,MAAM,MAAM,EAAE,SAAS,IAE1C,GAAG;AACf;;;;;;;;;AAUA,IAAa,6BAAb,MAEA;CACC,MAAM,OAAO,QAAgE;EAC5E,MAAM,SAAS,IAAI,WAAW,OAAO,MAAM;EAE3C,IAAI,WAAW,MAAM,iBACpB,QACA,OAAO,WACP,OAAO,IACR;EAEA,IAAI,UACH,IAAI,OAAO,YACV,OAAO,IAAI,KACV,kCAAkC,OAAO,KAAK,kBAAkB,OAAO,WAAW,gEACnF;OAEA,OAAO,IAAI,KACV,kCAAkC,OAAO,KAAK,KAAK,SAAS,EAC7D;OAEK;GACN,MAAM,OAAyD,EAC9D,QAAQ,EAAE,MAAM,OAAO,KAAK,EAC7B;GAEA,IAAI,OAAO,YAAY;IACtB,MAAM,WAAW,MAAM,iBACtB,QACA,OAAO,WACP,OAAO,UACR;IAEA,IAAI,CAAC,UACJ,MAAM,IAAI,MACT,uBAAuB,OAAO,WAAW,yBAAyB,OAAO,WAC1E;IAGD,KAAK,OAAO,YAAY;GACzB;GAOA,YAAW,MALU,OAAO,KAC3B,aAAa,OAAO,UAAU,YAC9B,IACD,GAEkB,OAAO;EAC1B;EAEA,OAAO;GAAE,IAAI;GAAU,MAAM,EAAE,GAAG,OAAO;EAAE;CAC5C;CAEA,MAAM,KACL,IACA,OACqC;EAGrC,MAAM,SAAS,MAAM,IAFF,WAAW,MAAM,MAEV,EAAE,IAC3B,aAAa,MAAM,UAAU,YAAY,IAC1C;EAIA,OAAO;GACN,IAAI,OAAO,OAAO;GAClB,OAAO;IAAE,GAAG;IAAO,MAAM,OAAO,OAAO;GAAK;EAC7C;CACD;CAEA,MAAM,OAAO,IAAY,OAAyC;EACjE,MAAM,SAAS,IAAI,WAAW,MAAM,MAAM;EAE1C,IAAI;GACH,MAAM,OAAO,OAAO,aAAa,MAAM,UAAU,YAAY,IAAI;EAClE,QAAQ;GACP,OAAO,IAAI,KAAK,uDAAuD;EACxE;CACD;CAEA,MAAM,KACL,KACA,MACA,MACqC;EACrC,MAAM,WAAqB,CAAC;EAE5B,IAAI,KAAK,cAAc,KAAK,WAC3B,SAAS,KAAK,WAAW;EAG1B,IAAI,KAAK,eAAe,KAAK,YAC5B,SAAS,KAAK,YAAY;EAG3B,OAAO;GACN,SAAS,SAAS,SAAS,KAAK,KAAK,SAAS,KAAK;GACnD;GACA,qBAAqB;EACtB;CACD;AACD;;AAGA,IAAM,qBAAN,cAAiC,OAAO,QAAQ,SAAS;CAGxD,YACC,MACA,MAOA,MACC;EACD,MAAM,IAAI,2BAA2B,GAAG,MAAM,EAAE,GAAG,KAAK,GAAG,IAAI;CAChE;AACD;;;;;;;;;;;;;;;;;;AAwCA,IAAa,aAAb,cAAgC,OAAO,kBAAkB;CAIxD,YAAY,MAAc,MAAsB,MAAyB;EACxE,MAAM,EAAE,UAAU,SAAS,GAAG,eAAe;EAE7C,MAAM,0BAA0B,MAAM,CAAC,GAAG,UAAU;EAEpD,MAAM,WAAW,IAAI,mBACpB,GAAG,KAAK,YACR;GACC,QAAQ,SAAS;GACjB,WAAW,QAAQ;GACnB,MAAM,KAAK;GACX,YAAY,KAAK;EAClB,GACA,EAAE,QAAQ,KAAK,CAChB;EAEA,KAAK,KAAK,SAAS;EAEnB,KAAK,gBAAgB,EAAE,IAAI,KAAK,GAAG,CAAC;CACrC;AACD"}
|
|
@@ -5,6 +5,14 @@ let _pulumi_pulumi = require("@pulumi/pulumi");
|
|
|
5
5
|
_pulumi_pulumi = require_chunk.__toESM(_pulumi_pulumi, 1);
|
|
6
6
|
|
|
7
7
|
//#region src/railway/environment.ts
|
|
8
|
+
const ENVIRONMENT_CREATE_MUTATION = `
|
|
9
|
+
mutation EnvironmentCreate($input: EnvironmentCreateInput!) {
|
|
10
|
+
environmentCreate(input: $input) {
|
|
11
|
+
id
|
|
12
|
+
name
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
`;
|
|
8
16
|
const PROJECT_ENVIRONMENTS_QUERY = `
|
|
9
17
|
query($projectId: String!) {
|
|
10
18
|
project(id: $projectId) {
|
|
@@ -26,18 +34,44 @@ async function findEnvironmentId(client, projectId, name) {
|
|
|
26
34
|
return (await client.query(PROJECT_ENVIRONMENTS_QUERY, { projectId })).project.environments.edges.find((edge) => edge.node.name === name)?.node.id;
|
|
27
35
|
}
|
|
28
36
|
/**
|
|
29
|
-
* Dynamic provider that resolves a Railway environment
|
|
37
|
+
* Dynamic provider that resolves or creates a Railway environment by name.
|
|
38
|
+
*
|
|
39
|
+
* @internal Exported only for unit testing; not part of the public API surface.
|
|
30
40
|
*/
|
|
31
41
|
var RailwayEnvironmentResourceProvider = class {
|
|
42
|
+
/**
|
|
43
|
+
* Adopts an existing Railway environment when found by name, or creates a new
|
|
44
|
+
* one (optionally forked from a source environment) when not found.
|
|
45
|
+
*
|
|
46
|
+
* @param inputs Resolved provider inputs including token, projectId, name, and optional source.
|
|
47
|
+
* @returns Pulumi dynamic create result with the environment UUID as the resource ID.
|
|
48
|
+
* @throws {Error} When `source` is provided but cannot be resolved to an environment ID.
|
|
49
|
+
*/
|
|
32
50
|
async create(inputs) {
|
|
33
|
-
const
|
|
34
|
-
|
|
51
|
+
const client = new require_railway_client.RailwayClient(inputs.token);
|
|
52
|
+
let environmentId = await findEnvironmentId(client, inputs.projectId, inputs.name);
|
|
53
|
+
if (environmentId) _pulumi_pulumi.log.info(`Adopting existing Railway environment "${inputs.name}" (${environmentId})`);
|
|
54
|
+
else {
|
|
55
|
+
let sourceEnvironmentId;
|
|
56
|
+
if (inputs.source) {
|
|
57
|
+
sourceEnvironmentId = await findEnvironmentId(client, inputs.projectId, inputs.source);
|
|
58
|
+
if (!sourceEnvironmentId) throw new Error(`Railway source environment "${inputs.source}" not found in project ${inputs.projectId}`);
|
|
59
|
+
}
|
|
60
|
+
environmentId = (await client.query(ENVIRONMENT_CREATE_MUTATION, { input: {
|
|
61
|
+
projectId: inputs.projectId,
|
|
62
|
+
name: inputs.name,
|
|
63
|
+
skipInitialDeploys: true,
|
|
64
|
+
...sourceEnvironmentId ? { sourceEnvironmentId } : {}
|
|
65
|
+
} })).environmentCreate.id;
|
|
66
|
+
_pulumi_pulumi.log.info(`Created Railway environment "${inputs.name}" (${environmentId})`);
|
|
67
|
+
}
|
|
68
|
+
const outs = {
|
|
69
|
+
...inputs,
|
|
70
|
+
environmentId
|
|
71
|
+
};
|
|
35
72
|
return {
|
|
36
73
|
id: environmentId,
|
|
37
|
-
outs
|
|
38
|
-
...inputs,
|
|
39
|
-
environmentId
|
|
40
|
-
}
|
|
74
|
+
outs
|
|
41
75
|
};
|
|
42
76
|
}
|
|
43
77
|
async read(_id, props) {
|
|
@@ -83,17 +117,28 @@ var RailwayEnvironmentResource = class extends _pulumi_pulumi.dynamic.Resource {
|
|
|
83
117
|
}
|
|
84
118
|
};
|
|
85
119
|
/**
|
|
86
|
-
* Resolves a Railway environment
|
|
120
|
+
* Resolves or creates a Railway environment by name within a project.
|
|
121
|
+
*
|
|
122
|
+
* When the named environment already exists it is adopted (no mutation).
|
|
123
|
+
* When it does not exist it is created — optionally forked from a source
|
|
124
|
+
* environment so the new env inherits service instances and variables.
|
|
87
125
|
*
|
|
88
126
|
* @example
|
|
89
127
|
* ```typescript
|
|
90
|
-
*
|
|
128
|
+
* // Adopt or create "production" (no source)
|
|
129
|
+
* const production = new RailwayEnvironment("production", {
|
|
91
130
|
* name: "production",
|
|
92
131
|
* }, { provider, project });
|
|
93
132
|
*
|
|
133
|
+
* // Adopt or create "staging", forked from "production"
|
|
134
|
+
* const staging = new RailwayEnvironment("staging", {
|
|
135
|
+
* name: "staging",
|
|
136
|
+
* source: "production",
|
|
137
|
+
* }, { provider, project });
|
|
138
|
+
*
|
|
94
139
|
* // Use environmentId downstream
|
|
95
140
|
* const service = new RailwayService("api", { name: "api" }, {
|
|
96
|
-
* provider, project, environment,
|
|
141
|
+
* provider, project, environment: staging,
|
|
97
142
|
* });
|
|
98
143
|
* ```
|
|
99
144
|
*/
|
|
@@ -104,7 +149,8 @@ var RailwayEnvironment = class extends _pulumi_pulumi.ComponentResource {
|
|
|
104
149
|
const resource = new RailwayEnvironmentResource(`${name}-resource`, {
|
|
105
150
|
token: provider.token,
|
|
106
151
|
projectId: project.id,
|
|
107
|
-
name: args.name
|
|
152
|
+
name: args.name,
|
|
153
|
+
source: args.source
|
|
108
154
|
}, { parent: this });
|
|
109
155
|
this.id = resource.environmentId;
|
|
110
156
|
this.registerOutputs({ id: this.id });
|
|
@@ -113,4 +159,5 @@ var RailwayEnvironment = class extends _pulumi_pulumi.ComponentResource {
|
|
|
113
159
|
|
|
114
160
|
//#endregion
|
|
115
161
|
exports.RailwayEnvironment = RailwayEnvironment;
|
|
162
|
+
exports.RailwayEnvironmentResourceProvider = RailwayEnvironmentResourceProvider;
|
|
116
163
|
//# sourceMappingURL=environment.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment.cjs","names":["RailwayClient","pulumi"],"sources":["../../src/railway/environment.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\nimport { RailwayClient } from \"./client\";\nimport type { RailwayProject } from \"./project\";\nimport type { RailwayProvider } from \"./provider\";\n\n/** Resolved inputs for the Railway environment dynamic provider. */\ninterface RailwayEnvironmentInputs {\n\t/** Railway API bearer token. */\n\ttoken: string;\n\n\t/** Railway project UUID. */\n\tprojectId: string;\n\n\t/** Environment display name (e.g. `\"production\"`, `\"staging\"`). */\n\tname: string;\n}\n\n/** Persisted state for the Railway environment. */\ninterface RailwayEnvironmentOutputs extends RailwayEnvironmentInputs {\n\t/** Railway-assigned environment UUID. */\n\tenvironmentId: string;\n}\n\nconst PROJECT_ENVIRONMENTS_QUERY = `\n query($projectId: String!) {\n project(id: $projectId) {\n environments {\n edges {\n node {\n id\n name\n }\n }\n }\n }\n }\n`;\n\n/**\n * Queries a project's environments and resolves the ID for the given name.\n */\nasync function findEnvironmentId(\n\tclient: RailwayClient,\n\tprojectId: string,\n\tname: string,\n): Promise<string | undefined> {\n\tconst result = await client.query<{\n\t\tproject: {\n\t\t\tenvironments: {\n\t\t\t\tedges: Array<{ node: { id: string; name: string } }>;\n\t\t\t};\n\t\t};\n\t}>(PROJECT_ENVIRONMENTS_QUERY, { projectId });\n\n\tconst match = result.project.environments.edges.find(\n\t\t(edge) => edge.node.name === name,\n\t);\n\n\treturn match?.node.id;\n}\n\n/**\n * Dynamic provider that resolves a Railway environment UUID by name from a project.\n */\nclass RailwayEnvironmentResourceProvider\n\timplements pulumi.dynamic.ResourceProvider\n{\n\tasync create(\n\t\tinputs: RailwayEnvironmentInputs,\n\t): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new RailwayClient(inputs.token);\n\n\t\tconst environmentId = await findEnvironmentId(\n\t\t\tclient,\n\t\t\tinputs.projectId,\n\t\t\tinputs.name,\n\t\t);\n\n\t\tif (!environmentId) {\n\t\t\tthrow new Error(\n\t\t\t\t`Railway environment \"${inputs.name}\" not found in project ${inputs.projectId}`,\n\t\t\t);\n\t\t}\n\n\t\tconst outs: RailwayEnvironmentOutputs = { ...inputs, environmentId };\n\n\t\treturn { id: environmentId, outs };\n\t}\n\n\tasync read(\n\t\t_id: string,\n\t\tprops: RailwayEnvironmentOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new RailwayClient(props.token);\n\n\t\tconst environmentId = await findEnvironmentId(\n\t\t\tclient,\n\t\t\tprops.projectId,\n\t\t\tprops.name,\n\t\t);\n\n\t\tif (!environmentId) {\n\t\t\tthrow new Error(\n\t\t\t\t`Railway environment \"${props.name}\" not found during refresh`,\n\t\t\t);\n\t\t}\n\n\t\treturn { id: environmentId, props: { ...props, environmentId } };\n\t}\n\n\tasync update(\n\t\t_id: string,\n\t\t_olds: RailwayEnvironmentOutputs,\n\t\tnews: RailwayEnvironmentInputs,\n\t): Promise<pulumi.dynamic.UpdateResult> {\n\t\tconst client = new RailwayClient(news.token);\n\n\t\tconst environmentId = await findEnvironmentId(\n\t\t\tclient,\n\t\t\tnews.projectId,\n\t\t\tnews.name,\n\t\t);\n\n\t\tif (!environmentId) {\n\t\t\tthrow new Error(\n\t\t\t\t`Railway environment \"${news.name}\" not found in project ${news.projectId}`,\n\t\t\t);\n\t\t}\n\n\t\treturn { outs: { ...news, environmentId } };\n\t}\n\n\tasync delete(): Promise<void> {\n\t\tpulumi.log.warn(\n\t\t\t\"Railway environment deletion skipped — environments are not deleted by Pulumi\",\n\t\t);\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: RailwayEnvironmentOutputs,\n\t\tnews: RailwayEnvironmentInputs,\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.name !== news.name) {\n\t\t\treplaces.push(\"name\");\n\t\t}\n\n\t\treturn {\n\t\t\tchanges: replaces.length > 0,\n\t\t\treplaces,\n\t\t\tdeleteBeforeReplace: true,\n\t\t};\n\t}\n}\n\n/** Internal dynamic resource — not part of the public API. */\nclass RailwayEnvironmentResource extends pulumi.dynamic.Resource {\n\tpublic declare readonly environmentId: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\ttoken: pulumi.Input<string>;\n\t\t\tprojectId: pulumi.Input<string>;\n\t\t\tname: pulumi.Input<string>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(\n\t\t\tnew RailwayEnvironmentResourceProvider(),\n\t\t\tname,\n\t\t\t{\n\t\t\t\t...args,\n\t\t\t\tenvironmentId: undefined,\n\t\t\t},\n\t\t\topts,\n\t\t);\n\t}\n}\n\n/** Options type for RailwayEnvironment — replaces Pulumi's native `provider` field. */\ntype RailwayEnvironmentOptions = Omit<\n\tpulumi.ComponentResourceOptions,\n\t\"provider\"\n> & {\n\t/** Railway authentication context. */\n\tprovider: RailwayProvider;\n\n\t/** Railway project context to resolve the environment from. */\n\tproject: RailwayProject;\n};\n\n/** Args for RailwayEnvironment. */\nexport interface RailwayEnvironmentArgs {\n\t/** Environment display name (e.g. `\"production\"`, `\"staging\"`). */\n\tname: pulumi.Input<string>;\n}\n\n/**\n * Resolves a Railway environment UUID by name from a project.\n *\n * @example\n * ```typescript\n * const environment = new RailwayEnvironment(\"production\", {\n * name: \"production\",\n * }, { provider, project });\n *\n * // Use environmentId downstream\n * const service = new RailwayService(\"api\", { name: \"api\" }, {\n * provider, project, environment,\n * });\n * ```\n */\nexport class RailwayEnvironment extends pulumi.ComponentResource {\n\t/** Railway environment UUID. */\n\tpublic readonly id: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: RailwayEnvironmentArgs,\n\t\topts: RailwayEnvironmentOptions,\n\t) {\n\t\tconst { provider, project, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:railway:Environment\", name, {}, pulumiOpts);\n\n\t\tconst resource = new RailwayEnvironmentResource(\n\t\t\t`${name}-resource`,\n\t\t\t{\n\t\t\t\ttoken: provider.token,\n\t\t\t\tprojectId: project.id,\n\t\t\t\tname: args.name,\n\t\t\t},\n\t\t\t{ parent: this },\n\t\t);\n\n\t\tthis.id = resource.environmentId;\n\n\t\tthis.registerOutputs({ id: this.id });\n\t}\n}\n"],"mappings":";;;;;;;AAuBA,MAAM,6BAA6B;;;;;;;;;;;;;;;;;AAkBnC,eAAe,kBACd,QACA,WACA,MAC8B;CAa9B,QAJc,MARO,OAAO,MAMzB,4BAA4B,EAAE,UAAU,CAAC,GAEvB,QAAQ,aAAa,MAAM,MAC9C,SAAS,KAAK,KAAK,SAAS,IAGnB,GAAG,KAAK;AACpB;;;;AAKA,IAAM,qCAAN,MAEA;CACC,MAAM,OACL,QACuC;EAGvC,MAAM,gBAAgB,MAAM,kBAC3B,IAHkBA,qCAAc,OAAO,KAGlC,GACL,OAAO,WACP,OAAO,IACR;EAEA,IAAI,CAAC,eACJ,MAAM,IAAI,MACT,wBAAwB,OAAO,KAAK,yBAAyB,OAAO,WACrE;EAKD,OAAO;GAAE,IAAI;GAAe;IAFc,GAAG;IAAQ;GAEtB;EAAE;CAClC;CAEA,MAAM,KACL,KACA,OACqC;EAGrC,MAAM,gBAAgB,MAAM,kBAC3B,IAHkBA,qCAAc,MAAM,KAGjC,GACL,MAAM,WACN,MAAM,IACP;EAEA,IAAI,CAAC,eACJ,MAAM,IAAI,MACT,wBAAwB,MAAM,KAAK,2BACpC;EAGD,OAAO;GAAE,IAAI;GAAe,OAAO;IAAE,GAAG;IAAO;GAAc;EAAE;CAChE;CAEA,MAAM,OACL,KACA,OACA,MACuC;EAGvC,MAAM,gBAAgB,MAAM,kBAC3B,IAHkBA,qCAAc,KAAK,KAGhC,GACL,KAAK,WACL,KAAK,IACN;EAEA,IAAI,CAAC,eACJ,MAAM,IAAI,MACT,wBAAwB,KAAK,KAAK,yBAAyB,KAAK,WACjE;EAGD,OAAO,EAAE,MAAM;GAAE,GAAG;GAAM;EAAc,EAAE;CAC3C;CAEA,MAAM,SAAwB;EAC7B,eAAO,IAAI,KACV,+EACD;CACD;CAEA,MAAM,KACL,KACA,MACA,MACqC;EACrC,MAAM,WAAqB,CAAC;EAE5B,IAAI,KAAK,cAAc,KAAK,WAC3B,SAAS,KAAK,WAAW;EAG1B,IAAI,KAAK,SAAS,KAAK,MACtB,SAAS,KAAK,MAAM;EAGrB,OAAO;GACN,SAAS,SAAS,SAAS;GAC3B;GACA,qBAAqB;EACtB;CACD;AACD;;AAGA,IAAM,6BAAN,cAAyCC,eAAO,QAAQ,SAAS;CAGhE,YACC,MACA,MAKA,MACC;EACD,MACC,IAAI,mCAAmC,GACvC,MACA;GACC,GAAG;GACH,eAAe;EAChB,GACA,IACD;CACD;AACD;;;;;;;;;;;;;;;;AAmCA,IAAa,qBAAb,cAAwCA,eAAO,kBAAkB;CAIhE,YACC,MACA,MACA,MACC;EACD,MAAM,EAAE,UAAU,SAAS,GAAG,eAAe;EAE7C,MAAM,kCAAkC,MAAM,CAAC,GAAG,UAAU;EAE5D,MAAM,WAAW,IAAI,2BACpB,GAAG,KAAK,YACR;GACC,OAAO,SAAS;GAChB,WAAW,QAAQ;GACnB,MAAM,KAAK;EACZ,GACA,EAAE,QAAQ,KAAK,CAChB;EAEA,KAAK,KAAK,SAAS;EAEnB,KAAK,gBAAgB,EAAE,IAAI,KAAK,GAAG,CAAC;CACrC;AACD"}
|
|
1
|
+
{"version":3,"file":"environment.cjs","names":["RailwayClient","pulumi"],"sources":["../../src/railway/environment.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\nimport { RailwayClient } from \"./client\";\nimport type { RailwayProject } from \"./project\";\nimport type { RailwayProvider } from \"./provider\";\n\n/** Resolved inputs for the Railway environment dynamic provider. */\ninterface RailwayEnvironmentInputs {\n\t/** Railway API bearer token. */\n\ttoken: string;\n\n\t/** Railway project UUID. */\n\tprojectId: string;\n\n\t/** Environment display name (e.g. `\"production\"`, `\"staging\"`). */\n\tname: string;\n\n\t/** Name of an existing environment to fork from when creating a new one. */\n\tsource?: string;\n}\n\n/** Persisted state for the Railway environment. */\ninterface RailwayEnvironmentOutputs extends RailwayEnvironmentInputs {\n\t/** Railway-assigned environment UUID. */\n\tenvironmentId: string;\n}\n\nconst ENVIRONMENT_CREATE_MUTATION = `\n mutation EnvironmentCreate($input: EnvironmentCreateInput!) {\n environmentCreate(input: $input) {\n id\n name\n }\n }\n`;\n\nconst PROJECT_ENVIRONMENTS_QUERY = `\n query($projectId: String!) {\n project(id: $projectId) {\n environments {\n edges {\n node {\n id\n name\n }\n }\n }\n }\n }\n`;\n\n/**\n * Queries a project's environments and resolves the ID for the given name.\n */\nasync function findEnvironmentId(\n\tclient: RailwayClient,\n\tprojectId: string,\n\tname: string,\n): Promise<string | undefined> {\n\tconst result = await client.query<{\n\t\tproject: {\n\t\t\tenvironments: {\n\t\t\t\tedges: Array<{ node: { id: string; name: string } }>;\n\t\t\t};\n\t\t};\n\t}>(PROJECT_ENVIRONMENTS_QUERY, { projectId });\n\n\tconst match = result.project.environments.edges.find(\n\t\t(edge) => edge.node.name === name,\n\t);\n\n\treturn match?.node.id;\n}\n\n/**\n * Dynamic provider that resolves or creates a Railway environment by name.\n *\n * @internal Exported only for unit testing; not part of the public API surface.\n */\nexport class RailwayEnvironmentResourceProvider\n\timplements pulumi.dynamic.ResourceProvider\n{\n\t/**\n\t * Adopts an existing Railway environment when found by name, or creates a new\n\t * one (optionally forked from a source environment) when not found.\n\t *\n\t * @param inputs Resolved provider inputs including token, projectId, name, and optional source.\n\t * @returns Pulumi dynamic create result with the environment UUID as the resource ID.\n\t * @throws {Error} When `source` is provided but cannot be resolved to an environment ID.\n\t */\n\tasync create(\n\t\tinputs: RailwayEnvironmentInputs,\n\t): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new RailwayClient(inputs.token);\n\n\t\tlet environmentId = await findEnvironmentId(\n\t\t\tclient,\n\t\t\tinputs.projectId,\n\t\t\tinputs.name,\n\t\t);\n\n\t\tif (environmentId) {\n\t\t\tpulumi.log.info(\n\t\t\t\t`Adopting existing Railway environment \"${inputs.name}\" (${environmentId})`,\n\t\t\t);\n\t\t} else {\n\t\t\tlet sourceEnvironmentId: string | undefined;\n\n\t\t\tif (inputs.source) {\n\t\t\t\tsourceEnvironmentId = await findEnvironmentId(\n\t\t\t\t\tclient,\n\t\t\t\t\tinputs.projectId,\n\t\t\t\t\tinputs.source,\n\t\t\t\t);\n\n\t\t\t\tif (!sourceEnvironmentId) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`Railway source environment \"${inputs.source}\" not found in project ${inputs.projectId}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst result = await client.query<{\n\t\t\t\tenvironmentCreate: { id: string; name: string };\n\t\t\t}>(ENVIRONMENT_CREATE_MUTATION, {\n\t\t\t\tinput: {\n\t\t\t\t\tprojectId: inputs.projectId,\n\t\t\t\t\tname: inputs.name,\n\t\t\t\t\t// skipInitialDeploys: hold deploys so a forked env doesn't run with inherited\n\t\t\t\t\t// source/production variables before our RailwayVariable resources overwrite them.\n\t\t\t\t\tskipInitialDeploys: true,\n\t\t\t\t\t...(sourceEnvironmentId ? { sourceEnvironmentId } : {}),\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tenvironmentId = result.environmentCreate.id;\n\n\t\t\tpulumi.log.info(\n\t\t\t\t`Created Railway environment \"${inputs.name}\" (${environmentId})`,\n\t\t\t);\n\t\t}\n\n\t\tconst outs: RailwayEnvironmentOutputs = { ...inputs, environmentId };\n\n\t\treturn { id: environmentId, outs };\n\t}\n\n\tasync read(\n\t\t_id: string,\n\t\tprops: RailwayEnvironmentOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new RailwayClient(props.token);\n\n\t\tconst environmentId = await findEnvironmentId(\n\t\t\tclient,\n\t\t\tprops.projectId,\n\t\t\tprops.name,\n\t\t);\n\n\t\tif (!environmentId) {\n\t\t\tthrow new Error(\n\t\t\t\t`Railway environment \"${props.name}\" not found during refresh`,\n\t\t\t);\n\t\t}\n\n\t\treturn { id: environmentId, props: { ...props, environmentId } };\n\t}\n\n\tasync update(\n\t\t_id: string,\n\t\t_olds: RailwayEnvironmentOutputs,\n\t\tnews: RailwayEnvironmentInputs,\n\t): Promise<pulumi.dynamic.UpdateResult> {\n\t\tconst client = new RailwayClient(news.token);\n\n\t\tconst environmentId = await findEnvironmentId(\n\t\t\tclient,\n\t\t\tnews.projectId,\n\t\t\tnews.name,\n\t\t);\n\n\t\tif (!environmentId) {\n\t\t\tthrow new Error(\n\t\t\t\t`Railway environment \"${news.name}\" not found in project ${news.projectId}`,\n\t\t\t);\n\t\t}\n\n\t\treturn { outs: { ...news, environmentId } };\n\t}\n\n\tasync delete(): Promise<void> {\n\t\tpulumi.log.warn(\n\t\t\t\"Railway environment deletion skipped — environments are not deleted by Pulumi\",\n\t\t);\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: RailwayEnvironmentOutputs,\n\t\tnews: RailwayEnvironmentInputs,\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.name !== news.name) {\n\t\t\treplaces.push(\"name\");\n\t\t}\n\n\t\treturn {\n\t\t\tchanges: replaces.length > 0,\n\t\t\treplaces,\n\t\t\tdeleteBeforeReplace: true,\n\t\t};\n\t}\n}\n\n/** Internal dynamic resource — not part of the public API. */\nclass RailwayEnvironmentResource extends pulumi.dynamic.Resource {\n\tpublic declare readonly environmentId: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\ttoken: pulumi.Input<string>;\n\t\t\tprojectId: pulumi.Input<string>;\n\t\t\tname: pulumi.Input<string>;\n\t\t\tsource?: pulumi.Input<string>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(\n\t\t\tnew RailwayEnvironmentResourceProvider(),\n\t\t\tname,\n\t\t\t{\n\t\t\t\t...args,\n\t\t\t\tenvironmentId: undefined,\n\t\t\t},\n\t\t\topts,\n\t\t);\n\t}\n}\n\n/** Options type for RailwayEnvironment — replaces Pulumi's native `provider` field. */\ntype RailwayEnvironmentOptions = Omit<\n\tpulumi.ComponentResourceOptions,\n\t\"provider\"\n> & {\n\t/** Railway authentication context. */\n\tprovider: RailwayProvider;\n\n\t/** Railway project context to resolve the environment from. */\n\tproject: RailwayProject;\n};\n\n/** Args for RailwayEnvironment. */\nexport interface RailwayEnvironmentArgs {\n\t/** Environment display name (e.g. `\"production\"`, `\"staging\"`). */\n\tname: pulumi.Input<string>;\n\n\t/**\n\t * Name of an existing environment to fork from when this environment is created.\n\t * Evaluated only at creation time — changing `source` after the environment exists\n\t * has no effect (an existing environment is never re-forked).\n\t */\n\tsource?: pulumi.Input<string>;\n}\n\n/**\n * Resolves or creates a Railway environment by name within a project.\n *\n * When the named environment already exists it is adopted (no mutation).\n * When it does not exist it is created — optionally forked from a source\n * environment so the new env inherits service instances and variables.\n *\n * @example\n * ```typescript\n * // Adopt or create \"production\" (no source)\n * const production = new RailwayEnvironment(\"production\", {\n * name: \"production\",\n * }, { provider, project });\n *\n * // Adopt or create \"staging\", forked from \"production\"\n * const staging = new RailwayEnvironment(\"staging\", {\n * name: \"staging\",\n * source: \"production\",\n * }, { provider, project });\n *\n * // Use environmentId downstream\n * const service = new RailwayService(\"api\", { name: \"api\" }, {\n * provider, project, environment: staging,\n * });\n * ```\n */\nexport class RailwayEnvironment extends pulumi.ComponentResource {\n\t/** Railway environment UUID. */\n\tpublic readonly id: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: RailwayEnvironmentArgs,\n\t\topts: RailwayEnvironmentOptions,\n\t) {\n\t\tconst { provider, project, ...pulumiOpts } = opts;\n\n\t\tsuper(\"infracraft:railway:Environment\", name, {}, pulumiOpts);\n\n\t\tconst resource = new RailwayEnvironmentResource(\n\t\t\t`${name}-resource`,\n\t\t\t{\n\t\t\t\ttoken: provider.token,\n\t\t\t\tprojectId: project.id,\n\t\t\t\tname: args.name,\n\t\t\t\tsource: args.source,\n\t\t\t},\n\t\t\t{ parent: this },\n\t\t);\n\n\t\tthis.id = resource.environmentId;\n\n\t\tthis.registerOutputs({ id: this.id });\n\t}\n}\n"],"mappings":";;;;;;;AA0BA,MAAM,8BAA8B;;;;;;;;AASpC,MAAM,6BAA6B;;;;;;;;;;;;;;;;;AAkBnC,eAAe,kBACd,QACA,WACA,MAC8B;CAa9B,QAJc,MARO,OAAO,MAMzB,4BAA4B,EAAE,UAAU,CAAC,GAEvB,QAAQ,aAAa,MAAM,MAC9C,SAAS,KAAK,KAAK,SAAS,IAGnB,GAAG,KAAK;AACpB;;;;;;AAOA,IAAa,qCAAb,MAEA;;;;;;;;;CASC,MAAM,OACL,QACuC;EACvC,MAAM,SAAS,IAAIA,qCAAc,OAAO,KAAK;EAE7C,IAAI,gBAAgB,MAAM,kBACzB,QACA,OAAO,WACP,OAAO,IACR;EAEA,IAAI,eACH,eAAO,IAAI,KACV,0CAA0C,OAAO,KAAK,KAAK,cAAc,EAC1E;OACM;GACN,IAAI;GAEJ,IAAI,OAAO,QAAQ;IAClB,sBAAsB,MAAM,kBAC3B,QACA,OAAO,WACP,OAAO,MACR;IAEA,IAAI,CAAC,qBACJ,MAAM,IAAI,MACT,+BAA+B,OAAO,OAAO,yBAAyB,OAAO,WAC9E;GAEF;GAeA,iBAAgB,MAbK,OAAO,MAEzB,6BAA6B,EAC/B,OAAO;IACN,WAAW,OAAO;IAClB,MAAM,OAAO;IAGb,oBAAoB;IACpB,GAAI,sBAAsB,EAAE,oBAAoB,IAAI,CAAC;GACtD,EACD,CAAC,GAEsB,kBAAkB;GAEzC,eAAO,IAAI,KACV,gCAAgC,OAAO,KAAK,KAAK,cAAc,EAChE;EACD;EAEA,MAAM,OAAkC;GAAE,GAAG;GAAQ;EAAc;EAEnE,OAAO;GAAE,IAAI;GAAe;EAAK;CAClC;CAEA,MAAM,KACL,KACA,OACqC;EAGrC,MAAM,gBAAgB,MAAM,kBAC3B,IAHkBA,qCAAc,MAAM,KAGjC,GACL,MAAM,WACN,MAAM,IACP;EAEA,IAAI,CAAC,eACJ,MAAM,IAAI,MACT,wBAAwB,MAAM,KAAK,2BACpC;EAGD,OAAO;GAAE,IAAI;GAAe,OAAO;IAAE,GAAG;IAAO;GAAc;EAAE;CAChE;CAEA,MAAM,OACL,KACA,OACA,MACuC;EAGvC,MAAM,gBAAgB,MAAM,kBAC3B,IAHkBA,qCAAc,KAAK,KAGhC,GACL,KAAK,WACL,KAAK,IACN;EAEA,IAAI,CAAC,eACJ,MAAM,IAAI,MACT,wBAAwB,KAAK,KAAK,yBAAyB,KAAK,WACjE;EAGD,OAAO,EAAE,MAAM;GAAE,GAAG;GAAM;EAAc,EAAE;CAC3C;CAEA,MAAM,SAAwB;EAC7B,eAAO,IAAI,KACV,+EACD;CACD;CAEA,MAAM,KACL,KACA,MACA,MACqC;EACrC,MAAM,WAAqB,CAAC;EAE5B,IAAI,KAAK,cAAc,KAAK,WAC3B,SAAS,KAAK,WAAW;EAG1B,IAAI,KAAK,SAAS,KAAK,MACtB,SAAS,KAAK,MAAM;EAGrB,OAAO;GACN,SAAS,SAAS,SAAS;GAC3B;GACA,qBAAqB;EACtB;CACD;AACD;;AAGA,IAAM,6BAAN,cAAyCC,eAAO,QAAQ,SAAS;CAGhE,YACC,MACA,MAMA,MACC;EACD,MACC,IAAI,mCAAmC,GACvC,MACA;GACC,GAAG;GACH,eAAe;EAChB,GACA,IACD;CACD;AACD;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqDA,IAAa,qBAAb,cAAwCA,eAAO,kBAAkB;CAIhE,YACC,MACA,MACA,MACC;EACD,MAAM,EAAE,UAAU,SAAS,GAAG,eAAe;EAE7C,MAAM,kCAAkC,MAAM,CAAC,GAAG,UAAU;EAE5D,MAAM,WAAW,IAAI,2BACpB,GAAG,KAAK,YACR;GACC,OAAO,SAAS;GAChB,WAAW,QAAQ;GACnB,MAAM,KAAK;GACX,QAAQ,KAAK;EACd,GACA,EAAE,QAAQ,KAAK,CAChB;EAEA,KAAK,KAAK,SAAS;EAEnB,KAAK,gBAAgB,EAAE,IAAI,KAAK,GAAG,CAAC;CACrC;AACD"}
|
|
@@ -4,6 +4,42 @@ import { RailwayProject } from "./project.cjs";
|
|
|
4
4
|
import * as pulumi from "@pulumi/pulumi";
|
|
5
5
|
|
|
6
6
|
//#region src/railway/environment.d.ts
|
|
7
|
+
/** Resolved inputs for the Railway environment dynamic provider. */
|
|
8
|
+
interface RailwayEnvironmentInputs {
|
|
9
|
+
/** Railway API bearer token. */
|
|
10
|
+
token: string;
|
|
11
|
+
/** Railway project UUID. */
|
|
12
|
+
projectId: string;
|
|
13
|
+
/** Environment display name (e.g. `"production"`, `"staging"`). */
|
|
14
|
+
name: string;
|
|
15
|
+
/** Name of an existing environment to fork from when creating a new one. */
|
|
16
|
+
source?: string;
|
|
17
|
+
}
|
|
18
|
+
/** Persisted state for the Railway environment. */
|
|
19
|
+
interface RailwayEnvironmentOutputs extends RailwayEnvironmentInputs {
|
|
20
|
+
/** Railway-assigned environment UUID. */
|
|
21
|
+
environmentId: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Dynamic provider that resolves or creates a Railway environment by name.
|
|
25
|
+
*
|
|
26
|
+
* @internal Exported only for unit testing; not part of the public API surface.
|
|
27
|
+
*/
|
|
28
|
+
declare class RailwayEnvironmentResourceProvider implements pulumi.dynamic.ResourceProvider {
|
|
29
|
+
/**
|
|
30
|
+
* Adopts an existing Railway environment when found by name, or creates a new
|
|
31
|
+
* one (optionally forked from a source environment) when not found.
|
|
32
|
+
*
|
|
33
|
+
* @param inputs Resolved provider inputs including token, projectId, name, and optional source.
|
|
34
|
+
* @returns Pulumi dynamic create result with the environment UUID as the resource ID.
|
|
35
|
+
* @throws {Error} When `source` is provided but cannot be resolved to an environment ID.
|
|
36
|
+
*/
|
|
37
|
+
create(inputs: RailwayEnvironmentInputs): Promise<pulumi.dynamic.CreateResult>;
|
|
38
|
+
read(_id: string, props: RailwayEnvironmentOutputs): Promise<pulumi.dynamic.ReadResult>;
|
|
39
|
+
update(_id: string, _olds: RailwayEnvironmentOutputs, news: RailwayEnvironmentInputs): Promise<pulumi.dynamic.UpdateResult>;
|
|
40
|
+
delete(): Promise<void>;
|
|
41
|
+
diff(_id: string, olds: RailwayEnvironmentOutputs, news: RailwayEnvironmentInputs): Promise<pulumi.dynamic.DiffResult>;
|
|
42
|
+
}
|
|
7
43
|
/** Options type for RailwayEnvironment — replaces Pulumi's native `provider` field. */
|
|
8
44
|
type RailwayEnvironmentOptions = Omit<pulumi.ComponentResourceOptions, "provider"> & {
|
|
9
45
|
/** Railway authentication context. */provider: RailwayProvider; /** Railway project context to resolve the environment from. */
|
|
@@ -13,19 +49,36 @@ type RailwayEnvironmentOptions = Omit<pulumi.ComponentResourceOptions, "provider
|
|
|
13
49
|
interface RailwayEnvironmentArgs {
|
|
14
50
|
/** Environment display name (e.g. `"production"`, `"staging"`). */
|
|
15
51
|
name: pulumi.Input<string>;
|
|
52
|
+
/**
|
|
53
|
+
* Name of an existing environment to fork from when this environment is created.
|
|
54
|
+
* Evaluated only at creation time — changing `source` after the environment exists
|
|
55
|
+
* has no effect (an existing environment is never re-forked).
|
|
56
|
+
*/
|
|
57
|
+
source?: pulumi.Input<string>;
|
|
16
58
|
}
|
|
17
59
|
/**
|
|
18
|
-
* Resolves a Railway environment
|
|
60
|
+
* Resolves or creates a Railway environment by name within a project.
|
|
61
|
+
*
|
|
62
|
+
* When the named environment already exists it is adopted (no mutation).
|
|
63
|
+
* When it does not exist it is created — optionally forked from a source
|
|
64
|
+
* environment so the new env inherits service instances and variables.
|
|
19
65
|
*
|
|
20
66
|
* @example
|
|
21
67
|
* ```typescript
|
|
22
|
-
*
|
|
68
|
+
* // Adopt or create "production" (no source)
|
|
69
|
+
* const production = new RailwayEnvironment("production", {
|
|
23
70
|
* name: "production",
|
|
24
71
|
* }, { provider, project });
|
|
25
72
|
*
|
|
73
|
+
* // Adopt or create "staging", forked from "production"
|
|
74
|
+
* const staging = new RailwayEnvironment("staging", {
|
|
75
|
+
* name: "staging",
|
|
76
|
+
* source: "production",
|
|
77
|
+
* }, { provider, project });
|
|
78
|
+
*
|
|
26
79
|
* // Use environmentId downstream
|
|
27
80
|
* const service = new RailwayService("api", { name: "api" }, {
|
|
28
|
-
* provider, project, environment,
|
|
81
|
+
* provider, project, environment: staging,
|
|
29
82
|
* });
|
|
30
83
|
* ```
|
|
31
84
|
*/
|
|
@@ -35,5 +88,5 @@ declare class RailwayEnvironment extends pulumi.ComponentResource {
|
|
|
35
88
|
constructor(name: string, args: RailwayEnvironmentArgs, opts: RailwayEnvironmentOptions);
|
|
36
89
|
}
|
|
37
90
|
//#endregion
|
|
38
|
-
export { RailwayEnvironment, RailwayEnvironmentArgs };
|
|
91
|
+
export { RailwayEnvironment, RailwayEnvironmentArgs, RailwayEnvironmentResourceProvider };
|
|
39
92
|
//# sourceMappingURL=environment.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"environment.d.cts","names":[],"sources":["../../src/railway/environment.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"environment.d.cts","names":[],"sources":["../../src/railway/environment.ts"],"mappings":";;;;;;;UAMU,wBAAA;;EAET,KAAA;EAFiC;EAKjC,SAAA;EALiC;EAQjC,IAAA;EAHA;EAMA,MAAA;AAAA;;UAIS,yBAAA,SAAkC,wBAAwB;EAA1D;EAET,aAAa;AAAA;;AAAA;AAuDd;;;cAAa,kCAAA,YACD,MAAA,CAAO,OAAA,CAAQ,gBAAA;EAYf;;;;;;;;EAFL,MAAA,CACL,MAAA,EAAQ,wBAAA,GACN,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,YAAA;EAuDpB,IAAA,CACL,GAAA,UACA,KAAA,EAAO,yBAAA,GACL,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;EAkBpB,MAAA,CACL,GAAA,UACA,KAAA,EAAO,yBAAA,EACP,IAAA,EAAM,wBAAA,GACJ,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,YAAA;EAkBpB,MAAA,CAAA,GAAU,OAAA;EAMV,IAAA,CACL,GAAA,UACA,IAAA,EAAM,yBAAA,EACN,IAAA,EAAM,wBAAA,GACJ,OAAA,CAAQ,MAAA,CAAO,OAAA,CAAQ,UAAA;AAAA;;KA8CtB,yBAAA,GAA4B,IAAA,CAChC,MAAA,CAAO,wBAAA;EAvKmC,sCA2K1C,QAAA,EAAU,eAAA,EA3KQ;EA8KlB,OAAA,EAAS,cAAA;AAAA;;UAIO,sBAAA;EAtKb;EAwKH,IAAA,EAAM,MAAA,CAAO,KAAA;EAxKK;;;;;EA+KlB,MAAA,GAAS,MAAA,CAAO,KAAK;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;cA6BT,kBAAA,SAA2B,MAAA,CAAO,iBAAA;EAlD1C;EAAA,SAoDY,EAAA,EAAI,MAAA,CAAO,MAAA;cAG1B,IAAA,UACA,IAAA,EAAM,sBAAA,EACN,IAAA,EAAM,yBAAA;AAAA"}
|