{"_id":"@afosto/cms-client","_rev":"2-fa74e1e89a0ba2bbfe890ac06bb2517c","name":"@afosto/cms-client","dist-tags":{"latest":"0.0.2"},"versions":{"0.0.1":{"name":"@afosto/cms-client","version":"0.0.1","license":"MIT","_id":"@afosto/cms-client@0.0.1","maintainers":[{"name":"rapid0o","email":"gertjan@afosto.io"},{"name":"gijsbotje","email":"gijs@afosto.io"},{"name":"robinstikfort","email":"robin@afosto.com"}],"dist":{"shasum":"48be44dc5f426dde77c54fadaa5e7f4cda7cca41","tarball":"https://registry.npmjs.org/@afosto/cms-client/-/cms-client-0.0.1.tgz","fileCount":47,"integrity":"sha512-IJxEzsXMUqWoEcvIEt2yDhY8kp6bi8EDF424vxfot1OoLwJmf/XOQuGuNk0c5MiBrBiFWMM0ivibG37CY9AUvg==","signatures":[{"sig":"MEQCIGVDEfhUiUEWve5oxQHBfoYzbQQwgE2VoCL3qqSmN7o7AiAcNc3fOIvGcJU0iXBAa4ZeS0f1m9/Jcfh1RTF8+DPJjg==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":55084},"main":"./dist/index.js","type":"module","_from":"file:afosto-cms-client-0.0.1.tgz","types":"./dist/index.d.ts","module":"./dist/index.js","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js","@org/source":"./src/index.ts"},"./package.json":"./package.json"},"_npmUser":{"name":"gijsbotje","email":"gijs@afosto.io"},"_resolved":"/private/var/folders/g0/7yzptd0d7cz7fnhc5322fq040000gn/T/1c07fee384664dcde8f2e9ba3729b8bc/afosto-cms-client-0.0.1.tgz","_integrity":"sha512-IJxEzsXMUqWoEcvIEt2yDhY8kp6bi8EDF424vxfot1OoLwJmf/XOQuGuNk0c5MiBrBiFWMM0ivibG37CY9AUvg==","_npmVersion":"10.9.2","description":"Framework-agnostic Afosto Storefront API client with TypeScript types and formatter utilities. Used as the foundation for `@afosto/react` and `@afosto/vue`, but can also be used standalone for custom integrations.","directories":{},"sideEffects":false,"_nodeVersion":"22.17.1","dependencies":{},"publishConfig":{"access":"public"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/cms-client_0.0.1_1779918447281_0.04937361319041478","host":"s3://npm-registry-packages-npm-production"}},"0.0.2":{"name":"@afosto/cms-client","version":"0.0.2","type":"module","license":"MIT","sideEffects":false,"main":"./src/index.ts","module":"./src/index.ts","types":"./src/index.ts","exports":{"./package.json":"./package.json",".":{"types":"./src/index.ts","import":"./src/index.ts","default":"./src/index.ts"}},"publishConfig":{"access":"public","main":"./dist/index.js","module":"./dist/index.js","types":"./dist/index.d.ts","exports":{"./package.json":"./package.json",".":{"types":"./dist/index.d.ts","import":"./dist/index.js","default":"./dist/index.js"}}},"dependencies":{},"_id":"@afosto/cms-client@0.0.2","gitHead":"a6f218b268aef2009ea4bcd21d483b3bb063de33","description":"Framework-agnostic Afosto Storefront API client with TypeScript types and formatter utilities. Used as the foundation for `@afosto/react` and `@afosto/vue`, but can also be used standalone for custom integrations.","_nodeVersion":"22.22.2","_npmVersion":"10.9.7","dist":{"integrity":"sha512-JisuY3ABhTMyZulJqXT3Vd7o1JOMJ/av/RB6zsOBJVzk0okzDazkUgDxvmRk9XQZEOcD3ERbgAhMcIbkdGPqyw==","shasum":"0e049844f2c29547db63da0163948677dd58a148","tarball":"https://registry.npmjs.org/@afosto/cms-client/-/cms-client-0.0.2.tgz","fileCount":69,"unpackedSize":92653,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQDpBbQvK2Azg4gq1A1wStpmp2b0AgqQYhKDf582Yb2KdQIgCXCmIkBqTYm2QZnGc6VS6dWOd9Y2wlSl1HH9RaID30g="}]},"_npmUser":{"name":"gijsbotje","email":"gijs@afosto.io"},"directories":{},"maintainers":[{"name":"rapid0o","email":"gertjan@afosto.io"},{"name":"gijsbotje","email":"gijs@afosto.io"},{"name":"robinstikfort","email":"robin@afosto.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/cms-client_0.0.2_1781103356040_0.09076097323887611"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-27T21:47:27.175Z","modified":"2026-06-10T14:55:56.374Z","0.0.1":"2026-05-27T21:47:27.469Z","0.0.2":"2026-06-10T14:55:56.179Z"},"license":"MIT","description":"Framework-agnostic Afosto Storefront API client with TypeScript types and formatter utilities. Used as the foundation for `@afosto/react` and `@afosto/vue`, but can also be used standalone for custom integrations.","maintainers":[{"name":"rapid0o","email":"gertjan@afosto.io"},{"name":"gijsbotje","email":"gijs@afosto.io"},{"name":"robinstikfort","email":"robin@afosto.com"}],"readme":"# @afosto/cms-client\n\nFramework-agnostic Afosto Storefront API client with TypeScript types and formatter utilities. Used as the foundation for `@afosto/react` and `@afosto/vue`, but can also be used standalone for custom integrations.\n\n## Installation\n\n```bash\nnpm install @afosto/cms-client\n# or\npnpm add @afosto/cms-client\n```\n\n## Quick start\n\n```ts\nimport { createClient } from '@afosto/cms-client';\n\nconst client = createClient('https://storefront.afosto.net');\n\n// Fetch a collection page\nconst page = await client.getPage('/heren/');\n\nif (page.type === 'collection') {\n  console.log(page.content.products); // ProductObject[]\n  console.log(page.filters); // Record<string, FormattedFilter>\n}\n\n// Fetch a product page\nconst product = await client.getPage('/heren/t-shirt-wit');\n\nif (product.type === 'product') {\n  console.log(product.content.price); // \"€29,95\"\n  console.log(product.content.attributes); // Record<string, Attribute>\n}\n```\n\n## API client\n\n### `createClient(baseURL)`\n\nCreates a fetch client configured for the Afosto Storefront API.\n\n- Sends `Content-Type: application/json` on every request\n- Automatically retries once on HTTP 429 (rate limit) with a 5–10 s delay\n- Returns a `FormattedPage` — all `Record<string, T>` fields already converted to arrays\n\n```ts\nconst client = createClient('https://storefront.afosto.net');\n```\n\n### `client.getPage(slug, params?, options?)`\n\nFetches any Afosto page by slug. Active filters are passed as query params.\n\n```ts\n// Collection with filters applied\nconst page = await client.getPage('/heren/', { kleur: 'wit', maat: 'M' });\n\n// Second page\nconst page = await client.getPage('/heren/', { page: '2' });\n```\n\nThe `page.type` field identifies the page:\n\n| `type`                              | What it contains                                                                      |\n| ----------------------------------- | ------------------------------------------------------------------------------------- |\n| `'collection'`                      | `content.products`, `content.filters`, `content.active_filters`, `content.pagination` |\n| `'product'`                         | `content.attributes` (variants), `content.price`, `content.specifications`            |\n| `'page'`                            | Static content blocks                                                                 |\n| `'cart'` / `'checkout'` / `'login'` | —                                                                                     |\n\n## Formatters\n\nThe Afosto API returns many fields as `Record<string, T>` keyed by an internal key rather than arrays. The formatters convert these to arrays so you never have to call `Object.values()` yourself.\n\n`client.getPage()` already applies all formatters. They are also exported individually if you are working with the raw API response.\n\n```ts\nimport {\n  formatPage,\n  formatFilters,\n  formatActiveFilters,\n  formatPagination,\n  formatSort,\n  formatMenus,\n  formatBreadcrumbs,\n  formatPrice,\n} from '@afosto/cms-client';\n```\n\n| Formatter                         | Converts                                                                                            |\n| --------------------------------- | --------------------------------------------------------------------------------------------------- |\n| `formatPage(page)`                | Orchestrates all formatters on the full `Page` response                                             |\n| `formatFilters(filters, locale?)` | `Record<string, Filter>` → `Record<string, FormattedFilter>` (attributes as array, locale-filtered) |\n| `formatActiveFilters(filters)`    | `Record<string, ActiveFilter>` → `Record<string, FormattedActiveFilter>`                            |\n| `formatPagination(pagination)`    | Adds `.page` (current page number) and `.itemsPerPage` helper                                       |\n| `formatSort(sort)`                | `sort.options` from `Record` to `SortOption[]`                                                      |\n| `formatMenus(menus)`              | Recursively converts `menu.items` from `Record` to `MenuItem[]`                                     |\n\n## Logic utilities\n\nPure helper functions for building filter and variant UIs on top of the API data.\n\n### Filters\n\n```ts\nimport {\n  filterReducer,\n  extractParamsFromLink,\n  buildFilterParams,\n  isFilterActive,\n} from '@afosto/cms-client';\n\n// Manage active filter state\nconst next = filterReducer(activeFilters, {\n  type: 'TOGGLE',\n  filterId: 'kleur',\n  value: 'wit',\n});\nconst reset = filterReducer(activeFilters, { type: 'RESET' });\n\n// Extract query params from a filter attribute's link URL (for re-fetching)\nconst params = extractParamsFromLink(filterAttribute.link);\n// → { kleur: 'wit', maat: 'M' }\n\n// Build query params from local state\nconst params = buildFilterParams(activeFilters);\n```\n\n### Quantity\n\n```ts\nimport {\n  clampQuantity,\n  validateQuantity,\n  incrementQuantity,\n  decrementQuantity,\n} from '@afosto/cms-client';\n\nclampQuantity(0, { min: 1, max: 99 }); // → 1\nclampQuantity(7, { min: 0, max: 100, step: 5 }); // → 5 (rounds to nearest step)\nvalidateQuantity(5, { min: 1, max: 99, step: 1 }); // → true\nincrementQuantity(3, { min: 1, max: 10, step: 2 }); // → 5\ndecrementQuantity(5, { min: 1, max: 10, step: 2 }); // → 3\n```\n\n### Variants\n\n```ts\nimport {\n  formatAttributes,\n  getAvailableOptions,\n  findOptionByKeys,\n} from '@afosto/cms-client';\n\n// Convert Record<string, Attribute> to FormattedAttribute[]\nconst attributes = formatAttributes(product.content.attributes);\n\n// Filter to only available options\nconst available = getAvailableOptions(attributes);\n\n// Find the selected option by key map\nconst selected = findOptionByKeys(attributes, { kleur: 'wit', maat: 'M' });\n```\n\n## TypeScript types\n\n```ts\nimport type {\n  Page,\n  FormattedPage,\n  PageType,\n  ProductObject,\n  Filter,\n  FormattedFilter,\n  FilterAttribute,\n  ActiveFilter,\n  FormattedActiveFilter,\n  Attribute,\n  FormattedAttribute,\n  AttributeOption,\n  Pagination,\n  FormattedPagination,\n  Sort,\n  FormattedSort,\n  SortOption,\n  Menu,\n  FormattedMenu,\n  MenuItem,\n  Breadcrumb,\n  Image,\n  ShopProperties,\n  Inventory,\n  Specification,\n  TextBlock,\n  Slider,\n} from '@afosto/cms-client';\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}