@bytebrand/export-cars 1.26.47 → 1.26.48

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 (52) hide show
  1. package/dist/configs/ooyyo.config.d.ts +14 -0
  2. package/dist/configs/ooyyo.config.js +40 -6
  3. package/dist/configs/ooyyo.config.js.map +1 -1
  4. package/dist/exporters/ooyyo.exporter.d.ts +5 -4
  5. package/dist/exporters/ooyyo.exporter.js +45 -25
  6. package/dist/exporters/ooyyo.exporter.js.map +1 -1
  7. package/dist/formats/ooyyo-xml.builder.d.ts +7 -2
  8. package/dist/formats/ooyyo-xml.builder.js +59 -36
  9. package/dist/formats/ooyyo-xml.builder.js.map +1 -1
  10. package/dist/interfaces/export-item.interface.d.ts +30 -2
  11. package/dist/interfaces/params.interface.d.ts +3 -0
  12. package/dist/services/ooyyo-feed-run.d.ts +81 -0
  13. package/dist/services/ooyyo-feed-run.js +183 -0
  14. package/dist/services/ooyyo-feed-run.js.map +1 -0
  15. package/dist/services/ooyyo-feed-verify.d.ts +13 -0
  16. package/dist/services/ooyyo-feed-verify.js +104 -0
  17. package/dist/services/ooyyo-feed-verify.js.map +1 -0
  18. package/dist/transformers/ooyyo.transformer.d.ts +51 -11
  19. package/dist/transformers/ooyyo.transformer.js +268 -95
  20. package/dist/transformers/ooyyo.transformer.js.map +1 -1
  21. package/dist/tsconfig.build.tsbuildinfo +1 -1
  22. package/docs/marktde/AUDIT.md +84 -84
  23. package/docs/marktde/PARTNER-QUESTIONS.md +49 -49
  24. package/docs/marktde/RUNBOOK.md +58 -58
  25. package/docs/marktde/TRACKING.md +75 -69
  26. package/docs/meinestadt/PARTNER-QUESTIONS.md +17 -0
  27. package/docs/meinestadt/TRACKING.md +107 -0
  28. package/docs/ooyyo/AUDIT.md +81 -0
  29. package/docs/ooyyo/PARTNER-QUESTIONS.md +32 -0
  30. package/docs/ooyyo/RUNBOOK.md +67 -0
  31. package/docs/ooyyo/TRACKING.md +54 -0
  32. package/package.json +66 -65
  33. package/src/configs/marktde.config.ts +70 -70
  34. package/src/configs/ooyyo.config.ts +65 -15
  35. package/src/exporters/marktde.exporter.ts +78 -78
  36. package/src/exporters/ooyyo.exporter.ts +75 -48
  37. package/src/formats/ooyyo-xml.builder.ts +87 -48
  38. package/src/interfaces/export-item.interface.ts +43 -2
  39. package/src/interfaces/params.interface.ts +5 -0
  40. package/src/services/marktde-feed-run.ts +233 -233
  41. package/src/services/ooyyo-feed-run.ts +265 -0
  42. package/src/services/ooyyo-feed-verify.ts +131 -0
  43. package/src/transformers/marktde.transformer.ts +255 -255
  44. package/src/transformers/ooyyo.transformer.ts +378 -109
  45. package/test/fixtures/ooyyo/OoyyoFormat.xml +125 -0
  46. package/test/fixtures/ooyyo/OoyyoFormat.xsd +116 -0
  47. package/test/fixtures/ooyyo.fixture.ts +53 -0
  48. package/test/mapping-csv.test.ts +65 -65
  49. package/test/marktde-feed-run.test.ts +263 -263
  50. package/test/marktde-mapping.test.ts +280 -280
  51. package/test/ooyyo-feed-run.test.ts +293 -0
  52. package/test/ooyyo-mapping.test.ts +276 -0
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.OoyyoFeedRun = void 0;
4
+ const fs_1 = require("fs");
5
+ const path_1 = require("path");
6
+ const promises_1 = require("stream/promises");
7
+ const zlib_1 = require("zlib");
8
+ const crypto_1 = require("crypto");
9
+ const ooyyo_xml_builder_1 = require("../formats/ooyyo-xml.builder");
10
+ const ooyyo_transformer_1 = require("../transformers/ooyyo.transformer");
11
+ const feed_guard_1 = require("./feed-guard");
12
+ const ooyyo_feed_verify_1 = require("./ooyyo-feed-verify");
13
+ const increment = (counter, key) => {
14
+ counter[key] = (counter[key] ?? 0) + 1;
15
+ };
16
+ const OPTIONAL_FIELDS = ['content', 'engine_size', 'body_type', 'color', 'mileage', 'fuel_type', 'transmission', 'euronorm',
17
+ 'power', 'doors', 'seats', 'gears', 'vin', 'is_new', 'date'];
18
+ const exists = (file) => fs_1.promises.stat(file).then(() => true, () => false);
19
+ class OoyyoFeedRun {
20
+ deps;
21
+ options;
22
+ constructor(deps, options) {
23
+ this.deps = deps;
24
+ this.options = options;
25
+ }
26
+ now() {
27
+ return this.options.now ? this.options.now() : new Date();
28
+ }
29
+ async run() {
30
+ const { guard } = this.deps;
31
+ const { xmlFile, gzFile, runId, dryRun } = this.options;
32
+ const startedAt = this.now();
33
+ const lastGood = await guard.readLastGood();
34
+ const report = {
35
+ runId,
36
+ mode: dryRun ? 'dry-run' : 'live',
37
+ startedAt: startedAt.toISOString(),
38
+ status: 'failed',
39
+ xmlFile,
40
+ gzFile,
41
+ source: { files: 0, newestChunkAt: null, cars: 0 },
42
+ items: 0,
43
+ excluded: {},
44
+ missing: {},
45
+ postcodePadded: 0,
46
+ imagesPerItem: { min: null, max: null, total: 0 },
47
+ images: {},
48
+ lastGood,
49
+ lastGoodAgeHours: guard.staleHours(lastGood, startedAt),
50
+ stale: guard.isStale(lastGood, startedAt),
51
+ };
52
+ await guard.acquireLock(runId ?? 'local', startedAt);
53
+ const tmpXml = `${xmlFile}.tmp`;
54
+ const tmpGz = gzFile.replace(/\.gz$/, '.tmp.gz');
55
+ try {
56
+ const snapshot = await (0, feed_guard_1.inspectSourceSnapshot)(this.options.sourceDirectory, this.options.sourceBaseFileName);
57
+ report.source.files = snapshot.files;
58
+ report.source.newestChunkAt = snapshot.newestMtime?.toISOString() ?? null;
59
+ guard.checkSource(snapshot, startedAt);
60
+ await fs_1.promises.mkdir((0, path_1.dirname)(xmlFile), { recursive: true });
61
+ await fs_1.promises.rm(tmpXml, { force: true });
62
+ await fs_1.promises.rm(tmpGz, { force: true });
63
+ const builder = new ooyyo_xml_builder_1.OoyyoXmlBuilder(tmpXml);
64
+ await builder.buildStart();
65
+ const seen = new Set();
66
+ try {
67
+ await this.deps.forEachChunk(async (cars) => {
68
+ for (const source of cars) {
69
+ report.source.cars += 1;
70
+ const id = String(source?.car?._id ?? '');
71
+ if (id && seen.has(id)) {
72
+ increment(report.excluded, ooyyo_transformer_1.OoyyoExclusion.duplicateId);
73
+ continue;
74
+ }
75
+ seen.add(id);
76
+ if (!this.deps.filterCar(source)) {
77
+ increment(report.excluded, ooyyo_transformer_1.OoyyoExclusion.filtered);
78
+ continue;
79
+ }
80
+ const excluded = (0, ooyyo_transformer_1.getOoyyoExclusion)(source.car, startedAt);
81
+ if (excluded) {
82
+ increment(report.excluded, excluded);
83
+ continue;
84
+ }
85
+ const images = await this.deps.resolveImages(source);
86
+ if (!images.length) {
87
+ increment(report.excluded, ooyyo_transformer_1.OoyyoExclusion.noImage);
88
+ continue;
89
+ }
90
+ const country = source.car?.location?.countryCode;
91
+ const postcode = (0, ooyyo_transformer_1.getOoyyoPostcode)(source.car?.location?.zipCode, country);
92
+ const mapped = (0, ooyyo_transformer_1.mapOoyyoItem)(source.car, {
93
+ domain: this.options.domain,
94
+ images,
95
+ translate: this.deps.translate,
96
+ region: await this.deps.region(postcode, country),
97
+ now: startedAt,
98
+ });
99
+ if (mapped.ok === false) {
100
+ increment(report.excluded, mapped.reason);
101
+ continue;
102
+ }
103
+ await builder.addItem(mapped.item);
104
+ this.count(report, mapped.item, String(source.car?.location?.zipCode ?? ''));
105
+ }
106
+ });
107
+ }
108
+ finally {
109
+ await builder.buildEnd();
110
+ }
111
+ report.images = this.deps.imageStats();
112
+ const verify = (0, ooyyo_feed_verify_1.verifyOoyyoXml)(await fs_1.promises.readFile(tmpXml, 'utf8'), report.items);
113
+ report.verify = { ads: verify.ads, issues: verify.issues.length, firstIssues: verify.issues.slice(0, 20) };
114
+ if (verify.issues.length) {
115
+ throw new feed_guard_1.FeedGuardError('verify_failed', `${verify.issues.length} problem(s) in the written XML, first: ${verify.issues[0].problem}`);
116
+ }
117
+ const counts = { sourceItems: report.source.cars, publishedItems: report.items };
118
+ guard.checkCounts(counts, lastGood);
119
+ const xmlBytes = await fs_1.promises.readFile(tmpXml);
120
+ await (0, promises_1.pipeline)((0, fs_1.createReadStream)(tmpXml), (0, zlib_1.createGzip)({ level: 9 }), (0, fs_1.createWriteStream)(tmpGz));
121
+ const gzBytes = await fs_1.promises.readFile(tmpGz);
122
+ if (!(0, zlib_1.gunzipSync)(gzBytes).equals(xmlBytes)) {
123
+ throw new Error('gzip round trip does not match the XML');
124
+ }
125
+ report.bytes = { xml: xmlBytes.length, gz: gzBytes.length, sha256: (0, crypto_1.createHash)('sha256').update(xmlBytes).digest('hex') };
126
+ if (await exists(gzFile)) {
127
+ await fs_1.promises.copyFile(gzFile, `${gzFile}.prev`);
128
+ }
129
+ await fs_1.promises.rename(tmpGz, gzFile);
130
+ report.lastGood = await guard.publish(tmpXml, xmlFile, counts, this.now(), runId);
131
+ report.status = 'published';
132
+ report.lastGoodAgeHours = 0;
133
+ report.stale = false;
134
+ return report;
135
+ }
136
+ catch (error) {
137
+ if (error instanceof feed_guard_1.FeedGuardError) {
138
+ report.status = 'blocked';
139
+ report.guard = { code: error.code, message: error.message };
140
+ }
141
+ else {
142
+ report.error = error?.message ?? String(error);
143
+ }
144
+ await fs_1.promises.rename(tmpXml, `${xmlFile}.rejected`).catch(() => undefined);
145
+ await fs_1.promises.rm(tmpGz, { force: true }).catch(() => undefined);
146
+ throw error;
147
+ }
148
+ finally {
149
+ await this.writeReport(report);
150
+ await guard.releaseLock();
151
+ }
152
+ }
153
+ count(report, item, rawZip) {
154
+ report.items += 1;
155
+ for (const field of OPTIONAL_FIELDS) {
156
+ if (!item[field]) {
157
+ increment(report.missing, field);
158
+ }
159
+ }
160
+ if (!item.location.postcode) {
161
+ increment(report.missing, 'postcode');
162
+ }
163
+ if (!item.location.region) {
164
+ increment(report.missing, 'region');
165
+ }
166
+ if (item.location.postcode && item.location.postcode !== rawZip) {
167
+ report.postcodePadded += 1;
168
+ }
169
+ const images = item.pictures.length;
170
+ const stats = report.imagesPerItem;
171
+ stats.min = stats.min === null ? images : Math.min(stats.min, images);
172
+ stats.max = stats.max === null ? images : Math.max(stats.max, images);
173
+ stats.total += images;
174
+ }
175
+ async writeReport(report) {
176
+ report.finishedAt = this.now().toISOString();
177
+ await fs_1.promises.mkdir(this.options.stateDir, { recursive: true });
178
+ await fs_1.promises.writeFile((0, path_1.join)(this.options.stateDir, 'last-run-report.json'), JSON.stringify(report, null, 2), 'utf8');
179
+ console.log(`ooyyo feed report: ${JSON.stringify(report)}`);
180
+ }
181
+ }
182
+ exports.OoyyoFeedRun = OoyyoFeedRun;
183
+ //# sourceMappingURL=ooyyo-feed-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ooyyo-feed-run.js","sourceRoot":"","sources":["../../src/services/ooyyo-feed-run.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export declare const OOYYO_AD_ELEMENTS: string[];
2
+ export declare const OOYYO_LOCATION_ELEMENTS: string[];
3
+ export declare const OOYYO_UNIT_ELEMENTS: string[];
4
+ export declare const OOYYO_UNITS: Record<string, string[]>;
5
+ export interface OoyyoVerifyIssue {
6
+ ad: number;
7
+ problem: string;
8
+ }
9
+ export interface OoyyoVerifyResult {
10
+ ads: number;
11
+ issues: OoyyoVerifyIssue[];
12
+ }
13
+ export declare const verifyOoyyoXml: (xml: string, expectedAds: number) => OoyyoVerifyResult;
@@ -0,0 +1,104 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.verifyOoyyoXml = exports.OOYYO_UNITS = exports.OOYYO_UNIT_ELEMENTS = exports.OOYYO_LOCATION_ELEMENTS = exports.OOYYO_AD_ELEMENTS = void 0;
4
+ const fast_xml_parser_1 = require("fast-xml-parser");
5
+ const ooyyo_transformer_1 = require("../transformers/ooyyo.transformer");
6
+ exports.OOYYO_AD_ELEMENTS = [
7
+ 'url', 'title', 'content', 'price', 'make', 'model', 'engine_size', 'trim', 'body_type', 'color', 'year',
8
+ 'mileage', 'fuel_type', 'transmission', 'euronorm', 'power', 'doors', 'seats', 'gears', 'location',
9
+ 'pictures', 'vin', 'is_new', 'date', 'time',
10
+ ];
11
+ exports.OOYYO_LOCATION_ELEMENTS = ['city', 'postcode', 'region'];
12
+ exports.OOYYO_UNIT_ELEMENTS = ['price', 'engine_size', 'mileage', 'power'];
13
+ exports.OOYYO_UNITS = {
14
+ price: [ooyyo_transformer_1.OOYYO_PRICE_UNIT],
15
+ engine_size: ['cc', 'l'],
16
+ mileage: ['km', 'mi'],
17
+ power: ['kw', 'hp'],
18
+ };
19
+ const TEXT = '#text';
20
+ const valueOf = (node) => {
21
+ if (node === null || node === undefined) {
22
+ return '';
23
+ }
24
+ if (typeof node === 'object') {
25
+ return String(node[TEXT] ?? '');
26
+ }
27
+ return String(node);
28
+ };
29
+ const asList = (node) => (Array.isArray(node) ? node : node === undefined ? [] : [node]);
30
+ const verifyOoyyoXml = (xml, expectedAds) => {
31
+ const issues = [];
32
+ const wellFormed = fast_xml_parser_1.XMLValidator.validate(xml);
33
+ if (wellFormed !== true) {
34
+ return { ads: 0, issues: [{ ad: -1, problem: `not well-formed: ${wellFormed.err.msg} (line ${wellFormed.err.line})` }] };
35
+ }
36
+ const parser = new fast_xml_parser_1.XMLParser({
37
+ ignoreAttributes: false,
38
+ attributeNamePrefix: '@',
39
+ parseTagValue: false,
40
+ parseAttributeValue: false,
41
+ trimValues: false,
42
+ isArray: name => name === 'ad' || name === 'picture',
43
+ });
44
+ const doc = parser.parse(xml);
45
+ const rootNames = Object.keys(doc).filter(k => k !== '?xml');
46
+ if (rootNames.length !== 1 || rootNames[0] !== 'ooyyo') {
47
+ return { ads: 0, issues: [{ ad: -1, problem: `root element is ${rootNames.join(',') || 'missing'}, expected ooyyo` }] };
48
+ }
49
+ const ads = asList(doc.ooyyo?.ad);
50
+ const urls = new Set();
51
+ ads.forEach((ad, index) => {
52
+ for (const key of Object.keys(ad)) {
53
+ if (key.startsWith('@') || key === TEXT) {
54
+ continue;
55
+ }
56
+ if (!exports.OOYYO_AD_ELEMENTS.includes(key)) {
57
+ issues.push({ ad: index, problem: `element <${key}> is not in OoyyoFormat.xsd` });
58
+ }
59
+ if (Array.isArray(ad[key])) {
60
+ issues.push({ ad: index, problem: `element <${key}> appears more than once` });
61
+ }
62
+ }
63
+ for (const tag of exports.OOYYO_UNIT_ELEMENTS) {
64
+ if (ad[tag] === undefined) {
65
+ continue;
66
+ }
67
+ const unit = typeof ad[tag] === 'object' ? String(ad[tag]['@unit'] ?? '') : '';
68
+ if (!exports.OOYYO_UNITS[tag].includes(unit)) {
69
+ issues.push({ ad: index, problem: `<${tag}> unit="${unit}" (allowed: ${exports.OOYYO_UNITS[tag].join(', ')})` });
70
+ }
71
+ }
72
+ const location = (ad.location ?? {});
73
+ for (const key of Object.keys(location)) {
74
+ if (!key.startsWith('@') && key !== TEXT && !exports.OOYYO_LOCATION_ELEMENTS.includes(key)) {
75
+ issues.push({ ad: index, problem: `element <location><${key}> is not in OoyyoFormat.xsd` });
76
+ }
77
+ }
78
+ const pictures = asList(ad.pictures?.picture).map(valueOf);
79
+ const priceUnit = typeof ad.price === 'object' ? ad.price['@unit'] : undefined;
80
+ const item = {
81
+ url: valueOf(ad.url),
82
+ price: valueOf(ad.price),
83
+ priceUnit: priceUnit,
84
+ make: valueOf(ad.make),
85
+ model: valueOf(ad.model),
86
+ year: valueOf(ad.year),
87
+ pictures,
88
+ };
89
+ const invalid = (0, ooyyo_transformer_1.validateOoyyoItem)(item);
90
+ if (invalid) {
91
+ issues.push({ ad: index, problem: `rejected by partner rules: ${invalid}` });
92
+ }
93
+ if (item.url && urls.has(item.url)) {
94
+ issues.push({ ad: index, problem: 'duplicate vehicle url' });
95
+ }
96
+ urls.add(item.url);
97
+ });
98
+ if (ads.length !== expectedAds) {
99
+ issues.push({ ad: -1, problem: `file holds ${ads.length} ads, the run wrote ${expectedAds}` });
100
+ }
101
+ return { ads: ads.length, issues };
102
+ };
103
+ exports.verifyOoyyoXml = verifyOoyyoXml;
104
+ //# sourceMappingURL=ooyyo-feed-verify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ooyyo-feed-verify.js","sourceRoot":"","sources":["../../src/services/ooyyo-feed-verify.ts"],"names":[],"mappings":"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"}
@@ -1,16 +1,56 @@
1
1
  import { DataSchemes } from '@bytebrand/car-schema';
