@prisma/compute-sdk 0.1.0 → 0.3.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.
@@ -1,5 +1,6 @@
1
1
  import type { ManagementApiClient } from "@prisma/management-api-sdk";
2
2
  import { type InferOk, Result } from "better-result";
3
+ import invariant from "tiny-invariant";
3
4
  import {
4
5
  InternalApiClient,
5
6
  readUploadUrl,
@@ -15,18 +16,26 @@ import type {
15
16
  DestroyVersionProgress,
16
17
  UpdateEnvProgress,
17
18
  } from "./callbacks.ts";
18
- import type { ComputeError } from "./errors.ts";
19
19
  import {
20
20
  ApiError,
21
+ type ApiRequestError,
21
22
  ArtifactError,
23
+ type AuthenticationError,
22
24
  BuildError,
23
25
  CancelledError,
26
+ type DeployError,
24
27
  DestroyAggregateError,
28
+ type DestroyServiceError,
29
+ type DestroyVersionError,
25
30
  MissingArgumentError,
26
31
  NoExistingVersionError,
32
+ NoVersionsFoundError,
33
+ type UpdateEnvError,
34
+ type VersionOperationError,
27
35
  } from "./errors.ts";
28
36
  import { pollVersionStatus } from "./polling.ts";
29
37
  import type {
38
+ CreateProjectResult,
30
39
  PortMapping,
31
40
  ProjectInfo,
32
41
  ResolvedConfig,
@@ -110,6 +119,13 @@ export interface DeleteServiceOptions {
110
119
  signal?: AbortSignal;
111
120
  }
112
121
 
122
+ export interface CreateProjectOptions {
123
+ name: string;
124
+ createDatabase?: boolean;
125
+ region?: string;
126
+ signal?: AbortSignal;
127
+ }
128
+
113
129
  export interface ListProjectsOptions {
114
130
  signal?: AbortSignal;
115
131
  }
@@ -182,7 +198,7 @@ export class ComputeClient {
182
198
 
183
199
  async deploy(
184
200
  options: DeployOptions,
185
- ): Promise<Result<DeployResult, ComputeError>> {
201
+ ): Promise<Result<DeployResult, DeployError>> {
186
202
  const self = this;
187
203
  return Result.gen(async function* () {
188
204
  yield* self.#checkAborted(options.signal);
@@ -246,7 +262,9 @@ export class ComputeClient {
246
262
  yield* self.#checkAborted(options.signal);
247
263
 
248
264
  options.progress?.onUploadStart?.();
249
- yield* Result.await(self.#uploadArtifact(uploadUrl, archiveBytes));
265
+ yield* Result.await(
266
+ self.#uploadArtifact(uploadUrl, archiveBytes, options.signal),
267
+ );
250
268
  options.progress?.onUploadComplete?.();
251
269
 
252
270
  yield* self.#checkAborted(options.signal);
@@ -292,7 +310,7 @@ export class ComputeClient {
292
310
 
293
311
  async updateEnv(
294
312
  options: UpdateEnvOptions,
295
- ): Promise<Result<UpdateEnvResult, ComputeError>> {
313
+ ): Promise<Result<UpdateEnvResult, UpdateEnvError>> {
296
314
  const self = this;
297
315
  return Result.gen(async function* () {
298
316
  yield* self.#checkAborted(options.signal);
@@ -361,7 +379,7 @@ export class ComputeClient {
361
379
 
362
380
  async destroyVersion(
363
381
  options: DestroyVersionOptions,
364
- ): Promise<Result<DestroyVersionResult, ComputeError>> {
382
+ ): Promise<Result<DestroyVersionResult, DestroyVersionError>> {
365
383
  const self = this;
366
384
  return Result.gen(async function* () {
367
385
  yield* self.#checkAborted(options.signal);
@@ -402,7 +420,7 @@ export class ComputeClient {
402
420
  .sort(versionSortComparator);
403
421
 
404
422
  if (versionInfos.length === 0) {
405
- return Result.err(new MissingArgumentError({ field: "versionId" }));
423
+ return Result.err(new NoVersionsFoundError({ serviceId }));
406
424
  }
407
425
 
408
426
  if (!options.interaction?.selectVersion) {
@@ -451,7 +469,7 @@ export class ComputeClient {
451
469
 
452
470
  async destroyService(
453
471
  options: DestroyServiceOptions,
454
- ): Promise<Result<DestroyServiceResult, ComputeError>> {
472
+ ): Promise<Result<DestroyServiceResult, DestroyServiceError>> {
455
473
  const self = this;
456
474
  return Result.gen(async function* () {
457
475
  yield* self.#checkAborted(options.signal);
@@ -477,7 +495,10 @@ export class ComputeClient {
477
495
  );
478
496
 
479
497
  const succeededIds: string[] = [];
480
- const failures: Array<{ versionId: string; error: ComputeError }> = [];
498
+ const failures: Array<{
499
+ versionId: string;
500
+ error: VersionOperationError;
501
+ }> = [];
481
502
 
482
503
  if (activeVersions.length > 0) {
483
504
  const activeIds = activeVersions.map((v) => v.id);
@@ -594,9 +615,48 @@ export class ComputeClient {
594
615
  });
595
616
  }
596
617
 
618
+ async createProject(
619
+ options: CreateProjectOptions,
620
+ ): Promise<Result<CreateProjectResult, ApiRequestError>> {
621
+ const self = this;
622
+ return Result.gen(async function* () {
623
+ yield* self.#checkAborted(options.signal);
624
+ const createDatabase = options.createDatabase ?? false;
625
+ const response = yield* Result.await(
626
+ self.#api.createProject(
627
+ {
628
+ name: options.name,
629
+ createDatabase,
630
+ region: options.region,
631
+ },
632
+ options.signal,
633
+ ),
634
+ );
635
+
636
+ const result: CreateProjectResult = {
637
+ id: response.id,
638
+ name: response.name,
639
+ defaultRegion: response.defaultRegion ?? undefined,
640
+ };
641
+
642
+ if (response.database) {
643
+ const connection = response.database.connections?.[0];
644
+ result.database = {
645
+ id: response.database.id,
646
+ name: response.database.name,
647
+ region: response.database.region.id,
648
+ connectionString:
649
+ connection?.endpoints?.direct?.connectionString ?? undefined,
650
+ };
651
+ }
652
+
653
+ return Result.ok(result);
654
+ });
655
+ }
656
+
597
657
  async listProjects(
598
658
  options: ListProjectsOptions = {},
599
- ): Promise<Result<ProjectInfo[], ComputeError>> {
659
+ ): Promise<Result<ProjectInfo[], ApiRequestError>> {
600
660
  const self = this;
601
661
  return Result.gen(async function* () {
602
662
  yield* self.#checkAborted(options.signal);
@@ -617,7 +677,7 @@ export class ComputeClient {
617
677
 
618
678
  async listServices(
619
679
  options: ListServicesOptions,
620
- ): Promise<Result<ServiceInfo[], ComputeError>> {
680
+ ): Promise<Result<ServiceInfo[], ApiRequestError>> {
621
681
  const self = this;
622
682
  return Result.gen(async function* () {
623
683
  yield* self.#checkAborted(options.signal);
@@ -639,7 +699,7 @@ export class ComputeClient {
639
699
 
640
700
  async createService(
641
701
  options: CreateServiceOptions,
642
- ): Promise<Result<ServiceInfo, ComputeError>> {
702
+ ): Promise<Result<ServiceInfo, ApiRequestError>> {
643
703
  const self = this;
644
704
  return Result.gen(async function* () {
645
705
  yield* self.#checkAborted(options.signal);
@@ -664,7 +724,7 @@ export class ComputeClient {
664
724
 
665
725
  async showService(
666
726
  options: ShowServiceOptions,
667
- ): Promise<Result<ServiceDetail, ComputeError>> {
727
+ ): Promise<Result<ServiceDetail, ApiRequestError>> {
668
728
  const self = this;
669
729
  return Result.gen(async function* () {
670
730
  yield* self.#checkAborted(options.signal);
@@ -683,7 +743,7 @@ export class ComputeClient {
683
743
 
684
744
  async deleteService(
685
745
  options: DeleteServiceOptions,
686
- ): Promise<Result<void, ComputeError>> {
746
+ ): Promise<Result<void, ApiRequestError>> {
687
747
  const self = this;
688
748
  return Result.gen(async function* () {
689
749
  yield* self.#checkAborted(options.signal);
@@ -696,7 +756,7 @@ export class ComputeClient {
696
756
 
697
757
  async listVersions(
698
758
  options: ListVersionsOptions,
699
- ): Promise<Result<VersionInfo[], ComputeError>> {
759
+ ): Promise<Result<VersionInfo[], ApiRequestError>> {
700
760
  const self = this;
701
761
  return Result.gen(async function* () {
702
762
  yield* self.#checkAborted(options.signal);
@@ -732,7 +792,7 @@ export class ComputeClient {
732
792
 
733
793
  async showVersion(
734
794
  options: ShowVersionOptions,
735
- ): Promise<Result<VersionDetail, ComputeError>> {
795
+ ): Promise<Result<VersionDetail, ApiRequestError>> {
736
796
  const self = this;
737
797
  return Result.gen(async function* () {
738
798
  yield* self.#checkAborted(options.signal);
@@ -751,7 +811,7 @@ export class ComputeClient {
751
811
 
752
812
  async startVersion(
753
813
  options: StartVersionOptions,
754
- ): Promise<Result<void, ComputeError>> {
814
+ ): Promise<Result<void, ApiRequestError>> {
755
815
  const self = this;
756
816
  return Result.gen(async function* () {
757
817
  yield* self.#checkAborted(options.signal);
@@ -764,7 +824,7 @@ export class ComputeClient {
764
824
 
765
825
  async stopVersion(
766
826
  options: StopVersionOptions,
767
- ): Promise<Result<void, ComputeError>> {
827
+ ): Promise<Result<void, ApiRequestError>> {
768
828
  const self = this;
769
829
  return Result.gen(async function* () {
770
830
  yield* self.#checkAborted(options.signal);
@@ -777,7 +837,7 @@ export class ComputeClient {
777
837
 
778
838
  async deleteVersion(
779
839
  options: DeleteVersionOptions,
780
- ): Promise<Result<void, ComputeError>> {
840
+ ): Promise<Result<void, ApiRequestError>> {
781
841
  const self = this;
782
842
  return Result.gen(async function* () {
783
843
  yield* self.#checkAborted(options.signal);
@@ -810,7 +870,7 @@ export class ComputeClient {
810
870
  serviceName: string;
811
871
  region: string;
812
872
  },
813
- CancelledError | MissingArgumentError | ComputeError
873
+ MissingArgumentError | CancelledError | AuthenticationError | ApiError
814
874
  >
815
875
  > {
816
876
  const self = this;
@@ -891,9 +951,7 @@ export class ComputeClient {
891
951
 
892
952
  if (selectedServiceId !== null) {
893
953
  const service = services.find((s) => s.id === selectedServiceId);
894
- if (!service) {
895
- throw new Error("selectService returned service ID not in the list");
896
- }
954
+ invariant(service, "selectService returned service ID not in the list");
897
955
  return Result.ok({
898
956
  projectId,
899
957
  serviceId: selectedServiceId,
@@ -941,13 +999,15 @@ export class ComputeClient {
941
999
  async #uploadArtifact(
942
1000
  url: string,
943
1001
  body: Uint8Array,
944
- ): Promise<Result<void, ArtifactError>> {
1002
+ signal?: AbortSignal,
1003
+ ): Promise<Result<void, ArtifactError | CancelledError>> {
945
1004
  return Result.tryPromise({
946
1005
  try: async () => {
947
1006
  const res = await fetch(url, {
948
1007
  method: "PUT",
949
1008
  headers: { "content-type": "application/gzip" },
950
1009
  body,
1010
+ signal,
951
1011
  });
952
1012
 
953
1013
  if (!res.ok) {
@@ -964,10 +1024,12 @@ export class ComputeClient {
964
1024
  }
965
1025
  },
966
1026
  catch: (e) =>
967
- new ArtifactError({
968
- message: e instanceof Error ? e.message : String(e),
969
- cause: e,
970
- }),
1027
+ signal?.aborted
1028
+ ? new CancelledError()
1029
+ : new ArtifactError({
1030
+ message: e instanceof Error ? e.message : String(e),
1031
+ cause: e,
1032
+ }),
971
1033
  });
972
1034
  }
973
1035
  }
package/src/errors.ts CHANGED
@@ -80,6 +80,18 @@ export class NoExistingVersionError extends TaggedError(
80
80
  }
81
81
  }
82
82
 
83
+ export class NoVersionsFoundError extends TaggedError("NoVersionsFoundError")<{
84
+ serviceId: string;
85
+ message: string;
86
+ }>() {
87
+ constructor(args: { serviceId: string }) {
88
+ super({
89
+ serviceId: args.serviceId,
90
+ message: `Service ${args.serviceId} has no versions to destroy`,
91
+ });
92
+ }
93
+ }
94
+
83
95
  export class CancelledError extends TaggedError("CancelledError")<{
84
96
  message: string;
85
97
  }>() {
@@ -93,12 +105,12 @@ export class DestroyAggregateError extends TaggedError(
93
105
  )<{
94
106
  message: string;
95
107
  succeededVersionIds: string[];
96
- failures: Array<{ versionId: string; error: ComputeError }>;
108
+ failures: Array<{ versionId: string; error: VersionOperationError }>;
97
109
  serviceDeleted: boolean;
98
110
  }>() {
99
111
  constructor(args: {
100
112
  succeededVersionIds: string[];
101
- failures: Array<{ versionId: string; error: ComputeError }>;
113
+ failures: Array<{ versionId: string; error: VersionOperationError }>;
102
114
  serviceDeleted: boolean;
103
115
  }) {
104
116
  const failedIds = args.failures.map((f) => f.versionId).join(", ");
@@ -109,18 +121,6 @@ export class DestroyAggregateError extends TaggedError(
109
121
  }
110
122
  }
111
123
 
112
- export type ComputeError =
113
- | AuthenticationError
114
- | ApiError
115
- | MissingArgumentError
116
- | BuildError
117
- | ArtifactError
118
- | TimeoutError
119
- | VersionFailedError
120
- | NoExistingVersionError
121
- | CancelledError
122
- | DestroyAggregateError;
123
-
124
124
  export type DeployError =
125
125
  | AuthenticationError
126
126
  | ApiError
@@ -140,9 +140,26 @@ export type UpdateEnvError =
140
140
  | VersionFailedError
141
141
  | CancelledError;
142
142
 
143
- export type DestroyError =
143
+ export type DestroyVersionError =
144
+ | CancelledError
145
+ | MissingArgumentError
146
+ | NoVersionsFoundError
144
147
  | AuthenticationError
145
148
  | ApiError
146
- | MissingArgumentError
149
+ | TimeoutError
150
+ | VersionFailedError;
151
+
152
+ export type DestroyServiceError =
147
153
  | CancelledError
154
+ | AuthenticationError
155
+ | ApiError
148
156
  | DestroyAggregateError;
157
+
158
+ export type ApiRequestError = CancelledError | AuthenticationError | ApiError;
159
+
160
+ export type VersionOperationError =
161
+ | CancelledError
162
+ | AuthenticationError
163
+ | ApiError
164
+ | TimeoutError
165
+ | VersionFailedError;
package/src/index.ts CHANGED
@@ -21,6 +21,7 @@ export type {
21
21
  UpdateEnvProgress,
22
22
  } from "./callbacks.ts";
23
23
  export type {
24
+ CreateProjectOptions,
24
25
  CreateServiceOptions,
25
26
  DeleteServiceOptions,
26
27
  DeleteVersionOptions,
@@ -43,10 +44,12 @@ export type {
43
44
  // Core client
44
45
  export { ComputeClient } from "./compute-client.ts";
45
46
  export type {
46
- ComputeError,
47
+ ApiRequestError,
47
48
  DeployError,
48
- DestroyError,
49
+ DestroyServiceError,
50
+ DestroyVersionError,
49
51
  UpdateEnvError,
52
+ VersionOperationError,
50
53
  } from "./errors.ts";
51
54
  // Errors
52
55
  export {
@@ -58,11 +61,14 @@ export {
58
61
  DestroyAggregateError,
59
62
  MissingArgumentError,
60
63
  NoExistingVersionError,
64
+ NoVersionsFoundError,
61
65
  TimeoutError,
62
66
  VersionFailedError,
63
67
  } from "./errors.ts";
64
68
  // Domain types
65
69
  export type {
70
+ CreateProjectResult,
71
+ DatabaseInfo,
66
72
  PortMapping,
67
73
  ProjectInfo,
68
74
  RegionInfo,
package/src/polling.ts CHANGED
@@ -45,7 +45,9 @@ export async function pollVersionStatus(
45
45
  return Result.err(new CancelledError());
46
46
  }
47
47
 
48
- const version = yield* Result.await(api.getVersion(versionId));
48
+ const version = yield* Result.await(
49
+ api.getVersion(versionId, options.signal),
50
+ );
49
51
 
50
52
  if (version.status !== lastStatus) {
51
53
  lastStatus = version.status;
package/src/types.ts CHANGED
@@ -12,6 +12,17 @@ export interface ProjectInfo {
12
12
  defaultRegion?: string;
13
13
  }
14
14
 
15
+ export interface DatabaseInfo {
16
+ id: string;
17
+ name: string;
18
+ region: string;
19
+ connectionString?: string;
20
+ }
21
+
22
+ export interface CreateProjectResult extends ProjectInfo {
23
+ database?: DatabaseInfo;
24
+ }
25
+
15
26
  export interface ServiceInfo {
16
27
  id: string;
17
28
  name: string;