@aepstore-dev/contracts 1.1.0 → 1.2.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.
package/gen/upload.ts CHANGED
@@ -10,84 +10,203 @@ import { Observable } from "rxjs";
10
10
 
11
11
  export const protobufPackage = "upload.v1";
12
12
 
13
- export interface FileChunk {
14
- filename: string;
15
- data: Uint8Array;
13
+ /**
14
+ * Determines the object key prefix (and future ACL/privacy policy).
15
+ * ATTACHMENT = paid product deliverable (private; presigned GET only after purchase).
16
+ * MEDIA / AVATAR / BANNER = preview assets.
17
+ */
18
+ export enum UploadKind {
19
+ UPLOAD_KIND_UNSPECIFIED = 0,
20
+ UPLOAD_KIND_ATTACHMENT = 1,
21
+ UPLOAD_KIND_MEDIA = 2,
22
+ UPLOAD_KIND_AVATAR = 3,
23
+ UPLOAD_KIND_BANNER = 4,
24
+ UNRECOGNIZED = -1,
25
+ }
26
+
27
+ export interface Ok {
28
+ ok: boolean;
29
+ }
30
+
31
+ export interface CreateMultipartUploadRequest {
32
+ fileName: string;
16
33
  mimeType: string;
17
- isLast: boolean;
18
- chunkIndex: number;
34
+ fileSize: number;
35
+ kind: UploadKind;
36
+ /** user initiating, for key namespacing + audit */
37
+ ownerId: string;
38
+ }
39
+
40
+ export interface CreateMultipartUploadResponse {
41
+ /** S3 multipart UploadId */
19
42
  uploadId: string;
43
+ /** object key this service generated */
44
+ fileKey: string;
45
+ /** recommended part size (bytes) the client should slice with */
46
+ partSize: number;
47
+ /** number of parts for file_size at part_size */
48
+ partCount: number;
20
49
  }
21
50
 
22
- export interface UploadResponse {
23
- fileUrl: string;
24
- success: boolean;
25
- message: string;
51
+ export interface SignPartRequest {
52
+ fileKey: string;
26
53
  uploadId: string;
54
+ /** 1-based */
55
+ partNumber: number;
56
+ }
57
+
58
+ export interface SignPartResponse {
59
+ /** presigned PUT URL for this single part */
60
+ url: string;
61
+ expiresIn: number;
62
+ }
63
+
64
+ export interface CompletedPart {
65
+ partNumber: number;
66
+ /** ETag the client received in the S3 PUT response header for this part */
67
+ etag: string;
68
+ }
69
+
70
+ export interface CompleteMultipartUploadRequest {
71
+ fileKey: string;
72
+ uploadId: string;
73
+ parts: CompletedPart[];
74
+ }
75
+
76
+ export interface CompleteMultipartUploadResponse {
77
+ fileKey: string;
78
+ /** final object location (internal reference) */
79
+ location: string;
27
80
  fileSize: number;
28
81
  }
29
82
 
30
- export interface UploadStatusRequest {
83
+ export interface AbortMultipartUploadRequest {
84
+ fileKey: string;
31
85
  uploadId: string;
32
86
  }
33
87
 
34
- export interface UploadStatusResponse {
35
- status: string;
36
- progressPercent: number;
37
- message: string;
88
+ export interface CreateUploadUrlRequest {
89
+ fileName: string;
90
+ mimeType: string;
91
+ kind: UploadKind;
92
+ ownerId: string;
93
+ }
94
+
95
+ export interface CreateUploadUrlResponse {
96
+ /** presigned PUT URL (client PUTs the whole file) */
97
+ url: string;
98
+ fileKey: string;
99
+ expiresIn: number;
38
100
  }
39
101
 
40
102
  export interface SignedUrlRequest {
41
103
  fileKey: string;
104
+ /** optional, default 3600 */
42
105
  expiresIn: number;
106
+ /** optional: forces Content-Disposition attachment filename */
107
+ downloadFileName: string;
43
108
  }
44
109
 
45
110
  export interface SignedUrlResponse {
46
111
  signedUrl: string;
47
- success: boolean;
48
- message: string;
112
+ expiresIn: number;
113
+ }
114
+
115
+ export interface DeleteObjectRequest {
116
+ fileKey: string;
49
117
  }
50
118
 
51
119
  export const UPLOAD_V1_PACKAGE_NAME = "upload.v1";
52
120
 
53
121
  /**
54
- * Ported from legacy libs/shared/src/proto/upload.proto.
55
- * Bumped package to upload.v1 for consistency with the rest of the new stack.
122
+ * Thin signing service. File bytes NEVER pass through this service — clients
123
+ * upload/download directly to/from S3 (Yandex Object Storage) using presigned
124
+ * URLs this service mints. Memory/bandwidth flat regardless of file size.
125
+ *
126
+ * Large files (product deliverables, up to ~1GB) use the multipart flow:
127
+ * CreateMultipartUpload → (SignPart × N, client PUTs each part to S3) →
128
+ * CompleteMultipartUpload (or AbortMultipartUpload on failure)
129
+ *
130
+ * Small files (preview images, avatars) use the single-PUT flow: CreateUploadUrl.
131
+ *
132
+ * Downloads are gated elsewhere (products-service verifies purchase, then calls
133
+ * GenerateSignedUrl). This service does not know about purchases.
56
134
  */
57
135
 
58
136
  export interface UploadServiceClient {
59
- uploadFile(request: Observable<FileChunk>): Observable<UploadResponse>;
137
+ createMultipartUpload(request: CreateMultipartUploadRequest): Observable<CreateMultipartUploadResponse>;
138
+
139
+ signPart(request: SignPartRequest): Observable<SignPartResponse>;
140
+
141
+ completeMultipartUpload(request: CompleteMultipartUploadRequest): Observable<CompleteMultipartUploadResponse>;
142
+
143
+ abortMultipartUpload(request: AbortMultipartUploadRequest): Observable<Ok>;
60
144
 
61
- getUploadStatus(request: UploadStatusRequest): Observable<UploadStatusResponse>;
145
+ createUploadUrl(request: CreateUploadUrlRequest): Observable<CreateUploadUrlResponse>;
62
146
 
63
147
  generateSignedUrl(request: SignedUrlRequest): Observable<SignedUrlResponse>;
148
+
149
+ deleteObject(request: DeleteObjectRequest): Observable<Ok>;
64
150
  }
65
151
 
66
152
  /**
67
- * Ported from legacy libs/shared/src/proto/upload.proto.
68
- * Bumped package to upload.v1 for consistency with the rest of the new stack.
153
+ * Thin signing service. File bytes NEVER pass through this service — clients
154
+ * upload/download directly to/from S3 (Yandex Object Storage) using presigned
155
+ * URLs this service mints. Memory/bandwidth flat regardless of file size.
156
+ *
157
+ * Large files (product deliverables, up to ~1GB) use the multipart flow:
158
+ * CreateMultipartUpload → (SignPart × N, client PUTs each part to S3) →
159
+ * CompleteMultipartUpload (or AbortMultipartUpload on failure)
160
+ *
161
+ * Small files (preview images, avatars) use the single-PUT flow: CreateUploadUrl.
162
+ *
163
+ * Downloads are gated elsewhere (products-service verifies purchase, then calls
164
+ * GenerateSignedUrl). This service does not know about purchases.
69
165
  */
70
166
 
71
167
  export interface UploadServiceController {
72
- uploadFile(request: Observable<FileChunk>): Promise<UploadResponse> | Observable<UploadResponse> | UploadResponse;
168
+ createMultipartUpload(
169
+ request: CreateMultipartUploadRequest,
170
+ ): Promise<CreateMultipartUploadResponse> | Observable<CreateMultipartUploadResponse> | CreateMultipartUploadResponse;
171
+
172
+ signPart(request: SignPartRequest): Promise<SignPartResponse> | Observable<SignPartResponse> | SignPartResponse;
173
+
174
+ completeMultipartUpload(
175
+ request: CompleteMultipartUploadRequest,
176
+ ):
177
+ | Promise<CompleteMultipartUploadResponse>
178
+ | Observable<CompleteMultipartUploadResponse>
179
+ | CompleteMultipartUploadResponse;
73
180
 
74
- getUploadStatus(
75
- request: UploadStatusRequest,
76
- ): Promise<UploadStatusResponse> | Observable<UploadStatusResponse> | UploadStatusResponse;
181
+ abortMultipartUpload(request: AbortMultipartUploadRequest): Promise<Ok> | Observable<Ok> | Ok;
182
+
183
+ createUploadUrl(
184
+ request: CreateUploadUrlRequest,
185
+ ): Promise<CreateUploadUrlResponse> | Observable<CreateUploadUrlResponse> | CreateUploadUrlResponse;
77
186
 
78
187
  generateSignedUrl(
79
188
  request: SignedUrlRequest,
80
189
  ): Promise<SignedUrlResponse> | Observable<SignedUrlResponse> | SignedUrlResponse;
190
+
191
+ deleteObject(request: DeleteObjectRequest): Promise<Ok> | Observable<Ok> | Ok;
81
192
  }
82
193
 
83
194
  export function UploadServiceControllerMethods() {
84
195
  return function (constructor: Function) {
85
- const grpcMethods: string[] = ["getUploadStatus", "generateSignedUrl"];
196
+ const grpcMethods: string[] = [
197
+ "createMultipartUpload",
198
+ "signPart",
199
+ "completeMultipartUpload",
200
+ "abortMultipartUpload",
201
+ "createUploadUrl",
202
+ "generateSignedUrl",
203
+ "deleteObject",
204
+ ];
86
205
  for (const method of grpcMethods) {
87
206
  const descriptor: any = Reflect.getOwnPropertyDescriptor(constructor.prototype, method);
88
207
  GrpcMethod("UploadService", method)(constructor.prototype[method], method, descriptor);
89
208
  }
90
- const grpcStreamMethods: string[] = ["uploadFile"];
209
+ const grpcStreamMethods: string[] = [];
91
210
  for (const method of grpcStreamMethods) {
92
211
  const descriptor: any = Reflect.getOwnPropertyDescriptor(constructor.prototype, method);
93
212
  GrpcStreamMethod("UploadService", method)(constructor.prototype[method], method, descriptor);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aepstore-dev/contracts",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Protobuf definitions for aepstore microservices",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",
@@ -2,48 +2,134 @@ syntax = "proto3";
2
2
 
3
3
  package upload.v1;
4
4
 
5
- // Ported from legacy libs/shared/src/proto/upload.proto.
6
- // Bumped package to upload.v1 for consistency with the rest of the new stack.
5
+ // Thin signing service. File bytes NEVER pass through this service — clients
6
+ // upload/download directly to/from S3 (Yandex Object Storage) using presigned
7
+ // URLs this service mints. Memory/bandwidth flat regardless of file size.
8
+ //
9
+ // Large files (product deliverables, up to ~1GB) use the multipart flow:
10
+ // CreateMultipartUpload → (SignPart × N, client PUTs each part to S3) →
11
+ // CompleteMultipartUpload (or AbortMultipartUpload on failure)
12
+ //
13
+ // Small files (preview images, avatars) use the single-PUT flow: CreateUploadUrl.
14
+ //
15
+ // Downloads are gated elsewhere (products-service verifies purchase, then calls
16
+ // GenerateSignedUrl). This service does not know about purchases.
7
17
  service UploadService {
8
- rpc UploadFile(stream FileChunk) returns (UploadResponse);
9
- rpc GetUploadStatus(UploadStatusRequest) returns (UploadStatusResponse);
18
+ rpc CreateMultipartUpload(CreateMultipartUploadRequest) returns (CreateMultipartUploadResponse);
19
+ rpc SignPart(SignPartRequest) returns (SignPartResponse);
20
+ rpc CompleteMultipartUpload(CompleteMultipartUploadRequest) returns (CompleteMultipartUploadResponse);
21
+ rpc AbortMultipartUpload(AbortMultipartUploadRequest) returns (Ok);
22
+
23
+ rpc CreateUploadUrl(CreateUploadUrlRequest) returns (CreateUploadUrlResponse);
24
+
10
25
  rpc GenerateSignedUrl(SignedUrlRequest) returns (SignedUrlResponse);
26
+
27
+ rpc DeleteObject(DeleteObjectRequest) returns (Ok);
11
28
  }
12
29
 
13
- message FileChunk {
14
- string filename = 1;
15
- bytes data = 2;
16
- string mime_type = 3;
17
- bool is_last = 4;
18
- int32 chunk_index = 5;
19
- string upload_id = 6;
30
+ // Determines the object key prefix (and future ACL/privacy policy).
31
+ // ATTACHMENT = paid product deliverable (private; presigned GET only after purchase).
32
+ // MEDIA / AVATAR / BANNER = preview assets.
33
+ enum UploadKind {
34
+ UPLOAD_KIND_UNSPECIFIED = 0;
35
+ UPLOAD_KIND_ATTACHMENT = 1;
36
+ UPLOAD_KIND_MEDIA = 2;
37
+ UPLOAD_KIND_AVATAR = 3;
38
+ UPLOAD_KIND_BANNER = 4;
20
39
  }
21
40
 
22
- message UploadResponse {
23
- string file_url = 1;
24
- bool success = 2;
25
- string message = 3;
26
- string upload_id = 4;
27
- int64 file_size = 5;
41
+ message Ok {
42
+ bool ok = 1;
28
43
  }
29
44
 
30
- message UploadStatusRequest {
31
- string upload_id = 1;
45
+ // ---------------------------------------------------------------------------
46
+ // Multipart upload (large files)
47
+ // ---------------------------------------------------------------------------
48
+
49
+ message CreateMultipartUploadRequest {
50
+ string file_name = 1;
51
+ string mime_type = 2;
52
+ int64 file_size = 3;
53
+ UploadKind kind = 4;
54
+ string owner_id = 5; // user initiating, for key namespacing + audit
32
55
  }
33
56
 
34
- message UploadStatusResponse {
35
- string status = 1;
36
- int32 progress_percent = 2;
37
- string message = 3;
57
+ message CreateMultipartUploadResponse {
58
+ string upload_id = 1; // S3 multipart UploadId
59
+ string file_key = 2; // object key this service generated
60
+ int64 part_size = 3; // recommended part size (bytes) the client should slice with
61
+ int32 part_count = 4; // number of parts for file_size at part_size
38
62
  }
39
63
 
40
- message SignedUrlRequest {
64
+ message SignPartRequest {
41
65
  string file_key = 1;
66
+ string upload_id = 2;
67
+ int32 part_number = 3; // 1-based
68
+ }
69
+
70
+ message SignPartResponse {
71
+ string url = 1; // presigned PUT URL for this single part
42
72
  int32 expires_in = 2;
43
73
  }
44
74
 
75
+ message CompletedPart {
76
+ int32 part_number = 1;
77
+ string etag = 2; // ETag the client received in the S3 PUT response header for this part
78
+ }
79
+
80
+ message CompleteMultipartUploadRequest {
81
+ string file_key = 1;
82
+ string upload_id = 2;
83
+ repeated CompletedPart parts = 3;
84
+ }
85
+
86
+ message CompleteMultipartUploadResponse {
87
+ string file_key = 1;
88
+ string location = 2; // final object location (internal reference)
89
+ int64 file_size = 3;
90
+ }
91
+
92
+ message AbortMultipartUploadRequest {
93
+ string file_key = 1;
94
+ string upload_id = 2;
95
+ }
96
+
97
+ // ---------------------------------------------------------------------------
98
+ // Single-PUT upload (small files)
99
+ // ---------------------------------------------------------------------------
100
+
101
+ message CreateUploadUrlRequest {
102
+ string file_name = 1;
103
+ string mime_type = 2;
104
+ UploadKind kind = 3;
105
+ string owner_id = 4;
106
+ }
107
+
108
+ message CreateUploadUrlResponse {
109
+ string url = 1; // presigned PUT URL (client PUTs the whole file)
110
+ string file_key = 2;
111
+ int32 expires_in = 3;
112
+ }
113
+
114
+ // ---------------------------------------------------------------------------
115
+ // Download
116
+ // ---------------------------------------------------------------------------
117
+
118
+ message SignedUrlRequest {
119
+ string file_key = 1;
120
+ int32 expires_in = 2; // optional, default 3600
121
+ string download_file_name = 3; // optional: forces Content-Disposition attachment filename
122
+ }
123
+
45
124
  message SignedUrlResponse {
46
125
  string signed_url = 1;
47
- bool success = 2;
48
- string message = 3;
126
+ int32 expires_in = 2;
127
+ }
128
+
129
+ // ---------------------------------------------------------------------------
130
+ // Cleanup
131
+ // ---------------------------------------------------------------------------
132
+
133
+ message DeleteObjectRequest {
134
+ string file_key = 1;
49
135
  }