@minipim/sdk 0.7.0 → 0.8.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.
package/README.md CHANGED
@@ -192,6 +192,20 @@ await pim.GET('/v1/content', { params: { query: { tag: 'Buying Guide' } } }); //
192
192
 
193
193
  Documented in the field descriptions from API **0.14.1+**, and in these types from v0.7.0.
194
194
 
195
+ ## Ordering a content archive (API 0.19.0+)
196
+
197
+ `GET /v1/content` defaults to `updatedAt` descending — the order things were last *edited*, which is rarely the order an archive should read in. Sort by `publishedAt`, which imports preserve from the source system:
198
+
199
+ ```ts
200
+ const { data } = await pim.GET('/v1/content', {
201
+ params: { query: { sortBy: 'publishedAt', sortDir: 'desc', limit: 20 } },
202
+ });
203
+ ```
204
+
205
+ Pages with no `publishedAt` sort **last in both directions** — an undated page is unscheduled, not newest. `sortBy` also accepts `updatedAt`, `createdAt` and `title`.
206
+
207
+ `categoryId` behaves exactly like it does on products: **self-only** unless you add `includeDescendants: true`. Content gets filed against leaf categories too, so filtering by a parent section returns an empty page without it.
208
+
195
209
  ## Uploading files
196
210
 
197
211
  `POST /v1/media` is `multipart/form-data`, not JSON. The file field is named `file`; everything else is optional and lets you attach the upload in the same request:
@@ -205,7 +219,21 @@ form.append('role', 'technical'); // hero | gallery | thumbnail | tech
205
219
  form.append('altText', JSON.stringify({ en_US: 'Sell sheet' })); // a JSON *string*, not an object
