@sixtyninecommerce/admin 0.10.0 → 0.12.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 (302) hide show
  1. package/README.md +5772 -118
  2. package/dist/auth/index.d.ts +7 -1
  3. package/dist/auth/index.js +8 -1
  4. package/dist/catalog/assets.d.ts +120 -8
  5. package/dist/catalog/assets.js +98 -12
  6. package/dist/catalog/collections.d.ts +279 -14
  7. package/dist/catalog/collections.js +246 -15
  8. package/dist/catalog/documents.d.ts +142 -0
  9. package/dist/catalog/documents.js +114 -0
  10. package/dist/catalog/index.d.ts +54 -6
  11. package/dist/catalog/index.js +10 -1
  12. package/dist/catalog/metadata.d.ts +244 -0
  13. package/dist/catalog/metadata.js +220 -0
  14. package/dist/catalog/products.d.ts +159 -19
  15. package/dist/catalog/products.js +88 -13
  16. package/dist/catalog/properties.d.ts +140 -14
  17. package/dist/catalog/properties.js +65 -1
  18. package/dist/catalog/recommendations.d.ts +288 -0
  19. package/dist/catalog/recommendations.js +237 -0
  20. package/dist/catalog/reviews.d.ts +381 -0
  21. package/dist/catalog/reviews.js +325 -0
  22. package/dist/catalog/types.d.ts +17 -1
  23. package/dist/catalog/types.js +10 -0
  24. package/dist/catalog/variant-find.d.ts +136 -0
  25. package/dist/catalog/variant-find.js +239 -0
  26. package/dist/catalog/variants.d.ts +293 -26
  27. package/dist/catalog/variants.js +164 -7
  28. package/dist/catalog/visibility.d.ts +38 -7
  29. package/dist/catalog/visibility.js +19 -1
  30. package/dist/client.d.ts +121 -9
  31. package/dist/client.js +53 -14
  32. package/dist/content/assets.d.ts +285 -0
  33. package/dist/content/assets.js +181 -0
  34. package/dist/content/forms.d.ts +332 -1
  35. package/dist/content/forms.js +140 -4
  36. package/dist/content/items.d.ts +292 -0
  37. package/dist/content/items.js +170 -0
  38. package/dist/content/menus.d.ts +254 -0
  39. package/dist/content/menus.js +70 -0
  40. package/dist/content/strings.d.ts +137 -0
  41. package/dist/content/strings.js +82 -0
  42. package/dist/content/types.d.ts +282 -0
  43. package/dist/content/types.js +100 -0
  44. package/dist/customers/age-verification.d.ts +66 -0
  45. package/dist/customers/age-verification.js +79 -0
  46. package/dist/customers/credit.d.ts +263 -0
  47. package/dist/customers/credit.js +244 -0
  48. package/dist/customers/delivery-preferences.d.ts +120 -0
  49. package/dist/customers/delivery-preferences.js +97 -0
  50. package/dist/customers/delivery-terms.d.ts +44 -0
  51. package/dist/customers/delivery-terms.js +32 -0
  52. package/dist/customers/groups.d.ts +207 -0
  53. package/dist/customers/groups.js +438 -0
  54. package/dist/customers/index.d.ts +462 -37
  55. package/dist/customers/index.js +317 -40
  56. package/dist/customers/invitation-status.d.ts +57 -0
  57. package/dist/customers/invitation-status.js +21 -0
  58. package/dist/customers/notes.d.ts +67 -0
  59. package/dist/customers/notes.js +51 -0
  60. package/dist/customers/notification-recipients.d.ts +97 -0
  61. package/dist/customers/notification-recipients.js +84 -0
  62. package/dist/customers/saved-lists.d.ts +42 -0
  63. package/dist/customers/saved-lists.js +61 -0
  64. package/dist/customers/vat.d.ts +83 -0
  65. package/dist/customers/vat.js +46 -0
  66. package/dist/customers/wire.d.ts +20 -0
  67. package/dist/customers/wire.js +35 -0
  68. package/dist/documents/ar.d.ts +307 -0
  69. package/dist/documents/ar.js +254 -0
  70. package/dist/documents/emails.d.ts +150 -0
  71. package/dist/documents/emails.js +220 -0
  72. package/dist/documents/index.d.ts +744 -21
  73. package/dist/documents/index.js +438 -24
  74. package/dist/documents/pdf.d.ts +2 -0
  75. package/dist/documents/pdf.js +11 -0
  76. package/dist/fulfillments/create.d.ts +167 -0
  77. package/dist/fulfillments/create.js +216 -0
  78. package/dist/fulfillments/index.d.ts +163 -11
  79. package/dist/fulfillments/index.js +135 -6
  80. package/dist/fulfillments/payment-policy.d.ts +64 -0
  81. package/dist/fulfillments/payment-policy.js +140 -0
  82. package/dist/fulfillments/warehouse.d.ts +724 -0
  83. package/dist/fulfillments/warehouse.js +914 -0
  84. package/dist/geo/index.d.ts +119 -0
  85. package/dist/geo/index.js +107 -0
  86. package/dist/index.d.ts +147 -39
  87. package/dist/index.js +51 -12
  88. package/dist/integrations/afas-actions.d.ts +234 -0
  89. package/dist/integrations/afas-actions.js +310 -0
  90. package/dist/integrations/afas-types.d.ts +483 -0
  91. package/dist/integrations/afas-types.js +5 -0
  92. package/dist/integrations/afas.d.ts +234 -0
  93. package/dist/integrations/afas.js +290 -0
  94. package/dist/integrations/connections.d.ts +103 -0
  95. package/dist/integrations/connections.js +55 -0
  96. package/dist/integrations/esp.d.ts +313 -0
  97. package/dist/integrations/esp.js +169 -0
  98. package/dist/integrations/exact-online-types.d.ts +965 -0
  99. package/dist/integrations/exact-online-types.js +6 -0
  100. package/dist/integrations/exact-online.d.ts +784 -0
  101. package/dist/integrations/exact-online.js +1089 -0
  102. package/dist/integrations/index.d.ts +44 -3
  103. package/dist/integrations/index.js +23 -3
  104. package/dist/integrations/pipeline-discoveries.d.ts +65 -0
  105. package/dist/integrations/pipeline-discoveries.js +65 -0
  106. package/dist/integrations/pipeline-keys.d.ts +13 -0
  107. package/dist/integrations/pipeline-keys.js +22 -0
  108. package/dist/integrations/pipeline-runs.d.ts +119 -0
  109. package/dist/integrations/pipeline-runs.js +87 -0
  110. package/dist/integrations/pipelines.d.ts +87 -15
  111. package/dist/integrations/pipelines.js +41 -22
  112. package/dist/integrations/price-import.d.ts +223 -0
  113. package/dist/integrations/price-import.js +124 -0
  114. package/dist/integrations/types.d.ts +367 -3
  115. package/dist/integrations/types.js +4 -3
  116. package/dist/locations/index.d.ts +66 -0
  117. package/dist/locations/index.js +31 -0
  118. package/dist/meta/index.d.ts +172 -0
  119. package/dist/metafields/index.d.ts +8 -1
  120. package/dist/metafields/index.js +10 -0
  121. package/dist/orders/cancel-with-money.d.ts +237 -0
  122. package/dist/orders/cancel-with-money.js +155 -0
  123. package/dist/orders/commit-edit.d.ts +23 -1
  124. package/dist/orders/commit-edit.js +19 -2
  125. package/dist/orders/deposit-policy.d.ts +3 -1
  126. package/dist/orders/drafts.d.ts +800 -0
  127. package/dist/orders/drafts.js +771 -0
  128. package/dist/orders/fields.d.ts +245 -0
  129. package/dist/orders/fields.js +188 -0
  130. package/dist/orders/get.d.ts +29 -19
  131. package/dist/orders/get.js +17 -8
  132. package/dist/orders/index.d.ts +66 -15
  133. package/dist/orders/index.js +25 -2
  134. package/dist/orders/lifecycle.d.ts +128 -0
  135. package/dist/orders/lifecycle.js +158 -0
  136. package/dist/orders/line-price-preview.d.ts +7 -2
  137. package/dist/orders/list.d.ts +243 -0
  138. package/dist/orders/list.js +487 -0
  139. package/dist/orders/manual-discounts.d.ts +13 -5
  140. package/dist/orders/manual-pricing.d.ts +5 -0
  141. package/dist/orders/money-view.d.ts +149 -0
  142. package/dist/orders/money-view.js +99 -0
  143. package/dist/orders/order-entry.d.ts +20 -7
  144. package/dist/orders/plan-edit.d.ts +34 -2
  145. package/dist/orders/plan-edit.js +112 -11
  146. package/dist/orders/settings.d.ts +201 -0
  147. package/dist/orders/settings.js +325 -0
  148. package/dist/orders/status.d.ts +159 -13
  149. package/dist/orders/status.js +21 -0
  150. package/dist/orders/surcharges.d.ts +20 -1
  151. package/dist/orders/surcharges.js +37 -11
  152. package/dist/payments/account-credit.d.ts +46 -0
  153. package/dist/payments/account-credit.js +42 -0
  154. package/dist/payments/ar.d.ts +292 -0
  155. package/dist/payments/ar.js +223 -0
  156. package/dist/payments/connected-account.d.ts +47 -0
  157. package/dist/payments/connected-account.js +61 -0
  158. package/dist/payments/credit-noted-fields.d.ts +19 -0
  159. package/dist/payments/credit-noted-fields.js +69 -0
  160. package/dist/payments/customer-consent.d.ts +30 -0
  161. package/dist/payments/customer-consent.js +49 -0
  162. package/dist/payments/index.d.ts +340 -19
  163. package/dist/payments/index.js +151 -1
  164. package/dist/payments/methods.d.ts +303 -8
  165. package/dist/payments/methods.js +337 -7
  166. package/dist/payments/mollie-methods.d.ts +159 -0
  167. package/dist/payments/mollie-methods.js +141 -0
  168. package/dist/payments/payment-links.d.ts +180 -0
  169. package/dist/payments/payment-links.js +97 -0
  170. package/dist/payments/provider-keys.d.ts +150 -0
  171. package/dist/payments/provider-keys.js +118 -0
  172. package/dist/payments/providers.d.ts +86 -11
  173. package/dist/payments/providers.js +29 -0
  174. package/dist/payments/requests.d.ts +147 -0
  175. package/dist/payments/requests.js +93 -0
  176. package/dist/payments/store-credit-fields.d.ts +15 -0
  177. package/dist/payments/store-credit-fields.js +51 -0
  178. package/dist/pickups/index.d.ts +106 -0
  179. package/dist/pickups/index.js +108 -0
  180. package/dist/platform/channels.d.ts +132 -0
  181. package/dist/platform/channels.js +128 -0
  182. package/dist/platform/email-gateways.d.ts +165 -0
  183. package/dist/platform/email-gateways.js +78 -0
  184. package/dist/platform/geo.d.ts +123 -0
  185. package/dist/platform/geo.js +144 -0
  186. package/dist/platform/tax.d.ts +162 -0
  187. package/dist/platform/tax.js +169 -0
  188. package/dist/pos/anomalies.d.ts +158 -0
  189. package/dist/pos/anomalies.js +64 -0
  190. package/dist/pos/assisted-selling.d.ts +79 -0
  191. package/dist/pos/assisted-selling.js +38 -0
  192. package/dist/pos/exchanges.d.ts +108 -0
  193. package/dist/pos/exchanges.js +22 -0
  194. package/dist/pos/gift-cards.d.ts +135 -0
  195. package/dist/pos/gift-cards.js +47 -0
  196. package/dist/pos/index.d.ts +2370 -58
  197. package/dist/pos/index.js +854 -7
  198. package/dist/pos/no-receipt.d.ts +94 -0
  199. package/dist/pos/no-receipt.js +25 -0
  200. package/dist/pos/offline-sales.d.ts +228 -0
  201. package/dist/pos/offline-sales.js +170 -0
  202. package/dist/pos/pay-by-link.d.ts +143 -0
  203. package/dist/pos/pay-by-link.js +57 -0
  204. package/dist/pos/quick-keys.d.ts +103 -0
  205. package/dist/pos/quick-keys.js +45 -0
  206. package/dist/pos/reports.d.ts +360 -0
  207. package/dist/pos/reports.js +62 -0
  208. package/dist/pos/returns.d.ts +244 -0
  209. package/dist/pos/returns.js +83 -0
  210. package/dist/pricing/bulk-coupons.d.ts +139 -0
  211. package/dist/pricing/bulk-coupons.js +112 -0
  212. package/dist/pricing/index.d.ts +174 -4
  213. package/dist/pricing/index.js +174 -1
  214. package/dist/pricing/price-lists.d.ts +606 -0
  215. package/dist/pricing/price-lists.js +600 -0
  216. package/dist/purchasing/alerts.d.ts +104 -0
  217. package/dist/purchasing/alerts.js +88 -0
  218. package/dist/purchasing/backorders.d.ts +61 -0
  219. package/dist/purchasing/backorders.js +92 -0
  220. package/dist/purchasing/cost.d.ts +110 -0
  221. package/dist/purchasing/cost.js +86 -0
  222. package/dist/purchasing/index.d.ts +54 -0
  223. package/dist/purchasing/index.js +24 -0
  224. package/dist/purchasing/links.d.ts +263 -0
  225. package/dist/purchasing/links.js +192 -0
  226. package/dist/purchasing/purchase-orders.d.ts +551 -0
  227. package/dist/purchasing/purchase-orders.js +491 -0
  228. package/dist/purchasing/receipts.d.ts +396 -0
  229. package/dist/purchasing/receipts.js +287 -0
  230. package/dist/purchasing/replenishment.d.ts +281 -0
  231. package/dist/purchasing/replenishment.js +240 -0
  232. package/dist/purchasing/returns.d.ts +273 -0
  233. package/dist/purchasing/returns.js +229 -0
  234. package/dist/purchasing/settings.d.ts +152 -0
  235. package/dist/purchasing/settings.js +181 -0
  236. package/dist/purchasing/suppliers.d.ts +476 -0
  237. package/dist/purchasing/suppliers.js +438 -0
  238. package/dist/quotes/index.d.ts +518 -0
  239. package/dist/quotes/index.js +439 -0
  240. package/dist/reports/index.d.ts +71 -8
  241. package/dist/reports/index.js +74 -11
  242. package/dist/returns/index.d.ts +675 -21
  243. package/dist/returns/index.js +756 -11
  244. package/dist/search/index.d.ts +76 -1
  245. package/dist/search/index.js +63 -0
  246. package/dist/seo/config.d.ts +128 -0
  247. package/dist/seo/config.js +95 -0
  248. package/dist/seo/redirects.d.ts +125 -0
  249. package/dist/seo/redirects.js +60 -1
  250. package/dist/seo/settings.d.ts +147 -0
  251. package/dist/seo/settings.js +209 -0
  252. package/dist/shipping/definitions.d.ts +29 -0
  253. package/dist/shipping/definitions.js +47 -0
  254. package/dist/shipping/fulfillment-profiles.d.ts +174 -0
  255. package/dist/shipping/fulfillment-profiles.js +104 -0
  256. package/dist/shipping/hendriks.d.ts +97 -0
  257. package/dist/shipping/hendriks.js +50 -0
  258. package/dist/shipping/index.d.ts +54 -0
  259. package/dist/shipping/index.js +27 -0
  260. package/dist/shipping/methods.d.ts +205 -0
  261. package/dist/shipping/methods.js +240 -0
  262. package/dist/shipping/myparcel.d.ts +668 -0
  263. package/dist/shipping/myparcel.js +466 -0
  264. package/dist/shipping/parcel-count-suggestion.d.ts +2 -0
  265. package/dist/shipping/parcel-rule.d.ts +6 -5
  266. package/dist/shipping/parcel-rule.js +21 -23
  267. package/dist/shipping/rate-tables.d.ts +324 -0
  268. package/dist/shipping/rate-tables.js +390 -0
  269. package/dist/shipping/ship-to-countries.d.ts +75 -0
  270. package/dist/shipping/ship-to-countries.js +47 -0
  271. package/dist/stock/by-location.d.ts +86 -0
  272. package/dist/stock/by-location.js +94 -0
  273. package/dist/stock/index.d.ts +18 -4
  274. package/dist/stock/index.js +7 -0
  275. package/dist/stock/locations.d.ts +144 -0
  276. package/dist/stock/locations.js +168 -0
  277. package/dist/stock/settings.d.ts +106 -0
  278. package/dist/stock/settings.js +103 -0
  279. package/dist/stock/transfers.d.ts +386 -52
  280. package/dist/stock/transfers.js +222 -17
  281. package/dist/stored-value/index.d.ts +312 -11
  282. package/dist/stored-value/index.js +223 -4
  283. package/dist/subscriptions/index.d.ts +682 -0
  284. package/dist/subscriptions/index.js +815 -0
  285. package/dist/tax/display-policy.d.ts +105 -0
  286. package/dist/tax/display-policy.js +84 -0
  287. package/dist/tax/index.d.ts +79 -1
  288. package/dist/tax/index.js +52 -0
  289. package/dist/tenant/email-style.d.ts +102 -0
  290. package/dist/tenant/email-style.js +72 -0
  291. package/dist/tenant/email-templates.d.ts +287 -0
  292. package/dist/tenant/email-templates.js +271 -0
  293. package/dist/tenant/notifications.d.ts +23 -17
  294. package/dist/tenant/settings-sources.d.ts +1 -1
  295. package/dist/tenant/time-zone.d.ts +17 -0
  296. package/dist/tenant/time-zone.js +11 -0
  297. package/dist/types.d.ts +50 -3
  298. package/dist/users/index.d.ts +3 -0
  299. package/dist/users/index.js +2 -0
  300. package/dist/users/warehouses.d.ts +50 -0
  301. package/dist/users/warehouses.js +51 -0
  302. package/package.json +2 -2
