merchi_sdk_ts 1.7.5 → 1.7.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,230 @@
1
+ var __extends = (this && this.__extends) || (function () {
2
+ var extendStatics = function (d, b) {
3
+ extendStatics = Object.setPrototypeOf ||
4
+ ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
5
+ function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
6
+ return extendStatics(d, b);
7
+ };
8
+ return function (d, b) {
9
+ if (typeof b !== "function" && b !== null)
10
+ throw new TypeError("Class extends value " + String(b) + " is not a constructor or null");
11
+ extendStatics(d, b);
12
+ function __() { this.constructor = d; }
13
+ d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
14
+ };
15
+ })();
16
+ var __assign = (this && this.__assign) || function () {
17
+ __assign = Object.assign || function(t) {
18
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
19
+ s = arguments[i];
20
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
21
+ t[p] = s[p];
22
+ }
23
+ return t;
24
+ };
25
+ return __assign.apply(this, arguments);
26
+ };
27
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
28
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
29
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
30
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
31
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
32
+ };
33
+ var __metadata = (this && this.__metadata) || function (k, v) {
34
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
35
+ };
36
+ import { Entity } from '../entity.js';
37
+ /**
38
+ * Post-purchase product review. List/create are nested under ``/products/:id/reviews/``;
39
+ * updates use ``/product-reviews/:id/``. Do not use :meth:`Entity.create` / :meth:`Entity.list`
40
+ * for this resource.
41
+ *
42
+ * API responses use ``jobId``, ``productId``, and ``domainId``; this entity maps those onto
43
+ * ``job``, ``product``, and ``domain`` (minimal ``{ id }`` objects unless the API nests more).
44
+ */
45
+ var ProductReview = /** @class */ (function (_super) {
46
+ __extends(ProductReview, _super);
47
+ function ProductReview() {
48
+ return _super !== null && _super.apply(this, arguments) || this;
49
+ }
50
+ /**
51
+ * Map flat API fields (``jobId``, ``productId``, ``domainId``) to nested
52
+ * ``job`` / ``product`` / ``domain`` objects before :meth:`Entity.fromJson`.
53
+ */
54
+ ProductReview.normalizeApiJson = function (json) {
55
+ if (json === null || json === undefined || typeof json !== 'object') {
56
+ return json;
57
+ }
58
+ var row = __assign({}, json);
59
+ if (row.jobId !== undefined && row.job === undefined) {
60
+ if (row.jobId != null) {
61
+ row.job = { id: row.jobId };
62
+ }
63
+ delete row.jobId;
64
+ }
65
+ if (row.productId !== undefined && row.product === undefined) {
66
+ if (row.productId != null) {
67
+ row.product = { id: row.productId };
68
+ }
69
+ delete row.productId;
70
+ }
71
+ if (row.domainId !== undefined && row.domain === undefined) {
72
+ if (row.domainId != null) {
73
+ row.domain = { id: row.domainId };
74
+ }
75
+ delete row.domainId;
76
+ }
77
+ return row;
78
+ };
79
+ /**
80
+ * Domain managers/admins: list reviews for a product.
81
+ */
82
+ ProductReview.listForProduct = function (productId, options) {
83
+ var Constructor = this;
84
+ var resource = "/products/".concat(productId, "/reviews/");
85
+ var fetchOptions = { method: 'GET' };
86
+ fetchOptions.query = [];
87
+ if (!(options && options.withRights)) {
88
+ fetchOptions.query.push(['skip_rights', 'y']);
89
+ }
90
+ return Constructor.merchi.authenticatedFetch(resource, fetchOptions).then(function (data) {
91
+ var _a;
92
+ var raw = (_a = data.productReviews) !== null && _a !== void 0 ? _a : [];
93
+ return raw.map(function (row) {
94
+ var e = new Constructor();
95
+ e.fromJson(ProductReview.normalizeApiJson(row));
96
+ return e;
97
+ });
98
+ });
99
+ };
100
+ /**
101
+ * Buyer: create a review for the catalog ``productId`` (master product).
102
+ * ``body.job.id`` must be a completed job whose line item resolves to this product.
103
+ */
104
+ ProductReview.createForProduct = function (productId, body, options) {
105
+ var Constructor = this;
106
+ var resource = "/products/".concat(productId, "/reviews/");
107
+ var wire = {
108
+ jobId: body.job.id,
109
+ rating: body.rating,
110
+ };
111
+ if (body.title !== undefined) {
112
+ wire.title = body.title;
113
+ }
114
+ if (body.content !== undefined) {
115
+ wire.content = body.content;
116
+ }
117
+ var fetchOptions = {
118
+ method: 'POST',
119
+ headers: { 'Content-Type': 'application/json' },
120
+ body: JSON.stringify(wire),
121
+ };
122
+ fetchOptions.query = [];
123
+ if (!(options && options.withRights)) {
124
+ fetchOptions.query.push(['skip_rights', 'y']);
125
+ }
126
+ return Constructor.merchi.authenticatedFetch(resource, fetchOptions).then(function (data) {
127
+ var e = new Constructor();
128
+ e.fromJson(ProductReview.normalizeApiJson(data.productReview));
129
+ return e;
130
+ });
131
+ };
132
+ /**
133
+ * Partial update (moderation or author edit). Uses ``multipart/form-data`` fields
134
+ * matching the Merchi API.
135
+ */
136
+ ProductReview.prototype.patch = function (payload, options) {
137
+ var _this = this;
138
+ var _a, _b, _c;
139
+ var id = this.id;
140
+ if (id === undefined) {
141
+ throw new Error('ProductReview.id is required to patch');
142
+ }
143
+ var resource = "/product-reviews/".concat(String(id), "/");
144
+ var form = new FormData();
145
+ if (payload.status !== undefined) {
146
+ form.set('status', payload.status);
147
+ }
148
+ if (payload.rejectionReason !== undefined) {
149
+ form.set('rejectionReason', (_a = payload.rejectionReason) !== null && _a !== void 0 ? _a : '');
150
+ }
151
+ if (payload.rating !== undefined) {
152
+ form.set('rating', String(payload.rating));
153
+ }
154
+ if (payload.title !== undefined) {
155
+ form.set('title', (_b = payload.title) !== null && _b !== void 0 ? _b : '');
156
+ }
157
+ if (payload.content !== undefined) {
158
+ form.set('content', (_c = payload.content) !== null && _c !== void 0 ? _c : '');
159
+ }
160
+ var fetchOptions = { method: 'PATCH', body: form };
161
+ fetchOptions.query = [];
162
+ if (!(options && options.withRights)) {
163
+ fetchOptions.query.push(['skip_rights', 'y']);
164
+ }
165
+ var singularName = this.constructor
166
+ .singularName;
167
+ return this.merchi.authenticatedFetch(resource, fetchOptions).then(function (data) {
168
+ _this.fromJson(ProductReview.normalizeApiJson(data[singularName]));
169
+ _this.cleanDirty();
170
+ return _this;
171
+ });
172
+ };
173
+ ProductReview.resourceName = 'product-reviews';
174
+ ProductReview.singularName = 'productReview';
175
+ ProductReview.pluralName = 'productReviews';
176
+ __decorate([
177
+ ProductReview.property(),
178
+ __metadata("design:type", Number)
179
+ ], ProductReview.prototype, "id", void 0);
180
+ __decorate([
181
+ ProductReview.property({ type: 'Product' }),
182
+ __metadata("design:type", Function)
183
+ ], ProductReview.prototype, "product", void 0);
184
+ __decorate([
185
+ ProductReview.property({ type: 'Domain' }),
186
+ __metadata("design:type", Function)
187
+ ], ProductReview.prototype, "domain", void 0);
188
+ __decorate([
189
+ ProductReview.property({ type: Number }),
190
+ __metadata("design:type", Number)
191
+ ], ProductReview.prototype, "authorUserId", void 0);
192
+ __decorate([
193
+ ProductReview.property({ type: 'Job' }),
194
+ __metadata("design:type", Function)
195
+ ], ProductReview.prototype, "job", void 0);
196
+ __decorate([
197
+ ProductReview.property({ type: Number }),
198
+ __metadata("design:type", Number)
199
+ ], ProductReview.prototype, "rating", void 0);
200
+ __decorate([
201
+ ProductReview.property({ type: String }),
202
+ __metadata("design:type", Object)
203
+ ], ProductReview.prototype, "title", void 0);
204
+ __decorate([
205
+ ProductReview.property({ type: String }),
206
+ __metadata("design:type", Object)
207
+ ], ProductReview.prototype, "content", void 0);
208
+ __decorate([
209
+ ProductReview.property({ type: String }),
210
+ __metadata("design:type", String)
211
+ ], ProductReview.prototype, "status", void 0);
212
+ __decorate([
213
+ ProductReview.property({ type: Number }),
214
+ __metadata("design:type", Object)
215
+ ], ProductReview.prototype, "purchaseInvoiceId", void 0);
216
+ __decorate([
217
+ ProductReview.property({ type: String }),
218
+ __metadata("design:type", Object)
219
+ ], ProductReview.prototype, "submittedAt", void 0);
220
+ __decorate([
221
+ ProductReview.property({ type: String }),
222
+ __metadata("design:type", Object)
223
+ ], ProductReview.prototype, "updatedAt", void 0);
224
+ __decorate([
225
+ ProductReview.property({ type: String }),
226
+ __metadata("design:type", Object)
227
+ ], ProductReview.prototype, "rejectionReason", void 0);
228
+ return ProductReview;
229
+ }(Entity));
230
+ export { ProductReview };
@@ -24,6 +24,16 @@ var __metadata = (this && this.__metadata) || function (k, v) {
24
24
  };
