@attlaz/client 1.97.0 → 1.98.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (30) hide show
  1. package/dist/Client.d.ts +4 -0
  2. package/dist/Client.js +10 -0
  3. package/dist/MarketPulse/Model/Competitor.d.ts +4 -3
  4. package/dist/MarketPulse/Model/Competitor.js +6 -5
  5. package/dist/MarketPulse/Model/MatchedVendorProduct.d.ts +6 -0
  6. package/dist/MarketPulse/Model/MatchedVendorProduct.js +12 -0
  7. package/dist/MarketPulse/Model/ReviewMatch.d.ts +8 -0
  8. package/dist/MarketPulse/Model/ReviewMatch.js +5 -0
  9. package/dist/MarketPulse/Model/TopCompetitor.d.ts +1 -1
  10. package/dist/MarketPulse/Model/TopCompetitor.js +2 -2
  11. package/dist/MarketPulse/Model/Vendor.d.ts +9 -0
  12. package/dist/MarketPulse/Model/Vendor.js +12 -0
  13. package/dist/MarketPulse/Service/CompetitorEndpoint.d.ts +24 -2
  14. package/dist/MarketPulse/Service/CompetitorEndpoint.js +27 -2
  15. package/dist/MarketPulse/Service/VendorEndpoint.d.ts +26 -0
  16. package/dist/MarketPulse/Service/VendorEndpoint.js +33 -0
  17. package/dist/MarketPulse/Service/VendorProductEndpoint.js +4 -0
  18. package/dist/Model/Component/Component.d.ts +18 -0
  19. package/dist/Model/Component/Component.js +16 -0
  20. package/dist/Model/Component/ComponentKind.d.ts +8 -0
  21. package/dist/Model/Component/ComponentKind.js +18 -0
  22. package/dist/Model/Component/ComponentStatus.d.ts +31 -0
  23. package/dist/Model/Component/ComponentStatus.js +31 -0
  24. package/dist/Model/Component/ComponentVersion.d.ts +16 -0
  25. package/dist/Model/Component/ComponentVersion.js +15 -0
  26. package/dist/Service/ComponentEndpoint.d.ts +26 -0
  27. package/dist/Service/ComponentEndpoint.js +77 -0
  28. package/dist/index.d.ts +6 -1
  29. package/dist/index.js +5 -0
  30. package/package.json +1 -1
package/dist/Client.d.ts CHANGED
@@ -8,6 +8,7 @@ import { ChannelEndpoint } from './Service/ChannelEndpoint.js';
8
8
  import { CodeDeployEndpoint } from './Service/CodeDeployEndpoint.js';
9
9
  import { CodeSourceStrategiesEndpoint } from './Service/CodeSourceStrategiesEndpoint.js';
10
10
  import { CollectionsEndpoint } from './Service/CollectionsEndpoint.js';
11
+ import { ComponentEndpoint } from './Service/ComponentEndpoint.js';
11
12
  import { CommandExecutionEndpoint } from './Service/CommandExecutionEndpoint.js';
12
13
  import { ConfigEndpoint } from './Service/ConfigEndpoint.js';
13
14
  import { ConfigurationEndpoint } from './Service/ConfigurationEndpoint.js';
@@ -37,6 +38,7 @@ import { ProductGroupEndpoint } from './MarketPulse/Service/ProductGroupEndpoint
37
38
  import { CatalogProductEndpoint } from './Catalog/Service/CatalogProductEndpoint.js';
38
39
  import { GenerateContentEndpoint } from './DataEnrichment/Service/GenerateContentEndpoint.js';
39
40
  import { CompetitorEndpoint } from './MarketPulse/Service/CompetitorEndpoint.js';
41
+ import { VendorEndpoint } from './MarketPulse/Service/VendorEndpoint.js';
40
42
  import { PulseStatisticsEndpoint } from './MarketPulse/Service/PulseStatisticsEndpoint.js';
41
43
  import { QualityEndpoint } from './DataQuality/Service/QualityEndpoint.js';
42
44
  import { CatalogFeedEndpoint } from './FeedManagement/Service/CatalogFeedEndpoint.js';
