@hed-hog/catalog 0.0.276

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.
Files changed (65) hide show
  1. package/dist/catalog-resource.config.d.ts +12 -0
  2. package/dist/catalog-resource.config.d.ts.map +1 -0
  3. package/dist/catalog-resource.config.js +209 -0
  4. package/dist/catalog-resource.config.js.map +1 -0
  5. package/dist/catalog.controller.d.ts +29 -0
  6. package/dist/catalog.controller.d.ts.map +1 -0
  7. package/dist/catalog.controller.js +117 -0
  8. package/dist/catalog.controller.js.map +1 -0
  9. package/dist/catalog.module.d.ts +3 -0
  10. package/dist/catalog.module.d.ts.map +1 -0
  11. package/dist/catalog.module.js +25 -0
  12. package/dist/catalog.module.js.map +1 -0
  13. package/dist/catalog.service.d.ts +36 -0
  14. package/dist/catalog.service.d.ts.map +1 -0
  15. package/dist/catalog.service.js +142 -0
  16. package/dist/catalog.service.js.map +1 -0
  17. package/dist/index.d.ts +2 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +18 -0
  20. package/dist/index.js.map +1 -0
  21. package/hedhog/data/menu.yaml +233 -0
  22. package/hedhog/data/role.yaml +7 -0
  23. package/hedhog/data/route.yaml +56 -0
  24. package/hedhog/frontend/app/[resource]/page.tsx.ejs +684 -0
  25. package/hedhog/frontend/app/_components/catalog-nav.tsx.ejs +85 -0
  26. package/hedhog/frontend/app/_lib/catalog-resources.tsx.ejs +569 -0
  27. package/hedhog/frontend/app/dashboard/page.tsx.ejs +566 -0
  28. package/hedhog/frontend/app/page.tsx.ejs +5 -0
  29. package/hedhog/frontend/messages/en.json +293 -0
  30. package/hedhog/frontend/messages/pt.json +293 -0
  31. package/hedhog/table/catalog_affiliate_program.yaml +41 -0
  32. package/hedhog/table/catalog_attribute.yaml +53 -0
  33. package/hedhog/table/catalog_attribute_group.yaml +18 -0
  34. package/hedhog/table/catalog_brand.yaml +34 -0
  35. package/hedhog/table/catalog_category_attribute.yaml +36 -0
  36. package/hedhog/table/catalog_click_event.yaml +50 -0
  37. package/hedhog/table/catalog_comparison.yaml +65 -0
  38. package/hedhog/table/catalog_comparison_highlight.yaml +39 -0
  39. package/hedhog/table/catalog_comparison_item.yaml +30 -0
  40. package/hedhog/table/catalog_content_relation.yaml +42 -0
  41. package/hedhog/table/catalog_import_run.yaml +33 -0
  42. package/hedhog/table/catalog_import_source.yaml +24 -0
  43. package/hedhog/table/catalog_merchant.yaml +29 -0
  44. package/hedhog/table/catalog_offer.yaml +83 -0
  45. package/hedhog/table/catalog_price_history.yaml +34 -0
  46. package/hedhog/table/catalog_product.yaml +76 -0
  47. package/hedhog/table/catalog_product_attribute_value.yaml +60 -0
  48. package/hedhog/table/catalog_product_category.yaml +26 -0
  49. package/hedhog/table/catalog_product_image.yaml +34 -0
  50. package/hedhog/table/catalog_product_score.yaml +38 -0
  51. package/hedhog/table/catalog_product_site.yaml +47 -0
  52. package/hedhog/table/catalog_product_tag.yaml +19 -0
  53. package/hedhog/table/catalog_score_criterion.yaml +37 -0
  54. package/hedhog/table/catalog_seo_page_rule.yaml +51 -0
  55. package/hedhog/table/catalog_similarity_rule.yaml +28 -0
  56. package/hedhog/table/catalog_site.yaml +40 -0
  57. package/hedhog/table/catalog_site_category.yaml +26 -0
  58. package/package.json +40 -0
  59. package/src/catalog-resource.config.ts +218 -0
  60. package/src/catalog.controller.ts +82 -0
  61. package/src/catalog.module.ts +12 -0
  62. package/src/catalog.service.ts +167 -0
  63. package/src/index.ts +1 -0
  64. package/src/language/en.json +4 -0
  65. package/src/language/pt.json +4 -0