25
25
  import { Entity } from '../entity.js';
26
26
  import { User } from './user.js';
27
+ /**
28
+ * Runtime type tag only. The API returns `detailJson` as arbitrary JSON; the
29
+ * entity layer rejects `Object` from decorator metadata, so we use an empty
30
+ * class as the property `type` (same pattern as DraftTemplate.customisationMap).
31
+ */
32
+ var detailJsonPropertyType = /** @class */ (function () {
33
+ function detailJsonPropertyType() {
34
+ }
35
+ return detailJsonPropertyType;
36
+ }());
27
37
  var ShipmentLog = /** @class */ (function (_super) {
28
38
  __extends(ShipmentLog, _super);
29
39
  function ShipmentLog() {
@@ -53,7 +63,7 @@ var ShipmentLog = /** @class */ (function (_super) {
53
63
  __metadata("design:type", String)
54
64
  ], ShipmentLog.prototype, "message", void 0);
55
65
  __decorate([
56
- ShipmentLog.property(),
66
+ ShipmentLog.property({ type: detailJsonPropertyType }),
57
67
  __metadata("design:type", Object)
58
68
  ], ShipmentLog.prototype, "detailJson", void 0);
59
69
  __decorate([
package/dist/index.js CHANGED
@@ -51,6 +51,7 @@ import { Payment } from './entities/payment.js';
51
51
  import { PaymentDevice } from './entities/payment_device.js';
52
52
  import { PhoneNumber } from './entities/phone_number.js';
53
53
  import { Product } from './entities/product.js';
54
+ import { ProductReview } from './entities/product_review.js';
54
55
  import { ProductionComment } from './entities/production_comment.js';
55
56
  import { Quote } from './entities/quote.js';
56
57
  import { QuoteItem } from './entities/quote_item.js';
@@ -82,4 +83,4 @@ import * as constants from './constants/index.js';
82
83
  import * as request from './request.js';
83
84
  import * as util from './util/index.js';
84
85
  import { toastNotifications } from './toasts.js';
85
- export { constants, request, util, toastNotifications, Address, AgentConversation, AgentSkill, AgentSkillVersion, AgentSkillApproval, DomainChatSettings, SupportConversation, SupportMessage, Assignment, AutomaticPaymentRelationship, Bank, Cart, CartItem, CartShipmentGroup, CartShipmentQuote, Category, Company, CompanyInvitation, Component, ComponentTag, ComponentVersion, CountryTax, Discount, DiscountGroup, Domain, DomainInvitation, DomainTag, Draft, DraftComment, DraftTemplate, EmailAddress, EmailCounter, EnrolledDomain, Entity, ExchangeRate, InternalTag, Inventory, InventoryUnitVariation, Invoice, Item, Job, JobComment, MatchingInventory, Menu, MenuItem, Merchi, MerchiFile, Notification, Page, Payment, PaymentDevice, PhoneNumber, Product, ProductionComment, Quote, QuoteItem, Reminder, apiFetch, apiFetchWithProgress, Session, Shipment, ShipmentLog, ShipmentItem, ShipmentItemFulfillment, ShipmentMethod, ShipmentMethodVariation, ShortUrl, SubscriptionPlan, SupplyDomain, SystemRole, Theme, ThemeCssSetting, User, UserCompany, Variation, VariationField, VariationFieldsOption, VariationOption, VariationsGroup, generateUUID, getCookie };
86
+ export { constants, request, util, toastNotifications, Address, AgentConversation, AgentSkill, AgentSkillVersion, AgentSkillApproval, DomainChatSettings, SupportConversation, SupportMessage, Assignment, AutomaticPaymentRelationship, Bank, Cart, CartItem, CartShipmentGroup, CartShipmentQuote, Category, Company, CompanyInvitation, Component, ComponentTag, ComponentVersion, CountryTax, Discount, DiscountGroup, Domain, DomainInvitation, DomainTag, Draft, DraftComment, DraftTemplate, EmailAddress, EmailCounter, EnrolledDomain, Entity, ExchangeRate, InternalTag, Inventory, InventoryUnitVariation, Invoice, Item, Job, JobComment, MatchingInventory, Menu, MenuItem, Merchi, MerchiFile, Notification, Page, Payment, PaymentDevice, PhoneNumber, Product, ProductReview, ProductionComment, Quote, QuoteItem, Reminder, apiFetch, apiFetchWithProgress, Session, Shipment, ShipmentLog, ShipmentItem, ShipmentItemFulfillment, ShipmentMethod, ShipmentMethodVariation, ShortUrl, SubscriptionPlan, SupplyDomain, SystemRole, Theme, ThemeCssSetting, User, UserCompany, Variation, VariationField, VariationFieldsOption, VariationOption, VariationsGroup, generateUUID, getCookie };
package/dist/merchi.js CHANGED
@@ -20,6 +20,7 @@ import { VariationField } from './entities/variation_field.js';
20
20
  import { VariationOption } from './entities/variation_option.js';
21
21
  import { ProductionComment } from './entities/production_comment.js';
22
22
  import { Product } from './entities/product.js';
23
+ import { ProductReview } from './entities/product_review.js';
23
24
  import { InternalTag } from './entities/internal_tag.js';
24
25
  import { Inventory } from './entities/inventory.js';
25
26
  import { InventoryGroup } from './entities/inventory_group.js';
@@ -254,6 +255,7 @@ var Merchi = /** @class */ (function () {
254
255
  this.CountryTax = this.setupClass(CountryTax);
255
256
  this.ShortUrl = this.setupClass(ShortUrl);
256
257
  this.Product = this.setupClass(Product);
258
+ this.ProductReview = this.setupClass(ProductReview);
257
259
  this.SystemRole = this.setupClass(SystemRole);
258
260
  this.CartItem = this.setupClass(CartItem);
259
261
  this.UserCompany = this.setupClass(UserCompany);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "merchi_sdk_ts",
3
- "version": "1.7.5",
3
+ "version": "1.7.7",
4
4
  "main": "dist/index.js",
5
5
  "type": "module",
6
6
  "repository": "git@github.com:merchisdk/merchi_sdk_ts.git",
@@ -0,0 +1,218 @@
1
+ import { Entity } from '../entity.js';
2
+ import type { RequestOptions } from '../request.js';
3
+ import type { Domain } from './domain.js';
4
+ import type { Job } from './job.js';
5
+ import type { Product } from './product.js';
6
+
7
+ /** Create payload; the API expects ``jobId`` — pass ``job`` with at least ``id``. */
8
+ export interface ProductReviewCreateInput {
9
+ job: { id: number };
10
+ rating: number;
11
+ title?: string | null;
12
+ content?: string | null;
13
+ }
14
+
15
+ export interface ProductReviewPatchInput {
16
+ status?: string;
17
+ rejectionReason?: string | null;
18
+ rating?: number;
19
+ title?: string | null;
20
+ content?: string | null;
21
+ }
22
+
23
+ /**
24
+ * Post-purchase product review. List/create are nested under ``/products/:id/reviews/``;
25
+ * updates use ``/product-reviews/:id/``. Do not use :meth:`Entity.create` / :meth:`Entity.list`
26
+ * for this resource.
27
+ *
28
+ * API responses use ``jobId``, ``productId``, and ``domainId``; this entity maps those onto
29
+ * ``job``, ``product``, and ``domain`` (minimal ``{ id }`` objects unless the API nests more).
30
+ */
31
+ export class ProductReview extends Entity {
32
+ protected static resourceName = 'product-reviews';
33
+ protected static singularName = 'productReview';
34
+ protected static pluralName = 'productReviews';
35
+
36
+ @ProductReview.property()
37
+ public id?: number;
38
+
39
+ @ProductReview.property({ type: 'Product' })
40
+ public product?: Product;
41
+
42
+ @ProductReview.property({ type: 'Domain' })
43
+ public domain?: Domain;
44
+
45
+ @ProductReview.property({ type: Number })
46
+ public authorUserId?: number;
47
+
48
+ @ProductReview.property({ type: 'Job' })
49
+ public job?: Job;
50
+
51
+ @ProductReview.property({ type: Number })
52
+ public rating?: number;
53
+
54
+ @ProductReview.property({ type: String })
55
+ public title?: string | null;
56
+
57
+ @ProductReview.property({ type: String })
58
+ public content?: string | null;
59
+
60
+ @ProductReview.property({ type: String })
61
+ public status?: string;
62
+
63
+ @ProductReview.property({ type: Number })
64
+ public purchaseInvoiceId?: number | null;
65
+
66
+ /** ISO 8601 string from the API. */
67
+ @ProductReview.property({ type: String })
68
+ public submittedAt?: string | null;
69
+
70
+ /** ISO 8601 string from the API. */
71
+ @ProductReview.property({ type: String })
72
+ public updatedAt?: string | null;
73
+
74
+ @ProductReview.property({ type: String })
75
+ public rejectionReason?: string | null;
76
+
77
+ /**
78
+ * Map flat API fields (``jobId``, ``productId``, ``domainId``) to nested
79
+ * ``job`` / ``product`` / ``domain`` objects before :meth:`Entity.fromJson`.
80
+ */
81
+ public static normalizeApiJson(json: any): any {
82
+ if (json === null || json === undefined || typeof json !== 'object') {
83
+ return json;
84
+ }
85
+ const row: any = { ...json };
86
+ if (row.jobId !== undefined && row.job === undefined) {
87
+ if (row.jobId != null) {
88
+ row.job = { id: row.jobId };
89
+ }
90
+ delete row.jobId;
91
+ }
92
+ if (row.productId !== undefined && row.product === undefined) {
93
+ if (row.productId != null) {
94
+ row.product = { id: row.productId };
95
+ }
96
+ delete row.productId;
97
+ }
98
+ if (row.domainId !== undefined && row.domain === undefined) {
99
+ if (row.domainId != null) {
100
+ row.domain = { id: row.domainId };
101
+ }
102
+ delete row.domainId;
103
+ }
104
+ return row;
105
+ }
106
+
107
+ /**
108
+ * Domain managers/admins: list reviews for a product.
109
+ */
110
+ public static listForProduct(
111
+ this: typeof ProductReview,
112
+ productId: number,
113
+ options?: { withRights?: boolean }
114
+ ): Promise<ProductReview[]> {
115
+ const Constructor = this;
116
+ const resource = `/products/${productId}/reviews/`;
117
+ const fetchOptions: RequestOptions = { method: 'GET' };
118
+ fetchOptions.query = [];
119
+ if (!(options && options.withRights)) {
120
+ fetchOptions.query.push(['skip_rights', 'y']);
121
+ }
122
+ return Constructor.merchi.authenticatedFetch(resource, fetchOptions).then(
123
+ (data: any) => {
124
+ const raw = data.productReviews ?? [];
125
+ return raw.map((row: any) => {
126
+ const e: ProductReview = new Constructor() as ProductReview;
127
+ e.fromJson(ProductReview.normalizeApiJson(row));
128
+ return e;
129
+ });
130
+ }
131
+ );
132
+ }
133
+
134
+ /**
135
+ * Buyer: create a review for the catalog ``productId`` (master product).
136
+ * ``body.job.id`` must be a completed job whose line item resolves to this product.
137
+ */
138
+ public static createForProduct(
139
+ this: typeof ProductReview,
140
+ productId: number,
141
+ body: ProductReviewCreateInput,
142
+ options?: { withRights?: boolean }
143
+ ): Promise<ProductReview> {
144
+ const Constructor = this;
145
+ const resource = `/products/${productId}/reviews/`;
146
+ const wire: Record<string, unknown> = {
147
+ jobId: body.job.id,
148
+ rating: body.rating,
149
+ };
150
+ if (body.title !== undefined) {
151
+ wire.title = body.title;
152
+ }
153
+ if (body.content !== undefined) {
154
+ wire.content = body.content;
155
+ }
156
+ const fetchOptions: RequestOptions = {
157
+ method: 'POST',
158
+ headers: { 'Content-Type': 'application/json' },
159
+ body: JSON.stringify(wire),
160
+ };
161
+ fetchOptions.query = [];
162
+ if (!(options && options.withRights)) {
163
+ fetchOptions.query.push(['skip_rights', 'y']);
164
+ }
165
+ return Constructor.merchi.authenticatedFetch(resource, fetchOptions).then(
166
+ (data: any) => {
167
+ const e: ProductReview = new Constructor() as ProductReview;
168
+ e.fromJson(ProductReview.normalizeApiJson(data.productReview));
169
+ return e;
170
+ }
171
+ );
172
+ }
173
+
174
+ /**
175
+ * Partial update (moderation or author edit). Uses ``multipart/form-data`` fields
176
+ * matching the Merchi API.
177
+ */
178
+ public patch(
179
+ payload: ProductReviewPatchInput,
180
+ options?: { withRights?: boolean }
181
+ ): Promise<this> {
182
+ const id = this.id;
183
+ if (id === undefined) {
184
+ throw new Error('ProductReview.id is required to patch');
185
+ }
186
+ const resource = `/product-reviews/${String(id)}/`;
187
+ const form = new FormData();
188
+ if (payload.status !== undefined) {
189
+ form.set('status', payload.status);
190
+ }
191
+ if (payload.rejectionReason !== undefined) {
192
+ form.set('rejectionReason', payload.rejectionReason ?? '');
193
+ }
194
+ if (payload.rating !== undefined) {
195
+ form.set('rating', String(payload.rating));
196
+ }
197
+ if (payload.title !== undefined) {
198
+ form.set('title', payload.title ?? '');
199
+ }
200
+ if (payload.content !== undefined) {
201
+ form.set('content', payload.content ?? '');
202
+ }
203
+ const fetchOptions: RequestOptions = { method: 'PATCH', body: form };
204
+ fetchOptions.query = [];
205
+ if (!(options && options.withRights)) {
206
+ fetchOptions.query.push(['skip_rights', 'y']);
207
+ }
208
+ const singularName = (this.constructor as typeof ProductReview)
209
+ .singularName;
210
+ return this.merchi.authenticatedFetch(resource, fetchOptions).then(
211
+ (data: any) => {
212
+ this.fromJson(ProductReview.normalizeApiJson(data[singularName]));
213
+ this.cleanDirty();
214
+ return this;
215
+ }
216
+ );
217
+ }
218
+ }
@@ -2,6 +2,13 @@ import { Entity } from '../entity.js';
2
2
  import type { Shipment } from './shipment.js';
3
3
  import { User } from './user.js';
4
4
 
5
+ /**
6
+ * Runtime type tag only. The API returns `detailJson` as arbitrary JSON; the
7
+ * entity layer rejects `Object` from decorator metadata, so we use an empty
8
+ * class as the property `type` (same pattern as DraftTemplate.customisationMap).
9
+ */
10
+ const detailJsonPropertyType = class {};
11
+
5
12
  export class ShipmentLog extends Entity {
6
13
  protected static resourceName = 'shipment_logs';
7
14
  protected static singularName = 'shipmentLog';
@@ -22,7 +29,7 @@ export class ShipmentLog extends Entity {
22
29
  @ShipmentLog.property({ type: String })
23
30
  public message?: string;
24
31
 
25
- @ShipmentLog.property()
32
+ @ShipmentLog.property({ type: detailJsonPropertyType })
26
33
  public detailJson?: Record<string, unknown> | null;
27
34
 
28
35
  @ShipmentLog.property({ type: Date })
package/src/index.ts CHANGED
@@ -51,6 +51,11 @@ import { Payment } from './entities/payment.js';
51
51
  import { PaymentDevice } from './entities/payment_device.js';
52
52
  import { PhoneNumber } from './entities/phone_number.js';
53
53
  import { Product } from './entities/product.js';
54
+ import { ProductReview } from './entities/product_review.js';
55
+ export type {
56
+ ProductReviewCreateInput,
57
+ ProductReviewPatchInput,
58
+ } from './entities/product_review.js';
54
59
  import { ProductionComment } from './entities/production_comment.js';
55
60
  import { Quote } from './entities/quote.js';
56
61
  import { QuoteItem } from './entities/quote_item.js';
@@ -142,6 +147,7 @@ export {
142
147
  PaymentDevice,
143
148
  PhoneNumber,
144
149
  Product,
150
+ ProductReview,
145
151
  ProductionComment,
146
152
  Quote,
147
153
  QuoteItem,
package/src/merchi.ts CHANGED
@@ -14,6 +14,7 @@ import { VariationField } from './entities/variation_field.js';
14
14
  import { VariationOption } from './entities/variation_option.js';
15
15
  import { ProductionComment } from './entities/production_comment.js';
16
16
  import { Product } from './entities/product.js';
17
+ import { ProductReview } from './entities/product_review.js';
17
18
  import { InternalTag } from './entities/internal_tag.js';
18
19
  import { Inventory } from './entities/inventory.js';
19
20
  import { InventoryGroup } from './entities/inventory_group.js';
@@ -155,6 +156,7 @@ export class Merchi {
155
156
  public Job: typeof Job;
156
157
  public DomainInvitation: typeof DomainInvitation;
157
158
  public Product: typeof Product;
159
+ public ProductReview: typeof ProductReview;
158
160
  public DomainTag: typeof DomainTag;
159
161
  public EmailAddress: typeof EmailAddress;
160
162
  public PhoneNumber: typeof PhoneNumber;
@@ -330,6 +332,9 @@ export class Merchi {
330
332
  this.CountryTax = this.setupClass(CountryTax) as typeof CountryTax;
331
333
  this.ShortUrl = this.setupClass(ShortUrl) as typeof ShortUrl;
332
334
  this.Product = this.setupClass(Product) as typeof Product;
335
+ this.ProductReview = this.setupClass(
336
+ ProductReview
337
+ ) as typeof ProductReview;
333
338
  this.SystemRole = this.setupClass(SystemRole) as typeof SystemRole;
334
339
  this.CartItem = this.setupClass(CartItem) as typeof CartItem;
335
340
  this.UserCompany = this.setupClass(UserCompany) as typeof UserCompany;