@vucinatim/agentic-devtools 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +52 -2
- package/docs/auth-and-setup-guidelines.md +41 -2
- package/docs/publishing.md +12 -0
- package/docs/testing.md +4 -0
- package/docs/usage.md +70 -1
- package/package.json +1 -1
- package/src/cli.mjs +1 -1
- package/src/tools/railway/auth.mjs +1 -1
- package/src/tools/railway/client.mjs +751 -0
- package/src/tools/railway/mcp.mjs +535 -9
|
@@ -86,6 +86,16 @@ export const createRailwayClient = ({
|
|
|
86
86
|
);
|
|
87
87
|
};
|
|
88
88
|
|
|
89
|
+
const requireResolvedProjectId = async (projectId, operation) => {
|
|
90
|
+
try {
|
|
91
|
+
return await resolveProjectId(projectId);
|
|
92
|
+
} catch (error) {
|
|
93
|
+
throw new RailwayApiError(
|
|
94
|
+
error instanceof Error ? error.message : `${operation} requires a Railway project id.`,
|
|
95
|
+
);
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
|
|
89
99
|
const getCurrentViewer = async () => {
|
|
90
100
|
requireAccountToken("getRailwayViewer");
|
|
91
101
|
const data = await request(`
|
|
@@ -103,6 +113,20 @@ export const createRailwayClient = ({
|
|
|
103
113
|
return data.me;
|
|
104
114
|
};
|
|
105
115
|
|
|
116
|
+
const validateAccountToken = async () => {
|
|
117
|
+
requireAccountToken("validateRailwayAccountToken");
|
|
118
|
+
const projects = await listProjects({ first: 1, includeDeleted: false });
|
|
119
|
+
return {
|
|
120
|
+
ok: true,
|
|
121
|
+
projectCountSampled: projects.length,
|
|
122
|
+
sampleProjects: projects.map((project) => ({
|
|
123
|
+
id: project.id,
|
|
124
|
+
name: project.name,
|
|
125
|
+
workspace: project.workspace?.name ?? null,
|
|
126
|
+
})),
|
|
127
|
+
};
|
|
128
|
+
};
|
|
129
|
+
|
|
106
130
|
const listProjects = async ({
|
|
107
131
|
workspaceId = null,
|
|
108
132
|
includeDeleted = false,
|
|
@@ -217,6 +241,27 @@ export const createRailwayClient = ({
|
|
|
217
241
|
};
|
|
218
242
|
};
|
|
219
243
|
|
|
244
|
+
const getProjectMembers = async (projectId) => {
|
|
245
|
+
requireAccountToken("getRailwayProjectMembers");
|
|
246
|
+
const id = await requireResolvedProjectId(projectId, "getRailwayProjectMembers");
|
|
247
|
+
const data = await request(
|
|
248
|
+
`
|
|
249
|
+
query RailwayProjectMembers($projectId: String!) {
|
|
250
|
+
projectMembers(projectId: $projectId) {
|
|
251
|
+
id
|
|
252
|
+
role
|
|
253
|
+
user {
|
|
254
|
+
name
|
|
255
|
+
email
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
`,
|
|
260
|
+
{ projectId: id },
|
|
261
|
+
);
|
|
262
|
+
return data.projectMembers;
|
|
263
|
+
};
|
|
264
|
+
|
|
220
265
|
const listEnvironments = async ({ projectId, isEphemeral } = {}) => {
|
|
221
266
|
const resolvedProjectId = await resolveProjectId(projectId);
|
|
222
267
|
const data = await request(
|
|
@@ -294,6 +339,675 @@ export const createRailwayClient = ({
|
|
|
294
339
|
};
|
|
295
340
|
};
|
|
296
341
|
|
|
342
|
+
const getService = async (serviceId) => {
|
|
343
|
+
const data = await request(
|
|
344
|
+
`
|
|
345
|
+
query RailwayService($id: String!) {
|
|
346
|
+
service(id: $id) {
|
|
347
|
+
id
|
|
348
|
+
name
|
|
349
|
+
icon
|
|
350
|
+
createdAt
|
|
351
|
+
updatedAt
|
|
352
|
+
deletedAt
|
|
353
|
+
featureFlags
|
|
354
|
+
project {
|
|
355
|
+
id
|
|
356
|
+
name
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
`,
|
|
361
|
+
{ id: serviceId },
|
|
362
|
+
);
|
|
363
|
+
return {
|
|
364
|
+
...data.service,
|
|
365
|
+
projectId: data.service.project?.id ?? null,
|
|
366
|
+
projectName: data.service.project?.name ?? null,
|
|
367
|
+
};
|
|
368
|
+
};
|
|
369
|
+
|
|
370
|
+
const getServiceInstance = async ({ serviceId, environmentId }) => {
|
|
371
|
+
const data = await request(
|
|
372
|
+
`
|
|
373
|
+
query RailwayServiceInstance($serviceId: String!, $environmentId: String!) {
|
|
374
|
+
serviceInstance(serviceId: $serviceId, environmentId: $environmentId) {
|
|
375
|
+
id
|
|
376
|
+
serviceId
|
|
377
|
+
serviceName
|
|
378
|
+
environmentId
|
|
379
|
+
rootDirectory
|
|
380
|
+
railwayConfigFile
|
|
381
|
+
buildCommand
|
|
382
|
+
startCommand
|
|
383
|
+
healthcheckPath
|
|
384
|
+
cronSchedule
|
|
385
|
+
latestDeployment {
|
|
386
|
+
id
|
|
387
|
+
status
|
|
388
|
+
url
|
|
389
|
+
staticUrl
|
|
390
|
+
}
|
|
391
|
+
domains {
|
|
392
|
+
serviceDomains {
|
|
393
|
+
id
|
|
394
|
+
domain
|
|
395
|
+
}
|
|
396
|
+
customDomains {
|
|
397
|
+
id
|
|
398
|
+
domain
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
`,
|
|
404
|
+
{ serviceId, environmentId },
|
|
405
|
+
);
|
|
406
|
+
return data.serviceInstance;
|
|
407
|
+
};
|
|
408
|
+
|
|
409
|
+
const getServiceInstanceLimits = async ({ serviceId, environmentId }) => {
|
|
410
|
+
const data = await request(
|
|
411
|
+
`
|
|
412
|
+
query RailwayServiceInstanceLimits($serviceId: String!, $environmentId: String!) {
|
|
413
|
+
serviceInstanceLimits(serviceId: $serviceId, environmentId: $environmentId)
|
|
414
|
+
}
|
|
415
|
+
`,
|
|
416
|
+
{ serviceId, environmentId },
|
|
417
|
+
);
|
|
418
|
+
return data.serviceInstanceLimits;
|
|
419
|
+
};
|
|
420
|
+
|
|
421
|
+
const getDeployment = async (deploymentId) => {
|
|
422
|
+
const data = await request(
|
|
423
|
+
`
|
|
424
|
+
query RailwayDeployment($id: String!) {
|
|
425
|
+
deployment(id: $id) {
|
|
426
|
+
id
|
|
427
|
+
status
|
|
428
|
+
createdAt
|
|
429
|
+
updatedAt
|
|
430
|
+
statusUpdatedAt
|
|
431
|
+
canRedeploy
|
|
432
|
+
canRollback
|
|
433
|
+
deploymentStopped
|
|
434
|
+
environmentId
|
|
435
|
+
projectId
|
|
436
|
+
serviceId
|
|
437
|
+
url
|
|
438
|
+
staticUrl
|
|
439
|
+
service {
|
|
440
|
+
id
|
|
441
|
+
name
|
|
442
|
+
}
|
|
443
|
+
environment {
|
|
444
|
+
id
|
|
445
|
+
name
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
`,
|
|
450
|
+
{ id: deploymentId },
|
|
451
|
+
);
|
|
452
|
+
return {
|
|
453
|
+
...data.deployment,
|
|
454
|
+
serviceName: data.deployment.service?.name ?? null,
|
|
455
|
+
environmentName: data.deployment.environment?.name ?? null,
|
|
456
|
+
};
|
|
457
|
+
};
|
|
458
|
+
|
|
459
|
+
const listDeployments = async ({
|
|
460
|
+
projectId,
|
|
461
|
+
environmentId,
|
|
462
|
+
serviceId,
|
|
463
|
+
first = 20,
|
|
464
|
+
after = null,
|
|
465
|
+
before = null,
|
|
466
|
+
last = null,
|
|
467
|
+
} = {}) => {
|
|
468
|
+
const resolvedProjectId =
|
|
469
|
+
projectId == null && auth.kind === "project"
|
|
470
|
+
? await requireResolvedProjectId(null, "listRailwayDeployments")
|
|
471
|
+
: projectId;
|
|
472
|
+
|
|
473
|
+
const input = compactObject({
|
|
474
|
+
projectId: resolvedProjectId,
|
|
475
|
+
environmentId,
|
|
476
|
+
serviceId,
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
const data = await request(
|
|
480
|
+
`
|
|
481
|
+
query RailwayDeployments(
|
|
482
|
+
$input: DeploymentListInput!
|
|
483
|
+
$first: Int
|
|
484
|
+
$after: String
|
|
485
|
+
$before: String
|
|
486
|
+
$last: Int
|
|
487
|
+
) {
|
|
488
|
+
deployments(
|
|
489
|
+
input: $input
|
|
490
|
+
first: $first
|
|
491
|
+
after: $after
|
|
492
|
+
before: $before
|
|
493
|
+
last: $last
|
|
494
|
+
) {
|
|
495
|
+
edges {
|
|
496
|
+
node {
|
|
497
|
+
id
|
|
498
|
+
status
|
|
499
|
+
createdAt
|
|
500
|
+
updatedAt
|
|
501
|
+
environmentId
|
|
502
|
+
projectId
|
|
503
|
+
serviceId
|
|
504
|
+
url
|
|
505
|
+
staticUrl
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
pageInfo {
|
|
509
|
+
hasNextPage
|
|
510
|
+
hasPreviousPage
|
|
511
|
+
startCursor
|
|
512
|
+
endCursor
|
|
513
|
+
}
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
`,
|
|
517
|
+
{ input, first, after, before, last },
|
|
518
|
+
);
|
|
519
|
+
|
|
520
|
+
return {
|
|
521
|
+
deployments: connectionNodes(data.deployments),
|
|
522
|
+
pageInfo: data.deployments?.pageInfo ?? null,
|
|
523
|
+
};
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
const createProject = async (input = {}) => {
|
|
527
|
+
requireAccountToken("createRailwayProject");
|
|
528
|
+
const data = await request(
|
|
529
|
+
`
|
|
530
|
+
mutation RailwayProjectCreate($input: ProjectCreateInput!) {
|
|
531
|
+
projectCreate(input: $input) {
|
|
532
|
+
id
|
|
533
|
+
name
|
|
534
|
+
description
|
|
535
|
+
workspace {
|
|
536
|
+
id
|
|
537
|
+
name
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
`,
|
|
542
|
+
{ input: compactObject(input) },
|
|
543
|
+
);
|
|
544
|
+
return data.projectCreate;
|
|
545
|
+
};
|
|
546
|
+
|
|
547
|
+
const updateProject = async ({ projectId, ...input } = {}) => {
|
|
548
|
+
requireAccountToken("updateRailwayProject");
|
|
549
|
+
const id = await requireResolvedProjectId(projectId, "updateRailwayProject");
|
|
550
|
+
const data = await request(
|
|
551
|
+
`
|
|
552
|
+
mutation RailwayProjectUpdate($id: String!, $input: ProjectUpdateInput!) {
|
|
553
|
+
projectUpdate(id: $id, input: $input) {
|
|
554
|
+
id
|
|
555
|
+
name
|
|
556
|
+
description
|
|
557
|
+
prDeploys
|
|
558
|
+
focusedPrEnvironments
|
|
559
|
+
botPrEnvironments
|
|
560
|
+
isPublic
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
`,
|
|
564
|
+
{ id, input: compactObject(input) },
|
|
565
|
+
);
|
|
566
|
+
return data.projectUpdate;
|
|
567
|
+
};
|
|
568
|
+
|
|
569
|
+
const deleteProject = async (projectId) => {
|
|
570
|
+
requireAccountToken("deleteRailwayProject");
|
|
571
|
+
const id = await requireResolvedProjectId(projectId, "deleteRailwayProject");
|
|
572
|
+
const deleted = await request(
|
|
573
|
+
`
|
|
574
|
+
mutation RailwayProjectDelete($id: String!) {
|
|
575
|
+
projectDelete(id: $id)
|
|
576
|
+
}
|
|
577
|
+
`,
|
|
578
|
+
{ id },
|
|
579
|
+
);
|
|
580
|
+
return {
|
|
581
|
+
deleted: Boolean(deleted.projectDelete),
|
|
582
|
+
projectId: id,
|
|
583
|
+
};
|
|
584
|
+
};
|
|
585
|
+
|
|
586
|
+
const transferProject = async ({ projectId, workspaceId } = {}) => {
|
|
587
|
+
requireAccountToken("transferRailwayProject");
|
|
588
|
+
const id = await requireResolvedProjectId(projectId, "transferRailwayProject");
|
|
589
|
+
const transferred = await request(
|
|
590
|
+
`
|
|
591
|
+
mutation RailwayProjectTransfer($projectId: String!, $input: ProjectTransferInput!) {
|
|
592
|
+
projectTransfer(projectId: $projectId, input: $input)
|
|
593
|
+
}
|
|
594
|
+
`,
|
|
595
|
+
{
|
|
596
|
+
projectId: id,
|
|
597
|
+
input: { workspaceId },
|
|
598
|
+
},
|
|
599
|
+
);
|
|
600
|
+
return {
|
|
601
|
+
transferred: Boolean(transferred.projectTransfer),
|
|
602
|
+
projectId: id,
|
|
603
|
+
workspaceId,
|
|
604
|
+
};
|
|
605
|
+
};
|
|
606
|
+
|
|
607
|
+
const createService = async (input = {}) => {
|
|
608
|
+
const data = await request(
|
|
609
|
+
`
|
|
610
|
+
mutation RailwayServiceCreate($input: ServiceCreateInput!) {
|
|
611
|
+
serviceCreate(input: $input) {
|
|
612
|
+
id
|
|
613
|
+
name
|
|
614
|
+
icon
|
|
615
|
+
projectId
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
`,
|
|
619
|
+
{ input: compactObject(input) },
|
|
620
|
+
);
|
|
621
|
+
return data.serviceCreate;
|
|
622
|
+
};
|
|
623
|
+
|
|
624
|
+
const updateService = async ({ serviceId, ...input } = {}) => {
|
|
625
|
+
const data = await request(
|
|
626
|
+
`
|
|
627
|
+
mutation RailwayServiceUpdate($id: String!, $input: ServiceUpdateInput!) {
|
|
628
|
+
serviceUpdate(id: $id, input: $input) {
|
|
629
|
+
id
|
|
630
|
+
name
|
|
631
|
+
icon
|
|
632
|
+
projectId
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
`,
|
|
636
|
+
{ id: serviceId, input: compactObject(input) },
|
|
637
|
+
);
|
|
638
|
+
return data.serviceUpdate;
|
|
639
|
+
};
|
|
640
|
+
|
|
641
|
+
const connectService = async ({ serviceId, ...input } = {}) => {
|
|
642
|
+
const data = await request(
|
|
643
|
+
`
|
|
644
|
+
mutation RailwayServiceConnect($id: String!, $input: ServiceConnectInput!) {
|
|
645
|
+
serviceConnect(id: $id, input: $input) {
|
|
646
|
+
id
|
|
647
|
+
name
|
|
648
|
+
icon
|
|
649
|
+
projectId
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
`,
|
|
653
|
+
{ id: serviceId, input: compactObject(input) },
|
|
654
|
+
);
|
|
655
|
+
return data.serviceConnect;
|
|
656
|
+
};
|
|
657
|
+
|
|
658
|
+
const disconnectService = async (serviceId) => {
|
|
659
|
+
const disconnected = await request(
|
|
660
|
+
`
|
|
661
|
+
mutation RailwayServiceDisconnect($id: String!) {
|
|
662
|
+
serviceDisconnect(id: $id)
|
|
663
|
+
}
|
|
664
|
+
`,
|
|
665
|
+
{ id: serviceId },
|
|
666
|
+
);
|
|
667
|
+
return {
|
|
668
|
+
disconnected: Boolean(disconnected.serviceDisconnect),
|
|
669
|
+
serviceId,
|
|
670
|
+
};
|
|
671
|
+
};
|
|
672
|
+
|
|
673
|
+
const deleteService = async ({ serviceId, environmentId } = {}) => {
|
|
674
|
+
const deleted = await request(
|
|
675
|
+
`
|
|
676
|
+
mutation RailwayServiceDelete($id: String!, $environmentId: String) {
|
|
677
|
+
serviceDelete(id: $id, environmentId: $environmentId)
|
|
678
|
+
}
|
|
679
|
+
`,
|
|
680
|
+
{ id: serviceId, environmentId },
|
|
681
|
+
);
|
|
682
|
+
return {
|
|
683
|
+
deleted: Boolean(deleted.serviceDelete),
|
|
684
|
+
serviceId,
|
|
685
|
+
environmentId: environmentId ?? null,
|
|
686
|
+
};
|
|
687
|
+
};
|
|
688
|
+
|
|
689
|
+
const updateServiceInstance = async ({
|
|
690
|
+
serviceId,
|
|
691
|
+
environmentId,
|
|
692
|
+
...input
|
|
693
|
+
} = {}) => {
|
|
694
|
+
const updated = await request(
|
|
695
|
+
`
|
|
696
|
+
mutation RailwayServiceInstanceUpdate(
|
|
697
|
+
$serviceId: String!
|
|
698
|
+
$environmentId: String
|
|
699
|
+
$input: ServiceInstanceUpdateInput!
|
|
700
|
+
) {
|
|
701
|
+
serviceInstanceUpdate(
|
|
702
|
+
serviceId: $serviceId
|
|
703
|
+
environmentId: $environmentId
|
|
704
|
+
input: $input
|
|
705
|
+
)
|
|
706
|
+
}
|
|
707
|
+
`,
|
|
708
|
+
{
|
|
709
|
+
serviceId,
|
|
710
|
+
environmentId,
|
|
711
|
+
input: compactObject(input),
|
|
712
|
+
},
|
|
713
|
+
);
|
|
714
|
+
return {
|
|
715
|
+
updated: Boolean(updated.serviceInstanceUpdate),
|
|
716
|
+
serviceId,
|
|
717
|
+
environmentId: environmentId ?? null,
|
|
718
|
+
};
|
|
719
|
+
};
|
|
720
|
+
|
|
721
|
+
const deployService = async ({
|
|
722
|
+
serviceId,
|
|
723
|
+
environmentId,
|
|
724
|
+
commitSha,
|
|
725
|
+
latestCommit,
|
|
726
|
+
} = {}) => {
|
|
727
|
+
const deployment = await request(
|
|
728
|
+
`
|
|
729
|
+
mutation RailwayServiceInstanceDeploy(
|
|
730
|
+
$serviceId: String!
|
|
731
|
+
$environmentId: String!
|
|
732
|
+
$commitSha: String
|
|
733
|
+
$latestCommit: Boolean
|
|
734
|
+
) {
|
|
735
|
+
serviceInstanceDeploy(
|
|
736
|
+
serviceId: $serviceId
|
|
737
|
+
environmentId: $environmentId
|
|
738
|
+
commitSha: $commitSha
|
|
739
|
+
latestCommit: $latestCommit
|
|
740
|
+
) {
|
|
741
|
+
id
|
|
742
|
+
status
|
|
743
|
+
environmentId
|
|
744
|
+
serviceId
|
|
745
|
+
url
|
|
746
|
+
staticUrl
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
`,
|
|
750
|
+
{ serviceId, environmentId, commitSha, latestCommit },
|
|
751
|
+
);
|
|
752
|
+
return deployment.serviceInstanceDeploy;
|
|
753
|
+
};
|
|
754
|
+
|
|
755
|
+
const redeployService = async ({ serviceId, environmentId } = {}) => {
|
|
756
|
+
const deployment = await request(
|
|
757
|
+
`
|
|
758
|
+
mutation RailwayServiceInstanceRedeploy(
|
|
759
|
+
$serviceId: String!
|
|
760
|
+
$environmentId: String!
|
|
761
|
+
) {
|
|
762
|
+
serviceInstanceRedeploy(
|
|
763
|
+
serviceId: $serviceId
|
|
764
|
+
environmentId: $environmentId
|
|
765
|
+
) {
|
|
766
|
+
id
|
|
767
|
+
status
|
|
768
|
+
environmentId
|
|
769
|
+
serviceId
|
|
770
|
+
url
|
|
771
|
+
staticUrl
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
`,
|
|
775
|
+
{ serviceId, environmentId },
|
|
776
|
+
);
|
|
777
|
+
return deployment.serviceInstanceRedeploy;
|
|
778
|
+
};
|
|
779
|
+
|
|
780
|
+
const updateServiceInstanceLimits = async ({
|
|
781
|
+
serviceId,
|
|
782
|
+
environmentId,
|
|
783
|
+
memoryGB,
|
|
784
|
+
vCPUs,
|
|
785
|
+
} = {}) => {
|
|
786
|
+
const updated = await request(
|
|
787
|
+
`
|
|
788
|
+
mutation RailwayServiceInstanceLimitsUpdate(
|
|
789
|
+
$input: ServiceInstanceLimitsUpdateInput!
|
|
790
|
+
) {
|
|
791
|
+
serviceInstanceLimitsUpdate(input: $input)
|
|
792
|
+
}
|
|
793
|
+
`,
|
|
794
|
+
{
|
|
795
|
+
input: compactObject({
|
|
796
|
+
serviceId,
|
|
797
|
+
environmentId,
|
|
798
|
+
memoryGB,
|
|
799
|
+
vCPUs,
|
|
800
|
+
}),
|
|
801
|
+
},
|
|
802
|
+
);
|
|
803
|
+
return {
|
|
804
|
+
updated: Boolean(updated.serviceInstanceLimitsUpdate),
|
|
805
|
+
serviceId,
|
|
806
|
+
environmentId,
|
|
807
|
+
memoryGB: memoryGB ?? null,
|
|
808
|
+
vCPUs: vCPUs ?? null,
|
|
809
|
+
};
|
|
810
|
+
};
|
|
811
|
+
|
|
812
|
+
const createEnvironment = async (input = {}) => {
|
|
813
|
+
const environment = await request(
|
|
814
|
+
`
|
|
815
|
+
mutation RailwayEnvironmentCreate($input: EnvironmentCreateInput!) {
|
|
816
|
+
environmentCreate(input: $input) {
|
|
817
|
+
id
|
|
818
|
+
name
|
|
819
|
+
isEphemeral
|
|
820
|
+
projectId
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
`,
|
|
824
|
+
{ input: compactObject(input) },
|
|
825
|
+
);
|
|
826
|
+
return environment.environmentCreate;
|
|
827
|
+
};
|
|
828
|
+
|
|
829
|
+
const deleteEnvironment = async (environmentId) => {
|
|
830
|
+
const deleted = await request(
|
|
831
|
+
`
|
|
832
|
+
mutation RailwayEnvironmentDelete($id: String!) {
|
|
833
|
+
environmentDelete(id: $id)
|
|
834
|
+
}
|
|
835
|
+
`,
|
|
836
|
+
{ id: environmentId },
|
|
837
|
+
);
|
|
838
|
+
return {
|
|
839
|
+
deleted: Boolean(deleted.environmentDelete),
|
|
840
|
+
environmentId,
|
|
841
|
+
};
|
|
842
|
+
};
|
|
843
|
+
|
|
844
|
+
const upsertVariable = async (input = {}) => {
|
|
845
|
+
const updated = await request(
|
|
846
|
+
`
|
|
847
|
+
mutation RailwayVariableUpsert($input: VariableUpsertInput!) {
|
|
848
|
+
variableUpsert(input: $input)
|
|
849
|
+
}
|
|
850
|
+
`,
|
|
851
|
+
{ input: compactObject(input) },
|
|
852
|
+
);
|
|
853
|
+
return {
|
|
854
|
+
updated: Boolean(updated.variableUpsert),
|
|
855
|
+
name: input.name ?? null,
|
|
856
|
+
environmentId: input.environmentId ?? null,
|
|
857
|
+
serviceId: input.serviceId ?? null,
|
|
858
|
+
projectId: input.projectId ?? null,
|
|
859
|
+
};
|
|
860
|
+
};
|
|
861
|
+
|
|
862
|
+
const deleteVariable = async (input = {}) => {
|
|
863
|
+
const deleted = await request(
|
|
864
|
+
`
|
|
865
|
+
mutation RailwayVariableDelete($input: VariableDeleteInput!) {
|
|
866
|
+
variableDelete(input: $input)
|
|
867
|
+
}
|
|
868
|
+
`,
|
|
869
|
+
{ input: compactObject(input) },
|
|
870
|
+
);
|
|
871
|
+
return {
|
|
872
|
+
deleted: Boolean(deleted.variableDelete),
|
|
873
|
+
name: input.name ?? null,
|
|
874
|
+
environmentId: input.environmentId ?? null,
|
|
875
|
+
serviceId: input.serviceId ?? null,
|
|
876
|
+
projectId: input.projectId ?? null,
|
|
877
|
+
};
|
|
878
|
+
};
|
|
879
|
+
|
|
880
|
+
const createServiceDomain = async (input = {}) => {
|
|
881
|
+
const domain = await request(
|
|
882
|
+
`
|
|
883
|
+
mutation RailwayServiceDomainCreate($input: ServiceDomainCreateInput!) {
|
|
884
|
+
serviceDomainCreate(input: $input) {
|
|
885
|
+
id
|
|
886
|
+
domain
|
|
887
|
+
}
|
|
888
|
+
}
|
|
889
|
+
`,
|
|
890
|
+
{ input: compactObject(input) },
|
|
891
|
+
);
|
|
892
|
+
return domain.serviceDomainCreate;
|
|
893
|
+
};
|
|
894
|
+
|
|
895
|
+
const updateServiceDomain = async (input = {}) => {
|
|
896
|
+
const updated = await request(
|
|
897
|
+
`
|
|
898
|
+
mutation RailwayServiceDomainUpdate($input: ServiceDomainUpdateInput!) {
|
|
899
|
+
serviceDomainUpdate(input: $input)
|
|
900
|
+
}
|
|
901
|
+
`,
|
|
902
|
+
{ input: compactObject(input) },
|
|
903
|
+
);
|
|
904
|
+
return {
|
|
905
|
+
updated: Boolean(updated.serviceDomainUpdate),
|
|
906
|
+
serviceDomainId: input.serviceDomainId ?? null,
|
|
907
|
+
};
|
|
908
|
+
};
|
|
909
|
+
|
|
910
|
+
const deleteServiceDomain = async (serviceDomainId) => {
|
|
911
|
+
const deleted = await request(
|
|
912
|
+
`
|
|
913
|
+
mutation RailwayServiceDomainDelete($id: String!) {
|
|
914
|
+
serviceDomainDelete(id: $id)
|
|
915
|
+
}
|
|
916
|
+
`,
|
|
917
|
+
{ id: serviceDomainId },
|
|
918
|
+
);
|
|
919
|
+
return {
|
|
920
|
+
deleted: Boolean(deleted.serviceDomainDelete),
|
|
921
|
+
serviceDomainId,
|
|
922
|
+
};
|
|
923
|
+
};
|
|
924
|
+
|
|
925
|
+
const createCustomDomain = async (input = {}) => {
|
|
926
|
+
const domain = await request(
|
|
927
|
+
`
|
|
928
|
+
mutation RailwayCustomDomainCreate($input: CustomDomainCreateInput!) {
|
|
929
|
+
customDomainCreate(input: $input) {
|
|
930
|
+
id
|
|
931
|
+
domain
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
`,
|
|
935
|
+
{ input: compactObject(input) },
|
|
936
|
+
);
|
|
937
|
+
return domain.customDomainCreate;
|
|
938
|
+
};
|
|
939
|
+
|
|
940
|
+
const updateCustomDomain = async ({
|
|
941
|
+
customDomainId,
|
|
942
|
+
environmentId,
|
|
943
|
+
targetPort,
|
|
944
|
+
} = {}) => {
|
|
945
|
+
const updated = await request(
|
|
946
|
+
`
|
|
947
|
+
mutation RailwayCustomDomainUpdate(
|
|
948
|
+
$id: String!
|
|
949
|
+
$environmentId: String!
|
|
950
|
+
$targetPort: Int
|
|
951
|
+
) {
|
|
952
|
+
customDomainUpdate(
|
|
953
|
+
id: $id
|
|
954
|
+
environmentId: $environmentId
|
|
955
|
+
targetPort: $targetPort
|
|
956
|
+
)
|
|
957
|
+
}
|
|
958
|
+
`,
|
|
959
|
+
{ id: customDomainId, environmentId, targetPort },
|
|
960
|
+
);
|
|
961
|
+
return {
|
|
962
|
+
updated: Boolean(updated.customDomainUpdate),
|
|
963
|
+
customDomainId,
|
|
964
|
+
};
|
|
965
|
+
};
|
|
966
|
+
|
|
967
|
+
const deleteCustomDomain = async (customDomainId) => {
|
|
968
|
+
const deleted = await request(
|
|
969
|
+
`
|
|
970
|
+
mutation RailwayCustomDomainDelete($id: String!) {
|
|
971
|
+
customDomainDelete(id: $id)
|
|
972
|
+
}
|
|
973
|
+
`,
|
|
974
|
+
{ id: customDomainId },
|
|
975
|
+
);
|
|
976
|
+
return {
|
|
977
|
+
deleted: Boolean(deleted.customDomainDelete),
|
|
978
|
+
customDomainId,
|
|
979
|
+
};
|
|
980
|
+
};
|
|
981
|
+
|
|
982
|
+
const createVolume = async (input = {}) => {
|
|
983
|
+
const volume = await request(
|
|
984
|
+
`
|
|
985
|
+
mutation RailwayVolumeCreate($input: VolumeCreateInput!) {
|
|
986
|
+
volumeCreate(input: $input) {
|
|
987
|
+
id
|
|
988
|
+
}
|
|
989
|
+
}
|
|
990
|
+
`,
|
|
991
|
+
{ input: compactObject(input) },
|
|
992
|
+
);
|
|
993
|
+
return volume.volumeCreate;
|
|
994
|
+
};
|
|
995
|
+
|
|
996
|
+
const deleteVolume = async (volumeId) => {
|
|
997
|
+
const deleted = await request(
|
|
998
|
+
`
|
|
999
|
+
mutation RailwayVolumeDelete($volumeId: String!) {
|
|
1000
|
+
volumeDelete(volumeId: $volumeId)
|
|
1001
|
+
}
|
|
1002
|
+
`,
|
|
1003
|
+
{ volumeId },
|
|
1004
|
+
);
|
|
1005
|
+
return {
|
|
1006
|
+
deleted: Boolean(deleted.volumeDelete),
|
|
1007
|
+
volumeId,
|
|
1008
|
+
};
|
|
1009
|
+
};
|
|
1010
|
+
|
|
297
1011
|
const doctorProject = async ({ projectId } = {}) => {
|
|
298
1012
|
const project = await getProject(projectId);
|
|
299
1013
|
const primaryEnvironmentId =
|
|
@@ -348,11 +1062,43 @@ export const createRailwayClient = ({
|
|
|
348
1062
|
endpoint,
|
|
349
1063
|
getAuthStatus: () => getRailwayAuthStatus(env),
|
|
350
1064
|
getCurrentViewer,
|
|
1065
|
+
validateAccountToken,
|
|
351
1066
|
listProjects,
|
|
1067
|
+
createProject,
|
|
1068
|
+
updateProject,
|
|
1069
|
+
deleteProject,
|
|
1070
|
+
transferProject,
|
|
1071
|
+
getProjectMembers,
|
|
352
1072
|
getProjectTokenContext,
|
|
353
1073
|
getProject,
|
|
354
1074
|
listEnvironments,
|
|
355
1075
|
getEnvironment,
|
|
1076
|
+
createEnvironment,
|
|
1077
|
+
deleteEnvironment,
|
|
1078
|
+
getService,
|
|
1079
|
+
getServiceInstance,
|
|
1080
|
+
getServiceInstanceLimits,
|
|
1081
|
+
createService,
|
|
1082
|
+
updateService,
|
|
1083
|
+
connectService,
|
|
1084
|
+
disconnectService,
|
|
1085
|
+
deleteService,
|
|
1086
|
+
updateServiceInstance,
|
|
1087
|
+
deployService,
|
|
1088
|
+
redeployService,
|
|
1089
|
+
updateServiceInstanceLimits,
|
|
1090
|
+
getDeployment,
|
|
1091
|
+
listDeployments,
|
|
1092
|
+
upsertVariable,
|
|
1093
|
+
deleteVariable,
|
|
1094
|
+
createServiceDomain,
|
|
1095
|
+
updateServiceDomain,
|
|
1096
|
+
deleteServiceDomain,
|
|
1097
|
+
createCustomDomain,
|
|
1098
|
+
updateCustomDomain,
|
|
1099
|
+
deleteCustomDomain,
|
|
1100
|
+
createVolume,
|
|
1101
|
+
deleteVolume,
|
|
356
1102
|
doctorProject,
|
|
357
1103
|
};
|
|
358
1104
|
};
|
|
@@ -367,6 +1113,11 @@ const connectionNodes = (connection) => {
|
|
|
367
1113
|
return nodes;
|
|
368
1114
|
};
|
|
369
1115
|
|
|
1116
|
+
const compactObject = (value) =>
|
|
1117
|
+
Object.fromEntries(
|
|
1118
|
+
Object.entries(value ?? {}).filter(([, entry]) => entry !== undefined),
|
|
1119
|
+
);
|
|
1120
|
+
|
|
370
1121
|
const hasErrors = (payload) =>
|
|
371
1122
|
typeof payload === "object" &&
|
|
372
1123
|
payload !== null &&
|