@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,8 @@
|
|
|
1
|
+
import { RailwayClient } from "./client.mjs";
|
|
2
|
+
import { RailwayDeploy, RailwayDeployConfig } from "./deploy.mjs";
|
|
3
|
+
import { RailwayDomain, RailwayDomainInputs } from "./domain.mjs";
|
|
4
|
+
import { RailwayProject, RailwayProjectInputs } from "./project.mjs";
|
|
5
|
+
import { RailwayService, RailwayServiceInputs } from "./service.mjs";
|
|
6
|
+
import { RailwayVariable, RailwayVariableInputs } from "./variable.mjs";
|
|
7
|
+
import { RailwayVolume, RailwayVolumeInputs } from "./volume.mjs";
|
|
8
|
+
export { RailwayClient, RailwayDeploy, type RailwayDeployConfig, RailwayDomain, type RailwayDomainInputs, RailwayProject, type RailwayProjectInputs, RailwayService, type RailwayServiceInputs, RailwayVariable, type RailwayVariableInputs, RailwayVolume, type RailwayVolumeInputs };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { RailwayClient } from "./client.mjs";
|
|
2
|
+
import { RailwayDeploy } from "./deploy.mjs";
|
|
3
|
+
import { RailwayDomain } from "./domain.mjs";
|
|
4
|
+
import { RailwayProject } from "./project.mjs";
|
|
5
|
+
import { RailwayService } from "./service.mjs";
|
|
6
|
+
import { RailwayVariable } from "./variable.mjs";
|
|
7
|
+
import { RailwayVolume } from "./volume.mjs";
|
|
8
|
+
|
|
9
|
+
export { RailwayClient, RailwayDeploy, RailwayDomain, RailwayProject, RailwayService, RailwayVariable, RailwayVolume };
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_chunk = require('../chunk-BVYJZCqc.cjs');
|
|
3
|
+
const require_railway_client = require('./client.cjs');
|
|
4
|
+
let _pulumi_pulumi = require("@pulumi/pulumi");
|
|
5
|
+
_pulumi_pulumi = require_chunk.__toESM(_pulumi_pulumi, 1);
|
|
6
|
+
|
|
7
|
+
//#region src/railway/project.ts
|
|
8
|
+
const WORKSPACE_QUERY = `
|
|
9
|
+
query {
|
|
10
|
+
me {
|
|
11
|
+
workspaces {
|
|
12
|
+
id
|
|
13
|
+
name
|
|
14
|
+
projects {
|
|
15
|
+
edges {
|
|
16
|
+
node {
|
|
17
|
+
id
|
|
18
|
+
name
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
`;
|
|
26
|
+
const PROJECT_CREATE = `
|
|
27
|
+
mutation($input: ProjectCreateInput!) {
|
|
28
|
+
projectCreate(input: $input) {
|
|
29
|
+
id
|
|
30
|
+
name
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
`;
|
|
34
|
+
const PROJECT_UPDATE = `
|
|
35
|
+
mutation($id: String!, $input: ProjectUpdateInput!) {
|
|
36
|
+
projectUpdate(id: $id, input: $input) {
|
|
37
|
+
id
|
|
38
|
+
name
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
`;
|
|
42
|
+
const PROJECT_ENVIRONMENTS_QUERY = `
|
|
43
|
+
query($projectId: String!) {
|
|
44
|
+
project(id: $projectId) {
|
|
45
|
+
environments {
|
|
46
|
+
edges {
|
|
47
|
+
node {
|
|
48
|
+
id
|
|
49
|
+
name
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
`;
|
|
56
|
+
const PROJECT_TOKENS_QUERY = `
|
|
57
|
+
query($projectId: String!) {
|
|
58
|
+
projectTokens(projectId: $projectId) {
|
|
59
|
+
edges { node { id name } }
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
`;
|
|
63
|
+
const PROJECT_TOKEN_CREATE = `
|
|
64
|
+
mutation($input: ProjectTokenCreateInput!) {
|
|
65
|
+
projectTokenCreate(input: $input)
|
|
66
|
+
}
|
|
67
|
+
`;
|
|
68
|
+
const PROJECT_TOKEN_DELETE = `
|
|
69
|
+
mutation($id: String!) { projectTokenDelete(id: $id) }
|
|
70
|
+
`;
|
|
71
|
+
const PERMANENT_TOKEN_NAME = "pulumi";
|
|
72
|
+
/**
|
|
73
|
+
* Fetches all environments for a project and returns a name → UUID map.
|
|
74
|
+
*/
|
|
75
|
+
async function fetchProjectEnvironments(client, projectId) {
|
|
76
|
+
const result = await client.query(PROJECT_ENVIRONMENTS_QUERY, { projectId });
|
|
77
|
+
const environments = {};
|
|
78
|
+
for (const edge of result.project.environments.edges) environments[edge.node.name] = edge.node.id;
|
|
79
|
+
return environments;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Gets or creates a permanent project-scoped token named "pulumi".
|
|
83
|
+
*
|
|
84
|
+
* Deletes any stale tokens with the same name before creating a new one,
|
|
85
|
+
* ensuring a single canonical token exists. Does NOT write to Pulumi config —
|
|
86
|
+
* the token is returned as a secret output for the consumer to manage.
|
|
87
|
+
*/
|
|
88
|
+
async function getOrCreateProjectToken(client, projectId, environmentId) {
|
|
89
|
+
const stale = (await client.query(PROJECT_TOKENS_QUERY, { projectId })).projectTokens.edges.filter((edge) => edge.node.name === PERMANENT_TOKEN_NAME);
|
|
90
|
+
for (const entry of stale) await client.query(PROJECT_TOKEN_DELETE, { id: entry.node.id });
|
|
91
|
+
return (await client.query(PROJECT_TOKEN_CREATE, { input: {
|
|
92
|
+
projectId,
|
|
93
|
+
name: PERMANENT_TOKEN_NAME,
|
|
94
|
+
...environmentId ? { environmentId } : {}
|
|
95
|
+
} })).projectTokenCreate;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Dynamic provider that adopts an existing Railway project by name, or creates one.
|
|
99
|
+
*
|
|
100
|
+
* On create:
|
|
101
|
+
* 1. Queries workspaces to find the project by name.
|
|
102
|
+
* 2. If found → adopts. If not → creates via `projectCreate`.
|
|
103
|
+
* 3. Fetches all environments and resolves the production environment ID.
|
|
104
|
+
* 4. Creates/reuses a project-scoped token named "pulumi".
|
|
105
|
+
*
|
|
106
|
+
* Deletion is a no-op (with a warning) to prevent accidental project removal.
|
|
107
|
+
* Name changes trigger replacement.
|
|
108
|
+
*/
|
|
109
|
+
var RailwayProjectProvider = class {
|
|
110
|
+
async create(inputs) {
|
|
111
|
+
const client = new require_railway_client.RailwayClient(inputs.token);
|
|
112
|
+
const workspaces = (await client.query(WORKSPACE_QUERY)).me.workspaces;
|
|
113
|
+
if (workspaces.length === 0) throw new Error("No Railway workspace found — cannot create project");
|
|
114
|
+
let projectId;
|
|
115
|
+
for (const workspace of workspaces) {
|
|
116
|
+
const match = workspace.projects.edges.find((edge) => edge.node.name === inputs.name);
|
|
117
|
+
if (match) {
|
|
118
|
+
projectId = match.node.id;
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
if (projectId) {
|
|
123
|
+
_pulumi_pulumi.log.info(`Adopted existing Railway project "${inputs.name}" (${projectId})`);
|
|
124
|
+
if (inputs.description) await client.query(PROJECT_UPDATE, {
|
|
125
|
+
id: projectId,
|
|
126
|
+
input: { description: inputs.description }
|
|
127
|
+
});
|
|
128
|
+
} else {
|
|
129
|
+
const workspace = workspaces[0];
|
|
130
|
+
projectId = (await client.query(PROJECT_CREATE, { input: {
|
|
131
|
+
name: inputs.name,
|
|
132
|
+
description: inputs.description,
|
|
133
|
+
workspaceId: workspace.id
|
|
134
|
+
} })).projectCreate.id;
|
|
135
|
+
_pulumi_pulumi.log.info(`Created Railway project "${inputs.name}" (${projectId})`);
|
|
136
|
+
}
|
|
137
|
+
if (!projectId) throw new Error(`Failed to find or create Railway project "${inputs.name}"`);
|
|
138
|
+
const productionEnvironmentId = (await fetchProjectEnvironments(client, projectId)).production ?? "";
|
|
139
|
+
const projectToken = await getOrCreateProjectToken(client, projectId, productionEnvironmentId || void 0);
|
|
140
|
+
const outs = {
|
|
141
|
+
...inputs,
|
|
142
|
+
projectId,
|
|
143
|
+
productionEnvironmentId,
|
|
144
|
+
projectToken
|
|
145
|
+
};
|
|
146
|
+
return {
|
|
147
|
+
id: projectId,
|
|
148
|
+
outs
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
async update(id, _olds, news) {
|
|
152
|
+
const client = new require_railway_client.RailwayClient(news.token);
|
|
153
|
+
await client.query(PROJECT_UPDATE, {
|
|
154
|
+
id,
|
|
155
|
+
input: {
|
|
156
|
+
name: news.name,
|
|
157
|
+
description: news.description
|
|
158
|
+
}
|
|
159
|
+
});
|
|
160
|
+
const productionEnvironmentId = (await fetchProjectEnvironments(client, id)).production ?? "";
|
|
161
|
+
const projectToken = await getOrCreateProjectToken(client, id, productionEnvironmentId || void 0);
|
|
162
|
+
return { outs: {
|
|
163
|
+
...news,
|
|
164
|
+
projectId: id,
|
|
165
|
+
productionEnvironmentId,
|
|
166
|
+
projectToken
|
|
167
|
+
} };
|
|
168
|
+
}
|
|
169
|
+
async read(id, props) {
|
|
170
|
+
const productionEnvironmentId = (await fetchProjectEnvironments(new require_railway_client.RailwayClient(props.token), id)).production ?? props.productionEnvironmentId;
|
|
171
|
+
return {
|
|
172
|
+
id,
|
|
173
|
+
props: {
|
|
174
|
+
...props,
|
|
175
|
+
projectId: id,
|
|
176
|
+
productionEnvironmentId
|
|
177
|
+
}
|
|
178
|
+
};
|
|
179
|
+
}
|
|
180
|
+
async delete() {
|
|
181
|
+
_pulumi_pulumi.log.warn("Railway project deletion skipped — projects are not deleted by Pulumi");
|
|
182
|
+
}
|
|
183
|
+
async diff(_id, olds, news) {
|
|
184
|
+
const replaces = [];
|
|
185
|
+
const changes = [];
|
|
186
|
+
if (olds.name !== news.name) replaces.push("name");
|
|
187
|
+
if (olds.description !== news.description) changes.push("description");
|
|
188
|
+
return {
|
|
189
|
+
changes: replaces.length > 0 || changes.length > 0,
|
|
190
|
+
replaces,
|
|
191
|
+
deleteBeforeReplace: true
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
};
|
|
195
|
+
/**
|
|
196
|
+
* Manages a Railway project with adopt-or-create semantics.
|
|
197
|
+
*
|
|
198
|
+
* Discovers or creates the project, resolves the production environment ID,
|
|
199
|
+
* and provisions a project-scoped token named "pulumi" for CLI deploys.
|
|
200
|
+
* The token is exposed as a secret output — the consumer decides how to store it.
|
|
201
|
+
*
|
|
202
|
+
* @example
|
|
203
|
+
* ```typescript
|
|
204
|
+
* const project = new RailwayProject("railway-project", {
|
|
205
|
+
* token: railwayConfig.token,
|
|
206
|
+
* name: "my-app",
|
|
207
|
+
* description: "Railway services for my-app",
|
|
208
|
+
* });
|
|
209
|
+
*
|
|
210
|
+
* // Use outputs downstream
|
|
211
|
+
* const serviceVar = new RailwayVariable("...", {
|
|
212
|
+
* projectId: project.projectId,
|
|
213
|
+
* environmentId: project.productionEnvironmentId,
|
|
214
|
+
* ...
|
|
215
|
+
* });
|
|
216
|
+
* ```
|
|
217
|
+
*/
|
|
218
|
+
var RailwayProject = class extends _pulumi_pulumi.dynamic.Resource {
|
|
219
|
+
constructor(name, args, opts) {
|
|
220
|
+
super(new RailwayProjectProvider(), name, {
|
|
221
|
+
...args,
|
|
222
|
+
projectId: void 0,
|
|
223
|
+
productionEnvironmentId: void 0,
|
|
224
|
+
projectToken: _pulumi_pulumi.secret(void 0)
|
|
225
|
+
}, opts);
|
|
226
|
+
}
|
|
227
|
+
};
|
|
228
|
+
|
|
229
|
+
//#endregion
|
|
230
|
+
exports.RailwayProject = RailwayProject;
|
|
231
|
+
//# sourceMappingURL=project.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.cjs","names":["RailwayClient","pulumi"],"sources":["../../src/railway/project.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\nimport { RailwayClient } from \"./client.js\";\n\n/** Resolved inputs for the Railway project dynamic provider. */\nexport interface RailwayProjectInputs {\n\t/** Railway API bearer token. */\n\ttoken: string;\n\n\t/** Desired display name for the project in Railway's dashboard. */\n\tname: string;\n\n\t/** Optional description shown in Railway's dashboard. */\n\tdescription?: string;\n}\n\n/** Persisted state for the Railway project. */\ninterface RailwayProjectOutputs extends RailwayProjectInputs {\n\t/** Railway-assigned project UUID. */\n\tprojectId: string;\n\n\t/** Railway-assigned production environment UUID. */\n\tproductionEnvironmentId: string;\n\n\t/** Railway project-scoped token (auto-provisioned, exposed as secret output). */\n\tprojectToken: string;\n}\n\nconst WORKSPACE_QUERY = `\n query {\n me {\n workspaces {\n id\n name\n projects {\n edges {\n node {\n id\n name\n }\n }\n }\n }\n }\n }\n`;\n\nconst PROJECT_CREATE = `\n mutation($input: ProjectCreateInput!) {\n projectCreate(input: $input) {\n id\n name\n }\n }\n`;\n\nconst PROJECT_UPDATE = `\n mutation($id: String!, $input: ProjectUpdateInput!) {\n projectUpdate(id: $id, 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\nconst PROJECT_TOKENS_QUERY = `\n query($projectId: String!) {\n projectTokens(projectId: $projectId) {\n edges { node { id name } }\n }\n }\n`;\n\nconst PROJECT_TOKEN_CREATE = `\n mutation($input: ProjectTokenCreateInput!) {\n projectTokenCreate(input: $input)\n }\n`;\n\nconst PROJECT_TOKEN_DELETE = `\n mutation($id: String!) { projectTokenDelete(id: $id) }\n`;\n\nconst PERMANENT_TOKEN_NAME = \"pulumi\";\n\n/**\n * Fetches all environments for a project and returns a name → UUID map.\n */\nasync function fetchProjectEnvironments(\n\tclient: RailwayClient,\n\tprojectId: string,\n): Promise<Record<string, string>> {\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 environments: Record<string, string> = {};\n\n\tfor (const edge of result.project.environments.edges) {\n\t\tenvironments[edge.node.name] = edge.node.id;\n\t}\n\n\treturn environments;\n}\n\n/**\n * Gets or creates a permanent project-scoped token named \"pulumi\".\n *\n * Deletes any stale tokens with the same name before creating a new one,\n * ensuring a single canonical token exists. Does NOT write to Pulumi config —\n * the token is returned as a secret output for the consumer to manage.\n */\nasync function getOrCreateProjectToken(\n\tclient: RailwayClient,\n\tprojectId: string,\n\tenvironmentId?: string,\n): Promise<string> {\n\tconst tokensResult = await client.query<{\n\t\tprojectTokens: {\n\t\t\tedges: Array<{ node: { id: string; name: string } }>;\n\t\t};\n\t}>(PROJECT_TOKENS_QUERY, { projectId });\n\n\tconst stale = tokensResult.projectTokens.edges.filter(\n\t\t(edge) => edge.node.name === PERMANENT_TOKEN_NAME,\n\t);\n\n\tfor (const entry of stale) {\n\t\tawait client.query(PROJECT_TOKEN_DELETE, { id: entry.node.id });\n\t}\n\n\tconst result = await client.query<{ projectTokenCreate: string }>(\n\t\tPROJECT_TOKEN_CREATE,\n\t\t{\n\t\t\tinput: {\n\t\t\t\tprojectId,\n\t\t\t\tname: PERMANENT_TOKEN_NAME,\n\t\t\t\t...(environmentId ? { environmentId } : {}),\n\t\t\t},\n\t\t},\n\t);\n\n\treturn result.projectTokenCreate;\n}\n\n/**\n * Dynamic provider that adopts an existing Railway project by name, or creates one.\n *\n * On create:\n * 1. Queries workspaces to find the project by name.\n * 2. If found → adopts. If not → creates via `projectCreate`.\n * 3. Fetches all environments and resolves the production environment ID.\n * 4. Creates/reuses a project-scoped token named \"pulumi\".\n *\n * Deletion is a no-op (with a warning) to prevent accidental project removal.\n * Name changes trigger replacement.\n */\nclass RailwayProjectProvider implements pulumi.dynamic.ResourceProvider {\n\tasync create(\n\t\tinputs: RailwayProjectInputs,\n\t): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new RailwayClient(inputs.token);\n\n\t\tconst workspaceResult = await client.query<{\n\t\t\tme: {\n\t\t\t\tworkspaces: Array<{\n\t\t\t\t\tid: string;\n\t\t\t\t\tname: string;\n\t\t\t\t\tprojects: {\n\t\t\t\t\t\tedges: Array<{ node: { id: string; name: string } }>;\n\t\t\t\t\t};\n\t\t\t\t}>;\n\t\t\t};\n\t\t}>(WORKSPACE_QUERY);\n\n\t\tconst workspaces = workspaceResult.me.workspaces;\n\n\t\tif (workspaces.length === 0) {\n\t\t\tthrow new Error(\"No Railway workspace found — cannot create project\");\n\t\t}\n\n\t\tlet projectId: string | undefined;\n\n\t\tfor (const workspace of workspaces) {\n\t\t\tconst match = workspace.projects.edges.find(\n\t\t\t\t(edge) => edge.node.name === inputs.name,\n\t\t\t);\n\n\t\t\tif (match) {\n\t\t\t\tprojectId = match.node.id;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (projectId) {\n\t\t\tpulumi.log.info(\n\t\t\t\t`Adopted existing Railway project \"${inputs.name}\" (${projectId})`,\n\t\t\t);\n\n\t\t\tif (inputs.description) {\n\t\t\t\tawait client.query(PROJECT_UPDATE, {\n\t\t\t\t\tid: projectId,\n\t\t\t\t\tinput: { description: inputs.description },\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tconst workspace = workspaces[0];\n\n\t\t\tconst created = await client.query<{\n\t\t\t\tprojectCreate: { id: string; name: string };\n\t\t\t}>(PROJECT_CREATE, {\n\t\t\t\tinput: {\n\t\t\t\t\tname: inputs.name,\n\t\t\t\t\tdescription: inputs.description,\n\t\t\t\t\tworkspaceId: workspace.id,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tprojectId = created.projectCreate.id;\n\n\t\t\tpulumi.log.info(\n\t\t\t\t`Created Railway project \"${inputs.name}\" (${projectId})`,\n\t\t\t);\n\t\t}\n\n\t\tif (!projectId) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to find or create Railway project \"${inputs.name}\"`,\n\t\t\t);\n\t\t}\n\n\t\tconst environments = await fetchProjectEnvironments(client, projectId);\n\n\t\tconst productionEnvironmentId = environments.production ?? \"\";\n\n\t\tconst projectToken = await getOrCreateProjectToken(\n\t\t\tclient,\n\t\t\tprojectId,\n\t\t\tproductionEnvironmentId || undefined,\n\t\t);\n\n\t\tconst outs: RailwayProjectOutputs = {\n\t\t\t...inputs,\n\t\t\tprojectId,\n\t\t\tproductionEnvironmentId,\n\t\t\tprojectToken,\n\t\t};\n\n\t\treturn { id: projectId, outs };\n\t}\n\n\tasync update(\n\t\tid: string,\n\t\t_olds: RailwayProjectOutputs,\n\t\tnews: RailwayProjectInputs,\n\t): Promise<pulumi.dynamic.UpdateResult> {\n\t\tconst client = new RailwayClient(news.token);\n\n\t\tawait client.query(PROJECT_UPDATE, {\n\t\t\tid,\n\t\t\tinput: { name: news.name, description: news.description },\n\t\t});\n\n\t\tconst environments = await fetchProjectEnvironments(client, id);\n\n\t\tconst productionEnvironmentId = environments.production ?? \"\";\n\n\t\tconst projectToken = await getOrCreateProjectToken(\n\t\t\tclient,\n\t\t\tid,\n\t\t\tproductionEnvironmentId || undefined,\n\t\t);\n\n\t\tconst outs: RailwayProjectOutputs = {\n\t\t\t...news,\n\t\t\tprojectId: id,\n\t\t\tproductionEnvironmentId,\n\t\t\tprojectToken,\n\t\t};\n\n\t\treturn { outs };\n\t}\n\n\tasync read(\n\t\tid: string,\n\t\tprops: RailwayProjectOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new RailwayClient(props.token);\n\n\t\tconst environments = await fetchProjectEnvironments(client, id);\n\n\t\tconst productionEnvironmentId =\n\t\t\tenvironments.production ?? props.productionEnvironmentId;\n\n\t\treturn {\n\t\t\tid,\n\t\t\tprops: { ...props, projectId: id, productionEnvironmentId },\n\t\t};\n\t}\n\n\tasync delete(): Promise<void> {\n\t\tpulumi.log.warn(\n\t\t\t\"Railway project deletion skipped — projects are not deleted by Pulumi\",\n\t\t);\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: RailwayProjectOutputs,\n\t\tnews: RailwayProjectInputs,\n\t): Promise<pulumi.dynamic.DiffResult> {\n\t\tconst replaces: string[] = [];\n\t\tconst changes: string[] = [];\n\n\t\tif (olds.name !== news.name) {\n\t\t\treplaces.push(\"name\");\n\t\t}\n\n\t\tif (olds.description !== news.description) {\n\t\t\tchanges.push(\"description\");\n\t\t}\n\n\t\treturn {\n\t\t\tchanges: replaces.length > 0 || changes.length > 0,\n\t\t\treplaces,\n\t\t\tdeleteBeforeReplace: true,\n\t\t};\n\t}\n}\n\n/**\n * Manages a Railway project with adopt-or-create semantics.\n *\n * Discovers or creates the project, resolves the production environment ID,\n * and provisions a project-scoped token named \"pulumi\" for CLI deploys.\n * The token is exposed as a secret output — the consumer decides how to store it.\n *\n * @example\n * ```typescript\n * const project = new RailwayProject(\"railway-project\", {\n * token: railwayConfig.token,\n * name: \"my-app\",\n * description: \"Railway services for my-app\",\n * });\n *\n * // Use outputs downstream\n * const serviceVar = new RailwayVariable(\"...\", {\n * projectId: project.projectId,\n * environmentId: project.productionEnvironmentId,\n * ...\n * });\n * ```\n */\nexport class RailwayProject extends pulumi.dynamic.Resource {\n\t/** Railway project UUID. */\n\tpublic declare readonly projectId: pulumi.Output<string>;\n\n\t/** Railway production environment UUID. */\n\tpublic declare readonly productionEnvironmentId: pulumi.Output<string>;\n\n\t/** Railway project-scoped token (secret). */\n\tpublic declare readonly projectToken: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\t/** Railway API bearer token. */\n\t\t\ttoken: pulumi.Input<string>;\n\n\t\t\t/** Project display name to find and adopt or create. */\n\t\t\tname: pulumi.Input<string>;\n\n\t\t\t/** Optional description shown in Railway's dashboard. */\n\t\t\tdescription?: pulumi.Input<string>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(\n\t\t\tnew RailwayProjectProvider(),\n\t\t\tname,\n\t\t\t{\n\t\t\t\t...args,\n\t\t\t\tprojectId: undefined,\n\t\t\t\tproductionEnvironmentId: undefined,\n\t\t\t\tprojectToken: pulumi.secret(undefined as unknown as string),\n\t\t\t},\n\t\t\topts,\n\t\t);\n\t}\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { t as __name } from "../chunk-OPjESj5l.cjs";
|
|
2
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
3
|
+
|
|
4
|
+
//#region src/railway/project.d.ts
|
|
5
|
+
/** Resolved inputs for the Railway project dynamic provider. */
|
|
6
|
+
interface RailwayProjectInputs {
|
|
7
|
+
/** Railway API bearer token. */
|
|
8
|
+
token: string;
|
|
9
|
+
/** Desired display name for the project in Railway's dashboard. */
|
|
10
|
+
name: string;
|
|
11
|
+
/** Optional description shown in Railway's dashboard. */
|
|
12
|
+
description?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Manages a Railway project with adopt-or-create semantics.
|
|
16
|
+
*
|
|
17
|
+
* Discovers or creates the project, resolves the production environment ID,
|
|
18
|
+
* and provisions a project-scoped token named "pulumi" for CLI deploys.
|
|
19
|
+
* The token is exposed as a secret output — the consumer decides how to store it.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const project = new RailwayProject("railway-project", {
|
|
24
|
+
* token: railwayConfig.token,
|
|
25
|
+
* name: "my-app",
|
|
26
|
+
* description: "Railway services for my-app",
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* // Use outputs downstream
|
|
30
|
+
* const serviceVar = new RailwayVariable("...", {
|
|
31
|
+
* projectId: project.projectId,
|
|
32
|
+
* environmentId: project.productionEnvironmentId,
|
|
33
|
+
* ...
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
declare class RailwayProject extends pulumi.dynamic.Resource {
|
|
38
|
+
/** Railway project UUID. */
|
|
39
|
+
readonly projectId: pulumi.Output<string>;
|
|
40
|
+
/** Railway production environment UUID. */
|
|
41
|
+
readonly productionEnvironmentId: pulumi.Output<string>;
|
|
42
|
+
/** Railway project-scoped token (secret). */
|
|
43
|
+
readonly projectToken: pulumi.Output<string>;
|
|
44
|
+
constructor(name: string, args: {
|
|
45
|
+
/** Railway API bearer token. */token: pulumi.Input<string>; /** Project display name to find and adopt or create. */
|
|
46
|
+
name: pulumi.Input<string>; /** Optional description shown in Railway's dashboard. */
|
|
47
|
+
description?: pulumi.Input<string>;
|
|
48
|
+
}, opts?: pulumi.CustomResourceOptions);
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
export { RailwayProject, RailwayProjectInputs };
|
|
52
|
+
//# sourceMappingURL=project.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.d.cts","names":[],"sources":["../../src/railway/project.ts"],"mappings":";;;;;UAIiB,oBAAA;;EAEhB,KAAA;EAFoC;EAKpC,IAAA;EALoC;EAQpC,WAAA;AAAA;;;AAAW;AAwWZ;;;;;;;;;;;;;;;;;;;;cAAa,cAAA,SAAuB,MAAA,CAAO,OAAA,CAAQ,QAAA;EAKM;EAAA,SAHhC,SAAA,EAAW,MAAA,CAAO,MAAA;EAMJ;EAAA,SAHd,uBAAA,EAAyB,MAAA,CAAO,MAAA;;WAGhC,YAAA,EAAc,MAAA,CAAO,MAAA;cAG5C,IAAA,UACA,IAAA;IAEQ,gCAAP,KAAA,EAAO,MAAA,CAAO,KAAA,UAGd;IAAA,IAAA,EAAM,MAAA,CAAO,KAAA,UAAA;IAGb,WAAA,GAAc,MAAA,CAAO,KAAA;EAAA,GAEtB,IAAA,GAAO,MAAA,CAAO,qBAAA;AAAA"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { t as __name } from "../chunk-OPjESj5l.mjs";
|
|
2
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
3
|
+
|
|
4
|
+
//#region src/railway/project.d.ts
|
|
5
|
+
/** Resolved inputs for the Railway project dynamic provider. */
|
|
6
|
+
interface RailwayProjectInputs {
|
|
7
|
+
/** Railway API bearer token. */
|
|
8
|
+
token: string;
|
|
9
|
+
/** Desired display name for the project in Railway's dashboard. */
|
|
10
|
+
name: string;
|
|
11
|
+
/** Optional description shown in Railway's dashboard. */
|
|
12
|
+
description?: string;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Manages a Railway project with adopt-or-create semantics.
|
|
16
|
+
*
|
|
17
|
+
* Discovers or creates the project, resolves the production environment ID,
|
|
18
|
+
* and provisions a project-scoped token named "pulumi" for CLI deploys.
|
|
19
|
+
* The token is exposed as a secret output — the consumer decides how to store it.
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* ```typescript
|
|
23
|
+
* const project = new RailwayProject("railway-project", {
|
|
24
|
+
* token: railwayConfig.token,
|
|
25
|
+
* name: "my-app",
|
|
26
|
+
* description: "Railway services for my-app",
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* // Use outputs downstream
|
|
30
|
+
* const serviceVar = new RailwayVariable("...", {
|
|
31
|
+
* projectId: project.projectId,
|
|
32
|
+
* environmentId: project.productionEnvironmentId,
|
|
33
|
+
* ...
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*/
|
|
37
|
+
declare class RailwayProject extends pulumi.dynamic.Resource {
|
|
38
|
+
/** Railway project UUID. */
|
|
39
|
+
readonly projectId: pulumi.Output<string>;
|
|
40
|
+
/** Railway production environment UUID. */
|
|
41
|
+
readonly productionEnvironmentId: pulumi.Output<string>;
|
|
42
|
+
/** Railway project-scoped token (secret). */
|
|
43
|
+
readonly projectToken: pulumi.Output<string>;
|
|
44
|
+
constructor(name: string, args: {
|
|
45
|
+
/** Railway API bearer token. */token: pulumi.Input<string>; /** Project display name to find and adopt or create. */
|
|
46
|
+
name: pulumi.Input<string>; /** Optional description shown in Railway's dashboard. */
|
|
47
|
+
description?: pulumi.Input<string>;
|
|
48
|
+
}, opts?: pulumi.CustomResourceOptions);
|
|
49
|
+
}
|
|
50
|
+
//#endregion
|
|
51
|
+
export { RailwayProject, RailwayProjectInputs };
|
|
52
|
+
//# sourceMappingURL=project.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.d.mts","names":[],"sources":["../../src/railway/project.ts"],"mappings":";;;;;UAIiB,oBAAA;;EAEhB,KAAA;EAFoC;EAKpC,IAAA;EALoC;EAQpC,WAAA;AAAA;;;AAAW;AAwWZ;;;;;;;;;;;;;;;;;;;;cAAa,cAAA,SAAuB,MAAA,CAAO,OAAA,CAAQ,QAAA;EAKM;EAAA,SAHhC,SAAA,EAAW,MAAA,CAAO,MAAA;EAMJ;EAAA,SAHd,uBAAA,EAAyB,MAAA,CAAO,MAAA;;WAGhC,YAAA,EAAc,MAAA,CAAO,MAAA;cAG5C,IAAA,UACA,IAAA;IAEQ,gCAAP,KAAA,EAAO,MAAA,CAAO,KAAA,UAGd;IAAA,IAAA,EAAM,MAAA,CAAO,KAAA,UAAA;IAGb,WAAA,GAAc,MAAA,CAAO,KAAA;EAAA,GAEtB,IAAA,GAAO,MAAA,CAAO,qBAAA;AAAA"}
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
import { t as __name } from "../chunk-OPjESj5l.mjs";
|
|
2
|
+
import { RailwayClient } from "./client.mjs";
|
|
3
|
+
import * as pulumi from "@pulumi/pulumi";
|
|
4
|
+
|
|
5
|
+
//#region src/railway/project.ts
|
|
6
|
+
const WORKSPACE_QUERY = `
|
|
7
|
+
query {
|
|
8
|
+
me {
|
|
9
|
+
workspaces {
|
|
10
|
+
id
|
|
11
|
+
name
|
|
12
|
+
projects {
|
|
13
|
+
edges {
|
|
14
|
+
node {
|
|
15
|
+
id
|
|
16
|
+
name
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
`;
|
|
24
|
+
const PROJECT_CREATE = `
|
|
25
|
+
mutation($input: ProjectCreateInput!) {
|
|
26
|
+
projectCreate(input: $input) {
|
|
27
|
+
id
|
|
28
|
+
name
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
`;
|
|
32
|
+
const PROJECT_UPDATE = `
|
|
33
|
+
mutation($id: String!, $input: ProjectUpdateInput!) {
|
|
34
|
+
projectUpdate(id: $id, input: $input) {
|
|
35
|
+
id
|
|
36
|
+
name
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
`;
|
|
40
|
+
const PROJECT_ENVIRONMENTS_QUERY = `
|
|
41
|
+
query($projectId: String!) {
|
|
42
|
+
project(id: $projectId) {
|
|
43
|
+
environments {
|
|
44
|
+
edges {
|
|
45
|
+
node {
|
|
46
|
+
id
|
|
47
|
+
name
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
`;
|
|
54
|
+
const PROJECT_TOKENS_QUERY = `
|
|
55
|
+
query($projectId: String!) {
|
|
56
|
+
projectTokens(projectId: $projectId) {
|
|
57
|
+
edges { node { id name } }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
`;
|
|
61
|
+
const PROJECT_TOKEN_CREATE = `
|
|
62
|
+
mutation($input: ProjectTokenCreateInput!) {
|
|
63
|
+
projectTokenCreate(input: $input)
|
|
64
|
+
}
|
|
65
|
+
`;
|
|
66
|
+
const PROJECT_TOKEN_DELETE = `
|
|
67
|
+
mutation($id: String!) { projectTokenDelete(id: $id) }
|
|
68
|
+
`;
|
|
69
|
+
const PERMANENT_TOKEN_NAME = "pulumi";
|
|
70
|
+
/**
|
|
71
|
+
* Fetches all environments for a project and returns a name → UUID map.
|
|
72
|
+
*/
|
|
73
|
+
async function fetchProjectEnvironments(client, projectId) {
|
|
74
|
+
const result = await client.query(PROJECT_ENVIRONMENTS_QUERY, { projectId });
|
|
75
|
+
const environments = {};
|
|
76
|
+
for (const edge of result.project.environments.edges) environments[edge.node.name] = edge.node.id;
|
|
77
|
+
return environments;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Gets or creates a permanent project-scoped token named "pulumi".
|
|
81
|
+
*
|
|
82
|
+
* Deletes any stale tokens with the same name before creating a new one,
|
|
83
|
+
* ensuring a single canonical token exists. Does NOT write to Pulumi config —
|
|
84
|
+
* the token is returned as a secret output for the consumer to manage.
|
|
85
|
+
*/
|
|
86
|
+
async function getOrCreateProjectToken(client, projectId, environmentId) {
|
|
87
|
+
const stale = (await client.query(PROJECT_TOKENS_QUERY, { projectId })).projectTokens.edges.filter((edge) => edge.node.name === PERMANENT_TOKEN_NAME);
|
|
88
|
+
for (const entry of stale) await client.query(PROJECT_TOKEN_DELETE, { id: entry.node.id });
|
|
89
|
+
return (await client.query(PROJECT_TOKEN_CREATE, { input: {
|
|
90
|
+
projectId,
|
|
91
|
+
name: PERMANENT_TOKEN_NAME,
|
|
92
|
+
...environmentId ? { environmentId } : {}
|
|
93
|
+
} })).projectTokenCreate;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Dynamic provider that adopts an existing Railway project by name, or creates one.
|
|
97
|
+
*
|
|
98
|
+
* On create:
|
|
99
|
+
* 1. Queries workspaces to find the project by name.
|
|
100
|
+
* 2. If found → adopts. If not → creates via `projectCreate`.
|
|
101
|
+
* 3. Fetches all environments and resolves the production environment ID.
|
|
102
|
+
* 4. Creates/reuses a project-scoped token named "pulumi".
|
|
103
|
+
*
|
|
104
|
+
* Deletion is a no-op (with a warning) to prevent accidental project removal.
|
|
105
|
+
* Name changes trigger replacement.
|
|
106
|
+
*/
|
|
107
|
+
var RailwayProjectProvider = class {
|
|
108
|
+
async create(inputs) {
|
|
109
|
+
const client = new RailwayClient(inputs.token);
|
|
110
|
+
const workspaces = (await client.query(WORKSPACE_QUERY)).me.workspaces;
|
|
111
|
+
if (workspaces.length === 0) throw new Error("No Railway workspace found — cannot create project");
|
|
112
|
+
let projectId;
|
|
113
|
+
for (const workspace of workspaces) {
|
|
114
|
+
const match = workspace.projects.edges.find((edge) => edge.node.name === inputs.name);
|
|
115
|
+
if (match) {
|
|
116
|
+
projectId = match.node.id;
|
|
117
|
+
break;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
if (projectId) {
|
|
121
|
+
pulumi.log.info(`Adopted existing Railway project "${inputs.name}" (${projectId})`);
|
|
122
|
+
if (inputs.description) await client.query(PROJECT_UPDATE, {
|
|
123
|
+
id: projectId,
|
|
124
|
+
input: { description: inputs.description }
|
|
125
|
+
});
|
|
126
|
+
} else {
|
|
127
|
+
const workspace = workspaces[0];
|
|
128
|
+
projectId = (await client.query(PROJECT_CREATE, { input: {
|
|
129
|
+
name: inputs.name,
|
|
130
|
+
description: inputs.description,
|
|
131
|
+
workspaceId: workspace.id
|
|
132
|
+
} })).projectCreate.id;
|
|
133
|
+
pulumi.log.info(`Created Railway project "${inputs.name}" (${projectId})`);
|
|
134
|
+
}
|
|
135
|
+
if (!projectId) throw new Error(`Failed to find or create Railway project "${inputs.name}"`);
|
|
136
|
+
const productionEnvironmentId = (await fetchProjectEnvironments(client, projectId)).production ?? "";
|
|
137
|
+
const projectToken = await getOrCreateProjectToken(client, projectId, productionEnvironmentId || void 0);
|
|
138
|
+
const outs = {
|
|
139
|
+
...inputs,
|
|
140
|
+
projectId,
|
|
141
|
+
productionEnvironmentId,
|
|
142
|
+
projectToken
|
|
143
|
+
};
|
|
144
|
+
return {
|
|
145
|
+
id: projectId,
|
|
146
|
+
outs
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
async update(id, _olds, news) {
|
|
150
|
+
const client = new RailwayClient(news.token);
|
|
151
|
+
await client.query(PROJECT_UPDATE, {
|
|
152
|
+
id,
|
|
153
|
+
input: {
|
|
154
|
+
name: news.name,
|
|
155
|
+
description: news.description
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
const productionEnvironmentId = (await fetchProjectEnvironments(client, id)).production ?? "";
|
|
159
|
+
const projectToken = await getOrCreateProjectToken(client, id, productionEnvironmentId || void 0);
|
|
160
|
+
return { outs: {
|
|
161
|
+
...news,
|
|
162
|
+
projectId: id,
|
|
163
|
+
productionEnvironmentId,
|
|
164
|
+
projectToken
|
|
165
|
+
} };
|
|
166
|
+
}
|
|
167
|
+
async read(id, props) {
|
|
168
|
+
const productionEnvironmentId = (await fetchProjectEnvironments(new RailwayClient(props.token), id)).production ?? props.productionEnvironmentId;
|
|
169
|
+
return {
|
|
170
|
+
id,
|
|
171
|
+
props: {
|
|
172
|
+
...props,
|
|
173
|
+
projectId: id,
|
|
174
|
+
productionEnvironmentId
|
|
175
|
+
}
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
async delete() {
|
|
179
|
+
pulumi.log.warn("Railway project deletion skipped — projects are not deleted by Pulumi");
|
|
180
|
+
}
|
|
181
|
+
async diff(_id, olds, news) {
|
|
182
|
+
const replaces = [];
|
|
183
|
+
const changes = [];
|
|
184
|
+
if (olds.name !== news.name) replaces.push("name");
|
|
185
|
+
if (olds.description !== news.description) changes.push("description");
|
|
186
|
+
return {
|
|
187
|
+
changes: replaces.length > 0 || changes.length > 0,
|
|
188
|
+
replaces,
|
|
189
|
+
deleteBeforeReplace: true
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
/**
|
|
194
|
+
* Manages a Railway project with adopt-or-create semantics.
|
|
195
|
+
*
|
|
196
|
+
* Discovers or creates the project, resolves the production environment ID,
|
|
197
|
+
* and provisions a project-scoped token named "pulumi" for CLI deploys.
|
|
198
|
+
* The token is exposed as a secret output — the consumer decides how to store it.
|
|
199
|
+
*
|
|
200
|
+
* @example
|
|
201
|
+
* ```typescript
|
|
202
|
+
* const project = new RailwayProject("railway-project", {
|
|
203
|
+
* token: railwayConfig.token,
|
|
204
|
+
* name: "my-app",
|
|
205
|
+
* description: "Railway services for my-app",
|
|
206
|
+
* });
|
|
207
|
+
*
|
|
208
|
+
* // Use outputs downstream
|
|
209
|
+
* const serviceVar = new RailwayVariable("...", {
|
|
210
|
+
* projectId: project.projectId,
|
|
211
|
+
* environmentId: project.productionEnvironmentId,
|
|
212
|
+
* ...
|
|
213
|
+
* });
|
|
214
|
+
* ```
|
|
215
|
+
*/
|
|
216
|
+
var RailwayProject = class extends pulumi.dynamic.Resource {
|
|
217
|
+
constructor(name, args, opts) {
|
|
218
|
+
super(new RailwayProjectProvider(), name, {
|
|
219
|
+
...args,
|
|
220
|
+
projectId: void 0,
|
|
221
|
+
productionEnvironmentId: void 0,
|
|
222
|
+
projectToken: pulumi.secret(void 0)
|
|
223
|
+
}, opts);
|
|
224
|
+
}
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
//#endregion
|
|
228
|
+
export { RailwayProject };
|
|
229
|
+
//# sourceMappingURL=project.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.mjs","names":[],"sources":["../../src/railway/project.ts"],"sourcesContent":["import * as pulumi from \"@pulumi/pulumi\";\nimport { RailwayClient } from \"./client.js\";\n\n/** Resolved inputs for the Railway project dynamic provider. */\nexport interface RailwayProjectInputs {\n\t/** Railway API bearer token. */\n\ttoken: string;\n\n\t/** Desired display name for the project in Railway's dashboard. */\n\tname: string;\n\n\t/** Optional description shown in Railway's dashboard. */\n\tdescription?: string;\n}\n\n/** Persisted state for the Railway project. */\ninterface RailwayProjectOutputs extends RailwayProjectInputs {\n\t/** Railway-assigned project UUID. */\n\tprojectId: string;\n\n\t/** Railway-assigned production environment UUID. */\n\tproductionEnvironmentId: string;\n\n\t/** Railway project-scoped token (auto-provisioned, exposed as secret output). */\n\tprojectToken: string;\n}\n\nconst WORKSPACE_QUERY = `\n query {\n me {\n workspaces {\n id\n name\n projects {\n edges {\n node {\n id\n name\n }\n }\n }\n }\n }\n }\n`;\n\nconst PROJECT_CREATE = `\n mutation($input: ProjectCreateInput!) {\n projectCreate(input: $input) {\n id\n name\n }\n }\n`;\n\nconst PROJECT_UPDATE = `\n mutation($id: String!, $input: ProjectUpdateInput!) {\n projectUpdate(id: $id, 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\nconst PROJECT_TOKENS_QUERY = `\n query($projectId: String!) {\n projectTokens(projectId: $projectId) {\n edges { node { id name } }\n }\n }\n`;\n\nconst PROJECT_TOKEN_CREATE = `\n mutation($input: ProjectTokenCreateInput!) {\n projectTokenCreate(input: $input)\n }\n`;\n\nconst PROJECT_TOKEN_DELETE = `\n mutation($id: String!) { projectTokenDelete(id: $id) }\n`;\n\nconst PERMANENT_TOKEN_NAME = \"pulumi\";\n\n/**\n * Fetches all environments for a project and returns a name → UUID map.\n */\nasync function fetchProjectEnvironments(\n\tclient: RailwayClient,\n\tprojectId: string,\n): Promise<Record<string, string>> {\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 environments: Record<string, string> = {};\n\n\tfor (const edge of result.project.environments.edges) {\n\t\tenvironments[edge.node.name] = edge.node.id;\n\t}\n\n\treturn environments;\n}\n\n/**\n * Gets or creates a permanent project-scoped token named \"pulumi\".\n *\n * Deletes any stale tokens with the same name before creating a new one,\n * ensuring a single canonical token exists. Does NOT write to Pulumi config —\n * the token is returned as a secret output for the consumer to manage.\n */\nasync function getOrCreateProjectToken(\n\tclient: RailwayClient,\n\tprojectId: string,\n\tenvironmentId?: string,\n): Promise<string> {\n\tconst tokensResult = await client.query<{\n\t\tprojectTokens: {\n\t\t\tedges: Array<{ node: { id: string; name: string } }>;\n\t\t};\n\t}>(PROJECT_TOKENS_QUERY, { projectId });\n\n\tconst stale = tokensResult.projectTokens.edges.filter(\n\t\t(edge) => edge.node.name === PERMANENT_TOKEN_NAME,\n\t);\n\n\tfor (const entry of stale) {\n\t\tawait client.query(PROJECT_TOKEN_DELETE, { id: entry.node.id });\n\t}\n\n\tconst result = await client.query<{ projectTokenCreate: string }>(\n\t\tPROJECT_TOKEN_CREATE,\n\t\t{\n\t\t\tinput: {\n\t\t\t\tprojectId,\n\t\t\t\tname: PERMANENT_TOKEN_NAME,\n\t\t\t\t...(environmentId ? { environmentId } : {}),\n\t\t\t},\n\t\t},\n\t);\n\n\treturn result.projectTokenCreate;\n}\n\n/**\n * Dynamic provider that adopts an existing Railway project by name, or creates one.\n *\n * On create:\n * 1. Queries workspaces to find the project by name.\n * 2. If found → adopts. If not → creates via `projectCreate`.\n * 3. Fetches all environments and resolves the production environment ID.\n * 4. Creates/reuses a project-scoped token named \"pulumi\".\n *\n * Deletion is a no-op (with a warning) to prevent accidental project removal.\n * Name changes trigger replacement.\n */\nclass RailwayProjectProvider implements pulumi.dynamic.ResourceProvider {\n\tasync create(\n\t\tinputs: RailwayProjectInputs,\n\t): Promise<pulumi.dynamic.CreateResult> {\n\t\tconst client = new RailwayClient(inputs.token);\n\n\t\tconst workspaceResult = await client.query<{\n\t\t\tme: {\n\t\t\t\tworkspaces: Array<{\n\t\t\t\t\tid: string;\n\t\t\t\t\tname: string;\n\t\t\t\t\tprojects: {\n\t\t\t\t\t\tedges: Array<{ node: { id: string; name: string } }>;\n\t\t\t\t\t};\n\t\t\t\t}>;\n\t\t\t};\n\t\t}>(WORKSPACE_QUERY);\n\n\t\tconst workspaces = workspaceResult.me.workspaces;\n\n\t\tif (workspaces.length === 0) {\n\t\t\tthrow new Error(\"No Railway workspace found — cannot create project\");\n\t\t}\n\n\t\tlet projectId: string | undefined;\n\n\t\tfor (const workspace of workspaces) {\n\t\t\tconst match = workspace.projects.edges.find(\n\t\t\t\t(edge) => edge.node.name === inputs.name,\n\t\t\t);\n\n\t\t\tif (match) {\n\t\t\t\tprojectId = match.node.id;\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif (projectId) {\n\t\t\tpulumi.log.info(\n\t\t\t\t`Adopted existing Railway project \"${inputs.name}\" (${projectId})`,\n\t\t\t);\n\n\t\t\tif (inputs.description) {\n\t\t\t\tawait client.query(PROJECT_UPDATE, {\n\t\t\t\t\tid: projectId,\n\t\t\t\t\tinput: { description: inputs.description },\n\t\t\t\t});\n\t\t\t}\n\t\t} else {\n\t\t\tconst workspace = workspaces[0];\n\n\t\t\tconst created = await client.query<{\n\t\t\t\tprojectCreate: { id: string; name: string };\n\t\t\t}>(PROJECT_CREATE, {\n\t\t\t\tinput: {\n\t\t\t\t\tname: inputs.name,\n\t\t\t\t\tdescription: inputs.description,\n\t\t\t\t\tworkspaceId: workspace.id,\n\t\t\t\t},\n\t\t\t});\n\n\t\t\tprojectId = created.projectCreate.id;\n\n\t\t\tpulumi.log.info(\n\t\t\t\t`Created Railway project \"${inputs.name}\" (${projectId})`,\n\t\t\t);\n\t\t}\n\n\t\tif (!projectId) {\n\t\t\tthrow new Error(\n\t\t\t\t`Failed to find or create Railway project \"${inputs.name}\"`,\n\t\t\t);\n\t\t}\n\n\t\tconst environments = await fetchProjectEnvironments(client, projectId);\n\n\t\tconst productionEnvironmentId = environments.production ?? \"\";\n\n\t\tconst projectToken = await getOrCreateProjectToken(\n\t\t\tclient,\n\t\t\tprojectId,\n\t\t\tproductionEnvironmentId || undefined,\n\t\t);\n\n\t\tconst outs: RailwayProjectOutputs = {\n\t\t\t...inputs,\n\t\t\tprojectId,\n\t\t\tproductionEnvironmentId,\n\t\t\tprojectToken,\n\t\t};\n\n\t\treturn { id: projectId, outs };\n\t}\n\n\tasync update(\n\t\tid: string,\n\t\t_olds: RailwayProjectOutputs,\n\t\tnews: RailwayProjectInputs,\n\t): Promise<pulumi.dynamic.UpdateResult> {\n\t\tconst client = new RailwayClient(news.token);\n\n\t\tawait client.query(PROJECT_UPDATE, {\n\t\t\tid,\n\t\t\tinput: { name: news.name, description: news.description },\n\t\t});\n\n\t\tconst environments = await fetchProjectEnvironments(client, id);\n\n\t\tconst productionEnvironmentId = environments.production ?? \"\";\n\n\t\tconst projectToken = await getOrCreateProjectToken(\n\t\t\tclient,\n\t\t\tid,\n\t\t\tproductionEnvironmentId || undefined,\n\t\t);\n\n\t\tconst outs: RailwayProjectOutputs = {\n\t\t\t...news,\n\t\t\tprojectId: id,\n\t\t\tproductionEnvironmentId,\n\t\t\tprojectToken,\n\t\t};\n\n\t\treturn { outs };\n\t}\n\n\tasync read(\n\t\tid: string,\n\t\tprops: RailwayProjectOutputs,\n\t): Promise<pulumi.dynamic.ReadResult> {\n\t\tconst client = new RailwayClient(props.token);\n\n\t\tconst environments = await fetchProjectEnvironments(client, id);\n\n\t\tconst productionEnvironmentId =\n\t\t\tenvironments.production ?? props.productionEnvironmentId;\n\n\t\treturn {\n\t\t\tid,\n\t\t\tprops: { ...props, projectId: id, productionEnvironmentId },\n\t\t};\n\t}\n\n\tasync delete(): Promise<void> {\n\t\tpulumi.log.warn(\n\t\t\t\"Railway project deletion skipped — projects are not deleted by Pulumi\",\n\t\t);\n\t}\n\n\tasync diff(\n\t\t_id: string,\n\t\tolds: RailwayProjectOutputs,\n\t\tnews: RailwayProjectInputs,\n\t): Promise<pulumi.dynamic.DiffResult> {\n\t\tconst replaces: string[] = [];\n\t\tconst changes: string[] = [];\n\n\t\tif (olds.name !== news.name) {\n\t\t\treplaces.push(\"name\");\n\t\t}\n\n\t\tif (olds.description !== news.description) {\n\t\t\tchanges.push(\"description\");\n\t\t}\n\n\t\treturn {\n\t\t\tchanges: replaces.length > 0 || changes.length > 0,\n\t\t\treplaces,\n\t\t\tdeleteBeforeReplace: true,\n\t\t};\n\t}\n}\n\n/**\n * Manages a Railway project with adopt-or-create semantics.\n *\n * Discovers or creates the project, resolves the production environment ID,\n * and provisions a project-scoped token named \"pulumi\" for CLI deploys.\n * The token is exposed as a secret output — the consumer decides how to store it.\n *\n * @example\n * ```typescript\n * const project = new RailwayProject(\"railway-project\", {\n * token: railwayConfig.token,\n * name: \"my-app\",\n * description: \"Railway services for my-app\",\n * });\n *\n * // Use outputs downstream\n * const serviceVar = new RailwayVariable(\"...\", {\n * projectId: project.projectId,\n * environmentId: project.productionEnvironmentId,\n * ...\n * });\n * ```\n */\nexport class RailwayProject extends pulumi.dynamic.Resource {\n\t/** Railway project UUID. */\n\tpublic declare readonly projectId: pulumi.Output<string>;\n\n\t/** Railway production environment UUID. */\n\tpublic declare readonly productionEnvironmentId: pulumi.Output<string>;\n\n\t/** Railway project-scoped token (secret). */\n\tpublic declare readonly projectToken: pulumi.Output<string>;\n\n\tconstructor(\n\t\tname: string,\n\t\targs: {\n\t\t\t/** Railway API bearer token. */\n\t\t\ttoken: pulumi.Input<string>;\n\n\t\t\t/** Project display name to find and adopt or create. */\n\t\t\tname: pulumi.Input<string>;\n\n\t\t\t/** Optional description shown in Railway's dashboard. */\n\t\t\tdescription?: pulumi.Input<string>;\n\t\t},\n\t\topts?: pulumi.CustomResourceOptions,\n\t) {\n\t\tsuper(\n\t\t\tnew RailwayProjectProvider(),\n\t\t\tname,\n\t\t\t{\n\t\t\t\t...args,\n\t\t\t\tprojectId: undefined,\n\t\t\t\tproductionEnvironmentId: undefined,\n\t\t\t\tprojectToken: pulumi.secret(undefined as unknown as string),\n\t\t\t},\n\t\t\topts,\n\t\t);\n\t}\n}\n"],"mappings":"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"}
|