2
2
  import { OoyyoXmlItem } from '../interfaces';
3
- import { ImboImageResponseInterface } from '@bytebrand/chunkable';
4
- import { ConfigService, ImagesService } from '../services';
3
+ import { OpenAiImageSelection } from './openai-image-fields';
4
+ export declare const OOYYO_LINK_PARAMS = "source=ooyyo&medium=listing&campaign=listing&utm_source=ooyyo&utm_medium=listing&utm_campaign=listing";
5
+ export declare const OOYYO_MAX_URL_LENGTH = 1500;
6
+ export declare const OOYYO_PRICE_UNIT = "EUR";
7
+ export declare const OOYYO_TIME_ZONE = "Europe/Berlin";
8
+ export declare const getOoyyoListingUrl: (domain: string, carId: string) => string;
9
+ export declare enum OoyyoExclusion {
10
+ duplicateId = "duplicate_id",
11
+ filtered = "filtered",
12
+ noId = "no_id",
13
+ notAvailable = "reserved_or_sold",
14
+ noPrice = "no_valid_price",
15
+ noMake = "no_make",
16
+ noModel = "no_recognisable_model",
17
+ noYear = "no_valid_year",
18
+ noImage = "no_valid_image",
19
+ urlTooLong = "url_too_long"
20
+ }
21
+ export declare const getOoyyoPrice: (value: unknown) => string | null;
22
+ export declare const getOoyyoYear: (car: DataSchemes.Car, now?: Date) => string;
23
+ export declare const getOoyyoPostcode: (zip: unknown, countryCode: unknown) => string;
24
+ export declare const getOoyyoEuronorm: (selector: unknown) => string;
25
+ export declare const getOoyyoDateTime: (creationDate: unknown) => {
26
+ date: string;
27
+ time: string;
28
+ };
29
+ export declare const getOoyyoContent: (description: unknown) => string;
30
+ export declare const getOoyyoTitle: (car: DataSchemes.Car) => string;
31
+ export declare const getOoyyoVin: (car: DataSchemes.Car) => string;
32
+ export declare const toOoyyoImages: (selection: OpenAiImageSelection, maxImages?: number) => string[];
33
+ export declare const validateOoyyoItem: (item: Partial<OoyyoXmlItem>) => OoyyoExclusion | null;
34
+ export declare const getOoyyoExclusion: (car: DataSchemes.Car, now?: Date) => OoyyoExclusion | null;
35
+ export interface OoyyoMappingContext {
36
+ domain: string;
37
+ images: string[];
38
+ translate: (selector: string) => string;
39
+ region: string;
40
+ now?: Date;
41
+ }
42
+ export type OoyyoMapResult = {
43
+ ok: true;
44
+ item: OoyyoXmlItem;
45
+ } | {
46
+ ok: false;
47
+ reason: OoyyoExclusion;
48
+ };
49
+ export declare const mapOoyyoItem: (car: DataSchemes.Car, ctx: OoyyoMappingContext) => OoyyoMapResult;
5
50
  export declare class OoyyoTransformer {
6
- private configService;
7
- private imageService;
8
51
  private translator;
9
- constructor(configService: ConfigService, imageService: ImagesService);
10
- transform(car: DataSchemes.Car, imboImages: ImboImageResponseInterface[]): Promise<OoyyoXmlItem>;
11
- private getTitle;
12
- private getCondition;
13
- private translateSelector;
14
- private getEmissionClass;
15
- private formatTimestamp;
52
+ private postalCodes;
53
+ private regions;
54
+ translate(selector: string): string;
55
+ region(postcode: string, countryCode: unknown): Promise<string>;
16
56
  }