@@ -121,6 +123,7 @@ export declare class Client {
121
123
  getUserActionEndpoint(): UserActionEndpoint;
122
124
  getCommandExecutionEndpoint(): CommandExecutionEndpoint;
123
125
  getAccessTokenEndpoint(): AccessTokenEndpoint;
126
+ getComponentEndpoint(): ComponentEndpoint;
124
127
  getCollectionsEndpoint(): CollectionsEndpoint;
125
128
  getRunnerPoolEndpoint(): RunnerPoolEndpoint;
126
129
  getProviderTokenEndpoint(): ProviderTokenEndpoint;
@@ -138,6 +141,7 @@ export declare class Client {
138
141
  getProductGroupEndpoint(): ProductGroupEndpoint;
139
142
  getGenerateContentEndpoint(): GenerateContentEndpoint;
140
143
  getCompetitorEndpoint(): CompetitorEndpoint;
144
+ getVendorEndpoint(): VendorEndpoint;
141
145
  getPulseStatisticsEndpoint(): PulseStatisticsEndpoint;
142
146
  getQualityEndpoint(): QualityEndpoint;
143
147
  getCatalogFeedEndpoint(): CatalogFeedEndpoint;
package/dist/Client.js CHANGED
@@ -8,6 +8,7 @@ import { ChannelEndpoint } from './Service/ChannelEndpoint.js';
8
8
  import { CodeDeployEndpoint } from './Service/CodeDeployEndpoint.js';
9
9
  import { CodeSourceStrategiesEndpoint } from './Service/CodeSourceStrategiesEndpoint.js';
10
10
  import { CollectionsEndpoint } from './Service/CollectionsEndpoint.js';
11
+ import { ComponentEndpoint } from './Service/ComponentEndpoint.js';
11
12
  import { CommandExecutionEndpoint } from './Service/CommandExecutionEndpoint.js';
12
13
  import { ConfigEndpoint } from './Service/ConfigEndpoint.js';
13
14
  import { ConfigurationEndpoint } from './Service/ConfigurationEndpoint.js';
@@ -37,6 +38,7 @@ import { ProductGroupEndpoint } from './MarketPulse/Service/ProductGroupEndpoint
37
38
  import { CatalogProductEndpoint } from './Catalog/Service/CatalogProductEndpoint.js';
38
39
  import { GenerateContentEndpoint } from './DataEnrichment/Service/GenerateContentEndpoint.js';
39
40
  import { CompetitorEndpoint } from './MarketPulse/Service/CompetitorEndpoint.js';
41
+ import { VendorEndpoint } from './MarketPulse/Service/VendorEndpoint.js';
40
42
  import { PulseStatisticsEndpoint } from './MarketPulse/Service/PulseStatisticsEndpoint.js';
41
43
  import { QualityEndpoint } from './DataQuality/Service/QualityEndpoint.js';
42
44
  import { CatalogFeedEndpoint } from './FeedManagement/Service/CatalogFeedEndpoint.js';
@@ -62,6 +64,7 @@ export class Client {
62
64
  AdapterEndpoint,
63
65
  ChannelEndpoint,
64
66
  CodeDeployEndpoint,
67
+ ComponentEndpoint,
65
68
  CodeSourceStrategiesEndpoint,
66
69
  CommandExecutionEndpoint,
67
70
  ConfigEndpoint,
@@ -104,6 +107,7 @@ export class Client {
104
107
  CatalogProductEndpoint,
105
108
  GenerateContentEndpoint,
106
109
  CompetitorEndpoint,
110
+ VendorEndpoint,
107
111
  PulseStatisticsEndpoint,
108
112
  QualityEndpoint,
109
113
  CatalogFeedEndpoint,
@@ -276,6 +280,9 @@ export class Client {
276
280
  getAccessTokenEndpoint() {
277
281
  return this.getEndpoint('accesstoken', this.Store.AccessTokenEndpoint);
278
282
  }
283
+ getComponentEndpoint() {
284
+ return this.getEndpoint('component', this.Store.ComponentEndpoint);
285
+ }
279
286
  getCollectionsEndpoint() {
280
287
  return this.getEndpoint('collections', this.Store.CollectionsEndpoint);
281
288
  }
@@ -327,6 +334,9 @@ export class Client {
327
334
  getCompetitorEndpoint() {
328
335
  return this.getEndpoint('competitor', this.Store.CompetitorEndpoint);
329
336
  }
337
+ getVendorEndpoint() {
338
+ return this.getEndpoint('vendor', this.Store.VendorEndpoint);
339
+ }
330
340
  getPulseStatisticsEndpoint() {
331
341
  return this.getEndpoint('pulse-statistics', this.Store.PulseStatisticsEndpoint);
332
342
  }
@@ -11,11 +11,12 @@ export declare class Competitor {
11
11
  id: string;
12
12
  vendorId: string;
13
13
  name: string;
14
- domain: string;
14
+ /** The competitor's storefront root, scheme included — e.g. `https://shop.com/nl`. */
15
+ url: string;
15
16
  icon: string | null;
16
17
  type: string | null;
17
- /** Which index (embedding set) the competitor's products are held in. */
18
- index: string;
18
+ /** ISO 4217 code this storefront quotes prices in. */
19
+ currency: string | null;
19
20
  matchCount: number;
20
21
  productCount: number;
21
22
  priceIndex: number;
@@ -10,11 +10,12 @@ export class Competitor {
10
10
  id;
11
11
  vendorId;
12
12
  name;
13
- domain = '';
13
+ /** The competitor's storefront root, scheme included — e.g. `https://shop.com/nl`. */
14
+ url = '';
14
15
  icon = null;
15
16
  type = null;
16
- /** Which index (embedding set) the competitor's products are held in. */
17
- index = '';
17
+ /** ISO 4217 code this storefront quotes prices in. */
18
+ currency = null;
18
19
  matchCount = 0;
19
20
  productCount = 0;
20
21
  priceIndex = 0;
@@ -28,10 +29,10 @@ export class Competitor {
28
29
  }
29
30
  static parse(raw) {
30
31
  const competitor = new Competitor(raw.id, raw.vendor, raw.name ?? '');
31
- competitor.domain = raw.domain ?? '';
32
+ competitor.url = raw.url ?? '';
32
33
  competitor.icon = raw.icon ?? null;
33
34
  competitor.type = raw.type ?? null;
34
- competitor.index = raw.index ?? '';
35
+ competitor.currency = raw.currency ?? null;
35
36
  competitor.matchCount = Number(raw.match_count ?? 0);
36
37
  competitor.productCount = Number(raw.product_count ?? 0);
37
38
  competitor.priceIndex = Number(raw.price_index ?? 0);
@@ -19,10 +19,16 @@ export declare class MatchedVendorProduct {
19
19
  image: string | null;
20
20
  brand: string | null;
21
21
  gtin: string | null;
22
+ sku: string | null;
22
23
  url: string | null;
23
24
  price: number;
25
+ originalPrice: number | null;
26
+ /** ISO 4217. Null falls back to the vendor's currency — never assume EUR when rendering. */
27
+ currency: string | null;
24
28
  shippingCost: number;
25
29
  inStock: boolean | null;
30
+ /** The scraped attribute bag (category, tags, variant options). Keys are data, not schema. */
31
+ properties: Record<string, unknown> | null;
26
32
  updatedAt: Date | null;
27
33
  constructor(id: string);
28
34
  static parse(raw: ApiRecord): MatchedVendorProduct;
@@ -18,10 +18,16 @@ export class MatchedVendorProduct {
18
18
  image = null;
19
19
  brand = null;
20
20
  gtin = null;
21
+ sku = null;
21
22
  url = null;
22
23
  price = 0;
24
+ originalPrice = null;
25
+ /** ISO 4217. Null falls back to the vendor's currency — never assume EUR when rendering. */
26
+ currency = null;
23
27
  shippingCost = 0;
24
28
  inStock = null;
29
+ /** The scraped attribute bag (category, tags, variant options). Keys are data, not schema. */
30
+ properties = null;
25
31
  updatedAt = null;
26
32
  constructor(id) {
27
33
  this.id = id;
@@ -38,10 +44,16 @@ export class MatchedVendorProduct {
38
44
  product.image = raw.image ?? null;
39
45
  product.brand = raw.brand ?? null;
40
46
  product.gtin = raw.gtin ?? null;
47
+ product.sku = raw.sku ?? null;
41
48
  product.url = raw.url ?? null;
42
49
  product.price = parseFloat(raw.price) || 0;
50
+ product.originalPrice = raw.original_price === null || raw.original_price === undefined
51
+ ? null
52
+ : parseFloat(raw.original_price);
53
+ product.currency = raw.currency ?? null;
43
54
  product.shippingCost = parseFloat(raw.shipping_cost) || 0;
44
55
  product.inStock = typeof raw.in_stock === 'boolean' ? raw.in_stock : null;
56
+ product.properties = raw.properties ?? null;
45
57
  product.updatedAt = raw.updated ? new Date(raw.updated) : null;
46
58
  return product;
47
59
  }
@@ -6,11 +6,19 @@ export type ReviewProduct = {
6
6
  name: string;
7
7
  brand: string | null;
8
8
  gtin: string | null;
9
+ sku: string | null;
9
10
  price: number | null;
11
+ originalPrice: number | null;
12
+ /** ISO 4217. Null falls back to the vendor's currency — never assume EUR when rendering. */
13
+ currency: string | null;
14
+ shippingCost: number | null;
10
15
  url: string | null;
11
16
  image: string | null;
17
+ /** Lifted out of {@link properties} because the matcher scores against it. */
12
18
  category: string | null;
13
19
  inStock: boolean | null;
20
+ /** The scraped attribute bag (tags, variant options, …). Keys are data, not schema. */
21
+ properties: Record<string, unknown> | null;
14
22
  };
15
23
  /** The competitor side additionally names the vendor it came from. */
16
24
  export type ReviewCompetitorProduct = ReviewProduct & {
@@ -45,11 +45,16 @@ export class ReviewMatch {
45
45
  name: raw.name,
46
46
  brand: raw.brand ?? null,
47
47
  gtin: raw.gtin ?? null,
48
+ sku: raw.sku ?? null,
48
49
  price: raw.price ?? null,
50
+ originalPrice: raw.original_price ?? null,
51
+ currency: raw.currency ?? null,
52
+ shippingCost: raw.shipping_cost ?? null,
49
53
  url: raw.url ?? null,
50
54
  image: raw.image ?? null,
51
55
  category: raw.category ?? null,
52
56
  inStock: typeof raw.in_stock === 'boolean' ? raw.in_stock : null,
57
+ properties: raw.properties ?? null,
53
58
  };
54
59
  }
55
60
  }
@@ -10,7 +10,7 @@ export declare class TopCompetitor {
10
10
  competitorId: string;
11
11
  vendorId: string;
12
12
  vendorName: string;
13
- vendorDomain: string;
13
+ vendorUrl: string;
14
14
  vendorIcon: string | null;
15
15
  matchCount: number;
16
16
  productCount: number;
@@ -9,7 +9,7 @@ export class TopCompetitor {
9
9
  competitorId;
10
10
  vendorId;
11
11
  vendorName = '';
12
- vendorDomain = '';
12
+ vendorUrl = '';
13
13
  vendorIcon = null;
14
14
  matchCount = 0;
15
15
  productCount = 0;
@@ -26,7 +26,7 @@ export class TopCompetitor {
26
26
  static parse(raw) {
27
27
  const competitor = new TopCompetitor(raw.competitor, raw.vendor);
28
28
  competitor.vendorName = raw.vendor_name ?? '';
29
- competitor.vendorDomain = raw.vendor_domain ?? '';
29
+ competitor.vendorUrl = raw.vendor_url ?? '';
30
30
  competitor.vendorIcon = raw.vendor_icon ?? null;
31
31
  competitor.matchCount = Number(raw.match_count ?? 0);
32
32
  competitor.productCount = Number(raw.product_count ?? 0);
@@ -2,11 +2,20 @@ import { ApiRecord } from '../../Model/ApiRecord.js';
2
2
  /**
3
3
  * A shop whose products Market Pulse tracks — your own or a competitor's. It is the same entity in
4
4
  * both roles; a {@link Competitor} is a vendor as one catalog watches it.
5
+ *
6
+ * One vendor is one storefront view: a single `url`, a single `currency`. A merchant selling in
7
+ * several markets is several vendors.
5
8
  */
6
9
  export declare class Vendor {
7
10
  id: string;
8
11
  name: string;
12
+ /** Storefront root, scheme included, no trailing slash — e.g. `https://shop.com/nl`. */
13
+ url: string;
9
14
  icon: string | null;
15
+ /** ISO 4217 code this storefront quotes prices in. */
16
+ currency: string | null;
17
+ /** Platform hint used to pick a scrape strategy, e.g. `shopify`. */
18
+ type: string | null;
10
19
  constructor(id: string, name: string);
11
20
  static parse(raw: ApiRecord): Vendor;
12
21
  }
@@ -1,18 +1,30 @@
1
1
  /**
2
2
  * A shop whose products Market Pulse tracks — your own or a competitor's. It is the same entity in
3
3
  * both roles; a {@link Competitor} is a vendor as one catalog watches it.
4
+ *
5
+ * One vendor is one storefront view: a single `url`, a single `currency`. A merchant selling in
6
+ * several markets is several vendors.
4
7
  */
5
8
  export class Vendor {
6
9
  id;
7
10
  name;
11
+ /** Storefront root, scheme included, no trailing slash — e.g. `https://shop.com/nl`. */
12
+ url = '';
8
13
  icon = null;
14
+ /** ISO 4217 code this storefront quotes prices in. */
15
+ currency = null;
16
+ /** Platform hint used to pick a scrape strategy, e.g. `shopify`. */
17
+ type = null;
9
18
  constructor(id, name) {
10
19
  this.id = id;
11
20
  this.name = name;
12
21
  }
13
22
  static parse(raw) {
14
23
  const vendor = new Vendor(raw.id, raw.name ?? '');
24
+ vendor.url = raw.url ?? '';
15
25
  vendor.icon = raw.icon ?? null;
26
+ vendor.currency = raw.currency ?? null;
27
+ vendor.type = raw.type ?? null;
16
28
  return vendor;
17
29
  }
18
30
  }
@@ -10,6 +10,28 @@ import { Competitor } from '../Model/Competitor.js';
10
10
  export declare class CompetitorEndpoint extends Endpoint {
11
11
  getByCatalog(catalogId: CatalogId | string, pagination?: CursorPagination | null): Promise<CollectionResult<Competitor>>;
12
12
  getById(competitorId: string): Promise<Competitor | null>;
13
- /** Start watching a vendor as a competitor of this catalog. */
14
- add(catalogId: CatalogId | string, vendorId: string): Promise<Competitor | null>;
13
+ /**
14
+ * Start watching an existing vendor as a competitor of this catalog.
15
+ *
16
+ * The vendor must already exist — create it with {@link VendorEndpoint.create} first. Re-adding
17
+ * a previously removed competitor reactivates the original link, so its matches and price
18
+ * history survive.
19
+ *
20
+ * Returns the link itself (`id`, `catalog`, `vendor`), not the populated competitor; read it
21
+ * back with {@link getById} if you need the counts and timestamps.
22
+ */
23
+ add(catalogId: CatalogId | string, vendorId: string): Promise<CompetitorLink | null>;
24
+ /**
25
+ * Stop watching a competitor.
26
+ *
27
+ * The vendor, its products and their price history are kept — only the catalog↔vendor link is
28
+ * retired, so {@link add} can resume it later.
29
+ */
30
+ remove(catalogId: CatalogId | string, competitorId: string): Promise<void>;
15
31
  }
32
+ /** The catalog↔vendor link row returned by {@link CompetitorEndpoint.add}. */
33
+ export type CompetitorLink = {
34
+ id: string;
35
+ catalogId: string;
36
+ vendorId: string;
37
+ };
@@ -16,9 +16,34 @@ export class CompetitorEndpoint extends Endpoint {
16
16
  const result = await this.requestObject(path('/pulse/competing-vendors/:competitorId', { competitorId }), null, Competitor.parse, 'GET');
17
17
  return result.getData();
18
18
  }
19
- /** Start watching a vendor as a competitor of this catalog. */
19
+ /**
20
+ * Start watching an existing vendor as a competitor of this catalog.
21
+ *
22
+ * The vendor must already exist — create it with {@link VendorEndpoint.create} first. Re-adding
23
+ * a previously removed competitor reactivates the original link, so its matches and price
24
+ * history survive.
25
+ *
26
+ * Returns the link itself (`id`, `catalog`, `vendor`), not the populated competitor; read it
27
+ * back with {@link getById} if you need the counts and timestamps.
28
+ */
20
29
  async add(catalogId, vendorId) {
21
- const result = await this.requestObject(path('/pulse/catalogs/:catalogId/competing-vendors', { catalogId: catalogId.toString() }), { vendor: vendorId }, Competitor.parse, 'POST');
30
+ const result = await this.requestObject(path('/pulse/catalogs/:catalogId/competing-vendors', { catalogId: catalogId.toString() }), { vendor: vendorId }, (raw) => ({
31
+ id: raw.id,
32
+ catalogId: raw.catalog,
33
+ vendorId: raw.vendor,
34
+ }), 'POST');
22
35
  return result.getData();
23
36
  }
37
+ /**
38
+ * Stop watching a competitor.
39
+ *
40
+ * The vendor, its products and their price history are kept — only the catalog↔vendor link is
41
+ * retired, so {@link add} can resume it later.
42
+ */
43
+ async remove(catalogId, competitorId) {
44
+ await this.requestObject(path('/pulse/catalogs/:catalogId/competing-vendors/:competitorId', {
45
+ catalogId: catalogId.toString(),
46
+ competitorId,
47
+ }), null, (raw) => raw, 'DELETE');
48
+ }
24
49
  }
@@ -0,0 +1,26 @@
1
+ import { Endpoint } from '../../Service/Endpoint.js';
2
+ import { Vendor } from '../Model/Vendor.js';
3
+ /**
4
+ * Vendors — the shops Market Pulse knows about, independent of who watches them.
5
+ *
6
+ * Creating a vendor and watching it as a competitor are separate steps: create here, then link it
7
+ * to a catalog with {@link CompetitorEndpoint.add}. That split is what lets one vendor be watched
8
+ * by several catalogs without being duplicated.
9
+ *
10
+ * There is deliberately no "list vendors" method: vendors are global, so listing them would expose
11
+ * every customer's tracked shops. Discovery gets designed alongside the UI that needs it.
12
+ */
13
+ export declare class VendorEndpoint extends Endpoint {
14
+ getById(vendorId: string): Promise<Vendor | null>;
15
+ /**
16
+ * Register a shop.
17
+ *
18
+ * `url` is normalised server-side (scheme added, trailing slash dropped, host lowercased), and a
19
+ * storefront that already has a vendor is rejected — so this is safe to call without checking
20
+ * first, but it will throw rather than return the existing vendor.
21
+ *
22
+ * @param url Storefront root. A locale path is significant: `https://shop.com/nl` is a
23
+ * different storefront from `https://shop.com`.
24
+ */
25
+ create(name: string, url: string, currency?: string | null, type?: string | null): Promise<Vendor | null>;
26
+ }
@@ -0,0 +1,33 @@
1
+ import { path } from '../../Http/Data/Path.js';
2
+ import { Endpoint } from '../../Service/Endpoint.js';
3
+ import { Vendor } from '../Model/Vendor.js';
4
+ /**
5
+ * Vendors — the shops Market Pulse knows about, independent of who watches them.
6
+ *
7
+ * Creating a vendor and watching it as a competitor are separate steps: create here, then link it
8
+ * to a catalog with {@link CompetitorEndpoint.add}. That split is what lets one vendor be watched
9
+ * by several catalogs without being duplicated.
10
+ *
11
+ * There is deliberately no "list vendors" method: vendors are global, so listing them would expose
12
+ * every customer's tracked shops. Discovery gets designed alongside the UI that needs it.
13
+ */
14
+ export class VendorEndpoint extends Endpoint {
15
+ async getById(vendorId) {
16
+ const result = await this.requestObject(path('/pulse/vendors/:vendorId', { vendorId }), null, Vendor.parse, 'GET');
17
+ return result.getData();
18
+ }
19
+ /**
20
+ * Register a shop.
21
+ *
22
+ * `url` is normalised server-side (scheme added, trailing slash dropped, host lowercased), and a
23
+ * storefront that already has a vendor is rejected — so this is safe to call without checking
24
+ * first, but it will throw rather than return the existing vendor.
25
+ *
26
+ * @param url Storefront root. A locale path is significant: `https://shop.com/nl` is a
27
+ * different storefront from `https://shop.com`.
28
+ */
29
+ async create(name, url, currency = null, type = null) {
30
+ const result = await this.requestObject('/pulse/vendors', { name, url, currency, type }, Vendor.parse, 'POST');
31
+ return result.getData();
32
+ }
33
+ }
@@ -55,6 +55,7 @@ export class VendorProductEndpoint extends Endpoint {
55
55
  image: product.image,
56
56
  identifier: product.identifier,
57
57
  gtin: product.gtin,
58
+ sku: product.sku,
58
59
  brand: product.brand,
59
60
  url: product.url,
60
61
  currency: product.currency,
@@ -70,6 +71,7 @@ export class VendorProductEndpoint extends Endpoint {
70
71
  /** Update the mutable fields of an existing vendor product (JSON-patch style, per the API). */
71
72
  async update(product) {
72
73
  const operations = [
74
+ { op: 'add', path: 'name', value: product.name },
73
75
  { op: 'add', path: 'price', value: product.price },
74
76
  { op: 'add', path: 'original_price', value: product.originalPrice },
75
77
  { op: 'add', path: 'brand', value: product.brand },
@@ -78,6 +80,8 @@ export class VendorProductEndpoint extends Endpoint {
78
80
  { op: 'add', path: 'url', value: product.url },
79
81
  { op: 'add', path: 'gtin', value: product.gtin },
80
82
  { op: 'add', path: 'image', value: product.image },
83
+ { op: 'add', path: 'sku', value: product.sku },
84
+ { op: 'add', path: 'currency', value: product.currency },
81
85
  { op: 'add', path: 'properties', value: product.properties },
82
86
  ];
83
87
  if (product.id === null) {
@@ -0,0 +1,18 @@
1
+ import { State } from '../State.js';
2
+ import { ComponentKind } from './ComponentKind.js';
3
+ /** One thing the platform builds and deploys: an api, a service, or the runner. */
4
+ export declare class Component {
5
+ id: string;
6
+ name: string;
7
+ kind: ComponentKind;
8
+ /** Registry path without a tag, e.g. `registry.gitlab.com/attlaz/platform/message_service`. */
9
+ imageRepository: string;
10
+ /**
11
+ * The version that *should* be deployed — desired state, set by promoting. Null means the
12
+ * component is not managed this way, never "deploy nothing".
13
+ */
14
+ activeVersionId: string | null;
15
+ createdAt: Date;
16
+ updatedAt: Date;
17
+ state: State;
18
+ }
@@ -0,0 +1,16 @@
1
+ /** One thing the platform builds and deploys: an api, a service, or the runner. */
2
+ export class Component {
3
+ id;
4
+ name;
5
+ kind;
6
+ /** Registry path without a tag, e.g. `registry.gitlab.com/attlaz/platform/message_service`. */
7
+ imageRepository;
8
+ /**
9
+ * The version that *should* be deployed — desired state, set by promoting. Null means the
10
+ * component is not managed this way, never "deploy nothing".
11
+ */
12
+ activeVersionId;
13
+ createdAt;
14
+ updatedAt;
15
+ state;
16
+ }
@@ -0,0 +1,8 @@
1
+ export declare enum ComponentKind {
2
+ Api = "api",
3
+ Service = "service",
4
+ Runner = "runner"
5
+ }
6
+ export declare namespace ComponentKind {
7
+ const fromString: (input: string) => ComponentKind;
8
+ }
@@ -0,0 +1,18 @@
1
+ export var ComponentKind;
2
+ (function (ComponentKind) {
3
+ ComponentKind["Api"] = "api";
4
+ ComponentKind["Service"] = "service";
5
+ ComponentKind["Runner"] = "runner";
6
+ })(ComponentKind || (ComponentKind = {}));
7
+ (function (ComponentKind) {
8
+ ComponentKind.fromString = (input) => {
9
+ switch (input) {
10
+ case ComponentKind.Api:
11
+ case ComponentKind.Service:
12
+ case ComponentKind.Runner:
13
+ return input;
14
+ default:
15
+ throw new Error('Unknown ComponentKind "' + input + '"');
16
+ }
17
+ };
18
+ })(ComponentKind || (ComponentKind = {}));
@@ -0,0 +1,31 @@
1
+ /**
2
+ * What one Kubernetes deployment of a component actually runs, as last observed.
3
+ *
4
+ * The counterpart to `Component.activeVersionId`: that is what should run, this is what does.
5
+ * One row per deployment — a component running several version lines has several.
6
+ */
7
+ export declare class ComponentStatus {
8
+ id: string;
9
+ componentId: string;
10
+ namespace: string;
11
+ deploymentName: string;
12
+ /** Fully-qualified image including the tag, exactly as the container reports it. */
13
+ image: string;
14
+ readyReplicas: number;
15
+ desiredReplicas: number;
16
+ /**
17
+ * Whether enough replicas are ready to serve. **True for a deployment scaled to zero** — with no
18
+ * replicas wanted, the requirement is trivially met. Treat `desiredReplicas > 0 &&
19
+ * readyReplicas < desiredReplicas` as unhealthy rather than trusting this alone.
20
+ */
21
+ available: boolean;
22
+ /**
23
+ * Reads backwards: false means the last rollout missed its deadline, i.e. the deploy failed.
24
+ * True covers both a settled deployment and one still rolling out. Replica counts cannot
25
+ * substitute — a new pod that never becomes ready leaves the old ones serving, so the counts
26
+ * still look right while the deploy has failed.
27
+ */
28
+ progressing: boolean;
29
+ /** When the cluster was last read. Stale means nobody has looked, not that all is well. */
30
+ observedAt: Date;
31
+ }
@@ -0,0 +1,31 @@
1
+ /**
2
+ * What one Kubernetes deployment of a component actually runs, as last observed.
3
+ *
4
+ * The counterpart to `Component.activeVersionId`: that is what should run, this is what does.
5
+ * One row per deployment — a component running several version lines has several.
6
+ */
7
+ export class ComponentStatus {
8
+ id;
9
+ componentId;
10
+ namespace;
11
+ deploymentName;
12
+ /** Fully-qualified image including the tag, exactly as the container reports it. */
13
+ image;
14
+ readyReplicas;
15
+ desiredReplicas;
16
+ /**
17
+ * Whether enough replicas are ready to serve. **True for a deployment scaled to zero** — with no
18
+ * replicas wanted, the requirement is trivially met. Treat `desiredReplicas > 0 &&
19
+ * readyReplicas < desiredReplicas` as unhealthy rather than trusting this alone.
20
+ */
21
+ available;
22
+ /**
23
+ * Reads backwards: false means the last rollout missed its deadline, i.e. the deploy failed.
24
+ * True covers both a settled deployment and one still rolling out. Replica counts cannot
25
+ * substitute — a new pod that never becomes ready leaves the old ones serving, so the counts
26
+ * still look right while the deploy has failed.
27
+ */
28
+ progressing;
29
+ /** When the cluster was last read. Stale means nobody has looked, not that all is well. */
30
+ observedAt;
31
+ }
@@ -0,0 +1,16 @@
1
+ import { State } from '../State.js';
2
+ /** One tag of a component as the container registry has it. */
3
+ export declare class ComponentVersion {
4
+ id: string;
5
+ componentId: string;
6
+ /** The registry tag, e.g. `1.15.1`. */
7
+ version: string;
8
+ /** Fully-qualified reference including the tag. */
9
+ image: string;
10
+ /**
11
+ * When the image was published to the registry and became available to select. Not a build time,
12
+ * and not evidence it was ever deployed — most versions never are.
13
+ */
14
+ releasedAt: Date;
15
+ state: State;
16
+ }
@@ -0,0 +1,15 @@
1
+ /** One tag of a component as the container registry has it. */
2
+ export class ComponentVersion {
3
+ id;
4
+ componentId;
5
+ /** The registry tag, e.g. `1.15.1`. */
6
+ version;
7
+ /** Fully-qualified reference including the tag. */
8
+ image;
9
+ /**
10
+ * When the image was published to the registry and became available to select. Not a build time,
11
+ * and not evidence it was ever deployed — most versions never are.
12
+ */
13
+ releasedAt;
14
+ state;
15
+ }
@@ -0,0 +1,26 @@
1
+ import { Component } from '../Model/Component/Component.js';
2
+ import { ComponentStatus } from '../Model/Component/ComponentStatus.js';
3
+ import { ComponentVersion } from '../Model/Component/ComponentVersion.js';
4
+ import { CursorPagination } from '../Model/Pagination/CursorPagination.js';
5
+ import { CollectionResult } from '../Model/Result/CollectionResult.js';
6
+ import { Endpoint } from './Endpoint.js';
7
+ /**
8
+ * The platform's own inventory: what we build, which versions the registry has, what the cluster is
9
+ * actually running, and which version each component should run.
10
+ *
11
+ * Root-only, reads included.
12
+ */
13
+ export declare class ComponentEndpoint extends Endpoint {
14
+ getAll(pagination?: CursorPagination | null): Promise<CollectionResult<Component>>;
15
+ getVersions(componentId: string, pagination?: CursorPagination | null): Promise<CollectionResult<ComponentVersion>>;
16
+ /** Observed state for every component at once — one call, not one per component. */
17
+ getStatus(pagination?: CursorPagination | null): Promise<CollectionResult<ComponentStatus>>;
18
+ /**
19
+ * Declare which version a component should run. Writes desired state only — the rollout is a
20
+ * separate asynchronous step that can fail, so a success here does not mean it is running.
21
+ */
22
+ setActiveVersion(componentId: string, versionId: string): Promise<void>;
23
+ private static parseComponent;
24
+ private static parseVersion;
25
+ private static parseStatus;
26
+ }
@@ -0,0 +1,77 @@
1
+ import { path } from '../Http/Data/Path.js';
2
+ import { QueryString } from '../Http/Data/QueryString.js';
3
+ import { Component } from '../Model/Component/Component.js';
4
+ import { ComponentKind } from '../Model/Component/ComponentKind.js';
5
+ import { ComponentStatus } from '../Model/Component/ComponentStatus.js';
6
+ import { ComponentVersion } from '../Model/Component/ComponentVersion.js';
7
+ import { State } from '../Model/State.js';
8
+ import { Utils } from '../Utils.js';
9
+ import { Endpoint } from './Endpoint.js';
10
+ /**
11
+ * The platform's own inventory: what we build, which versions the registry has, what the cluster is
12
+ * actually running, and which version each component should run.
13
+ *
14
+ * Root-only, reads included.
15
+ */
16
+ export class ComponentEndpoint extends Endpoint {
17
+ async getAll(pagination = null) {
18
+ const queryString = new QueryString('/system/components');
19
+ queryString.addPagination(pagination);
20
+ return await this.requestCollection(queryString, ComponentEndpoint.parseComponent, null, 'GET');
21
+ }
22
+ async getVersions(componentId, pagination = null) {
23
+ const queryString = new QueryString(path('/system/components/:componentId/versions', { componentId }));
24
+ queryString.addPagination(pagination);
25
+ return await this.requestCollection(queryString, ComponentEndpoint.parseVersion, null, 'GET');
26
+ }
27
+ /** Observed state for every component at once — one call, not one per component. */
28
+ async getStatus(pagination = null) {
29
+ const queryString = new QueryString('/system/component-status');
30
+ queryString.addPagination(pagination);
31
+ return await this.requestCollection(queryString, ComponentEndpoint.parseStatus, null, 'GET');
32
+ }
33
+ /**
34
+ * Declare which version a component should run. Writes desired state only — the rollout is a
35
+ * separate asynchronous step that can fail, so a success here does not mean it is running.
36
+ */
37
+ async setActiveVersion(componentId, versionId) {
38
+ const queryString = new QueryString(path('/system/components/:componentId/active-version', { componentId }));
39
+ await this.requestObject(queryString, { version_id: versionId }, (raw) => raw, 'POST');
40
+ }
41
+ static parseComponent(raw) {
42
+ const component = new Component();
43
+ component.id = raw.id;
44
+ component.name = raw.name;
45
+ component.kind = ComponentKind.fromString(raw.kind);
46
+ component.imageRepository = raw.image_repository;
47
+ component.activeVersionId = raw.active_version ?? null;
48
+ component.createdAt = Utils.parseRawDate(raw.created_at);
49
+ component.updatedAt = Utils.parseRawDate(raw.updated_at);
50
+ component.state = State.fromString(raw.state);
51
+ return component;
52
+ }
53
+ static parseVersion(raw) {
54
+ const version = new ComponentVersion();
55
+ version.id = raw.id;
56
+ version.componentId = raw.component;
57
+ version.version = raw.version;
58
+ version.image = raw.image;
59
+ version.releasedAt = Utils.parseRawDate(raw.released_at);
60
+ version.state = State.fromString(raw.state);
61
+ return version;
62
+ }
63
+ static parseStatus(raw) {
64
+ const status = new ComponentStatus();
65
+ status.id = raw.id;
66
+ status.componentId = raw.component;
67
+ status.namespace = raw.namespace;
68
+ status.deploymentName = raw.deployment_name;
69
+ status.image = raw.image;
70
+ status.readyReplicas = raw.ready_replicas;
71
+ status.desiredReplicas = raw.desired_replicas;
72
+ status.available = raw.available;
73
+ status.progressing = raw.progressing;
74
+ status.observedAt = Utils.parseRawDate(raw.observed_at);
75
+ return status;
76
+ }
77
+ }
package/dist/index.d.ts CHANGED
@@ -127,7 +127,8 @@ export { CatalogProductEndpoint } from './Catalog/Service/CatalogProductEndpoint
127
127
  export { GenerateContentBatch } from './DataEnrichment/Model/GenerateContentBatch.js';
128
128
  export { GenerateContentBatchData } from './DataEnrichment/Model/GenerateContentBatchData.js';
129
129
  export { GenerateContentEndpoint } from './DataEnrichment/Service/GenerateContentEndpoint.js';
130
- export { CompetitorEndpoint } from './MarketPulse/Service/CompetitorEndpoint.js';
130
+ export { CompetitorEndpoint, CompetitorLink } from './MarketPulse/Service/CompetitorEndpoint.js';
131
+ export { VendorEndpoint } from './MarketPulse/Service/VendorEndpoint.js';
131
132
  export { MarketSummaryEntry } from './MarketPulse/Model/MarketSummaryEntry.js';
132
133
  export { ProductSegmentType } from './MarketPulse/Model/ProductSegmentType.js';
133
134
  export { ProductsSegment } from './MarketPulse/Model/ProductsSegment.js';
@@ -208,6 +209,10 @@ export type { UserActionFilter } from './Model/User/UserActionFilter.js';
208
209
  export { UserSummary } from './Model/User/UserSummary.js';
209
210
  export type { UserSummaryType } from './Model/User/UserSummary.js';
210
211
  export { RunnerImage } from './Model/Runner/RunnerImage.js';
212
+ export { Component } from './Model/Component/Component.js';
213
+ export { ComponentKind } from './Model/Component/ComponentKind.js';
214
+ export { ComponentStatus } from './Model/Component/ComponentStatus.js';
215
+ export { ComponentVersion } from './Model/Component/ComponentVersion.js';
211
216
  export { CommandExecutionHistory } from './Model/Command/CommandExecutionHistory.js';
212
217
  export { CommandExecutionStatus } from './Model/Command/CommandExecutionStatus.js';
213
218
  export { CommandExecutionFilter } from './Model/Command/CommandExecutionFilter.js';
package/dist/index.js CHANGED
@@ -104,6 +104,7 @@ export { CatalogProductEndpoint } from './Catalog/Service/CatalogProductEndpoint
104
104
  export { GenerateContentBatch } from './DataEnrichment/Model/GenerateContentBatch.js';
105
105
  export { GenerateContentEndpoint } from './DataEnrichment/Service/GenerateContentEndpoint.js';
106
106
  export { CompetitorEndpoint } from './MarketPulse/Service/CompetitorEndpoint.js';
107
+ export { VendorEndpoint } from './MarketPulse/Service/VendorEndpoint.js';
107
108
  export { PulseStatisticsEndpoint } from './MarketPulse/Service/PulseStatisticsEndpoint.js';
108
109
  export { QualityDataset } from './DataQuality/Model/QualityDataset.js';
109
110
  export { QualityEntity } from './DataQuality/Model/QualityEntity.js';
@@ -171,6 +172,10 @@ export { UserAuthProvider } from './Model/User/UserAuthProvider.js';
171
172
  export { UserAction } from './Model/User/UserAction.js';
172
173
  export { UserSummary } from './Model/User/UserSummary.js';
173
174
  export { RunnerImage } from './Model/Runner/RunnerImage.js';
175
+ export { Component } from './Model/Component/Component.js';
176
+ export { ComponentKind } from './Model/Component/ComponentKind.js';
177
+ export { ComponentStatus } from './Model/Component/ComponentStatus.js';
178
+ export { ComponentVersion } from './Model/Component/ComponentVersion.js';
174
179
  export { CommandExecutionHistory } from './Model/Command/CommandExecutionHistory.js';
175
180
  export { CommandExecutionStatus } from './Model/Command/CommandExecutionStatus.js';
176
181
  export { Endpoint } from './Service/Endpoint.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@attlaz/client",
3
- "version": "1.97.0",
3
+ "version": "1.98.0",
4
4
  "description": "Javascript Client to access Attlaz API",
5
5
  "types": "./dist/index.d.ts",
6
6
  "main": "./dist/index.js",