@@ -0,0 +1,292 @@
1
+ import { type Page, type Transport } from '@sixtyninecommerce/core';
2
+ import type { Call, ListOptions } from '../types.js';
3
+ /** The statuses the CMS gives an item; a read types `status` open, as {@link ContentItem} says. */
4
+ export type ContentItemStatus = 'draft' | 'published' | 'archived';
5
+ /**
6
+ * An item's own row: what every item answer carries, the write answers included.
7
+ *
8
+ * `collectionId` is the id of the item's content type (what the CMS calls a collection).
9
+ */
10
+ export interface ContentItemRecord {
11
+ id: string;
12
+ channelId: string;
13
+ collectionId: string;
14
+ /** Unique within the type; null for an item that has none (it then has no URL either). */
15
+ slug: string | null;
16
+ /** One of {@link ContentItemStatus}, typed open so a newer CMS's status still reads. */
17
+ status: string;
18
+ publishedAt: string | null;
19
+ /** The parent item in a hierarchical type; null at the top level. */
20
+ parentId: string | null;
21
+ /**
22
+ * The storefront URL path; null when the type has no `basePath` or the item has no slug.
23
+ */
24
+ path: string | null;
25
+ /** Order among its siblings. */
26
+ position: number;
27
+ createdAt: string;
28
+ updatedAt: string;
29
+ [extra: string]: unknown;
30
+ }
31
+ /** An item with its field values, as `items.list` answers it. */
32
+ export interface ContentItem extends ContentItemRecord {
33
+ /**
34
+ * Field slug → value, stored verbatim: the keys are the merchant's own field slugs and a
35
+ * value's inner keys are whatever was written, so neither is ever case-converted. With a
36
+ * `languageCode`, a localizable field's value in that language where one is stored, else its
37
+ * base value; without one, base values only.
38
+ */
39
+ values: Record<string, unknown>;
40
+ }
41
+ /** An item's slug and URL path in one language other than the store's default. */
42
+ export interface ContentItemSlugTranslation {
43
+ slug: string;
44
+ path: string | null;
45
+ }
46
+ /** One item as `items.get` answers it. */
47
+ export interface ContentItemDetail extends ContentItem {
48
+ /** Language code → the item's translated slug and path, for each language that has one. */
49
+ slugTranslations: Record<string, ContentItemSlugTranslation>;
50
+ }
51
+ /** One item as `items.lookup` resolves it: enough to label a reference to it. */
52
+ export interface ContentItemSummary {
53
+ id: string;
54
+ slug: string | null;
55
+ /** One of {@link ContentItemStatus}. */
56
+ status: string;
57
+ /** The item's content type. */
58
+ collectionId: string;
59
+ collectionName: string;
60
+ collectionTitleFieldSlug: string | null;
61
+ /** The item's base title-field value when it is a string, else null. */
62
+ title: string | null;
63
+ [extra: string]: unknown;
64
+ }
65
+ /** One item as `items.lookupWithFields` resolves it. */
66
+ export interface ContentItemWithFields {
67
+ id: string;
68
+ title: string | null;
69
+ /**
70
+ * Base (unlocalized) values of the requested field slugs, stored verbatim; a slug with no
71
+ * stored value is absent.
72
+ */
73
+ fieldValues: Record<string, unknown>;
74
+ [extra: string]: unknown;
75
+ }
76
+ /** One named item's outcome in `items.bulkSetStatus`. */
77
+ export interface ContentItemStatusOutcome {
78
+ id: string;
79
+ /** `OK`, or `FAILED` (a string on the wire: read anything else as not done). */
80
+ status: 'OK' | 'FAILED' | (string & {});
81
+ /**
82
+ * When FAILED: `VALIDATION_ERROR` (publishing an item that leaves a required field empty, the
83
+ * refusal `publish` answers) or `NOT_FOUND` (no live item of the type in this store).
84
+ */
85
+ code: string | null;
86
+ /** When FAILED: the CMS's sentence; for an empty required field it names the fields. */
87
+ message: string | null;
88
+ }
89
+ /** What `items.bulkSetStatus` answers. */
90
+ export interface ContentItemBulkStatusResult {
91
+ /** How many items now have the status. */
92
+ updated: number;
93
+ /**
94
+ * One outcome per id named, in the order named, each id once. Null when the CMS answering
95
+ * predates per-item outcomes; such a CMS also publishes without the required-field check.
96
+ */
97
+ results: ContentItemStatusOutcome[] | null;
98
+ }
99
+ export interface ContentItemListOptions extends ListOptions {
100
+ /**
101
+ * Only items in this status. Honoured for a credential holding `ReadCmsContent` on the
102
+ * store; any other caller is served published items only, whatever it asks for.
103
+ */
104
+ status?: ContentItemStatus;
105
+ /** Only the children of this item; `null` for the top-level items. Ignored with `search`. */
106
+ parentId?: string | null;
107
+ /** Only the item with this exact slug. Ignored with `search`. */
108
+ slug?: string;
109
+ /**
110
+ * Full-text search over the items' values; its results come in relevance order. The CMS's
111
+ * search applies `status` but not `parentId`, `slug` or `sort`, which it then ignores.
112
+ */
113
+ search?: string;
114
+ /**
115
+ * `position` (or `-position`) orders by the items' own order; without it, newest first.
116
+ * Ignored with `search`.
117
+ */
118
+ sort?: 'position' | '-position';
119
+ /**
120
+ * Each localizable value in this language where one is stored, else the base value. Without
121
+ * one, base values only: the client's tenant `language` is NOT applied here, so a list read
122
+ * and an `update` that writes it back name the same rows.
123
+ */
124
+ languageCode?: string;
125
+ }
126
+ export interface GetContentItemOptions extends Call {
127
+ /** As on {@link ContentItemListOptions.languageCode}: base values when omitted. */
128
+ languageCode?: string;
129
+ }
130
+ /**
131
+ * Exactly what `CreateItemDto` whitelists (the CMS runs `forbidNonWhitelisted`, so a fetched
132
+ * item handed back is a 400). No index signature, so excess-property checking fires.
133
+ */
134
+ export interface CreateContentItemInput {
135
+ /**
136
+ * Lowercase letters, digits and hyphens. Without one, the slug is made from the type's title
137
+ * field value when the type has one.
138
+ */
139
+ slug?: string;
140
+ /** A parent item of the same type; only a hierarchical type takes one. */
141
+ parentId?: string | null;
142
+ position?: number;
143
+ /**
144
+ * Field slug → value for the type's top-level `item` fields, sent verbatim. A slug that is
145
+ * not one of them is refused and nothing is written.
146
+ */
147
+ values?: Record<string, unknown>;
148
+ /**
149
+ * The language `values` are written in: a localizable field's value goes to that language,
150
+ * every other field's to the base. Omit it for the base values (the store's default
151
+ * language); naming the default language explicitly writes a separate language row.
152
+ */
153
+ languageCode?: string;
154
+ }
155
+ /**
156
+ * The members `items.update` acts on, the same DTO as create. An absent key leaves the stored
157
+ * value alone, and `values` writes only the slugs it names.
158
+ */
159
+ export interface UpdateContentItemInput {
160
+ /**
161
+ * The base slug; moves the item's path and every descendant's. With a non-default
162
+ * `languageCode`, the slug of that language instead. `null` clears the base slug (the item
163
+ * then has no URL).
164
+ */
165
+ slug?: string | null;
166
+ /** Moves the item under another parent of the same type; `null` to the top level. */
167
+ parentId?: string | null;
168
+ position?: number;
169
+ values?: Record<string, unknown>;
170
+ languageCode?: string;
171
+ }
172
+ /**
173
+ * The entries of a content type, read and written through the CMS.
174
+ *
175
+ * Reads need no permission, but what they answer depends on the credential: drafts and archived
176
+ * items are served only to a holder of `ReadCmsContent` on the store, and everyone else reads
177
+ * published items alone (`items.get` of an unpublished item is then `NotFoundError`). Writes
178
+ * need the permission each method names (`@permission`).
179
+ *
180
+ * Refusals are the CMS's problem+json, mapped by status:
181
+ * - `NotFoundError` (404, `NOT_FOUND`): no such type or item in this store.
182
+ * - `ConflictError` (409, `CONFLICT`): the slug or the URL path is taken, or a singleton type
183
+ * already has its item.
184
+ * - `ValidationError` (400): `VALIDATION_FAILED` with one `details[]` entry per refused input
185
+ * member; `VALIDATION_ERROR` for what the CMS refuses on its own (a value for no field, a
186
+ * parent on a type that is not hierarchical, a slug reserved by the storefront, publishing an
187
+ * item with a required field empty, deleting an item that has children).
188
+ * - `PermissionDeniedError` (403): the credential lacks the write's permission.
189
+ *
190
+ * The CMS records the platform events (`content.published`, `content.updated`,
191
+ * `content.unpublished`) itself; nothing here emits one. No write here is deduplicated: an
192
+ * `idempotencyKey` is sent and acts on nothing, so a repeated `create` is a second item.
193
+ */
194
+ export interface ContentItemsModule {
195
+ /**
196
+ * The type's items, a page at a time, newest first unless `sort` says otherwise. Pages are
197
+ * offset-based (`Page.total` counts the matches), so `after: offsetCursor((n - 1) * size)`
198
+ * opens page `n`, and an item written while a walk runs can be seen twice or not at all.
199
+ *
200
+ * @effect read
201
+ */
202
+ list(typeId: string, options?: ContentItemListOptions): Promise<Page<ContentItem>>;
203
+ /**
204
+ * One item with its values and its translated slugs.
205
+ *
206
+ * @effect read
207
+ */
208
+ get(typeId: string, itemId: string, options?: GetContentItemOptions): Promise<ContentItemDetail>;
209
+ /**
210
+ * Adds an item as a draft. Answers its row; read its values back with `get`.
211
+ *
212
+ * @effect write
213
+ * @permission CreateCmsContent
214
+ */
215
+ create(typeId: string, input: CreateContentItemInput, options?: Call): Promise<ContentItemRecord>;
216
+ /**
217
+ * Writes what the input names in one transaction. Answers the item's row; read its values
218
+ * back with `get`.
219
+ *
220
+ * @effect write
221
+ * @permission UpdateCmsContent
222
+ */
223
+ update(typeId: string, itemId: string, input: UpdateContentItemInput, options?: Call): Promise<ContentItemRecord>;
224
+ /**
225
+ * Removes the item: it leaves the storefront and its URL is freed, and nothing in the SDK
226
+ * brings it back. An item that still has children is refused (`ValidationError`).
227
+ *
228
+ * @effect destructive
229
+ * @permission DeleteCmsContent
230
+ */
231
+ delete(typeId: string, itemId: string, options?: Call): Promise<void>;
232
+ /**
233
+ * Puts the item on the storefront. Refused (`ValidationError`, naming the fields) while a
234
+ * required field is empty.
235
+ *
236
+ * @effect write
237
+ * @permission UpdateCmsContent
238
+ */
239
+ publish(typeId: string, itemId: string, options?: Call): Promise<ContentItemRecord>;
240
+ /**
241
+ * Takes the item off the storefront; it becomes a draft.
242
+ *
243
+ * @effect write
244
+ * @permission UpdateCmsContent
245
+ */
246
+ unpublish(typeId: string, itemId: string, options?: Call): Promise<ContentItemRecord>;
247
+ /**
248
+ * Sets one status on several items of the type in one transaction, and reports each item on its
249
+ * own (`results`). Publishing refuses an item that leaves a required field empty, as `publish`
250
+ * does: that item keeps its status (`FAILED`, `VALIDATION_ERROR`) and the others still change.
251
+ * An id that is not a live item of this type in this store changes nothing (`NOT_FOUND`). The
252
+ * call itself fails only for the whole selection (an unknown type, a malformed id or status).
253
+ *
254
+ * @effect write
255
+ * @permission UpdateCmsContent
256
+ */
257
+ bulkSetStatus(typeId: string, itemIds: readonly string[], status: ContentItemStatus, options?: Call): Promise<ContentItemBulkStatusResult>;
258
+ /**
259
+ * Removes several items of the type in one transaction, and answers how many it removed. An
260
+ * id that is not a live item of this type is skipped; a selected item whose child is not
261
+ * selected too refuses the whole call (`ValidationError`) and removes nothing.
262
+ *
263
+ * @effect destructive
264
+ * @permission DeleteCmsContent
265
+ */
266
+ bulkDelete(typeId: string, itemIds: readonly string[], options?: Call): Promise<{
267
+ deleted: number;
268
+ }>;
269
+ /**
270
+ * Resolves item ids of ANY content type of the store to a label: what a content reference
271
+ * field, a menu entry or a product property stores. Any number of ids; the SDK splits them
272
+ * into the CMS's batches of 50. Answers the ids that resolved, in the order given, each once:
273
+ * an unknown id, another store's, or one the credential may not see is absent, never an
274
+ * error. An id that is not a UUID is absent too (a CMS before 2026-10-14 refused the whole batch
275
+ * with it, `ValidationError` `INVALID_DATA`).
276
+ *
277
+ * Every status for a holder of `ReadCmsContent`, `UpdateCatalog` or `UpdateProduct` on the
278
+ * store (a catalog writer resolves a draft its product references); published items only for
279
+ * everyone else.
280
+ *
281
+ * @effect read
282
+ */
283
+ lookup(ids: readonly string[], options?: Call): Promise<ContentItemSummary[]>;
284
+ /**
285
+ * As `lookup`, with the base values of the named field slugs. With no ids or no slugs it
286
+ * answers `[]` without a request.
287
+ *
288
+ * @effect read
289
+ */
290
+ lookupWithFields(ids: readonly string[], fieldSlugs: readonly string[], options?: Call): Promise<ContentItemWithFields[]>;
291
+ }
292
+ export declare function createContentItemsModule(transport: Transport): ContentItemsModule;
@@ -0,0 +1,170 @@
1
+ import { createPage, offsetCursor, PLATFORM_PASSTHROUGH_KEYS, readOffsetCursor, } from '@sixtyninecommerce/core';
2
+ const DEFAULT_PAGE_SIZE = 50;
3
+ /**
4
+ * `GET /items/lookup*` refuses more ids than this (`ITEM_LOOKUP_MAX_IDS` in the CMS's
5
+ * `collections.controller.ts`): it once sliced to 50 and dropped the rest without a word.
6
+ */
7
+ const LOOKUP_BATCH_SIZE = 50;
8
+ /**
9
+ * Item `values` are keyed by the merchant's field slugs (`hero_2_image` camelised is
10
+ * `hero2Image`, and back is `hero2_image`), in both directions. `slug_translations` is keyed by
11
+ * language code. `values` cannot join the platform set: content strings use the name for a DTO
12
+ * array.
13
+ */
14
+ const ITEM_PASSTHROUGH = new Set([
15
+ ...PLATFORM_PASSTHROUGH_KEYS,
16
+ 'values',
17
+ 'slug_translations',
18
+ ]);
19
+ function itemsPath(typeId) {
20
+ return `/collections/${encodeURIComponent(typeId)}/items`;
21
+ }
22
+ function itemPath(typeId, itemId) {
23
+ return `${itemsPath(typeId)}/${encodeURIComponent(itemId)}`;
24
+ }
25
+ function isRecord(value) {
26
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
27
+ }
28
+ /**
29
+ * A write answers the item ENTITY: `values` there is the stored value rows (with each row's
30
+ * field), not the slug-keyed map a read answers, and `slugTranslations` the translation rows.
31
+ * Neither is the read shape, so neither is passed on.
32
+ */
33
+ function toRecord(item) {
34
+ const { values: _rows, slugTranslations: _translations, ...record } = item;
35
+ return record;
36
+ }
37
+ /**
38
+ * The item read sends both the translation rows (`slugTranslations`) and the same data keyed by
39
+ * language (`slug_translations`); camelised, the two land on ONE key and the later one wins.
40
+ * Today that is the map; a row array (the CMS reordering its answer) is folded into one.
41
+ */
42
+ function slugTranslationMap(value) {
43
+ if (!Array.isArray(value))
44
+ return isRecord(value) ? value : {};
45
+ const map = {};
46
+ for (const row of value) {
47
+ if (isRecord(row) && typeof row.languageCode === 'string' && typeof row.slug === 'string') {
48
+ map[row.languageCode] = {
49
+ slug: row.slug,
50
+ path: typeof row.path === 'string' ? row.path : null,
51
+ };
52
+ }
53
+ }
54
+ return map;
55
+ }
56
+ function batched(items, size) {
57
+ const out = [];
58
+ for (let i = 0; i < items.length; i += size)
59
+ out.push(items.slice(i, i + size));
60
+ return out;
61
+ }
62
+ /** The CMS answers a lookup in no guaranteed order; give it back in the caller's. */
63
+ function inOrderOf(ids, found) {
64
+ const byId = new Map(found.map((item) => [item.id, item]));
65
+ return ids.flatMap((id) => {
66
+ const item = byId.get(id);
67
+ return item === undefined ? [] : [item];
68
+ });
69
+ }
70
+ export function createContentItemsModule(transport) {
71
+ async function listPage(typeId, offset, limit, options) {
72
+ const body = await transport.rest('cms', {
73
+ method: 'GET',
74
+ path: itemsPath(typeId),
75
+ query: {
76
+ // `offset` is always sent: it keeps the CMS out of its keyset mode, which can resume
77
+ // neither `sort` nor `search` and cannot open page n. Without `limit` an offset read
78
+ // answers the WHOLE list.
79
+ limit,
80
+ offset,
81
+ status: options?.status,
82
+ parent_id: options?.parentId === null ? 'root' : options?.parentId,
83
+ slug: options?.slug,
84
+ search: options?.search,
85
+ sort: options?.sort,
86
+ // Always sent, empty for the base values: the transport adds the tenant's `language`
87
+ // to any read that names none, and a write never gets it.
88
+ language_code: options?.languageCode ?? '',
89
+ },
90
+ }, { ...options, preserveKeys: ITEM_PASSTHROUGH });
91
+ const items = body.data ?? [];
92
+ // An offset read echoes neither the offset nor a cursor, so the page is built from what
93
+ // THIS call asked for.
94
+ const total = body.pagination?.total ?? items.length;
95
+ const advanced = offset + (items.length > 0 ? items.length : limit);
96
+ const hasNext = advanced < total;
97
+ return createPage(items, { nextCursor: hasNext ? offsetCursor(advanced) : null, hasNext, total }, (cursor) => listPage(typeId, readOffsetCursor(cursor), limit, options));
98
+ }
99
+ async function writeItem(method, path, body, options) {
100
+ const answer = await transport.rest('cms', { method, path, ...(body === undefined ? {} : { body }) }, { ...options, preserveKeys: ITEM_PASSTHROUGH });
101
+ return toRecord(answer.data);
102
+ }
103
+ return {
104
+ list(typeId, options) {
105
+ const limit = options?.limit ?? DEFAULT_PAGE_SIZE;
106
+ const offset = options?.after === undefined ? 0 : readOffsetCursor(options.after);
107
+ return listPage(typeId, offset, limit, options);
108
+ },
109
+ async get(typeId, itemId, options) {
110
+ const body = await transport.rest('cms', {
111
+ method: 'GET',
112
+ path: itemPath(typeId, itemId),
113
+ query: { language_code: options?.languageCode ?? '' },
114
+ }, { ...options, preserveKeys: ITEM_PASSTHROUGH });
115
+ return {
116
+ ...body.data,
117
+ slugTranslations: slugTranslationMap(body.data.slugTranslations),
118
+ };
119
+ },
120
+ create(typeId, input, options) {
121
+ return writeItem('POST', itemsPath(typeId), input, options);
122
+ },
123
+ update(typeId, itemId, input, options) {
124
+ return writeItem('PATCH', itemPath(typeId, itemId), input, options);
125
+ },
126
+ async delete(typeId, itemId, options) {
127
+ await transport.rest('cms', { method: 'DELETE', path: itemPath(typeId, itemId), expect: 'void' }, options);
128
+ },
129
+ publish(typeId, itemId, options) {
130
+ return writeItem('POST', `${itemPath(typeId, itemId)}/publish`, undefined, options);
131
+ },
132
+ unpublish(typeId, itemId, options) {
133
+ return writeItem('POST', `${itemPath(typeId, itemId)}/unpublish`, undefined, options);
134
+ },
135
+ async bulkSetStatus(typeId, itemIds, status, options) {
136
+ const body = await transport.rest('cms', {
137
+ method: 'POST',
138
+ path: `${itemsPath(typeId)}/bulk-status`,
139
+ body: { itemIds: [...itemIds], status },
140
+ }, options);
141
+ return { updated: body.data.updated, results: body.data.results ?? null };
142
+ },
143
+ async bulkDelete(typeId, itemIds, options) {
144
+ const body = await transport.rest('cms', {
145
+ method: 'POST',
146
+ path: `${itemsPath(typeId)}/bulk-delete`,
147
+ body: { itemIds: [...itemIds] },
148
+ }, options);
149
+ return { deleted: body.data.deleted };
150
+ },
151
+ async lookup(ids, options) {
152
+ const unique = [...new Set(ids)];
153
+ if (unique.length === 0)
154
+ return [];
155
+ const pages = await Promise.all(batched(unique, LOOKUP_BATCH_SIZE).map((batch) => transport.rest('cms', { method: 'GET', path: '/items/lookup', query: { ids: batch.join(',') } }, options)));
156
+ return inOrderOf(unique, pages.flatMap((page) => page.data));
157
+ },
158
+ async lookupWithFields(ids, fieldSlugs, options) {
159
+ const unique = [...new Set(ids)];
160
+ if (unique.length === 0 || fieldSlugs.length === 0)
161
+ return [];
162
+ const pages = await Promise.all(batched(unique, LOOKUP_BATCH_SIZE).map((batch) => transport.rest('cms', {
163
+ method: 'GET',
164
+ path: '/items/lookup-with-fields',
165
+ query: { ids: batch.join(','), field_slugs: fieldSlugs.join(',') },
166
+ }, { ...options, preserveKeys: PLATFORM_PASSTHROUGH_KEYS })));
167
+ return inOrderOf(unique, pages.flatMap((page) => page.data));
168
+ },
169
+ };
170
+ }