Javascript SDK for accessing XMan I/O data
- Sign-up and create a workspace at https://xman.io
- Create and publish some content
- Create an API Client Key in Xman I/O a. Make sure you add localhost to allowed hosts, if you are doing development on localhost b. Secret key is required for SSR and Static Generation (Nuxt, NextJS, Gatsby, etc.)
- Generate and copy Types for your API. Paste these types in xman.d.ts file in your project and add "xman.d.ts" entry to your tsconfig.json > "include" section. This will provide IntelliSense in the IDE/editor you are using.
With globally distributed Cloudflare CDN, we have sub-second response times for content queries. Static generation is not recommended.
Server side rendering (SSR) could be used for better SEO.
Examples coming soon...
# Add XMan SDK to your project
yarn add @xman.io/xman-js-sdk
Or
npm install --save @xman.io/xman-js-sdk
Then
import { getWorkspace } from '@xman.io/xman-js-sdk'
// Workspace can be a global variable
// Default stage is 'live'
const workspace = getWorkspace('api-client-id', 'workspace-id')
// You can pass a stage name to get a different stage
const workspace = getWorkspace('api-client-id', 'workspace-id', 'pre-production')
// or
const workspace = getWorkspace('api-client-id', 'workspace-id')
.stage('pre-production')
For server side access pass the the secret key. Make sure the key does not leak to the client.
This step also applies to frameworks that do server side rendering or static page generation, such as: Nuxt, NextJS, Gatsby, etc.
let workspace = getWorkspace('api-client-id', 'workspace-id')
.secret('api-secret-key')
Get data from XMan I/O
Use XMan SDK to read collections and items
// Get a list of items
const itemsList = await workspace.list<T>('collection-id', optionalListParams)
// returns
interface XmanItemsList<T> {
items: XmanItem<T>[],
nextPageToken?: string
}
// Where
interface XmanItem<T> {
id: string
data: T,
createTime: string,
updateTime: string,
version: number
}
// E.g.
const articleList = await workspace.list<Article>('xman-article')
// articleList.should.be.an('object')
// articleList.items.should.be.an('array')
// Get one item
const item = await workspace.read<T>('collection-id', 'item-id')
// item.should.have.keys('id', 'data', 'version', 'updateTime', 'createTime')
const item = await workspace.read<PropertyDevelopment>('xman-property-development', '0123456789abcdefghIJ')
// item.should.be.an('object')
// item.should.have.keys('id', 'data', 'version', 'updateTime', 'createTime')
Would return an item or null
:
{
"id": "0123456789abcdefghIJ",
"data": {
"coverImage": [{
"collection": "xman-assets-image-set",
"id": "image-id"
}],
"about": "Centrally located ...",
"description": "Perfectly positioned ...",
"imageGallery": [
{
"collection": "xman-assets-image-set",
"id": "image-id"
},
{
"collection": "xman-assets-image-set",
"id": "image-id"
}
],
"communitiesAround": [{"collection": "xman-property-development", "id": "another-property-id"}]
},
"version": 2,
"createTime": "2019-10-31T13:44:13.625Z",
"updateTime": "2020-04-02T22:09:40.874Z"
}
Result Field | type | description |
---|---|---|
id | string |
XMan I/O item id |
item.data | Object |
Properties managed in XMan I/O. References to Items and Images get special types with helper methods |
createTime | string |
Timestamp when the item was first published to this stage |
updateTime | string |
Timestamp when the item was most recently published to this stage |
interface ListParams {
/** in page size. Default 12. Max 24. */
pageSize?: number,
/** the `nextPageToken` returned by the previous `list()` call. */
nextPage?: string,
/** property path to order by, followed by direction. E.g. `name asc` */
orderBy?: string
}
interface XmanItemsList<T> {
items: XmanItem<T>[],
nextPageToken?: string
}
list<T> (collection: string, listParams?: ListParams): Promise<XmanItemsList<T>>;
workspace.list
function
Input | type | required | description |
---|---|---|---|
collection name | String |
Yes | |
listParams | Object |
No | Sorting and Paging parameters |
listParams.pageSize | Number |
No | Default: 12, Max: 24 |
listParams.orderBy | String |
No | Data property name, followed by blank space and desc or asc. Default: updateTime desc |
listParams.pageToken | String |
If Paging | Token returned by the previous list() call in nextPageToken field |
Would return an array of items. Array can be empty, but never undefined
or null
Result Field | type | Can be undefined | description |
---|---|---|---|
nextPageToken | String |
Yes | If there are more pages, This token can be passed to the next list() call |
items | Array<Item> |
No | List of items |
{
"items": [
{
"id": "0123456789abcdefghIJ",
"data": {
"coverImage": { "collection": "xman-assets-image-set", "id": "image-id" },
"about": "Centrally located ...",
"description": "Perfectly positioned ...",
"imageGallery": { "collection": "xman-assets-image-set", "id": "image-id" },
"communitiesAround": [{"collection": "xman-property-development", "id": "another-property-id"}]
},
"version": 2,
"createTime": "2019-10-31T13:44:13.625Z",
"updateTime": "2020-04-02T22:09:40.874Z"
},
{
"id": "z9y8x7w6v5u4t3s2r1q0",
"data": {
"coverImage": { "collection": "xman-assets-image-set", "id": "image-id" },
"about": "Centrally located ...",
"description": "Perfectly positioned ...",
"imageGallery": { "collection": "xman-assets-image-set", "id": "image-id" },
"communitiesAround": []
},
"version": 1,
"createTime": "2019-10-31T13:52:57.109Z",
"updateTime": "2019-10-31T17:46:37.373Z"
}
],
"nextPageToken": "loooooooooo...ooonnnnng...string"
}
An item may reference other items. E.g. An Article may reference an Author. In the above example, property developments are referencing Images (coverImage, imageGallery) and other property developments (communitiesAround)
We can get referenced objects by calling getReferencedItem()
for single (first) item or getReferencedItems()
for all items
const propertyDevelopment = await workspace.read<PropertyDevelopment>('xman-property-development', '0123456789abcdefghIJ')
const nearbyCommunities = await workspace.getReferencedItems<PropertyDevelopment>(propertyDevelopment?.data.communitiesAround)
// nearbyCommunities.should.be.an('array')
XMan.io comes with an Image Delivery Service backed by globally distributed Content Delivery Network (CDN). You can use this service to dynamically render images in specific sizes.
We use the Sharp Library for image operations. In the future releases we will support more image manipulation options supported by the Sharp Library
You can get alt text and the CDN URLs for image variations with specific settings (width
and height
) by calling workspace.getImage
for a single (first) image or workspace.getImages
for a set of images. The results can be used in a <picture>
tag or an <img>
tag.
Example:
const propertyDevelopment = await workspace.read('xman-property-development', '0123456789abcdefghIJ')
// Single image; no cropping
const coverImage = await workspace.getImage(propertyDevelopment.coverImage)
// When no settings are passed, the default variation is named 'main'
// Render <img src='${coverImage.variations.main?.src}' alt='${coverImage.alt}'>
// Single image
const coverImage = await workspace.getImage(propertyDevelopment.coverImage, [{key: 'default', width: 1266, height: 713}])
// Render <img src='${coverImage.variations.default?.src}' alt='${coverImage.alt}'>
// Single image, many responsive variations
const variations: ImageSettings[] = [
{ key: 'default', width: 500 },
{ key: 'medium', width: 750, fit: 'cover' },
{ key: 'full' }
]
const coverImage = await workspace.getImage(propertyDevelopment.coverImage, variations)
// Render:
// <picture>
// <source srcset="${coverImage.full.src}" media="(min-width: 800px)" />
// <source srcset="${coverImage.medium.src}" media="(min-width: 550px)" />
// <img src="${coverImage.default.src}" alt="${coverImage.alt}" />
// </picture>
// Set of Images, with responsive variations
const galleryImages = await workspace.getImages(propertyDevelopment.imageGallery, variations)
galleryImages.forEach(img => {
// <picture>
// <source srcset="${img.full.src}" media="(min-width: 800px)" />
// <source srcset="${img.medium.src}" media="(min-width: 550px)" />
// <img src="${img.default.src}" alt="${img.alt}" />
// </picture>
})
If you specify either width
or height
(but not both), the aspect ratio is maintained and the original image is scaled. The image is never scaled up beyond the original width and height. We may do this in later releases.
If you specify both width
and height
, the original image is focus cropped (if needed) and resized to fit in the box. Focus is set on the region with the highest Shannon Entropy (aka "art direction").
For example:
With only { height: 200 }
With { width: 120, height: 200}
Credit: Photo by Eye for Ebony on Unsplash
You can also choose the focus point manually in XMan.io.
Image service always delivers images in progressive JPEG format (image/jpeg
)