@aepstore-dev/contracts 1.66.0 → 1.68.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/products.ts CHANGED
@@ -1,607 +1,614 @@
1
- // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
- // versions:
3
- // protoc-gen-ts_proto v2.10.1
4
- // protoc v7.35.0
5
- // source: products.proto
6
-
7
- /* eslint-disable */
8
- import { GrpcMethod, GrpcStreamMethod } from "@nestjs/microservices";
9
- import { Observable } from "rxjs";
10
-
11
- export const protobufPackage = "products.v1";
12
-
13
- /**
14
- * Member names match the DB enum string values exactly (enums: String on the
15
- * wire) so values pass straight through with no mapping. UNSPECIFIED=0 covers
16
- * null/optional (e.g. nullable moderation_status, missing list filters).
17
- */
18
- export enum ProductStatus {
19
- PRODUCT_STATUS_UNSPECIFIED = 0,
20
- ACTIVE = 1,
21
- DRAFT = 2,
22
- UNRECOGNIZED = -1,
23
- }
24
-
25
- export enum ModerationStatus {
26
- MODERATION_STATUS_UNSPECIFIED = 0,
27
- PENDING = 1,
28
- APPROVED = 2,
29
- REJECTED = 3,
30
- UNRECOGNIZED = -1,
31
- }
32
-
33
- export enum MediaType {
34
- MEDIA_TYPE_UNSPECIFIED = 0,
35
- IMAGE = 1,
36
- VIDEO = 2,
37
- UNRECOGNIZED = -1,
38
- }
39
-
40
- export interface Category {
41
- id: string;
42
- name: string;
43
- }
44
-
45
- export interface Application {
46
- id: string;
47
- name: string;
48
- }
49
-
50
- export interface Tag {
51
- id: string;
52
- name: string;
53
- }
54
-
55
- export interface ProductMedia {
56
- id: string;
57
- url: string;
58
- type: MediaType;
59
- }
60
-
61
- export interface Attachment {
62
- id: string;
63
- url: string;
64
- fileKey: string;
65
- fileName: string;
66
- fileSize: number;
67
- createdAt: string;
68
- }
69
-
70
- export interface ProductUser {
71
- id: string;
72
- username: string;
73
- avatarUrl: string;
74
- }
75
-
76
- /**
77
- * Moderation block — null on the product while it's a DRAFT / never submitted.
78
- * status is one of PENDING | APPROVED | REJECTED (never UNSPECIFIED here).
79
- */
80
- export interface ProductModeration {
81
- status: ModerationStatus;
82
- /** moderator note (mainly on REJECTED) */
83
- comment: string;
84
- /** moderator user id */
85
- moderatedBy: string;
86
- /** ISO 8601 */
87
- moderatedAt: string;
88
- }
89
-
90
- export interface Product {
91
- id: string;
92
- name: string;
93
- description: string;
94
- /** Decimal as string (D7), in `currency` */
95
- price: string;
96
- /** Decimal as string */
97
- discountPercent: string;
98
- /** Decimal as string, in `currency` */
99
- finalPrice: string;
100
- /**
101
- * Converted final_price display amounts by currency (RUB/USD/EUR).
102
- * Not persisted; computed from the cached payments-service FX rates.
103
- */
104
- prices: { [key: string]: string };
105
- /** double as string for consistency */
106
- averageRating: string;
107
- status: ProductStatus;
108
- /**
109
- * Listing currency the seller priced in: RUB | USD | EUR (default RUB).
110
- * Settlement/ledger is always RUB — conversion is snapshotted at checkout.
111
- */
112
- currency: string;
113
- /** null while DRAFT / not yet submitted */
114
- moderation: ProductModeration | undefined;
115
- createdAt: string;
116
- updatedAt: string;
117
- /** ISO 8601 when soft-deleted, empty/null otherwise */
118
- deletedAt: string;
119
- preview: string;
120
- video: string;
121
- user: ProductUser | undefined;
122
- media: ProductMedia[];
123
- categories: Category[];
124
- applications: Application[];
125
- tags: Tag[];
126
- /** Aggregate counts (populated where the query includes _count). */
127
- favoritesCount: number;
128
- viewsCount: number;
129
- reviewsCount: number;
130
- /** Viewer-contextual flags (populated by FindOne when a viewer is known). */
131
- owner: boolean;
132
- isFavorite: boolean;
133
- isViewed: boolean;
134
- /** owner-only, current-month revenue (Decimal as string) */
135
- revenue: string;
136
- /** viewer has a COMPLETED purchase of this product */
137
- isBuyed: boolean;
138
- /** viewer has already left a review on this product */
139
- isReviewed: boolean;
140
- /** Popularity (populated by GetTopProduct / GetPopularProducts). */
141
- popularityScore: string;
142
- /**
143
- * OWNER-ONLY: the product's deliverable files. Populated by FindOne only
144
- * when the viewer is the product owner; empty for everyone else (never
145
- * exposes private attachment metadata to non-owners).
146
- */
147
- attachments: ProductAttachment[];
148
- }
149
-
150
- export interface Product_PricesEntry {
151
- key: string;
152
- value: string;
153
- }
154
-
155
- export interface ProductAttachment {
156
- id: string;
157
- fileName: string;
158
- fileSize: number;
159
- }
160
-
161
- /** Compact product shape for "related products" — only the fields a card needs. */
162
- export interface RelatedProduct {
163
- id: string;
164
- name: string;
165
- /** Decimal as string */
166
- price: string;
167
- /** Decimal as string */
168
- discountPercent: string;
169
- /** Decimal as string */
170
- finalPrice: string;
171
- preview: string;
172
- user: ProductUser | undefined;
173
- categories: Category[];
174
- /** RUB | USD | EUR */
175
- currency: string;
176
- /** Converted final_price display amounts. */
177
- prices: { [key: string]: string };
178
- }
179
-
180
- export interface RelatedProduct_PricesEntry {
181
- key: string;
182
- value: string;
183
- }
184
-
185
- export interface ProductResponse {
186
- product:
187
- | Product
188
- | undefined;
189
- /** Populated only by FindOne: up to 2 other approved products by the same author. */
190
- relatedProducts: RelatedProduct[];
191
- }
192
-
193
- export interface TopProductRequest {
194
- /** Optional. If set, the top product is searched only among this seller's products. */
195
- userId: string;
196
- }
197
-
198
- export interface ProductsListResponse {
199
- items: Product[];
200
- total: number;
201
- page: number;
202
- limit: number;
203
- }
204
-
205
- export interface Ok {
206
- ok: boolean;
207
- }
208
-
209
- export interface Empty {
210
- }
211
-
212
- export interface CreateProductRequest {
213
- userId: string;
214
- name: string;
215
- /** Decimal as string */
216
- price: string;
217
- categoryIds: string[];
218
- applicationIds: string[];
219
- tags: string[];
220
- /** optional */
221
- discountPercent: string;
222
- /** optional */
223
- finalPrice: string;
224
- video: string;
225
- description: string;
226
- status: ProductStatus;
227
- /** RUB | USD | EUR; empty → RUB */
228
- currency: string;
229
- }
230
-
231
- export interface UpdateProductRequest {
232
- userId: string;
233
- id: string;
234
- name: string;
235
- description: string;
236
- price: string;
237
- discountPercent: string;
238
- finalPrice: string;
239
- tags: string[];
240
- categoryIds: string[];
241
- applicationIds: string[];
242
- /** RUB | USD | EUR; empty → no change */
243
- currency: string;
244
- }
245
-
246
- export interface QueryProductsRequest {
247
- search: string;
248
- categoryIds: string[];
249
- applicationIds: string[];
250
- tags: string[];
251
- minPrice: string;
252
- maxPrice: string;
253
- page: number;
254
- limit: number;
255
- /** createdAt | price | name | updatedAt | finalPrice */
256
- sortBy: string;
257
- /** asc | desc */
258
- sortOrder: string;
259
- status: ProductStatus;
260
- moderationStatus: ModerationStatus;
261
- /** owner-only list filter; used by /products/my?status=deleted */
262
- deletedOnly: boolean;
263
- }
264
-
265
- export interface FindMyRequest {
266
- userId: string;
267
- query: QueryProductsRequest | undefined;
268
- }
269
-
270
- export interface FindOneRequest {
271
- id: string;
272
- /** optional to compute is_favorited etc. */
273
- viewerUserId: string;
274
- /** dedup key for view counting (userId or hashed ip+ua) */
275
- viewerKey: string;
276
- }
277
-
278
- export interface RemoveProductRequest {
279
- id: string;
280
- userId: string;
281
- }
282
-
283
- export interface RestoreProductRequest {
284
- id: string;
285
- userId: string;
286
- }
287
-
288
- export interface SubmitForModerationRequest {
289
- id: string;
290
- userId: string;
291
- }
292
-
293
- export interface PriceRangeResponse {
294
- /** Decimal as string */
295
- min: string;
296
- max: string;
297
- }
298
-
299
- export interface FavoriteRequest {
300
- userId: string;
301
- productId: string;
302
- }
303
-
304
- export interface MediaFile {
305
- url: string;
306
- type: MediaType;
307
- }
308
-
309
- export interface SaveMediaMetadataRequest {
310
- id: string;
311
- userId: string;
312
- files: MediaFile[];
313
- uploadId: string;
314
- }
315
-
316
- export interface AttachmentMeta {
317
- url: string;
318
- fileKey: string;
319
- fileName: string;
320
- fileSize: number;
321
- }
322
-
323
- export interface SaveAttachmentMetadataRequest {
324
- id: string;
325
- userId: string;
326
- attachment: AttachmentMeta | undefined;
327
- uploadId: string;
328
- }
329
-
330
- export interface RemoveMediaRequest {
331
- /** product id */
332
- id: string;
333
- userId: string;
334
- mediaId: string;
335
- }
336
-
337
- export interface RemoveAttachmentRequest {
338
- /** product id */
339
- id: string;
340
- userId: string;
341
- attachmentId: string;
342
- }
343
-
344
- export interface ProductModerationQueryRequest {
345
- status: ModerationStatus;
346
- page: number;
347
- limit: number;
348
- sortBy: string;
349
- sortOrder: string;
350
- }
351
-
352
- export interface ModerateProductRequest {
353
- productId: string;
354
- moderatorId: string;
355
- /** 'approve' | 'reject' */
356
- action: string;
357
- comment: string;
358
- }
359
-
360
- export interface ModerationResponse {
361
- success: boolean;
362
- message: string;
363
- product: Product | undefined;
364
- moderationStatus: ModerationStatus;
365
- moderationComment: string;
366
- moderatedBy: string;
367
- moderatedAt: string;
368
- }
369
-
370
- export interface ResubmitProductRequest {
371
- productId: string;
372
- userId: string;
373
- comment: string;
374
- /**
375
- * Free-form payload of changes — serialized as JSON string to keep the
376
- * legacy `any` shape without forcing a strict schema on a free-form patch.
377
- */
378
- changesJson: string;
379
- }
380
-
381
- export interface GetSecureDownloadLinksRequest {
382
- productId: string;
383
- userId: string;
384
- expiresIn: number;
385
- }
386
-
387
- export interface SecureDownloadLink {
388
- downloadUrl: string;
389
- expiresIn: number;
390
- fileName: string;
391
- fileSize: number;
392
- attachmentId: string;
393
- }
394
-
395
- export interface SecureDownloadLinksResponse {
396
- links: SecureDownloadLink[];
397
- }
398
-
399
- export interface GetAttachmentDownloadInfoRequest {
400
- productId: string;
401
- attachmentId: string;
402
- userId: string;
403
- }
404
-
405
- export interface AttachmentDownloadInfoResponse {
406
- fileName: string;
407
- fileSize: number;
408
- contentType: string;
409
- }
410
-
411
- export interface GetAttachmentDownloadUrlRequest {
412
- productId: string;
413
- attachmentId: string;
414
- userId: string;
415
- }
416
-
417
- export interface AttachmentDownloadUrlResponse {
418
- downloadUrl: string;
419
- expiresIn: number;
420
- fileName: string;
421
- fileSize: number;
422
- }
423
-
424
- export const PRODUCTS_V1_PACKAGE_NAME = "products.v1";
425
-
426
- export interface ProductsServiceClient {
427
- create(request: CreateProductRequest): Observable<ProductResponse>;
428
-
429
- findAll(request: QueryProductsRequest): Observable<ProductsListResponse>;
430
-
431
- findAllApproved(request: QueryProductsRequest): Observable<ProductsListResponse>;
432
-
433
- findMy(request: FindMyRequest): Observable<ProductsListResponse>;
434
-
435
- findOne(request: FindOneRequest): Observable<ProductResponse>;
436
-
437
- update(request: UpdateProductRequest): Observable<ProductResponse>;
438
-
439
- remove(request: RemoveProductRequest): Observable<Ok>;
440
-
441
- restore(request: RestoreProductRequest): Observable<ProductResponse>;
442
-
443
- submitForModeration(request: SubmitForModerationRequest): Observable<ProductResponse>;
444
-
445
- getPriceRange(request: Empty): Observable<PriceRangeResponse>;
446
-
447
- addToFavorites(request: FavoriteRequest): Observable<Ok>;
448
-
449
- removeFromFavorites(request: FavoriteRequest): Observable<Ok>;
450
-
451
- saveMediaMetadata(request: SaveMediaMetadataRequest): Observable<ProductResponse>;
452
-
453
- saveAttachmentMetadata(request: SaveAttachmentMetadataRequest): Observable<ProductResponse>;
454
-
455
- removeMedia(request: RemoveMediaRequest): Observable<ProductResponse>;
456
-
457
- removeAttachment(request: RemoveAttachmentRequest): Observable<ProductResponse>;
458
-
459
- getProductsForModeration(request: ProductModerationQueryRequest): Observable<ProductsListResponse>;
460
-
461
- moderateProduct(request: ModerateProductRequest): Observable<ModerationResponse>;
462
-
463
- resubmitProduct(request: ResubmitProductRequest): Observable<ProductResponse>;
464
-
465
- getSecureDownloadLinks(request: GetSecureDownloadLinksRequest): Observable<SecureDownloadLinksResponse>;
466
-
467
- getAttachmentDownloadInfo(request: GetAttachmentDownloadInfoRequest): Observable<AttachmentDownloadInfoResponse>;
468
-
469
- /**
470
- * Single presigned GET URL for one attachment (after purchase/access check).
471
- * Bytes never traverse the backend — see upload-service.
472
- */
473
-
474
- getAttachmentDownloadUrl(request: GetAttachmentDownloadUrlRequest): Observable<AttachmentDownloadUrlResponse>;
475
-
476
- getTopProduct(request: TopProductRequest): Observable<ProductResponse>;
477
-
478
- getPopularProducts(request: QueryProductsRequest): Observable<ProductsListResponse>;
479
- }
480
-
481
- export interface ProductsServiceController {
482
- create(request: CreateProductRequest): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
483
-
484
- findAll(
485
- request: QueryProductsRequest,
486
- ): Promise<ProductsListResponse> | Observable<ProductsListResponse> | ProductsListResponse;
487
-
488
- findAllApproved(
489
- request: QueryProductsRequest,
490
- ): Promise<ProductsListResponse> | Observable<ProductsListResponse> | ProductsListResponse;
491
-
492
- findMy(
493
- request: FindMyRequest,
494
- ): Promise<ProductsListResponse> | Observable<ProductsListResponse> | ProductsListResponse;
495
-
496
- findOne(request: FindOneRequest): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
497
-
498
- update(request: UpdateProductRequest): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
499
-
500
- remove(request: RemoveProductRequest): Promise<Ok> | Observable<Ok> | Ok;
501
-
502
- restore(request: RestoreProductRequest): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
503
-
504
- submitForModeration(
505
- request: SubmitForModerationRequest,
506
- ): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
507
-
508
- getPriceRange(request: Empty): Promise<PriceRangeResponse> | Observable<PriceRangeResponse> | PriceRangeResponse;
509
-
510
- addToFavorites(request: FavoriteRequest): Promise<Ok> | Observable<Ok> | Ok;
511
-
512
- removeFromFavorites(request: FavoriteRequest): Promise<Ok> | Observable<Ok> | Ok;
513
-
514
- saveMediaMetadata(
515
- request: SaveMediaMetadataRequest,
516
- ): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
517
-
518
- saveAttachmentMetadata(
519
- request: SaveAttachmentMetadataRequest,
520
- ): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
521
-
522
- removeMedia(request: RemoveMediaRequest): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
523
-
524
- removeAttachment(
525
- request: RemoveAttachmentRequest,
526
- ): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
527
-
528
- getProductsForModeration(
529
- request: ProductModerationQueryRequest,
530
- ): Promise<ProductsListResponse> | Observable<ProductsListResponse> | ProductsListResponse;
531
-
532
- moderateProduct(
533
- request: ModerateProductRequest,
534
- ): Promise<ModerationResponse> | Observable<ModerationResponse> | ModerationResponse;
535
-
536
- resubmitProduct(
537
- request: ResubmitProductRequest,
538
- ): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
539
-
540
- getSecureDownloadLinks(
541
- request: GetSecureDownloadLinksRequest,
542
- ): Promise<SecureDownloadLinksResponse> | Observable<SecureDownloadLinksResponse> | SecureDownloadLinksResponse;
543
-
544
- getAttachmentDownloadInfo(
545
- request: GetAttachmentDownloadInfoRequest,
546
- ):
547
- | Promise<AttachmentDownloadInfoResponse>
548
- | Observable<AttachmentDownloadInfoResponse>
549
- | AttachmentDownloadInfoResponse;
550
-
551
- /**
552
- * Single presigned GET URL for one attachment (after purchase/access check).
553
- * Bytes never traverse the backend — see upload-service.
554
- */
555
-
556
- getAttachmentDownloadUrl(
557
- request: GetAttachmentDownloadUrlRequest,
558
- ): Promise<AttachmentDownloadUrlResponse> | Observable<AttachmentDownloadUrlResponse> | AttachmentDownloadUrlResponse;
559
-
560
- getTopProduct(request: TopProductRequest): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
561
-
562
- getPopularProducts(
563
- request: QueryProductsRequest,
564
- ): Promise<ProductsListResponse> | Observable<ProductsListResponse> | ProductsListResponse;
565
- }
566
-
567
- export function ProductsServiceControllerMethods() {
568
- return function (constructor: Function) {
569
- const grpcMethods: string[] = [
570
- "create",
571
- "findAll",
572
- "findAllApproved",
573
- "findMy",
574
- "findOne",
575
- "update",
576
- "remove",
577
- "restore",
578
- "submitForModeration",
579
- "getPriceRange",
580
- "addToFavorites",
581
- "removeFromFavorites",
582
- "saveMediaMetadata",
583
- "saveAttachmentMetadata",
584
- "removeMedia",
585
- "removeAttachment",
586
- "getProductsForModeration",
587
- "moderateProduct",
588
- "resubmitProduct",
589
- "getSecureDownloadLinks",
590
- "getAttachmentDownloadInfo",
591
- "getAttachmentDownloadUrl",
592
- "getTopProduct",
593
- "getPopularProducts",
594
- ];
595
- for (const method of grpcMethods) {
596
- const descriptor: any = Reflect.getOwnPropertyDescriptor(constructor.prototype, method);
597
- GrpcMethod("ProductsService", method)(constructor.prototype[method], method, descriptor);
598
- }
599
- const grpcStreamMethods: string[] = [];
600
- for (const method of grpcStreamMethods) {
601
- const descriptor: any = Reflect.getOwnPropertyDescriptor(constructor.prototype, method);
602
- GrpcStreamMethod("ProductsService", method)(constructor.prototype[method], method, descriptor);
603
- }
604
- };
605
- }
606
-
607
- export const PRODUCTS_SERVICE_NAME = "ProductsService";
1
+ // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
+ // versions:
3
+ // protoc-gen-ts_proto v2.10.1
4
+ // protoc v7.35.1
5
+ // source: products.proto
6
+
7
+ /* eslint-disable */
8
+ import { GrpcMethod, GrpcStreamMethod } from "@nestjs/microservices";
9
+ import { Observable } from "rxjs";
10
+
11
+ export const protobufPackage = "products.v1";
12
+
13
+ /**
14
+ * Member names match the DB enum string values exactly (enums: String on the
15
+ * wire) so values pass straight through with no mapping. UNSPECIFIED=0 covers
16
+ * null/optional (e.g. nullable moderation_status, missing list filters).
17
+ */
18
+ export enum ProductStatus {
19
+ PRODUCT_STATUS_UNSPECIFIED = 0,
20
+ ACTIVE = 1,
21
+ DRAFT = 2,
22
+ UNRECOGNIZED = -1,
23
+ }
24
+
25
+ export enum ModerationStatus {
26
+ MODERATION_STATUS_UNSPECIFIED = 0,
27
+ PENDING = 1,
28
+ APPROVED = 2,
29
+ REJECTED = 3,
30
+ UNRECOGNIZED = -1,
31
+ }
32
+
33
+ export enum MediaType {
34
+ MEDIA_TYPE_UNSPECIFIED = 0,
35
+ IMAGE = 1,
36
+ VIDEO = 2,
37
+ UNRECOGNIZED = -1,
38
+ }
39
+
40
+ export interface Category {
41
+ id: string;
42
+ name: string;
43
+ }
44
+
45
+ export interface Application {
46
+ id: string;
47
+ name: string;
48
+ }
49
+
50
+ export interface Tag {
51
+ id: string;
52
+ name: string;
53
+ }
54
+
55
+ export interface ProductMedia {
56
+ id: string;
57
+ url: string;
58
+ type: MediaType;
59
+ fileName: string;
60
+ fileSize: number;
61
+ mimeType: string;
62
+ }
63
+
64
+ export interface Attachment {
65
+ id: string;
66
+ url: string;
67
+ fileKey: string;
68
+ fileName: string;
69
+ fileSize: number;
70
+ createdAt: string;
71
+ }
72
+
73
+ export interface ProductUser {
74
+ id: string;
75
+ username: string;
76
+ avatarUrl: string;
77
+ }
78
+
79
+ /**
80
+ * Moderation block — null on the product while it's a DRAFT / never submitted.
81
+ * status is one of PENDING | APPROVED | REJECTED (never UNSPECIFIED here).
82
+ */
83
+ export interface ProductModeration {
84
+ status: ModerationStatus;
85
+ /** moderator note (mainly on REJECTED) */
86
+ comment: string;
87
+ /** moderator user id */
88
+ moderatedBy: string;
89
+ /** ISO 8601 */
90
+ moderatedAt: string;
91
+ }
92
+
93
+ export interface Product {
94
+ id: string;
95
+ name: string;
96
+ description: string;
97
+ /** Decimal as string (D7), in `currency` */
98
+ price: string;
99
+ /** Decimal as string */
100
+ discountPercent: string;
101
+ /** Decimal as string, in `currency` */
102
+ finalPrice: string;
103
+ /**
104
+ * Converted final_price display amounts by currency (RUB/USD/EUR).
105
+ * Not persisted; computed from the cached payments-service FX rates.
106
+ */
107
+ prices: { [key: string]: string };
108
+ /** double as string for consistency */
109
+ averageRating: string;
110
+ status: ProductStatus;
111
+ /**
112
+ * Listing currency the seller priced in: RUB | USD | EUR (default RUB).
113
+ * Settlement/ledger is always RUB conversion is snapshotted at checkout.
114
+ */
115
+ currency: string;
116
+ /** null while DRAFT / not yet submitted */
117
+ moderation: ProductModeration | undefined;
118
+ createdAt: string;
119
+ updatedAt: string;
120
+ /** ISO 8601 when soft-deleted, empty/null otherwise */
121
+ deletedAt: string;
122
+ preview: string;
123
+ video: string;
124
+ user: ProductUser | undefined;
125
+ media: ProductMedia[];
126
+ categories: Category[];
127
+ applications: Application[];
128
+ tags: Tag[];
129
+ /** Aggregate counts (populated where the query includes _count). */
130
+ favoritesCount: number;
131
+ viewsCount: number;
132
+ reviewsCount: number;
133
+ /** Viewer-contextual flags (populated by FindOne when a viewer is known). */
134
+ owner: boolean;
135
+ isFavorite: boolean;
136
+ isViewed: boolean;
137
+ /** owner-only, current-month revenue (Decimal as string) */
138
+ revenue: string;
139
+ /** viewer has a COMPLETED purchase of this product */
140
+ isBuyed: boolean;
141
+ /** viewer has already left a review on this product */
142
+ isReviewed: boolean;
143
+ /** Popularity (populated by GetTopProduct / GetPopularProducts). */
144
+ popularityScore: string;
145
+ /**
146
+ * OWNER-ONLY: the product's deliverable files. Populated by FindOne only
147
+ * when the viewer is the product owner; empty for everyone else (never
148
+ * exposes private attachment metadata to non-owners).
149
+ */
150
+ attachments: ProductAttachment[];
151
+ }
152
+
153
+ export interface Product_PricesEntry {
154
+ key: string;
155
+ value: string;
156
+ }
157
+
158
+ export interface ProductAttachment {
159
+ id: string;
160
+ fileName: string;
161
+ fileSize: number;
162
+ url: string;
163
+ mimeType: string;
164
+ }
165
+
166
+ /** Compact product shape for "related products" — only the fields a card needs. */
167
+ export interface RelatedProduct {
168
+ id: string;
169
+ name: string;
170
+ /** Decimal as string */
171
+ price: string;
172
+ /** Decimal as string */
173
+ discountPercent: string;
174
+ /** Decimal as string */
175
+ finalPrice: string;
176
+ preview: string;
177
+ user: ProductUser | undefined;
178
+ categories: Category[];
179
+ /** RUB | USD | EUR */
180
+ currency: string;
181
+ /** Converted final_price display amounts. */
182
+ prices: { [key: string]: string };
183
+ }
184
+
185
+ export interface RelatedProduct_PricesEntry {
186
+ key: string;
187
+ value: string;
188
+ }
189
+
190
+ export interface ProductResponse {
191
+ product:
192
+ | Product
193
+ | undefined;
194
+ /** Populated only by FindOne: up to 2 other approved products by the same author. */
195
+ relatedProducts: RelatedProduct[];
196
+ }
197
+
198
+ export interface TopProductRequest {
199
+ /** Optional. If set, the top product is searched only among this seller's products. */
200
+ userId: string;
201
+ }
202
+
203
+ export interface ProductsListResponse {
204
+ items: Product[];
205
+ total: number;
206
+ page: number;
207
+ limit: number;
208
+ }
209
+
210
+ export interface Ok {
211
+ ok: boolean;
212
+ }
213
+
214
+ export interface Empty {
215
+ }
216
+
217
+ export interface CreateProductRequest {
218
+ userId: string;
219
+ name: string;
220
+ /** Decimal as string */
221
+ price: string;
222
+ categoryIds: string[];
223
+ applicationIds: string[];
224
+ tags: string[];
225
+ /** optional */
226
+ discountPercent: string;
227
+ /** optional */
228
+ finalPrice: string;
229
+ video: string;
230
+ description: string;
231
+ status: ProductStatus;
232
+ /** RUB | USD | EUR; empty → RUB */
233
+ currency: string;
234
+ }
235
+
236
+ export interface UpdateProductRequest {
237
+ userId: string;
238
+ id: string;
239
+ name: string;
240
+ description: string;
241
+ price: string;
242
+ discountPercent: string;
243
+ finalPrice: string;
244
+ tags: string[];
245
+ categoryIds: string[];
246
+ applicationIds: string[];
247
+ /** RUB | USD | EUR; empty → no change */
248
+ currency: string;
249
+ }
250
+
251
+ export interface QueryProductsRequest {
252
+ search: string;
253
+ categoryIds: string[];
254
+ applicationIds: string[];
255
+ tags: string[];
256
+ minPrice: string;
257
+ maxPrice: string;
258
+ page: number;
259
+ limit: number;
260
+ /** createdAt | price | name | updatedAt | finalPrice */
261
+ sortBy: string;
262
+ /** asc | desc */
263
+ sortOrder: string;
264
+ status: ProductStatus;
265
+ moderationStatus: ModerationStatus;
266
+ /** owner-only list filter; used by /products/my?status=deleted */
267
+ deletedOnly: boolean;
268
+ }
269
+
270
+ export interface FindMyRequest {
271
+ userId: string;
272
+ query: QueryProductsRequest | undefined;
273
+ }
274
+
275
+ export interface FindOneRequest {
276
+ id: string;
277
+ /** optional — to compute is_favorited etc. */
278
+ viewerUserId: string;
279
+ /** dedup key for view counting (userId or hashed ip+ua) */
280
+ viewerKey: string;
281
+ }
282
+
283
+ export interface RemoveProductRequest {
284
+ id: string;
285
+ userId: string;
286
+ }
287
+
288
+ export interface RestoreProductRequest {
289
+ id: string;
290
+ userId: string;
291
+ }
292
+
293
+ export interface SubmitForModerationRequest {
294
+ id: string;
295
+ userId: string;
296
+ }
297
+
298
+ export interface PriceRangeResponse {
299
+ /** Decimal as string */
300
+ min: string;
301
+ max: string;
302
+ }
303
+
304
+ export interface FavoriteRequest {
305
+ userId: string;
306
+ productId: string;
307
+ }
308
+
309
+ export interface MediaFile {
310
+ fileName: string;
311
+ fileSize: number;
312
+ mimeType: string;
313
+ storageKey: string;
314
+ }
315
+
316
+ export interface SaveMediaMetadataRequest {
317
+ id: string;
318
+ userId: string;
319
+ files: MediaFile[];
320
+ uploadId: string;
321
+ }
322
+
323
+ export interface AttachmentMeta {
324
+ storageKey: string;
325
+ fileName: string;
326
+ fileSize: number;
327
+ mimeType: string;
328
+ }
329
+
330
+ export interface SaveAttachmentMetadataRequest {
331
+ id: string;
332
+ userId: string;
333
+ attachment: AttachmentMeta | undefined;
334
+ uploadId: string;
335
+ }
336
+
337
+ export interface RemoveMediaRequest {
338
+ /** product id */
339
+ id: string;
340
+ userId: string;
341
+ mediaId: string;
342
+ }
343
+
344
+ export interface RemoveAttachmentRequest {
345
+ /** product id */
346
+ id: string;
347
+ userId: string;
348
+ attachmentId: string;
349
+ }
350
+
351
+ export interface ProductModerationQueryRequest {
352
+ status: ModerationStatus;
353
+ page: number;
354
+ limit: number;
355
+ sortBy: string;
356
+ sortOrder: string;
357
+ }
358
+
359
+ export interface ModerateProductRequest {
360
+ productId: string;
361
+ moderatorId: string;
362
+ /** 'approve' | 'reject' */
363
+ action: string;
364
+ comment: string;
365
+ }
366
+
367
+ export interface ModerationResponse {
368
+ success: boolean;
369
+ message: string;
370
+ product: Product | undefined;
371
+ moderationStatus: ModerationStatus;
372
+ moderationComment: string;
373
+ moderatedBy: string;
374
+ moderatedAt: string;
375
+ }
376
+
377
+ export interface ResubmitProductRequest {
378
+ productId: string;
379
+ userId: string;
380
+ comment: string;
381
+ /**
382
+ * Free-form payload of changes — serialized as JSON string to keep the
383
+ * legacy `any` shape without forcing a strict schema on a free-form patch.
384
+ */
385
+ changesJson: string;
386
+ }
387
+
388
+ export interface GetSecureDownloadLinksRequest {
389
+ productId: string;
390
+ userId: string;
391
+ expiresIn: number;
392
+ }
393
+
394
+ export interface SecureDownloadLink {
395
+ downloadUrl: string;
396
+ expiresIn: number;
397
+ fileName: string;
398
+ fileSize: number;
399
+ attachmentId: string;
400
+ }
401
+
402
+ export interface SecureDownloadLinksResponse {
403
+ links: SecureDownloadLink[];
404
+ }
405
+
406
+ export interface GetAttachmentDownloadInfoRequest {
407
+ productId: string;
408
+ attachmentId: string;
409
+ userId: string;
410
+ }
411
+
412
+ export interface AttachmentDownloadInfoResponse {
413
+ fileName: string;
414
+ fileSize: number;
415
+ contentType: string;
416
+ }
417
+
418
+ export interface GetAttachmentDownloadUrlRequest {
419
+ productId: string;
420
+ attachmentId: string;
421
+ userId: string;
422
+ }
423
+
424
+ export interface AttachmentDownloadUrlResponse {
425
+ downloadUrl: string;
426
+ expiresIn: number;
427
+ fileName: string;
428
+ fileSize: number;
429
+ }
430
+
431
+ export const PRODUCTS_V1_PACKAGE_NAME = "products.v1";
432
+
433
+ export interface ProductsServiceClient {
434
+ create(request: CreateProductRequest): Observable<ProductResponse>;
435
+
436
+ findAll(request: QueryProductsRequest): Observable<ProductsListResponse>;
437
+
438
+ findAllApproved(request: QueryProductsRequest): Observable<ProductsListResponse>;
439
+
440
+ findMy(request: FindMyRequest): Observable<ProductsListResponse>;
441
+
442
+ findOne(request: FindOneRequest): Observable<ProductResponse>;
443
+
444
+ update(request: UpdateProductRequest): Observable<ProductResponse>;
445
+
446
+ remove(request: RemoveProductRequest): Observable<Ok>;
447
+
448
+ restore(request: RestoreProductRequest): Observable<ProductResponse>;
449
+
450
+ submitForModeration(request: SubmitForModerationRequest): Observable<ProductResponse>;
451
+
452
+ getPriceRange(request: Empty): Observable<PriceRangeResponse>;
453
+
454
+ addToFavorites(request: FavoriteRequest): Observable<Ok>;
455
+
456
+ removeFromFavorites(request: FavoriteRequest): Observable<Ok>;
457
+
458
+ saveMediaMetadata(request: SaveMediaMetadataRequest): Observable<ProductResponse>;
459
+
460
+ saveAttachmentMetadata(request: SaveAttachmentMetadataRequest): Observable<ProductResponse>;
461
+
462
+ removeMedia(request: RemoveMediaRequest): Observable<ProductResponse>;
463
+
464
+ removeAttachment(request: RemoveAttachmentRequest): Observable<ProductResponse>;
465
+
466
+ getProductsForModeration(request: ProductModerationQueryRequest): Observable<ProductsListResponse>;
467
+
468
+ moderateProduct(request: ModerateProductRequest): Observable<ModerationResponse>;
469
+
470
+ resubmitProduct(request: ResubmitProductRequest): Observable<ProductResponse>;
471
+
472
+ getSecureDownloadLinks(request: GetSecureDownloadLinksRequest): Observable<SecureDownloadLinksResponse>;
473
+
474
+ getAttachmentDownloadInfo(request: GetAttachmentDownloadInfoRequest): Observable<AttachmentDownloadInfoResponse>;
475
+
476
+ /**
477
+ * Single presigned GET URL for one attachment (after purchase/access check).
478
+ * Bytes never traverse the backend — see upload-service.
479
+ */
480
+
481
+ getAttachmentDownloadUrl(request: GetAttachmentDownloadUrlRequest): Observable<AttachmentDownloadUrlResponse>;
482
+
483
+ getTopProduct(request: TopProductRequest): Observable<ProductResponse>;
484
+
485
+ getPopularProducts(request: QueryProductsRequest): Observable<ProductsListResponse>;
486
+ }
487
+
488
+ export interface ProductsServiceController {
489
+ create(request: CreateProductRequest): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
490
+
491
+ findAll(
492
+ request: QueryProductsRequest,
493
+ ): Promise<ProductsListResponse> | Observable<ProductsListResponse> | ProductsListResponse;
494
+
495
+ findAllApproved(
496
+ request: QueryProductsRequest,
497
+ ): Promise<ProductsListResponse> | Observable<ProductsListResponse> | ProductsListResponse;
498
+
499
+ findMy(
500
+ request: FindMyRequest,
501
+ ): Promise<ProductsListResponse> | Observable<ProductsListResponse> | ProductsListResponse;
502
+
503
+ findOne(request: FindOneRequest): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
504
+
505
+ update(request: UpdateProductRequest): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
506
+
507
+ remove(request: RemoveProductRequest): Promise<Ok> | Observable<Ok> | Ok;
508
+
509
+ restore(request: RestoreProductRequest): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
510
+
511
+ submitForModeration(
512
+ request: SubmitForModerationRequest,
513
+ ): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
514
+
515
+ getPriceRange(request: Empty): Promise<PriceRangeResponse> | Observable<PriceRangeResponse> | PriceRangeResponse;
516
+
517
+ addToFavorites(request: FavoriteRequest): Promise<Ok> | Observable<Ok> | Ok;
518
+
519
+ removeFromFavorites(request: FavoriteRequest): Promise<Ok> | Observable<Ok> | Ok;
520
+
521
+ saveMediaMetadata(
522
+ request: SaveMediaMetadataRequest,
523
+ ): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
524
+
525
+ saveAttachmentMetadata(
526
+ request: SaveAttachmentMetadataRequest,
527
+ ): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
528
+
529
+ removeMedia(request: RemoveMediaRequest): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
530
+
531
+ removeAttachment(
532
+ request: RemoveAttachmentRequest,
533
+ ): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
534
+
535
+ getProductsForModeration(
536
+ request: ProductModerationQueryRequest,
537
+ ): Promise<ProductsListResponse> | Observable<ProductsListResponse> | ProductsListResponse;
538
+
539
+ moderateProduct(
540
+ request: ModerateProductRequest,
541
+ ): Promise<ModerationResponse> | Observable<ModerationResponse> | ModerationResponse;
542
+
543
+ resubmitProduct(
544
+ request: ResubmitProductRequest,
545
+ ): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
546
+
547
+ getSecureDownloadLinks(
548
+ request: GetSecureDownloadLinksRequest,
549
+ ): Promise<SecureDownloadLinksResponse> | Observable<SecureDownloadLinksResponse> | SecureDownloadLinksResponse;
550
+
551
+ getAttachmentDownloadInfo(
552
+ request: GetAttachmentDownloadInfoRequest,
553
+ ):
554
+ | Promise<AttachmentDownloadInfoResponse>
555
+ | Observable<AttachmentDownloadInfoResponse>
556
+ | AttachmentDownloadInfoResponse;
557
+
558
+ /**
559
+ * Single presigned GET URL for one attachment (after purchase/access check).
560
+ * Bytes never traverse the backend — see upload-service.
561
+ */
562
+
563
+ getAttachmentDownloadUrl(
564
+ request: GetAttachmentDownloadUrlRequest,
565
+ ): Promise<AttachmentDownloadUrlResponse> | Observable<AttachmentDownloadUrlResponse> | AttachmentDownloadUrlResponse;
566
+
567
+ getTopProduct(request: TopProductRequest): Promise<ProductResponse> | Observable<ProductResponse> | ProductResponse;
568
+
569
+ getPopularProducts(
570
+ request: QueryProductsRequest,
571
+ ): Promise<ProductsListResponse> | Observable<ProductsListResponse> | ProductsListResponse;
572
+ }
573
+
574
+ export function ProductsServiceControllerMethods() {
575
+ return function (constructor: Function) {
576
+ const grpcMethods: string[] = [
577
+ "create",
578
+ "findAll",
579
+ "findAllApproved",
580
+ "findMy",
581
+ "findOne",
582
+ "update",
583
+ "remove",
584
+ "restore",
585
+ "submitForModeration",
586
+ "getPriceRange",
587
+ "addToFavorites",
588
+ "removeFromFavorites",
589
+ "saveMediaMetadata",
590
+ "saveAttachmentMetadata",
591
+ "removeMedia",
592
+ "removeAttachment",
593
+ "getProductsForModeration",
594
+ "moderateProduct",
595
+ "resubmitProduct",
596
+ "getSecureDownloadLinks",
597
+ "getAttachmentDownloadInfo",
598
+ "getAttachmentDownloadUrl",
599
+ "getTopProduct",
600
+ "getPopularProducts",
601
+ ];
602
+ for (const method of grpcMethods) {
603
+ const descriptor: any = Reflect.getOwnPropertyDescriptor(constructor.prototype, method);
604
+ GrpcMethod("ProductsService", method)(constructor.prototype[method], method, descriptor);
605
+ }
606
+ const grpcStreamMethods: string[] = [];
607
+ for (const method of grpcStreamMethods) {
608
+ const descriptor: any = Reflect.getOwnPropertyDescriptor(constructor.prototype, method);
609
+ GrpcStreamMethod("ProductsService", method)(constructor.prototype[method], method, descriptor);
610
+ }
611
+ };
612
+ }
613
+
614
+ export const PRODUCTS_SERVICE_NAME = "ProductsService";