@@ -0,0 +1,34 @@
1
+ columns:
2
+ - type: pk
3
+ - name: product_id
4
+ type: fk
5
+ references:
6
+ table: catalog_product
7
+ column: id
8
+ onDelete: CASCADE
9
+ - name: file_id
10
+ type: fk
11
+ references:
12
+ table: file
13
+ column: id
14
+ onDelete: CASCADE
15
+ - name: role
16
+ type: enum
17
+ values: [primary, gallery, thumbnail, lifestyle, technical]
18
+ default: gallery
19
+ - name: sort_order
20
+ type: int
21
+ default: 0
22
+ - name: is_primary
23
+ type: boolean
24
+ default: false
25
+ - name: alt_text
26
+ type: varchar
27
+ length: 255
28
+ isNullable: true
29
+ - type: created_at
30
+ - type: updated_at
31
+ indices:
32
+ - columns: [product_id, sort_order]
33
+ - columns: [product_id, is_primary]
34
+ - columns: [file_id]
@@ -0,0 +1,38 @@
1
+ columns:
2
+ - type: pk
3
+ - name: product_id
4
+ type: fk
5
+ references:
6
+ table: catalog_product
7
+ column: id
8
+ onDelete: CASCADE
9
+ - name: criterion_id
10
+ type: fk
11
+ references:
12
+ table: catalog_score_criterion
13
+ column: id
14
+ onDelete: CASCADE
15
+ - name: score_value
16
+ type: decimal
17
+ precision: 5
18
+ scale: 2
19
+ - name: score_label
20
+ type: varchar
21
+ length: 255
22
+ isNullable: true
23
+ - name: summary
24
+ type: text
25
+ isNullable: true
26
+ - name: calculation_source
27
+ type: varchar
28
+ length: 255
29
+ isNullable: true
30
+ - name: is_manual_override
31
+ type: boolean
32
+ default: false
33
+ - type: created_at
34
+ - type: updated_at
35
+ indices:
36
+ - columns: [product_id, criterion_id]
37
+ isUnique: true
38
+ - columns: [criterion_id, score_value]
@@ -0,0 +1,47 @@
1
+ columns:
2
+ - type: pk
3
+ - name: product_id
4
+ type: fk
5
+ references:
6
+ table: catalog_product
7
+ column: id
8
+ onDelete: CASCADE
9
+ - name: site_id
10
+ type: fk
11
+ references:
12
+ table: catalog_site
13
+ column: id
14
+ onDelete: CASCADE
15
+ - name: publication_status
16
+ type: enum
17
+ values: [draft, published, hidden]
18
+ default: draft
19
+ - name: canonical_slug
20
+ type: varchar
21
+ length: 255
22
+ - name: is_featured
23
+ type: boolean
24
+ default: false
25
+ - name: visibility_score
26
+ type: int
27
+ default: 0
28
+ - name: override_brand_name
29
+ type: varchar
30
+ length: 255
31
+ isNullable: true
32
+ - name: seo_title
33
+ type: varchar
34
+ length: 255
35
+ isNullable: true
36
+ - name: seo_description
37
+ type: varchar
38
+ length: 500
39
+ isNullable: true
40
+ - type: created_at
41
+ - type: updated_at
42
+ indices:
43
+ - columns: [site_id, product_id]
44
+ isUnique: true
45
+ - columns: [site_id, canonical_slug]
46
+ isUnique: true
47
+ - columns: [site_id, publication_status]
@@ -0,0 +1,19 @@
1
+ columns:
2
+ - type: pk
3
+ - name: product_id
4
+ type: fk
5
+ references:
6
+ table: catalog_product
7
+ column: id
8
+ onDelete: CASCADE
9
+ - name: tag_id
10
+ type: fk
11
+ references:
12
+ table: tag
13
+ column: id
14
+ onDelete: CASCADE
15
+ - type: created_at
16
+ - type: updated_at
17
+ indices:
18
+ - columns: [product_id, tag_id]
19
+ isUnique: true
@@ -0,0 +1,37 @@
1
+ columns:
2
+ - type: pk
3
+ - name: category_id
4
+ type: fk
5
+ references:
6
+ table: category
7
+ column: id
8
+ onDelete: CASCADE
9
+ - name: slug
10
+ type: varchar
11
+ length: 255
12
+ - name: name
13
+ type: varchar
14
+ length: 255
15
+ - name: weight
16
+ type: int
17
+ default: 1
18
+ - name: score_type
19
+ type: enum
20
+ values: [manual, weighted, formula]
21
+ default: manual
22
+ - name: formula_json
23
+ type: json
24
+ isNullable: true
25
+ - name: display_order
26
+ type: int
27
+ default: 0
28
+ - name: status
29
+ type: enum
30
+ values: [active, inactive]
31
+ default: active
32
+ - type: created_at
33
+ - type: updated_at
34
+ indices:
35
+ - columns: [category_id, slug]
36
+ isUnique: true
37
+ - columns: [category_id, status]
@@ -0,0 +1,51 @@
1
+ columns:
2
+ - type: pk
3
+ - name: site_id
4
+ type: fk
5
+ references:
6
+ table: catalog_site
7
+ column: id
8
+ onDelete: CASCADE
9
+ - name: category_id
10
+ type: fk
11
+ isNullable: true
12
+ references:
13
+ table: category
14
+ column: id
15
+ onDelete: SET NULL
16
+ - name: page_type
17
+ type: enum
18
+ values: [comparison, best_of, cost_benefit, attribute, price_range, brand, use_case]
19
+ default: comparison
20
+ - name: rule_slug
21
+ type: varchar
22
+ length: 255
23
+ - name: status
24
+ type: enum
25
+ values: [active, inactive]
26
+ default: active
27
+ - name: generation_query_json
28
+ type: json
29
+ isNullable: true
30
+ - name: min_product_count
31
+ type: int
32
+ default: 2
33
+ - name: min_attribute_coverage
34
+ type: int
35
+ default: 1
36
+ - name: canonical_strategy
37
+ type: enum
38
+ values: [self, parent, custom]
39
+ default: self
40
+ - name: priority
41
+ type: int
42
+ default: 0
43
+ - name: template_json
44
+ type: json
45
+ isNullable: true
46
+ - type: created_at
47
+ - type: updated_at
48
+ indices:
49
+ - columns: [site_id, rule_slug]
50
+ isUnique: true
51
+ - columns: [site_id, page_type, status]
@@ -0,0 +1,28 @@
1
+ columns:
2
+ - type: pk
3
+ - name: category_id
4
+ type: fk
5
+ references:
6
+ table: category
7
+ column: id
8
+ onDelete: CASCADE
9
+ - name: rule_type
10
+ type: enum
11
+ values: [same_category, compatible_category, shared_attribute, manual]
12
+ default: same_category
13
+ - name: rule_json
14
+ type: json
15
+ isNullable: true
16
+ - name: min_similarity_score
17
+ type: decimal
18
+ precision: 5
19
+ scale: 2
20
+ default: 0
21
+ - name: status
22
+ type: enum
23
+ values: [active, inactive]
24
+ default: active
25
+ - type: created_at
26
+ - type: updated_at
27
+ indices:
28
+ - columns: [category_id, status]
@@ -0,0 +1,40 @@
1
+ columns:
2
+ - type: pk
3
+ - name: slug
4
+ type: varchar
5
+ length: 255
6
+ - name: name
7
+ type: varchar
8
+ length: 255
9
+ - name: domain
10
+ type: varchar
11
+ length: 255
12
+ - name: status
13
+ type: enum
14
+ values: [active, inactive]
15
+ default: active
16
+ - name: site_type
17
+ type: enum
18
+ values: [portal, niche, tenant]
19
+ default: portal
20
+ - name: default_locale_id
21
+ type: fk
22
+ references:
23
+ table: locale
24
+ column: id
25
+ onDelete: RESTRICT
26
+ - name: theme_settings_json
27
+ type: json
28
+ isNullable: true
29
+ - name: seo_defaults_json
30
+ type: json
31
+ isNullable: true
32
+ - type: created_at
33
+ - type: updated_at
34
+ indices:
35
+ - columns: [slug]
36
+ isUnique: true
37
+ - columns: [domain]
38
+ isUnique: true
39
+ - columns: [status]
40
+ - columns: [default_locale_id]
@@ -0,0 +1,26 @@
1
+ columns:
2
+ - type: pk
3
+ - name: site_id
4
+ type: fk
5
+ references:
6
+ table: catalog_site
7
+ column: id
8
+ onDelete: CASCADE
9
+ - name: category_id
10
+ type: fk
11
+ references:
12
+ table: category
13
+ column: id
14
+ onDelete: CASCADE
15
+ - name: is_primary
16
+ type: boolean
17
+ default: false
18
+ - name: visibility_status
19
+ type: enum
20
+ values: [visible, hidden]
21
+ default: visible
22
+ - type: created_at
23
+ - type: updated_at
24
+ indices:
25
+ - columns: [site_id, category_id]
26
+ isUnique: true
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@hed-hog/catalog",
3
+ "version": "0.0.276",
4
+ "main": "dist/index.js",
5
+ "types": "dist/index.d.ts",
6
+ "dependencies": {
7
+ "@nestjs/common": "*",
8
+ "@nestjs/config": "^4.0.2",
9
+ "@nestjs/core": "^11",
10
+ "@nestjs/jwt": "^11",
11
+ "@nestjs/mapped-types": "*",
12
+ "@hed-hog/api-locale": "0.0.13",
13
+ "@hed-hog/api": "0.0.4",
14
+ "@hed-hog/core": "0.0.276",
15
+ "@hed-hog/api-pagination": "0.0.6",
16
+ "@hed-hog/api-prisma": "0.0.5",
17
+ "@hed-hog/category": "0.0.276",
18
+ "@hed-hog/content": "0.0.276",
19
+ "@hed-hog/tag": "0.0.276"
20
+ },
21
+ "exports": {
22
+ ".": {
23
+ "import": "./dist/index.js",
24
+ "require": "./dist/index.js"
25
+ },
26
+ "./package.json": "./package.json"
27
+ },
28
+ "files": [
29
+ "dist",
30
+ "src",
31
+ "hedhog"
32
+ ],
33
+ "scripts": {
34
+ "lint": "eslint \"{src,apps,libs,test}/**/*.ts\"",
35
+ "prebuild": "npx ts-node ../../scripts/build-dependencies.ts libraries/catalog",
36
+ "build": "tsc --project tsconfig.production.json",
37
+ "patch": "npx ts-node ../../scripts/patch.ts libraries/catalog",
38
+ "prod": "pnpm run patch && pnpm run build && pnpm publish --access public --no-git-checks"
39
+ }
40
+ }
@@ -0,0 +1,218 @@
1
+ export type CatalogResourceConfig = {
2
+ resource: string;
3
+ model: string;
4
+ searchFields: string[];
5
+ filterFields?: string[];
6
+ fields: string[];
7
+ defaultOrderBy?: Record<string, 'asc' | 'desc'>;
8
+ statusField?: string;
9
+ };
10
+
11
+ export const catalogResources: CatalogResourceConfig[] = [
12
+ {
13
+ resource: 'brands',
14
+ model: 'catalog_brand',
15
+ searchFields: ['slug', 'name', 'normalized_name'],
16
+ filterFields: ['status', 'logo_file_id'],
17
+ fields: ['slug', 'name', 'normalized_name', 'logo_file_id', 'status', 'website_url'],
18
+ statusField: 'status',
19
+ },
20
+ {
21
+ resource: 'sites',
22
+ model: 'catalog_site',
23
+ searchFields: ['slug', 'name', 'domain'],
24
+ filterFields: ['status', 'site_type', 'default_locale_id'],
25
+ fields: ['slug', 'name', 'domain', 'status', 'site_type', 'default_locale_id', 'theme_settings_json', 'seo_defaults_json'],
26
+ statusField: 'status',
27
+ },
28
+ {
29
+ resource: 'products',
30
+ model: 'catalog_product',
31
+ searchFields: ['slug', 'name', 'model_name', 'sku', 'gtin'],
32
+ filterFields: ['status', 'comparison_status', 'brand_id', 'category_id', 'primary_content_id', 'is_active'],
33
+ fields: ['brand_id', 'category_id', 'primary_content_id', 'slug', 'name', 'short_description', 'description', 'model_name', 'sku', 'gtin', 'status', 'comparison_status', 'release_date', 'spec_snapshot_json', 'comparison_snapshot_json', 'is_active'],
34
+ statusField: 'status',
35
+ },
36
+ {
37
+ resource: 'product-categories',
38
+ model: 'catalog_product_category',
39
+ searchFields: [],
40
+ filterFields: ['product_id', 'category_id', 'is_primary'],
41
+ fields: ['product_id', 'category_id', 'is_primary', 'sort_order'],
42
+ },
43
+ {
44
+ resource: 'product-images',
45
+ model: 'catalog_product_image',
46
+ searchFields: ['alt_text', 'role'],
47
+ filterFields: ['product_id', 'file_id', 'role', 'is_primary'],
48
+ fields: ['product_id', 'file_id', 'role', 'sort_order', 'is_primary', 'alt_text'],
49
+ },
50
+ {
51
+ resource: 'product-sites',
52
+ model: 'catalog_product_site',
53
+ searchFields: ['canonical_slug', 'override_brand_name', 'seo_title'],
54
+ filterFields: ['product_id', 'site_id', 'publication_status', 'is_featured'],
55
+ fields: ['product_id', 'site_id', 'publication_status', 'canonical_slug', 'is_featured', 'visibility_score', 'override_brand_name', 'seo_title', 'seo_description'],
56
+ statusField: 'publication_status',
57
+ },
58
+ {
59
+ resource: 'attribute-groups',
60
+ model: 'catalog_attribute_group',
61
+ searchFields: ['slug', 'name'],
62
+ filterFields: ['status'],
63
+ fields: ['slug', 'name', 'status'],
64
+ statusField: 'status',
65
+ },
66
+ {
67
+ resource: 'attributes',
68
+ model: 'catalog_attribute',
69
+ searchFields: ['slug', 'label', 'description', 'unit'],
70
+ filterFields: ['group_id', 'data_type', 'comparison_mode', 'is_filterable', 'is_sortable', 'is_required_for_comparison'],
71
+ fields: ['group_id', 'slug', 'label', 'description', 'data_type', 'unit', 'comparison_mode', 'is_filterable', 'is_sortable', 'is_required_for_comparison', 'normalization_rule_json', 'display_order'],
72
+ },
73
+ {
74
+ resource: 'category-attributes',
75
+ model: 'catalog_category_attribute',
76
+ searchFields: [],
77
+ filterFields: ['category_id', 'attribute_id', 'is_required', 'is_highlighted', 'facet_mode'],
78
+ fields: ['category_id', 'attribute_id', 'is_required', 'is_highlighted', 'display_order', 'weight', 'facet_mode'],
79
+ },
80
+ {
81
+ resource: 'product-attributes',
82
+ model: 'catalog_product_attribute_value',
83
+ searchFields: ['value_text', 'normalized_text', 'source_type'],
84
+ filterFields: ['product_id', 'attribute_id', 'is_verified'],
85
+ fields: ['product_id', 'attribute_id', 'value_text', 'value_number', 'value_boolean', 'value_json', 'value_unit', 'normalized_text', 'normalized_number', 'source_type', 'confidence_score', 'is_verified'],
86
+ },
87
+ {
88
+ resource: 'score-criteria',
89
+ model: 'catalog_score_criterion',
90
+ searchFields: ['slug', 'name'],
91
+ filterFields: ['category_id', 'status', 'score_type'],
92
+ fields: ['category_id', 'slug', 'name', 'weight', 'score_type', 'formula_json', 'display_order', 'status'],
93
+ statusField: 'status',
94
+ },
95
+ {
96
+ resource: 'product-scores',
97
+ model: 'catalog_product_score',
98
+ searchFields: ['score_label', 'summary', 'calculation_source'],
99
+ filterFields: ['product_id', 'criterion_id', 'is_manual_override'],
100
+ fields: ['product_id', 'criterion_id', 'score_value', 'score_label', 'summary', 'calculation_source', 'is_manual_override'],
101
+ },
102
+ {
103
+ resource: 'comparisons',
104
+ model: 'catalog_comparison',
105
+ searchFields: ['slug', 'title', 'summary', 'verdict', 'eligibility_hash'],
106
+ filterFields: ['category_id', 'site_id', 'primary_content_id', 'comparison_type', 'generation_mode', 'status'],
107
+ fields: ['category_id', 'site_id', 'primary_content_id', 'slug', 'comparison_type', 'generation_mode', 'status', 'title', 'summary', 'intro', 'verdict', 'spec_snapshot_json', 'eligibility_hash', 'published_at'],
108
+ statusField: 'status',
109
+ },
110
+ {
111
+ resource: 'comparison-items',
112
+ model: 'catalog_comparison_item',
113
+ searchFields: ['badge_label'],
114
+ filterFields: ['comparison_id', 'product_id', 'is_winner'],
115
+ fields: ['comparison_id', 'product_id', 'sort_order', 'is_winner', 'badge_label'],
116
+ },
117
+ {
118
+ resource: 'comparison-highlights',
119
+ model: 'catalog_comparison_highlight',
120
+ searchFields: ['highlight_type', 'title', 'body'],
121
+ filterFields: ['comparison_id', 'product_id', 'attribute_id', 'highlight_type'],
122
+ fields: ['comparison_id', 'product_id', 'attribute_id', 'highlight_type', 'title', 'body', 'sort_order'],
123
+ },
124
+ {
125
+ resource: 'similarity-rules',
126
+ model: 'catalog_similarity_rule',
127
+ searchFields: ['rule_type'],
128
+ filterFields: ['category_id', 'status'],
129
+ fields: ['category_id', 'rule_type', 'rule_json', 'min_similarity_score', 'status'],
130
+ statusField: 'status',
131
+ },
132
+ {
133
+ resource: 'merchants',
134
+ model: 'catalog_merchant',
135
+ searchFields: ['slug', 'name'],
136
+ filterFields: ['status', 'merchant_type', 'logo_file_id'],
137
+ fields: ['slug', 'name', 'status', 'merchant_type', 'logo_file_id'],
138
+ statusField: 'status',
139
+ },
140
+ {
141
+ resource: 'affiliate-programs',
142
+ model: 'catalog_affiliate_program',
143
+ searchFields: ['slug', 'name', 'network_type', 'commission_type'],
144
+ filterFields: ['merchant_id', 'status', 'network_type'],
145
+ fields: ['merchant_id', 'slug', 'name', 'network_type', 'tracking_template', 'commission_type', 'default_commission_value', 'status'],
146
+ statusField: 'status',
147
+ },
148
+ {
149
+ resource: 'offers',
150
+ model: 'catalog_offer',
151
+ searchFields: ['external_offer_id', 'title', 'availability_status'],
152
+ filterFields: ['product_id', 'merchant_id', 'affiliate_program_id', 'site_id', 'availability_status', 'is_featured'],
153
+ fields: ['product_id', 'merchant_id', 'affiliate_program_id', 'site_id', 'external_offer_id', 'title', 'price_amount', 'price_currency', 'original_price_amount', 'installment_json', 'availability_status', 'affiliate_url', 'deep_link_url', 'priority_score', 'is_featured', 'valid_from', 'valid_until', 'last_seen_at'],
154
+ },
155
+ {
156
+ resource: 'price-history',
157
+ model: 'catalog_price_history',
158
+ searchFields: ['availability_status'],
159
+ filterFields: ['offer_id', 'product_id', 'availability_status'],
160
+ fields: ['offer_id', 'product_id', 'captured_at', 'price_amount', 'original_price_amount', 'availability_status'],
161
+ },
162
+ {
163
+ resource: 'click-events',
164
+ model: 'catalog_click_event',
165
+ searchFields: ['placement', 'session_hash', 'referrer_host'],
166
+ filterFields: ['offer_id', 'product_id', 'site_id', 'comparison_id'],
167
+ fields: ['offer_id', 'product_id', 'site_id', 'comparison_id', 'clicked_at', 'placement', 'utm_json', 'session_hash', 'referrer_host'],
168
+ },
169
+ {
170
+ resource: 'site-categories',
171
+ model: 'catalog_site_category',
172
+ searchFields: ['visibility_status'],
173
+ filterFields: ['site_id', 'category_id', 'is_primary', 'visibility_status'],
174
+ fields: ['site_id', 'category_id', 'is_primary', 'visibility_status'],
175
+ },
176
+ {
177
+ resource: 'content-relations',
178
+ model: 'catalog_content_relation',
179
+ searchFields: ['relation_type'],
180
+ filterFields: ['site_id', 'content_id', 'product_id', 'comparison_id', 'relation_type'],
181
+ fields: ['site_id', 'content_id', 'product_id', 'comparison_id', 'relation_type', 'sort_order'],
182
+ },
183
+ {
184
+ resource: 'seo-rules',
185
+ model: 'catalog_seo_page_rule',
186
+ searchFields: ['page_type', 'rule_slug', 'canonical_strategy'],
187
+ filterFields: ['site_id', 'category_id', 'status', 'page_type'],
188
+ fields: ['site_id', 'category_id', 'page_type', 'rule_slug', 'status', 'generation_query_json', 'min_product_count', 'min_attribute_coverage', 'canonical_strategy', 'priority', 'template_json'],
189
+ statusField: 'status',
190
+ },
191
+ {
192
+ resource: 'import-sources',
193
+ model: 'catalog_import_source',
194
+ searchFields: ['slug', 'name', 'source_type'],
195
+ filterFields: ['source_type', 'status'],
196
+ fields: ['slug', 'name', 'source_type', 'config_json', 'status'],
197
+ statusField: 'status',
198
+ },
199
+ {
200
+ resource: 'import-runs',
201
+ model: 'catalog_import_run',
202
+ searchFields: ['status', 'idempotency_key'],
203
+ filterFields: ['source_id', 'status'],
204
+ fields: ['source_id', 'started_at', 'finished_at', 'status', 'stats_json', 'error_log', 'idempotency_key'],
205
+ statusField: 'status',
206
+ },
207
+ {
208
+ resource: 'product-tags',
209
+ model: 'catalog_product_tag',
210
+ searchFields: [],
211
+ filterFields: ['product_id', 'tag_id'],
212
+ fields: ['product_id', 'tag_id'],
213
+ }
214
+ ];
215
+
216
+ export const catalogResourceMap = new Map(
217
+ catalogResources.map((resource) => [resource.resource, resource]),
218
+ );
@@ -0,0 +1,82 @@
1
+ import { Role } from '@hed-hog/api';
2
+ import { Locale } from '@hed-hog/api-locale';
3
+ import { Pagination } from '@hed-hog/api-pagination';
4
+ import {
5
+ Body,
6
+ Controller,
7
+ Delete,
8
+ Get,
9
+ Param,
10
+ ParseIntPipe,
11
+ Patch,
12
+ Post,
13
+ Query,
14
+ } from '@nestjs/common';
15
+ import { CatalogService } from './catalog.service';
16
+
17
+ @Role()
18
+ @Controller('catalog')
19
+ export class CatalogController {
20
+ constructor(private readonly catalogService: CatalogService) {}
21
+
22
+ @Get('products/:id/images')
23
+ async listProductImages(
24
+ @Param('id', ParseIntPipe) id: number,
25
+ @Pagination() paginationParams,
26
+ @Locale() locale: string,
27
+ ) {
28
+ return this.catalogService.listProductImages(id, locale, paginationParams);
29
+ }
30
+
31
+ @Get(':resource/stats')
32
+ async stats(@Param('resource') resource: string, @Locale() locale: string) {
33
+ return this.catalogService.stats(resource, locale);
34
+ }
35
+
36
+ @Get(':resource/:id')
37
+ async getById(
38
+ @Param('resource') resource: string,
39
+ @Param('id', ParseIntPipe) id: number,
40
+ @Locale() locale: string,
41
+ ) {
42
+ return this.catalogService.getById(resource, id, locale);
43
+ }
44
+
45
+ @Patch(':resource/:id')
46
+ async update(
47
+ @Param('resource') resource: string,
48
+ @Param('id', ParseIntPipe) id: number,
49
+ @Body() body: Record<string, unknown>,
50
+ @Locale() locale: string,
51
+ ) {
52
+ return this.catalogService.update(resource, id, body, locale);
53
+ }
54
+
55
+ @Delete(':resource/:id')
56
+ async delete(
57
+ @Param('resource') resource: string,
58
+ @Param('id', ParseIntPipe) id: number,
59
+ @Locale() locale: string,
60
+ ) {
61
+ return this.catalogService.delete(resource, id, locale);
62
+ }
63
+
64
+ @Get(':resource')
65
+ async list(
66
+ @Param('resource') resource: string,
67
+ @Pagination() paginationParams,
68
+ @Query() query: Record<string, unknown>,
69
+ @Locale() locale: string,
70
+ ) {
71
+ return this.catalogService.list(resource, locale, paginationParams, query);
72
+ }
73
+
74
+ @Post(':resource')
75
+ async create(
76
+ @Param('resource') resource: string,
77
+ @Body() body: Record<string, unknown>,
78
+ @Locale() locale: string,
79
+ ) {
80
+ return this.catalogService.create(resource, body, locale);
81
+ }
82
+ }
@@ -0,0 +1,12 @@
1
+ import { PaginationModule } from '@hed-hog/api-pagination';
2
+ import { Module, forwardRef } from '@nestjs/common';
3
+ import { CatalogController } from './catalog.controller';
4
+ import { CatalogService } from './catalog.service';
5
+
6
+ @Module({
7
+ imports: [forwardRef(() => PaginationModule)],
8
+ controllers: [CatalogController],
9
+ providers: [CatalogService],
10
+ exports: [CatalogService],
11
+ })
12
+ export class CatalogModule {}