@mamindom/contracts 1.0.140 → 1.0.142

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.
@@ -0,0 +1,154 @@
1
+ syntax = "proto3";
2
+
3
+ package catalog.v1;
4
+
5
+ import "common.proto";
6
+
7
+
8
+ service SeoFilterService {
9
+ // ─── Public ──────────────────────────────────────────────────────────────
10
+
11
+ // Резолв ЧПУ-URL → metadata + canonical. Викликається SSR Next.js для
12
+ // кожного category/[[...filters]] запиту. Якщо combo не знайдено —
13
+ // повертає isIndexed=false і автогенерований fallback metadata.
14
+ rpc ResolveSeoFilter (ResolveSeoFilterRequest) returns (ResolveSeoFilterResponse);
15
+
16
+ // ─── Admin ───────────────────────────────────────────────────────────────
17
+
18
+ rpc ListSeoFilters (ListSeoFiltersRequest) returns (ListSeoFiltersResponse);
19
+ rpc GetSeoFilter (GetSeoFilterRequest) returns (SeoFilterResponse);
20
+ rpc CreateSeoFilter (CreateSeoFilterRequest) returns (SeoFilterResponse);
21
+ rpc UpdateSeoFilter (UpdateSeoFilterRequest) returns (SeoFilterResponse);
22
+ rpc DeleteSeoFilter (DeleteSeoFilterRequest) returns (DeleteResponse);
23
+
24
+ // Топ-N непокритих combinations (за impressions/popularity) — для
25
+ // швидкого створення SeoFilter з адмін-форми "Автопідказки".
26
+ rpc SuggestSeoFilters (SuggestSeoFiltersRequest) returns (SuggestSeoFiltersResponse);
27
+ }
28
+
29
+ // ─────────────────────────── Domain types ────────────────────────────────
30
+
31
+ // Частина combo. Однаковий формат і у DB (combo_parts JSON), і у gRPC.
32
+ // type: 'brand'|'price'|'color'|'size'
33
+ message FilterPart {
34
+ string type = 1;
35
+ // Для brand/color/size:
36
+ optional string value_id = 2;
37
+ optional string value_slug = 3;
38
+ // Для price:
39
+ optional int32 price_min = 4;
40
+ optional int32 price_max = 5;
41
+ }
42
+
43
+ // Локалізовані поля (uk/ru) у форматі { uk: "...", ru: "..." }.
44
+ message LocaleStrings {
45
+ string uk = 1;
46
+ string ru = 2;
47
+ }
48
+
49
+ message SeoFilterResponse {
50
+ string id = 1;
51
+ string category_id = 2;
52
+ string combo_hash = 3;
53
+ repeated FilterPart combo_parts = 4;
54
+ LocaleStrings url_segments = 5;
55
+ LocaleStrings title = 6;
56
+ LocaleStrings description = 7;
57
+ LocaleStrings h1 = 8;
58
+ bool is_indexed = 9;
59
+ bool is_auto = 10;
60
+ int32 popularity = 11;
61
+ int64 created_at = 12;
62
+ int64 updated_at = 13;
63
+ }
64
+
65
+ // ─────────────────────────── Resolve (public) ────────────────────────────
66
+
67
+ message ResolveSeoFilterRequest {
68
+ string category_id = 1;
69
+ // Канонічно відсортовані URL segments як приходять з Next.js, напр.
70
+ // ["brend-cybex", "cina-1000-5000"]. Caller гарантує що порядок canonical.
71
+ repeated string url_segments = 2;
72
+ string locale = 3; // 'uk' | 'ru'
73
+ }
74
+
75
+ message ResolveSeoFilterResponse {
76
+ // Якщо false → caller рендерить категорію з noindex,follow.
77
+ bool found = 1;
78
+ // Якщо false → caller додає <meta robots="noindex,follow"> навіть якщо
79
+ // запис знайдено (наприклад, isIndexed=false manual override).
80
+ bool is_indexed = 2;
81
+ LocaleStrings title = 3;
82
+ LocaleStrings description = 4;
83
+ LocaleStrings h1 = 5;
84
+ // Canonical-URL-path без host: "/uk/c/koliaski/brend-cybex"
85
+ string canonical_path = 6;
86
+ // Денормалізовані combo_parts з resolved valueId — для побудови
87
+ // запиту до products (categoryId + filter ids).
88
+ repeated FilterPart resolved_parts = 7;
89
+ }
90
+
91
+ // ─────────────────────────── List (admin) ────────────────────────────────
92
+
93
+ message ListSeoFiltersRequest {
94
+ PaginationRequest pagination = 1;
95
+ optional string category_id = 2;
96
+ optional bool is_indexed = 3;
97
+ optional bool is_auto = 4;
98
+ // Пошук за uk/ru title (для адмін-фільтра).
99
+ optional string search = 5;
100
+ }
101
+
102
+ message ListSeoFiltersResponse {
103
+ repeated SeoFilterResponse items = 1;
104
+ PaginationMeta meta = 2;
105
+ }
106
+
107
+ message GetSeoFilterRequest {
108
+ string id = 1;
109
+ }
110
+
111
+ // ─────────────────────────── Create / Update ─────────────────────────────
112
+
113
+ message CreateSeoFilterRequest {
114
+ string category_id = 1;
115
+ repeated FilterPart combo_parts = 2;
116
+ LocaleStrings title = 3;
117
+ LocaleStrings description = 4;
118
+ LocaleStrings h1 = 5;
119
+ bool is_indexed = 6;
120
+ }
121
+
122
+ message UpdateSeoFilterRequest {
123
+ string id = 1;
124
+ optional LocaleStrings title = 2;
125
+ optional LocaleStrings description = 3;
126
+ optional LocaleStrings h1 = 4;
127
+ optional bool is_indexed = 5;
128
+ }
129
+
130
+ message DeleteSeoFilterRequest {
131
+ string id = 1;
132
+ }
133
+
134
+ // ─────────────────────────── Suggestions (admin) ─────────────────────────
135
+
136
+ message SuggestSeoFiltersRequest {
137
+ string category_id = 1;
138
+ int32 limit = 2; // default 20
139
+ }
140
+
141
+ message SuggestSeoFilterCandidate {
142
+ // Запропоновані combo_parts (валідні, з resolved slug).
143
+ repeated FilterPart combo_parts = 1;
144
+ // Оцінка популярності: clicks / impressions / товарообіг (single число).
145
+ int32 score = 2;
146
+ // Чи існує вже SeoFilter з таким комбо (тоді UI ховає кнопку Create).
147
+ bool already_exists = 3;
148
+ // Pre-built canonical URL path для preview.
149
+ LocaleStrings preview_segments = 4;
150
+ }
151
+
152
+ message SuggestSeoFiltersResponse {
153
+ repeated SuggestSeoFilterCandidate items = 1;
154
+ }
@@ -15,8 +15,7 @@ service ShopFilterService {
15
15
  message GetShopFiltersRequest {
16
16
  string category_id = 1;
17
17
 
18
- // Поточно застосовані фільтри. Counts по кожному facet рахуються
19
- // з виключенням саме того facet — щоб лічильники реагували на вибір.
18
+
20
19
  repeated string brand_ids = 2;
21
20
  repeated string color_ids = 3;
22
21
  repeated string size_ids = 4;
@@ -25,18 +24,16 @@ message GetShopFiltersRequest {
25
24
  optional bool in_stock = 7;
26
25
  optional string search = 8;
27
26
 
28
- // Обмеження множини товарів акцією — фасети рахуються тільки
29
- // по товарах, що належать поточній акції.
27
+
30
28
  optional PromotionFilter promotion_filter = 9;
31
29
 
32
- // Динамічні атрибути окрім color/size (матеріал, виробник тощо).
30
+
33
31
  repeated string attribute_value_ids = 10;
34
32
 
35
- // Явний прапор "ціновий фільтр активний". Без нього неможливо
36
- // відрізнити "користувач не вибирав" від "обрав від 0".
33
+
37
34
  optional bool price_active = 11;
38
35
 
39
- // 'uk' | 'ru' — для локалізації labels у відповіді (дефолт uk).
36
+
40
37
  optional string locale = 12;
41
38
  }
42
39
 
@@ -48,7 +45,15 @@ message GetShopFiltersResponse {
48
45
  repeated ShopFilterAttribute attributes = 4;
49
46
  double price_min = 5;
50
47
  double price_max = 6;
51
- repeated string subcategory_ids = 7;
48
+
49
+ repeated ShopFilterSubcategory subcategories = 7;
50
+ }
51
+
52
+ message ShopFilterSubcategory {
53
+ string id = 1;
54
+ string slug = 2;
55
+ string label = 3;
56
+ int32 count = 4;
52
57
  }
53
58
 
54
59
  message ShopFilterOption {
@@ -66,8 +71,7 @@ message ShopFilterColorOption {
66
71
 
67
72
  message ShopFilterAttribute {
68
73
  string slug = 1;
69
- // Локалізована назва атрибута (на стороні gateway вже згорнута у
70
- // одну рядкову label згідно locale запиту).
74
+
71
75
  string label = 2;
72
76
  repeated ShopFilterOption values = 3;
73
77
  }
@@ -16,6 +16,7 @@ export declare const PROTO_PATHS: {
16
16
  readonly BUNDLE: string;
17
17
  readonly FILTER: string;
18
18
  readonly SEARCH: string;
19
+ readonly SEO_FILTER: string;
19
20
  readonly PICKUP: string;
20
21
  readonly PRODUCT_REVIEW: string;
21
22
  readonly COMMON_PROMO: string;
@@ -20,6 +20,7 @@ exports.PROTO_PATHS = {
20
20
  BUNDLE: (0, node_path_1.join)(__dirname, '../../proto/bundle.proto'),
21
21
  FILTER: (0, node_path_1.join)(__dirname, '../../proto/shop_filters.proto'),
22
22
  SEARCH: (0, node_path_1.join)(__dirname, '../../proto/search.proto'),
23
+ SEO_FILTER: (0, node_path_1.join)(__dirname, '../../proto/seo_filter.proto'),
23
24
  PICKUP: (0, node_path_1.join)(__dirname, '../../proto/pickup.proto'),
24
25
  PRODUCT_REVIEW: (0, node_path_1.join)(__dirname, '../../proto/product_review.proto'),
25
26
  COMMON_PROMO: (0, node_path_1.join)(__dirname, '../../proto/common_promo.proto'),
package/gen/audit.ts CHANGED
@@ -13,21 +13,11 @@ export const protobufPackage = "audit.v1";
13
13
  export interface LogActionRequest {
14
14
  actorId?: string | undefined;
15
15
  actorName?: string | undefined;
16
- actorEmail?:
17
- | string
18
- | undefined;
19
- /** e.g. "order.cancelled", "product.price_changed" */
16
+ actorEmail?: string | undefined;
20
17
  action: string;
21
- /** e.g. "order", "product", "role" */
22
18
  targetType: string;
23
- targetId?:
24
- | string
25
- | undefined;
26
- /** human-readable summary */
27
- summary?:
28
- | string
29
- | undefined;
30
- /** serialized JSON snapshot (small!) */
19
+ targetId?: string | undefined;
20
+ summary?: string | undefined;
31
21
  beforeJson?: string | undefined;
32
22
  afterJson?: string | undefined;
33
23
  ip?: string | undefined;
@@ -44,14 +34,8 @@ export interface ListAuditRequest {
44
34
  actorId?: string | undefined;
45
35
  targetType?: string | undefined;
46
36
  targetId?: string | undefined;
47
- action?:
48
- | string
49
- | undefined;
50
- /** "orders" matches order.* etc */
51
- actionGroup?:
52
- | string
53
- | undefined;
54
- /** ISO date */
37
+ action?: string | undefined;
38
+ actionGroup?: string | undefined;
55
39
  from?: string | undefined;
56
40
  to?: string | undefined;
57
41
  }
package/gen/banner.ts CHANGED
@@ -129,7 +129,6 @@ export interface UpdateBannerRequest {
129
129
  id: string;
130
130
  slug?: string | undefined;
131
131
  name: { [key: string]: string };
132
- /** empty = не оновлювати; non-empty = заміна повного списку плейсментів. */
133
132
  placements: BannerPlacement[];
134
133
  status?: boolean | undefined;
135
134
  sortOrder?: number | undefined;
@@ -11,16 +11,9 @@ import { Observable } from "rxjs";
11
11
  export const protobufPackage = "promo.v1";
12
12
 
13
13
  export interface BonusSettingsResponse {
14
- /** Курс нарахування бонусів від суми замовлення (0.02 = 2%). */
15
14
  earnRate: number;
16
- /** Курс списання бонусів (1 бонус = N грн, default 1.0). */
17
15
  redeemRate: number;
18
- /** Мінімальна сума замовлення для нарахування бонусів (0 = без обмеження). */
19
16
  minOrderForEarn: number;
20
- /**
21
- * Максимальний відсоток від суми замовлення, який можна оплатити бонусами
22
- * (1.0 = до 100%, 0.5 = до 50%; 0 — без обмеження).
23
- */
24
17
  maxRedeemShare: number;
25
18
  updatedAt: string;
26
19
  }
package/gen/brand.ts CHANGED
@@ -20,10 +20,7 @@ export interface BrandResponse {
20
20
  metaTitle: { [key: string]: string };
21
21
  metaDescription: { [key: string]: string };
22
22
  guid1c?: string | undefined;
23
- imageId?:
24
- | string
25
- | undefined;
26
- /** Кількість АКТИВНИХ товарів бренду (для shop UI). */
23
+ imageId?: string | undefined;
27
24
  productCount: number;
28
25
  }
29
26
 
package/gen/bundle.ts CHANGED
@@ -94,7 +94,6 @@ export interface CreateBundleRequest {
94
94
  metaDescription: { [key: string]: string };
95
95
  items: BundleItemPayload[];
96
96
  createdById: string;
97
- /** NEW */
98
97
  displayPlacements: DisplayPlacement[];
99
98
  priceMode: PriceMode;
100
99
  requireAllInStock: boolean;
@@ -145,7 +144,6 @@ export interface UpdateBundleRequest {
145
144
  metaTitle: { [key: string]: string };
146
145
  metaDescription: { [key: string]: string };
147
146
  items: BundleItemPayload[];
148
- /** NEW */
149
147
  displayPlacements: DisplayPlacement[];
150
148
  priceMode?: PriceMode | undefined;
151
149
  requireAllInStock?: boolean | undefined;
@@ -320,7 +318,6 @@ export interface BundleDetailResponse {
320
318
  originalPrice: number;
321
319
  finalPrice: number;
322
320
  inStock: boolean;
323
- /** NEW */
324
321
  displayPlacements: DisplayPlacement[];
325
322
  priceMode: PriceMode;
326
323
  requireAllInStock: boolean;
@@ -402,7 +399,6 @@ export interface BundleItemAvailability {
402
399
  }
403
400
 
404
401
  export interface ExportBundlesResponse {
405
- /** JSON string or CSV string */
406
402
  content: string;
407
403
  format: string;
408
404
  count: number;
@@ -410,18 +406,13 @@ export interface ExportBundlesResponse {
410
406
 
411
407
  export interface GenerateBundleCollageRequest {
412
408
  bundleId: string;
413
- /** Optional: override cell pixel size (default 400) */
414
409
  cellSize?: number | undefined;
415
410
  }
416
411
 
417
412
  export interface GenerateBundleCollageResponse {
418
- /** Public CDN/S3 URL of the collage JPEG */
419
413
  url: string;
420
- /** S3 object key */
421
414
  key: string;
422
- /** Final image width in pixels */
423
415
  width: number;
424
- /** Final image height in pixels */
425
416
  height: number;
426
417
  bundleId: string;
427
418
  }
package/gen/search.ts CHANGED
@@ -165,11 +165,6 @@ export interface ClearZeroResultsRequest {
165
165
 
166
166
  export const CATALOG_V1_PACKAGE_NAME = "catalog.v1";
167
167
 
168
- /**
169
- * SearchService — окремий сервіс під autocomplete та керування пошуком
170
- * (синоніми, популярні запити). Логіка та індекс живуть у catalog-service.
171
- */
172
-
173
168
  export interface SearchServiceClient {
174
169
  /** ─── Public (autocomplete) ─────────────────────────────────────────────── */
175
170
 
@@ -206,11 +201,6 @@ export interface SearchServiceClient {
206
201
  clearZeroResults(request: ClearZeroResultsRequest): Observable<SuccessResponse>;
207
202
  }
208
203
 
209
- /**
210
- * SearchService — окремий сервіс під autocomplete та керування пошуком
211
- * (синоніми, популярні запити). Логіка та індекс живуть у catalog-service.
212
- */
213
-
214
204
  export interface SearchServiceController {
215
205
  /** ─── Public (autocomplete) ─────────────────────────────────────────────── */
216
206
 
@@ -0,0 +1,244 @@
1
+ // Code generated by protoc-gen-ts_proto. DO NOT EDIT.
2
+ // versions:
3
+ // protoc-gen-ts_proto v2.11.4
4
+ // protoc v3.21.12
5
+ // source: seo_filter.proto
6
+
7
+ /* eslint-disable */
8
+ import { GrpcMethod, GrpcStreamMethod } from "@nestjs/microservices";
9
+ import { Observable } from "rxjs";
10
+ import { DeleteResponse, PaginationMeta, PaginationRequest } from "./common";
11
+
12
+ export const protobufPackage = "catalog.v1";
13
+
14
+ /**
15
+ * Частина combo. Однаковий формат і у DB (combo_parts JSON), і у gRPC.
16
+ * type: 'brand'|'price'|'color'|'size'
17
+ */
18
+ export interface FilterPart {
19
+ type: string;
20
+ /** Для brand/color/size: */
21
+ valueId?: string | undefined;
22
+ valueSlug?:
23
+ | string
24
+ | undefined;
25
+ /** Для price: */
26
+ priceMin?: number | undefined;
27
+ priceMax?: number | undefined;
28
+ }
29
+
30
+ /** Локалізовані поля (uk/ru) у форматі { uk: "...", ru: "..." }. */
31
+ export interface LocaleStrings {
32
+ uk: string;
33
+ ru: string;
34
+ }
35
+
36
+ export interface SeoFilterResponse {
37
+ id: string;
38
+ categoryId: string;
39
+ comboHash: string;
40
+ comboParts: FilterPart[];
41
+ urlSegments: LocaleStrings | undefined;
42
+ title: LocaleStrings | undefined;
43
+ description: LocaleStrings | undefined;
44
+ h1: LocaleStrings | undefined;
45
+ isIndexed: boolean;
46
+ isAuto: boolean;
47
+ popularity: number;
48
+ createdAt: number;
49
+ updatedAt: number;
50
+ }
51
+
52
+ export interface ResolveSeoFilterRequest {
53
+ categoryId: string;
54
+ /**
55
+ * Канонічно відсортовані URL segments як приходять з Next.js, напр.
56
+ * ["brend-cybex", "cina-1000-5000"]. Caller гарантує що порядок canonical.
57
+ */
58
+ urlSegments: string[];
59
+ /** 'uk' | 'ru' */
60
+ locale: string;
61
+ }
62
+
63
+ export interface ResolveSeoFilterResponse {
64
+ /** Якщо false → caller рендерить категорію з noindex,follow. */
65
+ found: boolean;
66
+ /**
67
+ * Якщо false → caller додає <meta robots="noindex,follow"> навіть якщо
68
+ * запис знайдено (наприклад, isIndexed=false manual override).
69
+ */
70
+ isIndexed: boolean;
71
+ title: LocaleStrings | undefined;
72
+ description: LocaleStrings | undefined;
73
+ h1:
74
+ | LocaleStrings
75
+ | undefined;
76
+ /** Canonical-URL-path без host: "/uk/c/koliaski/brend-cybex" */
77
+ canonicalPath: string;
78
+ /**
79
+ * Денормалізовані combo_parts з resolved valueId — для побудови
80
+ * запиту до products (categoryId + filter ids).
81
+ */
82
+ resolvedParts: FilterPart[];
83
+ }
84
+
85
+ export interface ListSeoFiltersRequest {
86
+ pagination: PaginationRequest | undefined;
87
+ categoryId?: string | undefined;
88
+ isIndexed?: boolean | undefined;
89
+ isAuto?:
90
+ | boolean
91
+ | undefined;
92
+ /** Пошук за uk/ru title (для адмін-фільтра). */
93
+ search?: string | undefined;
94
+ }
95
+
96
+ export interface ListSeoFiltersResponse {
97
+ items: SeoFilterResponse[];
98
+ meta: PaginationMeta | undefined;
99
+ }
100
+
101
+ export interface GetSeoFilterRequest {
102
+ id: string;
103
+ }
104
+
105
+ export interface CreateSeoFilterRequest {
106
+ categoryId: string;
107
+ comboParts: FilterPart[];
108
+ title: LocaleStrings | undefined;
109
+ description: LocaleStrings | undefined;
110
+ h1: LocaleStrings | undefined;
111
+ isIndexed: boolean;
112
+ }
113
+
114
+ export interface UpdateSeoFilterRequest {
115
+ id: string;
116
+ title?: LocaleStrings | undefined;
117
+ description?: LocaleStrings | undefined;
118
+ h1?: LocaleStrings | undefined;
119
+ isIndexed?: boolean | undefined;
120
+ }
121
+
122
+ export interface DeleteSeoFilterRequest {
123
+ id: string;
124
+ }
125
+
126
+ export interface SuggestSeoFiltersRequest {
127
+ categoryId: string;
128
+ /** default 20 */
129
+ limit: number;
130
+ }
131
+
132
+ export interface SuggestSeoFilterCandidate {
133
+ /** Запропоновані combo_parts (валідні, з resolved slug). */
134
+ comboParts: FilterPart[];
135
+ /** Оцінка популярності: clicks / impressions / товарообіг (single число). */
136
+ score: number;
137
+ /** Чи існує вже SeoFilter з таким комбо (тоді UI ховає кнопку Create). */
138
+ alreadyExists: boolean;
139
+ /** Pre-built canonical URL path для preview. */
140
+ previewSegments: LocaleStrings | undefined;
141
+ }
142
+
143
+ export interface SuggestSeoFiltersResponse {
144
+ items: SuggestSeoFilterCandidate[];
145
+ }
146
+
147
+ export const CATALOG_V1_PACKAGE_NAME = "catalog.v1";
148
+
149
+ /** ─── Public ────────────────────────────────────────────────────────────── */
150
+
151
+ export interface SeoFilterServiceClient {
152
+ /**
153
+ * Резолв ЧПУ-URL → metadata + canonical. Викликається SSR Next.js для
154
+ * кожного category/[[...filters]] запиту. Якщо combo не знайдено —
155
+ * повертає isIndexed=false і автогенерований fallback metadata.
156
+ */
157
+
158
+ resolveSeoFilter(request: ResolveSeoFilterRequest): Observable<ResolveSeoFilterResponse>;
159
+
160
+ listSeoFilters(request: ListSeoFiltersRequest): Observable<ListSeoFiltersResponse>;
161
+
162
+ getSeoFilter(request: GetSeoFilterRequest): Observable<SeoFilterResponse>;
163
+
164
+ createSeoFilter(request: CreateSeoFilterRequest): Observable<SeoFilterResponse>;
165
+
166
+ updateSeoFilter(request: UpdateSeoFilterRequest): Observable<SeoFilterResponse>;
167
+
168
+ deleteSeoFilter(request: DeleteSeoFilterRequest): Observable<DeleteResponse>;
169
+
170
+ /**
171
+ * Топ-N непокритих combinations (за impressions/popularity) — для
172
+ * швидкого створення SeoFilter з адмін-форми "Автопідказки".
173
+ */
174
+
175
+ suggestSeoFilters(request: SuggestSeoFiltersRequest): Observable<SuggestSeoFiltersResponse>;
176
+ }
177
+
178
+ /** ─── Public ────────────────────────────────────────────────────────────── */
179
+
180
+ export interface SeoFilterServiceController {
181
+ /**
182
+ * Резолв ЧПУ-URL → metadata + canonical. Викликається SSR Next.js для
183
+ * кожного category/[[...filters]] запиту. Якщо combo не знайдено —
184
+ * повертає isIndexed=false і автогенерований fallback metadata.
185
+ */
186
+
187
+ resolveSeoFilter(
188
+ request: ResolveSeoFilterRequest,
189
+ ): Promise<ResolveSeoFilterResponse> | Observable<ResolveSeoFilterResponse> | ResolveSeoFilterResponse;
190
+
191
+ listSeoFilters(
192
+ request: ListSeoFiltersRequest,
193
+ ): Promise<ListSeoFiltersResponse> | Observable<ListSeoFiltersResponse> | ListSeoFiltersResponse;
194
+
195
+ getSeoFilter(
196
+ request: GetSeoFilterRequest,
197
+ ): Promise<SeoFilterResponse> | Observable<SeoFilterResponse> | SeoFilterResponse;
198
+
199
+ createSeoFilter(
200
+ request: CreateSeoFilterRequest,
201
+ ): Promise<SeoFilterResponse> | Observable<SeoFilterResponse> | SeoFilterResponse;
202
+
203
+ updateSeoFilter(
204
+ request: UpdateSeoFilterRequest,
205
+ ): Promise<SeoFilterResponse> | Observable<SeoFilterResponse> | SeoFilterResponse;
206
+
207
+ deleteSeoFilter(
208
+ request: DeleteSeoFilterRequest,
209
+ ): Promise<DeleteResponse> | Observable<DeleteResponse> | DeleteResponse;
210
+
211
+ /**
212
+ * Топ-N непокритих combinations (за impressions/popularity) — для
213
+ * швидкого створення SeoFilter з адмін-форми "Автопідказки".
214
+ */
215
+
216
+ suggestSeoFilters(
217
+ request: SuggestSeoFiltersRequest,
218
+ ): Promise<SuggestSeoFiltersResponse> | Observable<SuggestSeoFiltersResponse> | SuggestSeoFiltersResponse;
219
+ }
220
+
221
+ export function SeoFilterServiceControllerMethods() {
222
+ return function (constructor: Function) {
223
+ const grpcMethods: string[] = [
224
+ "resolveSeoFilter",
225
+ "listSeoFilters",
226
+ "getSeoFilter",
227
+ "createSeoFilter",
228
+ "updateSeoFilter",
229
+ "deleteSeoFilter",
230
+ "suggestSeoFilters",
231
+ ];
232
+ for (const method of grpcMethods) {
233
+ const descriptor: any = Reflect.getOwnPropertyDescriptor(constructor.prototype, method);
234
+ GrpcMethod("SeoFilterService", method)(constructor.prototype[method], method, descriptor);
235
+ }
236
+ const grpcStreamMethods: string[] = [];
237
+ for (const method of grpcStreamMethods) {
238
+ const descriptor: any = Reflect.getOwnPropertyDescriptor(constructor.prototype, method);
239
+ GrpcStreamMethod("SeoFilterService", method)(constructor.prototype[method], method, descriptor);
240
+ }
241
+ };
242
+ }
243
+
244
+ export const SEO_FILTER_SERVICE_NAME = "SeoFilterService";