206
220
  ```
207
221
 
208
- `altText` is parsed as JSON and parse failures are swallowed, so passing a real object silently stores no alt text. Send `JSON.stringify(...)`.
222
+ `altText` is parsed as JSON, so passing a real object rather than a string stores no alt text. Send `JSON.stringify(...)`.
223
+
224
+ That case no longer fails silently. From API **0.21.0** a malformed `altText` still lets the upload succeed — it never fails the request — but the response says what it ignored:
225
+
226
+ ```ts
227
+ const { data } = await pim.POST('/v1/media', { body: form as never });
228
+ if (data?.warnings?.length) console.warn(data.warnings);
229
+ // ["altText was not valid JSON and no alt text was stored; expected an object keyed by locale, …"]
230
+ ```
231
+
232
+ `warnings` is absent when there is nothing to report, so a clean upload's response is unchanged.
233
+
234
+ **You do not have to get the content type right.** From API **0.21.0** the leading bytes are sniffed whenever you send `application/octet-stream` or no type at all — so a PNG whose filename lost its extension uploads as a PNG. If a specific declared type contradicts the bytes, the bytes win. SVG, CSV, plain text and the Office formats have no distinguishing magic bytes and still need an explicit type.
235
+
236
+ `role` and `position` are validated: an unrecognised value is a 422 listing the accepted ones in `details.accepted`, not a 500.
209
237
 
210
238
  Requires API **0.14.0+** to appear in the spec at all — before that this endpoint published no request body, so generated clients had nothing for it.
211
239
 
@@ -3521,6 +3521,16 @@ interface paths {
3521
3521
  /**
3522
3522
  * List content pages
3523
3523
  * @description Filters and pagination mirror `GET /v1/products`. `tag` is repeatable and matches pages carrying ALL listed tags.
3524
+ *
3525
+ * Ordering defaults to `updatedAt` descending. For a blog archive sort by `publishedAt`, which imports preserve from the source system:
3526
+ *
3527
+ * ```
3528
+ * curl 'https://api.minipim.com/v1/content?sortBy=publishedAt&sortDir=desc&limit=20'
3529
+ * ```
3530
+ *
3531
+ * Pages with no `publishedAt` sort LAST in both directions — an undated page is unscheduled, not newest.
3532
+ *
3533
+ * `categoryId` is SELF-ONLY. Content is filed against leaf categories, so filtering by a parent returns an empty page unless you add `includeDescendants=true` to match the whole subtree.
3524
3534
  */
3525
3535
  get: {
3526
3536
  parameters: {
@@ -3529,10 +3539,13 @@ interface paths {
3529
3539
  q?: string;
3530
3540
  familyId?: string;
3531
3541
  categoryId?: string;
3542
+ includeDescendants?: boolean | ("true" | "false" | "1" | "0");
3532
3543
  channelId?: string;
3533
3544
  /** @description Repeatable — `?tag=a&tag=b` matches records carrying ALL listed tags. Values are canonicalized exactly as writes are, so `?tag=Buying%20Guide` matches the stored `buying-guide`; you never have to pre-slugify a filter. */
3534
3545
  tag?: string | string[];
3535
3546
  updatedSince?: string;
3547
+ sortBy?: "publishedAt" | "updatedAt" | "createdAt" | "title";
3548
+ sortDir?: "asc" | "desc";
3536
3549
  limit?: number;
3537
3550
  offset?: number;
3538
3551
  };
@@ -5990,11 +6003,11 @@ interface paths {
5990
6003
  "multipart/form-data": {
5991
6004
  /**
5992
6005
  * Format: binary
5993
- * @description The file to upload. Images, video and PDF are accepted; see the 400 response for the rejected-mime and blocked-extension cases.
6006
+ * @description The file to upload. Images, video, PDF, Office documents and glTF are accepted; the 422 response lists every allowed type in `details.allowed`. You do NOT have to get the content type right: when you send `application/octet-stream` (or no type at all), the leading bytes are sniffed and the detected type is used — so a PNG whose filename lost its extension uploads fine. SVG, CSV, plain text and Office formats have no distinguishing magic bytes and still need an explicit type. If a specific declared type contradicts the bytes, the bytes win.
5994
6007
  */
5995
6008
  file: string;
5996
6009
  /**
5997
- * @description Attach the upload in the same transaction. Requires `entityId`; supplying only one of the pair uploads the file WITHOUT associating it.
6010
+ * @description Attach the upload in the same transaction. Requires `entityId`; supplying only one of the pair uploads the file WITHOUT associating it. A value outside the enum is a 422, not a silent miss.
5998
6011
  * @enum {string}
5999
6012
  */
6000
6013
  entityType?: "product" | "variant" | "content_page";
@@ -6004,17 +6017,21 @@ interface paths {
6004
6017
  */
6005
6018
  entityId?: string;
6006
6019
  /**
6007
- * @description Association role. Ignored unless `entityType`+`entityId` are present.
6020
+ * @description Association role. Ignored unless `entityType`+`entityId` are present. A value outside this enum is rejected with a 422 that lists the accepted values in `details.accepted`.
6008
6021
  * @default gallery
6009
6022
  * @enum {string}
6010
6023
  */
6011
6024
  role?: "hero" | "gallery" | "thumbnail" | "technical" | "lifestyle" | "swatch";
6012
6025
  /**
6013
- * @description Sort position within the entity’s gallery.
6026
+ * @description Sort position within the entity’s gallery. Must be a non-negative integer; anything else is a 422.
6014
6027
  * @default 0
6015
6028
  */
6016
6029
  position?: number;
6017
- /** @description A JSON OBJECT keyed by locale, sent as a STRING — e.g. `{"en_US":"Blue widget on white"}`. Unparseable JSON is ignored rather than rejected, so malformed alt text costs you the alt text, not the upload. */
6030
+ /**
6031
+ * @description A JSON OBJECT keyed by locale, sent as a STRING — e.g. `{"en_US":"Blue widget on white"}`. Unparseable JSON, or JSON that is not an object of locale → string, does NOT fail the upload: the file is stored, no alt text is saved, and the 201 response carries a `warnings` entry saying so. Check `warnings` if you send alt text programmatically. Omit the field entirely if you have none.
6032
+ *
6033
+ * (0.20.0 briefly made this a 422; 0.21.0 restored the original behaviour and added `warnings` instead, so the problem is reported without breaking callers.)
6034
+ */
6018
6035
  altText?: string;
6019
6036
  };
6020
6037
  };
@@ -6071,6 +6088,8 @@ interface paths {
6071
6088
  channelId: string | null;
6072
6089
  };
6073
6090
  url: string;
6091
+ /** @description Non-fatal problems with this upload — currently only malformed `altText`. The upload succeeded; something you sent was ignored. Absent when there is nothing to report. */
6092
+ warnings?: string[];
6074
6093
  };
6075
6094
  };
6076
6095
  };
@@ -6090,6 +6109,36 @@ interface paths {
6090
6109
  };
6091
6110
  };
6092
6111
  /** @description Default Response */
6112
+ 413: {
6113
+ headers: {
6114
+ [name: string]: unknown;
6115
+ };
6116
+ content: {
6117
+ "application/json": {
6118
+ error: {
6119
+ code: string;
6120
+ message: string;
6121
+ details?: unknown;
6122
+ };
6123
+ };
6124
+ };
6125
+ };
6126
+ /** @description Default Response */
6127
+ 422: {
6128
+ headers: {
6129
+ [name: string]: unknown;
6130
+ };
6131
+ content: {
6132
+ "application/json": {
6133
+ error: {
6134
+ code: string;
6135
+ message: string;
6136
+ details?: unknown;
6137
+ };
6138
+ };
6139
+ };
6140
+ };
6141
+ /** @description Default Response */
6093
6142
  503: {
6094
6143
  headers: {
6095
6144
  [name: string]: unknown;
@@ -9039,6 +9088,8 @@ interface paths {
9039
9088
  }) | null;
9040
9089
  /** Format: date-time */
9041
9090
  createdAt: string;
9091
+ /** @description Display name for the actor: the user’s name or email for `user` rows, the connector’s name for `connector` rows, null when the actor is unattributed (`system`) or no longer resolvable. */
9092
+ actorLabel: string | null;
9042
9093
  }[];
9043
9094
  limit: number;
9044
9095
  offset: number;
package/dist/openapi.d.ts CHANGED
@@ -3521,6 +3521,16 @@ interface paths {
3521
3521
  /**
3522
3522
  * List content pages
3523
3523
  * @description Filters and pagination mirror `GET /v1/products`. `tag` is repeatable and matches pages carrying ALL listed tags.
3524
+ *
3525
+ * Ordering defaults to `updatedAt` descending. For a blog archive sort by `publishedAt`, which imports preserve from the source system:
3526
+ *
3527
+ * ```
3528
+ * curl 'https://api.minipim.com/v1/content?sortBy=publishedAt&sortDir=desc&limit=20'
3529
+ * ```
3530
+ *
3531
+ * Pages with no `publishedAt` sort LAST in both directions — an undated page is unscheduled, not newest.
3532
+ *
3533
+ * `categoryId` is SELF-ONLY. Content is filed against leaf categories, so filtering by a parent returns an empty page unless you add `includeDescendants=true` to match the whole subtree.
3524
3534
  */
3525
3535
  get: {
3526
3536
  parameters: {
@@ -3529,10 +3539,13 @@ interface paths {
3529
3539
  q?: string;
3530
3540
  familyId?: string;
3531
3541
  categoryId?: string;
3542
+ includeDescendants?: boolean | ("true" | "false" | "1" | "0");
3532
3543
  channelId?: string;
3533
3544
  /** @description Repeatable — `?tag=a&tag=b` matches records carrying ALL listed tags. Values are canonicalized exactly as writes are, so `?tag=Buying%20Guide` matches the stored `buying-guide`; you never have to pre-slugify a filter. */
3534
3545
  tag?: string | string[];
3535
3546
  updatedSince?: string;
3547
+ sortBy?: "publishedAt" | "updatedAt" | "createdAt" | "title";
3548
+ sortDir?: "asc" | "desc";
3536
3549
  limit?: number;
3537
3550
  offset?: number;
3538
3551
  };
@@ -5990,11 +6003,11 @@ interface paths {
5990
6003
  "multipart/form-data": {
5991
6004
  /**
5992
6005
  * Format: binary
5993
- * @description The file to upload. Images, video and PDF are accepted; see the 400 response for the rejected-mime and blocked-extension cases.
6006
+ * @description The file to upload. Images, video, PDF, Office documents and glTF are accepted; the 422 response lists every allowed type in `details.allowed`. You do NOT have to get the content type right: when you send `application/octet-stream` (or no type at all), the leading bytes are sniffed and the detected type is used — so a PNG whose filename lost its extension uploads fine. SVG, CSV, plain text and Office formats have no distinguishing magic bytes and still need an explicit type. If a specific declared type contradicts the bytes, the bytes win.
5994
6007
  */
5995
6008
  file: string;
5996
6009
  /**
5997
- * @description Attach the upload in the same transaction. Requires `entityId`; supplying only one of the pair uploads the file WITHOUT associating it.
6010
+ * @description Attach the upload in the same transaction. Requires `entityId`; supplying only one of the pair uploads the file WITHOUT associating it. A value outside the enum is a 422, not a silent miss.
5998
6011
  * @enum {string}
5999
6012
  */
6000
6013
  entityType?: "product" | "variant" | "content_page";
@@ -6004,17 +6017,21 @@ interface paths {
6004
6017
  */
6005
6018
  entityId?: string;
6006
6019
  /**
6007
- * @description Association role. Ignored unless `entityType`+`entityId` are present.
6020
+ * @description Association role. Ignored unless `entityType`+`entityId` are present. A value outside this enum is rejected with a 422 that lists the accepted values in `details.accepted`.
6008
6021
  * @default gallery
6009
6022
  * @enum {string}
6010
6023
  */
6011
6024
  role?: "hero" | "gallery" | "thumbnail" | "technical" | "lifestyle" | "swatch";
6012
6025
  /**
6013
- * @description Sort position within the entity’s gallery.
6026
+ * @description Sort position within the entity’s gallery. Must be a non-negative integer; anything else is a 422.
6014
6027
  * @default 0
6015
6028
  */
6016
6029
  position?: number;
6017
- /** @description A JSON OBJECT keyed by locale, sent as a STRING — e.g. `{"en_US":"Blue widget on white"}`. Unparseable JSON is ignored rather than rejected, so malformed alt text costs you the alt text, not the upload. */
6030
+ /**
6031
+ * @description A JSON OBJECT keyed by locale, sent as a STRING — e.g. `{"en_US":"Blue widget on white"}`. Unparseable JSON, or JSON that is not an object of locale → string, does NOT fail the upload: the file is stored, no alt text is saved, and the 201 response carries a `warnings` entry saying so. Check `warnings` if you send alt text programmatically. Omit the field entirely if you have none.
6032
+ *
6033
+ * (0.20.0 briefly made this a 422; 0.21.0 restored the original behaviour and added `warnings` instead, so the problem is reported without breaking callers.)
6034
+ */
6018
6035
  altText?: string;
6019
6036
  };
6020
6037
  };
@@ -6071,6 +6088,8 @@ interface paths {
6071
6088
  channelId: string | null;
6072
6089
  };
6073
6090
  url: string;
6091
+ /** @description Non-fatal problems with this upload — currently only malformed `altText`. The upload succeeded; something you sent was ignored. Absent when there is nothing to report. */
6092
+ warnings?: string[];
6074
6093
  };
6075
6094
  };
6076
6095
  };
@@ -6090,6 +6109,36 @@ interface paths {
6090
6109
  };
6091
6110
  };
6092
6111
  /** @description Default Response */
6112
+ 413: {
6113
+ headers: {
6114
+ [name: string]: unknown;
6115
+ };
6116
+ content: {
6117
+ "application/json": {
6118
+ error: {
6119
+ code: string;
6120
+ message: string;
6121
+ details?: unknown;
6122
+ };
6123
+ };
6124
+ };
6125
+ };
6126
+ /** @description Default Response */
6127
+ 422: {
6128
+ headers: {
6129
+ [name: string]: unknown;
6130
+ };
6131
+ content: {
6132
+ "application/json": {
6133
+ error: {
6134
+ code: string;
6135
+ message: string;
6136
+ details?: unknown;
6137
+ };
6138
+ };
6139
+ };
6140
+ };
6141
+ /** @description Default Response */
6093
6142
  503: {
6094
6143
  headers: {
6095
6144
  [name: string]: unknown;
@@ -9039,6 +9088,8 @@ interface paths {
9039
9088
  }) | null;
9040
9089
  /** Format: date-time */
9041
9090
  createdAt: string;
9091
+ /** @description Display name for the actor: the user’s name or email for `user` rows, the connector’s name for `connector` rows, null when the actor is unattributed (`system`) or no longer resolvable. */
9092
+ actorLabel: string | null;
9042
9093
  }[];
9043
9094
  limit: number;
9044
9095
  offset: number;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@minipim/sdk",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Typed TypeScript client for the MiniPim API.",
5
5
  "license": "Apache-2.0",
6
6
  "homepage": "https://github.com/Epic-Design-Labs/minipim",