@bytebrand/export-cars 1.26.27 → 1.26.29
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/README.md +128 -0
- package/dist/configs/config.d.ts +2 -1
- package/dist/configs/config.js +1 -0
- package/dist/configs/config.js.map +1 -1
- package/dist/configs/google.config.js +16 -0
- package/dist/configs/google.config.js.map +1 -1
- package/dist/configs/index.d.ts +1 -0
- package/dist/configs/index.js +1 -0
- package/dist/configs/index.js.map +1 -1
- package/dist/configs/openai-ads.config.d.ts +22 -0
- package/dist/configs/openai-ads.config.js +56 -0
- package/dist/configs/openai-ads.config.js.map +1 -0
- package/dist/enums/export-type.enum.d.ts +2 -1
- package/dist/enums/export-type.enum.js +1 -0
- package/dist/enums/export-type.enum.js.map +1 -1
- package/dist/enums/image-type.enum.d.ts +2 -1
- package/dist/enums/image-type.enum.js +1 -0
- package/dist/enums/image-type.enum.js.map +1 -1
- package/dist/export.schema.d.ts +6 -2
- package/dist/export.schema.js +4 -0
- package/dist/export.schema.js.map +1 -1
- package/dist/exporters/google.exporter.js +12 -2
- package/dist/exporters/google.exporter.js.map +1 -1
- package/dist/exporters/index.d.ts +1 -0
- package/dist/exporters/index.js +1 -0
- package/dist/exporters/index.js.map +1 -1
- package/dist/exporters/openai-ads.exporter.d.ts +13 -0
- package/dist/exporters/openai-ads.exporter.js +91 -0
- package/dist/exporters/openai-ads.exporter.js.map +1 -0
- package/dist/formats/openai-ads-csv.builder.d.ts +15 -0
- package/dist/formats/openai-ads-csv.builder.js +48 -0
- package/dist/formats/openai-ads-csv.builder.js.map +1 -0
- package/dist/interfaces/openai-ads.interface.d.ts +35 -0
- package/dist/interfaces/openai-ads.interface.js +37 -0
- package/dist/interfaces/openai-ads.interface.js.map +1 -0
- package/dist/interfaces/params.interface.d.ts +20 -0
- package/dist/services/feed-guard.d.ts +44 -0
- package/dist/services/feed-guard.js +156 -0
- package/dist/services/feed-guard.js.map +1 -0
- package/dist/services/image-url-validator.service.d.ts +45 -0
- package/dist/services/image-url-validator.service.js +141 -0
- package/dist/services/image-url-validator.service.js.map +1 -0
- package/dist/services/images.service.d.ts +12 -0
- package/dist/services/images.service.js +46 -1
- package/dist/services/images.service.js.map +1 -1
- package/dist/services/index.d.ts +1 -0
- package/dist/services/index.js +1 -0
- package/dist/services/index.js.map +1 -1
- package/dist/services/openai-ads-feed-run.d.ts +74 -0
- package/dist/services/openai-ads-feed-run.js +151 -0
- package/dist/services/openai-ads-feed-run.js.map +1 -0
- package/dist/services/openai-ads-ledger.d.ts +19 -0
- package/dist/services/openai-ads-ledger.js +72 -0
- package/dist/services/openai-ads-ledger.js.map +1 -0
- package/dist/services/publication-gate.d.ts +15 -0
- package/dist/services/publication-gate.js +107 -0
- package/dist/services/publication-gate.js.map +1 -0
- package/dist/transformers/google-feed-envkv.d.ts +2 -0
- package/dist/transformers/google-feed-envkv.js +62 -31
- package/dist/transformers/google-feed-envkv.js.map +1 -1
- package/dist/transformers/google-feed-item-row.d.ts +6 -1
- package/dist/transformers/google-feed-item-row.js +3 -1
- package/dist/transformers/google-feed-item-row.js.map +1 -1
- package/dist/transformers/openai-ads.transformer.d.ts +28 -0
- package/dist/transformers/openai-ads.transformer.js +144 -0
- package/dist/transformers/openai-ads.transformer.js.map +1 -0
- package/dist/transformers/openai-image-fields.d.ts +16 -0
- package/dist/transformers/openai-image-fields.js +34 -0
- package/dist/transformers/openai-image-fields.js.map +1 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/docs/openai-ads/AUDIT.md +235 -0
- package/docs/openai-ads/RUNBOOK.md +94 -0
- package/package.json +64 -64
- package/schema/feed-items.json +134 -122
- package/src/configs/config.ts +99 -97
- package/src/configs/google.config.ts +41 -26
- package/src/configs/index.ts +1 -0
- package/src/configs/openai-ads.config.ts +70 -0
- package/src/enums/export-type.enum.ts +2 -0
- package/src/enums/image-type.enum.ts +5 -0
- package/src/export.command.ts +38 -38
- package/src/export.schema.ts +6 -0
- package/src/exporters/google.exporter.ts +67 -56
- package/src/exporters/index.ts +1 -0
- package/src/exporters/openai-ads.exporter.ts +93 -0
- package/src/formats/openai-ads-csv.builder.ts +55 -0
- package/src/interfaces/openai-ads.interface.ts +64 -0
- package/src/interfaces/params.interface.ts +56 -29
- package/src/services/feed-guard.ts +219 -0
- package/src/services/feed-items-bigquery.writer.ts +101 -101
- package/src/services/image-url-validator.service.ts +181 -0
- package/src/services/images.service.ts +72 -0
- package/src/services/index.ts +1 -0
- package/src/services/openai-ads-feed-run.ts +226 -0
- package/src/services/openai-ads-ledger.ts +116 -0
- package/src/services/publication-gate.ts +119 -0
- package/src/transformers/google-feed-envkv.ts +81 -33
- package/src/transformers/google-feed-item-row.ts +78 -71
- package/src/transformers/openai-ads.transformer.ts +211 -0
- package/src/transformers/openai-image-fields.ts +60 -0
- package/test/clean-images.test.ts +86 -0
- package/test/fixtures/images-service.harness.ts +32 -0
- package/test/fixtures/images.golden.json +218 -0
- package/test/fixtures/imbo-images.fixture.ts +77 -0
- package/test/fixtures/openai-ads.fixture.ts +89 -0
- package/test/google-feed-item-row.test.ts +135 -121
- package/test/image-url-validator.test.ts +110 -0
- package/test/images-regression.test.ts +23 -0
- package/test/openai-ads-feed-run.test.ts +278 -0
- package/test/openai-ads-mapping.test.ts +136 -0
- package/test/openai-image-fields.test.ts +99 -0
- package/test/publication-gate.test.ts +86 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { ImagesService } from '../../src/services/images.service';
|
|
2
|
+
import { ImageType } from '../../src/enums';
|
|
3
|
+
import { IMBO_FIXTURES, MARKETING_CONFIG_FIXTURE, cloneImages } from './imbo-images.fixture';
|
|
4
|
+
|
|
5
|
+
export const buildImagesService = (): ImagesService => {
|
|
6
|
+
const configService: any = {
|
|
7
|
+
config: {
|
|
8
|
+
baseImageUrl: 'https://images.auto.de',
|
|
9
|
+
marketingImageUrl: 'https://images.auto.de/generated_images',
|
|
10
|
+
marketingImageConfigId: 3,
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
const userService: any = { getMarketingImageConfig: async () => MARKETING_CONFIG_FIXTURE };
|
|
14
|
+
return new ImagesService(configService, userService);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
// Every image output the existing partner exporters consume, per fixture car. The regression test
|
|
18
|
+
// compares this against images.golden.json, recorded from the pre-ADV-336 ImagesService.
|
|
19
|
+
export const snapshotExistingImageOutputs = async (): Promise<Record<string, unknown>> => {
|
|
20
|
+
const service = buildImagesService();
|
|
21
|
+
const out: Record<string, unknown> = {};
|
|
22
|
+
for (const [name, { carId, images }] of Object.entries(IMBO_FIXTURES)) {
|
|
23
|
+
const car: any = { _id: carId };
|
|
24
|
+
out[name] = {
|
|
25
|
+
defaultWithPlaceholders: await service.getImages(car, cloneImages(images), ImageType.default, false),
|
|
26
|
+
defaultIgnorePlaceholders: await service.getImages(car, cloneImages(images), ImageType.default, true),
|
|
27
|
+
marketing: images.length ? await service.getImages(car, cloneImages(images), ImageType.marketing, false) : null,
|
|
28
|
+
googleExtInt: await service.getExtIntDefaultImages(car, cloneImages(images), ImageType.default, false),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
return out;
|
|
32
|
+
};
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
{
|
|
2
|
+
"full": {
|
|
3
|
+
"defaultWithPlaceholders": [
|
|
4
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extRight0001/large",
|
|
5
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extCowl00001/large",
|
|
6
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extLeft00001/large",
|
|
7
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extSide00001/large",
|
|
8
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extBack00001/large",
|
|
9
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extOpened001/large",
|
|
10
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/conext000001/large",
|
|
11
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/engine000001/large",
|
|
12
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/intDash00001/large",
|
|
13
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/intSeats0001/large",
|
|
14
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/intTrunk0001/large",
|
|
15
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/seatHeat0001/large",
|
|
16
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/featRims0001/large",
|
|
17
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/simple000001/large",
|
|
18
|
+
"https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg",
|
|
19
|
+
"https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg",
|
|
20
|
+
"https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg"
|
|
21
|
+
],
|
|
22
|
+
"defaultIgnorePlaceholders": [
|
|
23
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extRight0001/large",
|
|
24
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extCowl00001/large",
|
|
25
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extLeft00001/large",
|
|
26
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extSide00001/large",
|
|
27
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extBack00001/large",
|
|
28
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extOpened001/large",
|
|
29
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/conext000001/large",
|
|
30
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/engine000001/large",
|
|
31
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/intDash00001/large",
|
|
32
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/intSeats0001/large",
|
|
33
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/intTrunk0001/large",
|
|
34
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/seatHeat0001/large",
|
|
35
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/featRims0001/large",
|
|
36
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/simple000001/large"
|
|
37
|
+
],
|
|
38
|
+
"marketing": [
|
|
39
|
+
"https://images.auto.de/generated_images/2/c/e/2ce1d71f-851f-4123-ae16-187ddd7923c5/criteo-channel-extRight0001.jpg",
|
|
40
|
+
"https://images.auto.de/generated_images/2/c/e/2ce1d71f-851f-4123-ae16-187ddd7923c5/criteo-channel-extBack00001.jpg",
|
|
41
|
+
"https://images.auto.de/generated_images/2/c/e/2ce1d71f-851f-4123-ae16-187ddd7923c5/criteo-channel-intDash00001.jpg",
|
|
42
|
+
"https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg",
|
|
43
|
+
"https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg",
|
|
44
|
+
"https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg"
|
|
45
|
+
],
|
|
46
|
+
"googleExtInt": {
|
|
47
|
+
"extMain": [
|
|
48
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extRight0001/small",
|
|
49
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extLeft00001/small",
|
|
50
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extOpened001/small"
|
|
51
|
+
],
|
|
52
|
+
"ext": [
|
|
53
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extCowl00001/small",
|
|
54
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extSide00001/small",
|
|
55
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/extBack00001/small"
|
|
56
|
+
],
|
|
57
|
+
"int": [
|
|
58
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/intDash00001/small",
|
|
59
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/intSeats0001/small",
|
|
60
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/intTrunk0001/small"
|
|
61
|
+
],
|
|
62
|
+
"feat": [
|
|
63
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/conext000001/small",
|
|
64
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/engine000001/small",
|
|
65
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/seatHeat0001/small",
|
|
66
|
+
"https://images.auto.de/carimage/2ce1d71f-851f-4123-ae16-187ddd7923c5/featRims0001/small"
|
|
67
|
+
]
|
|
68
|
+
}
|
|
69
|
+
},
|
|
70
|
+
"leftOnly": {
|
|
71
|
+
"defaultWithPlaceholders": [
|
|
72
|
+
"https://images.auto.de/carimage/3703a23a-654d-426e-801e-beeffcc1e9c8/extLeft00002/large",
|
|
73
|
+
"https://images.auto.de/carimage/3703a23a-654d-426e-801e-beeffcc1e9c8/extBack00002/large",
|
|
74
|
+
"https://images.auto.de/carimage/3703a23a-654d-426e-801e-beeffcc1e9c8/intDash00002/large",
|
|
75
|
+
"https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg",
|
|
76
|
+
"https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg",
|
|
77
|
+
"https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg"
|
|
78
|
+
],
|
|
79
|
+
"defaultIgnorePlaceholders": [
|
|
80
|
+
"https://images.auto.de/carimage/3703a23a-654d-426e-801e-beeffcc1e9c8/extLeft00002/large",
|
|
81
|
+
"https://images.auto.de/carimage/3703a23a-654d-426e-801e-beeffcc1e9c8/extBack00002/large",
|
|
82
|
+
"https://images.auto.de/carimage/3703a23a-654d-426e-801e-beeffcc1e9c8/intDash00002/large"
|
|
83
|
+
],
|
|
84
|
+
"marketing": [
|
|
85
|
+
"https://images.auto.de/generated_images/3/7/0/3703a23a-654d-426e-801e-beeffcc1e9c8/criteo-channel-extLeft00002.jpg",
|
|
86
|
+
"https://images.auto.de/generated_images/3/7/0/3703a23a-654d-426e-801e-beeffcc1e9c8/criteo-channel-extBack00002.jpg",
|
|
87
|
+
"https://images.auto.de/generated_images/3/7/0/3703a23a-654d-426e-801e-beeffcc1e9c8/criteo-channel-intDash00002.jpg",
|
|
88
|
+
"https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg",
|
|
89
|
+
"https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg",
|
|
90
|
+
"https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg"
|
|
91
|
+
],
|
|
92
|
+
"googleExtInt": {
|
|
93
|
+
"extMain": [
|
|
94
|
+
"https://images.auto.de/carimage/3703a23a-654d-426e-801e-beeffcc1e9c8/extLeft00002/small"
|
|
95
|
+
],
|
|
96
|
+
"ext": [
|
|
97
|
+
"https://images.auto.de/carimage/3703a23a-654d-426e-801e-beeffcc1e9c8/extBack00002/small"
|
|
98
|
+
],
|
|
99
|
+
"int": [
|
|
100
|
+
"https://images.auto.de/carimage/3703a23a-654d-426e-801e-beeffcc1e9c8/intDash00002/small"
|
|
101
|
+
],
|
|
102
|
+
"feat": []
|
|
103
|
+
}
|
|
104
|
+
},
|
|
105
|
+
"noHero": {
|
|
106
|
+
"defaultWithPlaceholders": [
|
|
107
|
+
"https://images.auto.de/carimage/2c91c177-ddd3-4224-8b04-bdb96bf1b64c/extBack00003/large",
|
|
108
|
+
"https://images.auto.de/carimage/2c91c177-ddd3-4224-8b04-bdb96bf1b64c/intDash00003/large",
|
|
109
|
+
"https://images.auto.de/carimage/2c91c177-ddd3-4224-8b04-bdb96bf1b64c/featRims0003/large",
|
|
110
|
+
"https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg",
|
|
111
|
+
"https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg",
|
|
112
|
+
"https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg"
|
|
113
|
+
],
|
|
114
|
+
"defaultIgnorePlaceholders": [
|
|
115
|
+
"https://images.auto.de/carimage/2c91c177-ddd3-4224-8b04-bdb96bf1b64c/extBack00003/large",
|
|
116
|
+
"https://images.auto.de/carimage/2c91c177-ddd3-4224-8b04-bdb96bf1b64c/intDash00003/large",
|
|
117
|
+
"https://images.auto.de/carimage/2c91c177-ddd3-4224-8b04-bdb96bf1b64c/featRims0003/large"
|
|
118
|
+
],
|
|
119
|
+
"marketing": [
|
|
120
|
+
"https://images.auto.de/generated_images/2/c/9/2c91c177-ddd3-4224-8b04-bdb96bf1b64c/criteo-channel-extBack00003.jpg",
|
|
121
|
+
"https://images.auto.de/generated_images/2/c/9/2c91c177-ddd3-4224-8b04-bdb96bf1b64c/criteo-channel-intDash00003.jpg",
|
|
122
|
+
"https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg",
|
|
123
|
+
"https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg",
|
|
124
|
+
"https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg"
|
|
125
|
+
],
|
|
126
|
+
"googleExtInt": {
|
|
127
|
+
"extMain": [],
|
|
128
|
+
"ext": [
|
|
129
|
+
"https://images.auto.de/carimage/2c91c177-ddd3-4224-8b04-bdb96bf1b64c/extBack00003/small"
|
|
130
|
+
],
|
|
131
|
+
"int": [
|
|
132
|
+
"https://images.auto.de/carimage/2c91c177-ddd3-4224-8b04-bdb96bf1b64c/intDash00003/small"
|
|
133
|
+
],
|
|
134
|
+
"feat": [
|
|
135
|
+
"https://images.auto.de/carimage/2c91c177-ddd3-4224-8b04-bdb96bf1b64c/featRims0003/small"
|
|
136
|
+
]
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
"duplicates": {
|
|
140
|
+
"defaultWithPlaceholders": [
|
|
141
|
+
"https://images.auto.de/carimage/2e101cac-fb72-4cd7-a598-2ebba983a4f9/extRight0004/large",
|
|
142
|
+
"https://images.auto.de/carimage/2e101cac-fb72-4cd7-a598-2ebba983a4f9/extRight0004/large",
|
|
143
|
+
"https://images.auto.de/carimage/2e101cac-fb72-4cd7-a598-2ebba983a4f9/extRight0005/large",
|
|
144
|
+
"https://images.auto.de/carimage/2e101cac-fb72-4cd7-a598-2ebba983a4f9/intDash00004/large",
|
|
145
|
+
"https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg",
|
|
146
|
+
"https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg",
|
|
147
|
+
"https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg"
|
|
148
|
+
],
|
|
149
|
+
"defaultIgnorePlaceholders": [
|
|
150
|
+
"https://images.auto.de/carimage/2e101cac-fb72-4cd7-a598-2ebba983a4f9/extRight0004/large",
|
|
151
|
+
"https://images.auto.de/carimage/2e101cac-fb72-4cd7-a598-2ebba983a4f9/extRight0004/large",
|
|
152
|
+
"https://images.auto.de/carimage/2e101cac-fb72-4cd7-a598-2ebba983a4f9/extRight0005/large",
|
|
153
|
+
"https://images.auto.de/carimage/2e101cac-fb72-4cd7-a598-2ebba983a4f9/intDash00004/large"
|
|
154
|
+
],
|
|
155
|
+
"marketing": [
|
|
156
|
+
"https://images.auto.de/generated_images/2/e/1/2e101cac-fb72-4cd7-a598-2ebba983a4f9/criteo-channel-extRight0005.jpg",
|
|
157
|
+
"https://images.auto.de/generated_images/2/e/1/2e101cac-fb72-4cd7-a598-2ebba983a4f9/criteo-channel-intDash00004.jpg",
|
|
158
|
+
"https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg",
|
|
159
|
+
"https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg",
|
|
160
|
+
"https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg"
|
|
161
|
+
],
|
|
162
|
+
"googleExtInt": {
|
|
163
|
+
"extMain": [
|
|
164
|
+
"https://images.auto.de/carimage/2e101cac-fb72-4cd7-a598-2ebba983a4f9/extRight0004/small",
|
|
165
|
+
"https://images.auto.de/carimage/2e101cac-fb72-4cd7-a598-2ebba983a4f9/extRight0004/small",
|
|
166
|
+
"https://images.auto.de/carimage/2e101cac-fb72-4cd7-a598-2ebba983a4f9/extRight0005/small"
|
|
167
|
+
],
|
|
168
|
+
"ext": [],
|
|
169
|
+
"int": [
|
|
170
|
+
"https://images.auto.de/carimage/2e101cac-fb72-4cd7-a598-2ebba983a4f9/intDash00004/small"
|
|
171
|
+
],
|
|
172
|
+
"feat": []
|
|
173
|
+
}
|
|
174
|
+
},
|
|
175
|
+
"onlyUnknown": {
|
|
176
|
+
"defaultWithPlaceholders": [
|
|
177
|
+
"https://images.auto.de/carimage/61889cf8-2193-4c1e-8cdd-521ca2d38c9a/simple000006/large",
|
|
178
|
+
"https://images.auto.de/carimage/61889cf8-2193-4c1e-8cdd-521ca2d38c9a/promo0000006/large",
|
|
179
|
+
"https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg",
|
|
180
|
+
"https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg",
|
|
181
|
+
"https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg"
|
|
182
|
+
],
|
|
183
|
+
"defaultIgnorePlaceholders": [
|
|
184
|
+
"https://images.auto.de/carimage/61889cf8-2193-4c1e-8cdd-521ca2d38c9a/simple000006/large",
|
|
185
|
+
"https://images.auto.de/carimage/61889cf8-2193-4c1e-8cdd-521ca2d38c9a/promo0000006/large"
|
|
186
|
+
],
|
|
187
|
+
"marketing": [
|
|
188
|
+
"https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg",
|
|
189
|
+
"https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg",
|
|
190
|
+
"https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg"
|
|
191
|
+
],
|
|
192
|
+
"googleExtInt": {
|
|
193
|
+
"extMain": [],
|
|
194
|
+
"ext": [],
|
|
195
|
+
"int": [],
|
|
196
|
+
"feat": []
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
"empty": {
|
|
200
|
+
"defaultWithPlaceholders": [
|
|
201
|
+
"https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg",
|
|
202
|
+
"https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg",
|
|
203
|
+
"https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg"
|
|
204
|
+
],
|
|
205
|
+
"defaultIgnorePlaceholders": [
|
|
206
|
+
"https://images.auto.de/carimage/noimage/7pNvWELuWhZX/large-cached.jpeg",
|
|
207
|
+
"https://images.auto.de/carimage/noimage/GvyXmrpaf1D6/large-cached.jpeg",
|
|
208
|
+
"https://images.auto.de/carimage/noimage/pFyfBsqBHEso/large-cached.jpeg"
|
|
209
|
+
],
|
|
210
|
+
"marketing": null,
|
|
211
|
+
"googleExtInt": {
|
|
212
|
+
"extMain": [],
|
|
213
|
+
"ext": [],
|
|
214
|
+
"int": [],
|
|
215
|
+
"feat": []
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { ImboImageResponseInterface } from '@bytebrand/chunkable';
|
|
2
|
+
|
|
3
|
+
// Imbo image lists as CarBasicDataCarsLoader hands them to the transformers (newest first, as Imbo
|
|
4
|
+
// returns them). Codes mirror real image_code_predicted labels, incl. the "-suffix" form.
|
|
5
|
+
const img = (imageIdentifier: string, imageCodePredicted?: string): ImboImageResponseInterface => ({
|
|
6
|
+
imageIdentifier,
|
|
7
|
+
imageCodePredicted,
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
export const IMBO_FIXTURES: Record<string, { carId: string; images: ImboImageResponseInterface[] }> = {
|
|
11
|
+
full: {
|
|
12
|
+
carId: '2ce1d71f-851f-4123-ae16-187ddd7923c5',
|
|
13
|
+
images: [
|
|
14
|
+
img('intDash00001', 'int_f_ipanel1'),
|
|
15
|
+
img('featRims0001', 'ext_feat_rims'),
|
|
16
|
+
img('extBack00001', 'ext_b_main'),
|
|
17
|
+
img('simple000001', 'simple_01'),
|
|
18
|
+
img('extLeft00001', 'ext_f_left'),
|
|
19
|
+
img('conext000001', 'conext_f_main'),
|
|
20
|
+
img('intSeats0001', 'int_f_driverseats-1'),
|
|
21
|
+
img('extCowl00001', 'ext_f_cowl'),
|
|
22
|
+
img('extOpened001', 'ext_f_main_opened'),
|
|
23
|
+
img('engine000001', 'ext_feat_engine'),
|
|
24
|
+
img('seatHeat0001', 'int_feat_seatheating'),
|
|
25
|
+
img('extRight0001', 'ext_f_right'),
|
|
26
|
+
img('extSide00001', 'ext_l_main'),
|
|
27
|
+
img('intTrunk0001', 'int_b_trunk'),
|
|
28
|
+
],
|
|
29
|
+
},
|
|
30
|
+
leftOnly: {
|
|
31
|
+
carId: '3703a23a-654d-426e-801e-beeffcc1e9c8',
|
|
32
|
+
images: [
|
|
33
|
+
img('intDash00002', 'int_f_ipanel1'),
|
|
34
|
+
img('extBack00002', 'ext_b_main'),
|
|
35
|
+
img('extLeft00002', 'ext_f_left'),
|
|
36
|
+
],
|
|
37
|
+
},
|
|
38
|
+
noHero: {
|
|
39
|
+
carId: '2c91c177-ddd3-4224-8b04-bdb96bf1b64c',
|
|
40
|
+
images: [
|
|
41
|
+
img('extBack00003', 'ext_b_main'),
|
|
42
|
+
img('intDash00003', 'int_f_ipanel1'),
|
|
43
|
+
img('featRims0003', 'ext_feat_rims'),
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
duplicates: {
|
|
47
|
+
carId: '2e101cac-fb72-4cd7-a598-2ebba983a4f9',
|
|
48
|
+
images: [
|
|
49
|
+
img('extRight0004', 'ext_f_right'),
|
|
50
|
+
img('extRight0004', 'ext_f_right'),
|
|
51
|
+
img('extRight0005', 'ext_f_right'),
|
|
52
|
+
img('intDash00004', 'int_f_ipanel1'),
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
onlyUnknown: {
|
|
56
|
+
carId: '61889cf8-2193-4c1e-8cdd-521ca2d38c9a',
|
|
57
|
+
images: [img('simple000006', 'simple_01'), img('promo0000006', 'promo_slide')],
|
|
58
|
+
},
|
|
59
|
+
empty: {
|
|
60
|
+
carId: '0b0999c6-2f02-4bc3-8852-2307e8a0232f',
|
|
61
|
+
images: [],
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
// Same shape as a stored MarketingImageConfig (criteo-like) for getMarketingImages.
|
|
66
|
+
export const MARKETING_CONFIG_FIXTURE = {
|
|
67
|
+
channelCode: 'criteo channel',
|
|
68
|
+
imageExtension: 'jpg',
|
|
69
|
+
marketingImages: [
|
|
70
|
+
{ imageCodes: ['ext_f_right', 'ext_f_left'] },
|
|
71
|
+
{ imageCodes: ['int_f_ipanel1'] },
|
|
72
|
+
{ imageCodes: ['ext_b_main'] },
|
|
73
|
+
],
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
export const cloneImages = (images: ImboImageResponseInterface[]): ImboImageResponseInterface[] =>
|
|
77
|
+
images.map(i => ({ ...i }));
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { ImboImageResponseInterface } from '@bytebrand/chunkable';
|
|
2
|
+
|
|
3
|
+
// Minimal RFC 4180 reader for the tests: whole file -> rows of cells (quoted newlines kept).
|
|
4
|
+
export const parseCsv = (text: string): string[][] => {
|
|
5
|
+
const rows: string[][] = [];
|
|
6
|
+
let row: string[] = [];
|
|
7
|
+
let cell = '';
|
|
8
|
+
let quoted = false;
|
|
9
|
+
for (let i = 0; i < text.length; i++) {
|
|
10
|
+
const c = text[i];
|
|
11
|
+
if (quoted) {
|
|
12
|
+
if (c === '"' && text[i + 1] === '"') { cell += '"'; i++; } else if (c === '"') { quoted = false; } else { cell += c; }
|
|
13
|
+
} else if (c === '"') {
|
|
14
|
+
quoted = true;
|
|
15
|
+
} else if (c === ',') {
|
|
16
|
+
row.push(cell); cell = '';
|
|
17
|
+
} else if (c === '\n') {
|
|
18
|
+
row.push(cell); rows.push(row); row = []; cell = '';
|
|
19
|
+
} else {
|
|
20
|
+
cell += c;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
if (cell || row.length) { row.push(cell); rows.push(row); }
|
|
24
|
+
return rows;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
export const csvObjects = (text: string): Record<string, string>[] => {
|
|
28
|
+
const [header, ...rows] = parseCsv(text);
|
|
29
|
+
return rows.map(cells => Object.fromEntries(header.map((name, i) => [name, cells[i]])));
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// German labels the TranslatorExtended returns for these selectors (checked against
|
|
33
|
+
// @bytebrand/i18n-dictionaries); anything else comes back as the key itself, like the real one.
|
|
34
|
+
const LABELS: Record<string, string> = {
|
|
35
|
+
selector_fuel_petrol: 'Benzin',
|
|
36
|
+
selector_fuel_diesel: 'Diesel',
|
|
37
|
+
selector_gearbox_manualShift: 'Manuell',
|
|
38
|
+
selector_gearbox_automatic: 'Automatik',
|
|
39
|
+
selector_category_sedan: 'Limousine',
|
|
40
|
+
selector_category_combi: 'Kombi',
|
|
41
|
+
selector_exteriorColor_black: 'Schwarz',
|
|
42
|
+
selector_exteriorColor_grey: 'Grau',
|
|
43
|
+
selector_unknown: 'Unbekannt',
|
|
44
|
+
};
|
|
45
|
+
export const translate = (key: string): string => LABELS[key] ?? key;
|
|
46
|
+
|
|
47
|
+
export const NOW = new Date('2026-10-12T08:00:00Z');
|
|
48
|
+
const MAR_2021 = Date.UTC(2021, 2, 15) / 1000;
|
|
49
|
+
|
|
50
|
+
export const car = (id: string, overrides: Record<string, any> = {}): any => {
|
|
51
|
+
const base: any = {
|
|
52
|
+
_id: id,
|
|
53
|
+
mainData: {
|
|
54
|
+
make: 'Volkswagen',
|
|
55
|
+
model: 'Golf',
|
|
56
|
+
subModel: '1.5 TSI Life',
|
|
57
|
+
condition: 'selector_condition_used',
|
|
58
|
+
firstRegistration: MAR_2021,
|
|
59
|
+
mileage: 45000,
|
|
60
|
+
category: 'selector_category_sedan',
|
|
61
|
+
},
|
|
62
|
+
metaData: { ownerId: 'dealer-1', imagesCount: 2, vehicleId: 'ABC123' },
|
|
63
|
+
price: { currentSalesPrice: 17990 },
|
|
64
|
+
rate: { monthlyInstallment: 199, paybackPeriod: 48 },
|
|
65
|
+
consumption: { fuel: 'selector_fuel_petrol' },
|
|
66
|
+
driveSuspension: { gearbox: 'selector_gearbox_manualShift' },
|
|
67
|
+
engineData: { powerKW: 110, powerPS: 150 },
|
|
68
|
+
exterior: { exteriorColor: 'selector_exteriorColor_black' },
|
|
69
|
+
offer: { offerAvailability: 'selector_unknown' },
|
|
70
|
+
state: { isOnline: true },
|
|
71
|
+
};
|
|
72
|
+
for (const [path, value] of Object.entries(overrides)) {
|
|
73
|
+
const keys = path.split('.');
|
|
74
|
+
let target = base;
|
|
75
|
+
keys.slice(0, -1).forEach((key) => { target[key] = target[key] ?? {}; target = target[key]; });
|
|
76
|
+
if (value === undefined) {
|
|
77
|
+
delete target[keys[keys.length - 1]];
|
|
78
|
+
} else {
|
|
79
|
+
target[keys[keys.length - 1]] = value;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return base;
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
export const images = (prefix: string): ImboImageResponseInterface[] => [
|
|
86
|
+
{ imageIdentifier: `${prefix}Back`, imageCodePredicted: 'ext_b_main' },
|
|
87
|
+
{ imageIdentifier: `${prefix}Right`, imageCodePredicted: 'ext_f_right' },
|
|
88
|
+
{ imageIdentifier: `${prefix}Dash`, imageCodePredicted: 'int_f_ipanel1' },
|
|
89
|
+
];
|