Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat: Add all & getAll methods to AppsRegistryCollection #1387

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 39 additions & 0 deletions docs/api/cozy-stack-client.md
Original file line number Diff line number Diff line change
Expand Up @@ -276,6 +276,45 @@ The returned documents are not paginated by the stack.
Extends `DocumentCollection` API along with specific methods for `io.cozy.apps_registry`.

**Kind**: global class

* [AppsRegistryCollection](#AppsRegistryCollection)
* [.all([option])](#AppsRegistryCollection+all) ⇒ <code>Promise.&lt;{data, meta, skip, next}&gt;</code>
* [.getAll(slugs)](#AppsRegistryCollection+getAll) ⇒ <code>Promise.&lt;{data, meta, skip, next}&gt;</code>
* [.get(slug)](#AppsRegistryCollection+get) ⇒ <code>Promise.&lt;{data: object}&gt;</code>

<a name="AppsRegistryCollection+all"></a>

### appsRegistryCollection.all([option]) ⇒ <code>Promise.&lt;{data, meta, skip, next}&gt;</code>
Fetches all apps from the registry.

**Kind**: instance method of [<code>AppsRegistryCollection</code>](#AppsRegistryCollection)
**Returns**: <code>Promise.&lt;{data, meta, skip, next}&gt;</code> - The JSON API conformant response.
**Throws**:

- <code>FetchError</code>


| Param | Type | Description |
| --- | --- | --- |
| [option] | <code>object</code> | The fetch option |
| [option.limit] | <code>number</code> | Limit of apps to fetch |

<a name="AppsRegistryCollection+getAll"></a>

### appsRegistryCollection.getAll(slugs) ⇒ <code>Promise.&lt;{data, meta, skip, next}&gt;</code>
Fetches many apps from the registry by ids.

**Kind**: instance method of [<code>AppsRegistryCollection</code>](#AppsRegistryCollection)
**Returns**: <code>Promise.&lt;{data, meta, skip, next}&gt;</code> - The JSON API conformant response.
**Throws**:

- <code>FetchError</code>


| Param | Type | Description |
| --- | --- | --- |
| slugs | <code>Array.&lt;string&gt;</code> | The slugs of the apps to fetch |

<a name="AppsRegistryCollection+get"></a>

### appsRegistryCollection.get(slug) ⇒ <code>Promise.&lt;{data: object}&gt;</code>
Expand Down
68 changes: 68 additions & 0 deletions packages/cozy-stack-client/src/AppsRegistryCollection.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { transformRegistryFormatToStackFormat } from 'cozy-client/dist/registry'

import DocumentCollection, { normalizeDoc } from './DocumentCollection'
import { FetchError } from './errors'
import { dontThrowNotFoundError } from './Collection'

export const APPS_REGISTRY_DOCTYPE = 'io.cozy.apps_registry'

Expand All @@ -20,6 +21,73 @@ class AppsRegistryCollection extends DocumentCollection {
this.endpoint = '/registry/'
}

/**
* Fetches all apps from the registry.
*
* @param {object} [option] - The fetch option
* @param {number} [option.limit] - Limit of apps to fetch
* @returns {Promise<{data, meta, skip, next}>} The JSON API conformant response.
* @throws {FetchError}
*/
async all({ limit = 1000 } = {}) {
const resp = await this.stackClient.fetchJSON(
'GET',
`${this.endpoint}?limit=${limit}`
)
const dataNormalized = resp.data.map(d => {
return normalizeAppFromRegistry(
transformRegistryFormatToStackFormat(d),
this.doctype
)
})

return {
data: dataNormalized,
meta: {
count: resp.meta.count
},
skip: 0,
next: false
}
}

/**
* Fetches many apps from the registry by ids.
*
* @param {Array<string>} slugs - The slugs of the apps to fetch
* @returns {Promise<{data, meta, skip, next}>} The JSON API conformant response.
* @throws {FetchError}
*/
async getAll(slugs = []) {
try {
/*
* While waiting for the stack to propose a route that meets this need, we retrieve all the apps then we filter them before returning the result.
* (The limit of 1000 seems more than sufficient for this need)
*/
const resp = await this.stackClient.fetchJSON(
'GET',
`${this.endpoint}?limit=1000`
)
const dataFiltered = resp.data.filter(data => slugs.includes(data.slug))
const dataNormalized = dataFiltered.map(d => {
return normalizeAppFromRegistry(
transformRegistryFormatToStackFormat(d),
this.doctype
)
})
return {
data: dataNormalized,
meta: {
count: resp.meta.count
},
skip: 0,
next: false
}
} catch (error) {
return dontThrowNotFoundError(error)
}
}

/**
* Fetches an app from the registry.
*
Expand Down
111 changes: 111 additions & 0 deletions packages/cozy-stack-client/src/AppsRegistryCollection.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,117 @@ import AppsRegistryCollection, {
describe(`AppsRegistryCollection`, () => {
const client = new CozyStackClient()

describe('getAll', () => {
const collection = new AppsRegistryCollection(client)
const slugs = ['alan', 'caf']

beforeAll(() => {
client.fetchJSON.mockReturnValue(
Promise.resolve({
data: [
{
id: 'git://github.com/konnectors/alan.git',
slug: 'alan',
_type: 'io.cozy.apps_registry',
latest_version: {
manifest: {
source: 'git://github.com/konnectors/alan.git'
}
}
},
{
id: 'git://github.com/konnectors/caf.git',
slug: 'caf',
_type: 'io.cozy.apps_registry',
latest_version: {
manifest: {
source: 'git://github.com/konnectors/caf.git'
}
}
}
],
meta: { count: 2 }
})
)
})

it('should call the right route', async () => {
await collection.getAll(slugs)
expect(client.fetchJSON).toHaveBeenCalledWith(
'GET',
'/registry/?limit=1000'
)
})

it('should return the correct data', async () => {
const resp = await collection.getAll(slugs)
expect(resp.data.length).toBeLessThanOrEqual(slugs.length)
expect(resp.data.every(d => slugs.includes(d.slug))).toBe(true)
})

it('should return a correct JSON API response', async () => {
const resp = await collection.getAll(slugs)
expect(resp).toConformToJSONAPI()
})

it('should return normalized documents', async () => {
const resp = await collection.getAll(slugs)
expect(resp.data[0]).toHaveDocumentIdentity()
expect(resp.data[0]._type).toEqual(APPS_REGISTRY_DOCTYPE)
})
})

describe('all', () => {
const collection = new AppsRegistryCollection(client)

beforeAll(() => {
client.fetchJSON.mockReturnValue(
Promise.resolve({
data: [
{
id: 'git://github.com/konnectors/alan.git',
_id: 'git://github.com/konnectors/alan.git',
_type: 'io.cozy.apps_registry',
latest_version: {
manifest: {
source: 'git://github.com/konnectors/alan.git'
}
}
}
],
meta: { count: 1 }
})
)
})

it('should call the right default route', async () => {
await collection.all()
expect(client.fetchJSON).toHaveBeenCalledWith(
'GET',
'/registry/?limit=1000'
)
})

it('should call the right route with custom limit', async () => {
await collection.all({ limit: 10 })
expect(client.fetchJSON).toHaveBeenCalledWith(
'GET',
'/registry/?limit=10'
)
})

it('should return a correct JSON API response', async () => {
const resp = await collection.all()
expect(resp).toConformToJSONAPI()
})

it('should return normalized documents', async () => {
const resp = await collection.all()
expect(resp.data[0]).toHaveDocumentIdentity()
expect(resp.data[0]._type).toEqual(APPS_REGISTRY_DOCTYPE)
})
})

describe('get', () => {
const collection = new AppsRegistryCollection(client)

Expand Down
Loading