)
diff --git a/en/cozy-home/src/components/Sections/SectionsTypes.ts b/en/cozy-home/src/components/Sections/SectionsTypes.ts
index 20f3f1957..215279754 100644
--- a/en/cozy-home/src/components/Sections/SectionsTypes.ts
+++ b/en/cozy-home/src/components/Sections/SectionsTypes.ts
@@ -43,6 +43,10 @@ export interface GroupedSectionViewProps {
sections: Section[]
}
+export interface GroupedSectionTileProps {
+ section: Section
+}
+
export interface SectionsViewProps {
data?: IOCozyFile[] | IOCozyKonnector[]
type: 'shortcuts' | 'konnectorCategories'
diff --git a/en/cozy-home/src/containers/App.spec.jsx b/en/cozy-home/src/containers/App.spec.jsx
index a6dd78448..cc7bf5c1c 100644
--- a/en/cozy-home/src/containers/App.spec.jsx
+++ b/en/cozy-home/src/containers/App.spec.jsx
@@ -3,7 +3,7 @@ import { isFlagshipApp } from 'cozy-device-helper'
import { render } from '@testing-library/react'
import App from '../components/AnimatedWrapper'
import AppLike from 'test/AppLike'
-import { CustomWallPaperProvider } from 'hooks/useCustomWallpaperContext'
+import { WallPaperProvider } from 'hooks/useWallpaperContext'
import { act } from 'react-dom/test-utils'
import CozyTheme from 'cozy-ui/transpiled/react/providers/CozyTheme'
@@ -50,9 +50,9 @@ describe('App', () => {
const { container } = render(
-
+
-
+
)
@@ -75,9 +75,9 @@ describe('App', () => {
const { container } = render(
-
+
-
+
)
diff --git a/en/cozy-home/src/hooks/useCustomWallpaperContext.tsx b/en/cozy-home/src/hooks/useCustomWallpaperContext.tsx
deleted file mode 100644
index 56a0bfde1..000000000
--- a/en/cozy-home/src/hooks/useCustomWallpaperContext.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import React from 'react'
-import useCustomWallpaper from './useCustomWallpaper'
-
-const CustomWallPaperContext = React.createContext<
- CustomWallPaperContextInterface | undefined
->(undefined)
-
-interface CustomWallPaperContextInterfaceData {
- wallpaperLink: string | null
- binaryCustomWallpaper: string | null
- isCustomWallpaper: boolean
-}
-interface CustomWallPaperContextInterface {
- data: CustomWallPaperContextInterfaceData
- fetchStatus: string
-}
-export const CustomWallPaperProvider = ({
- children
-}: {
- children: JSX.Element
-}): JSX.Element => {
- const data = useCustomWallpaper() as CustomWallPaperContextInterface
- return (
-
- {children}
-
- )
-}
-
-export const useCustomWallpaperContext =
- (): CustomWallPaperContextInterface => {
- const context = React.useContext(CustomWallPaperContext)
- if (context === undefined) {
- throw new Error(
- 'useCustomWallpaperContext must be used within a CustomWallpaperProvider'
- )
- }
- return context
- }
diff --git a/en/cozy-home/src/hooks/usePreferedTheme.ts b/en/cozy-home/src/hooks/usePreferedTheme.ts
deleted file mode 100644
index a6452b061..000000000
--- a/en/cozy-home/src/hooks/usePreferedTheme.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { useState, useEffect, useMemo } from 'react'
-import { useCustomWallpaperContext } from './useCustomWallpaperContext'
-import { useCozyTheme } from 'cozy-ui/transpiled/react/providers/CozyTheme'
-
-export const getHomeThemeCssVariable = (): string => {
- return getComputedStyle(document.getElementsByTagName('body')[0])
- .getPropertyValue('--home-theme')
- .trim()
-}
-
-export const usePreferedTheme = (): string => {
- const {
- data: { wallpaperLink, binaryCustomWallpaper, isCustomWallpaper }
- } = useCustomWallpaperContext()
- const { type } = useCozyTheme()
- const defaultVariant = useMemo(
- () => (type === 'dark' ? 'normal' : 'inverted'),
- [type]
- )
- const [preferedVariant, setPreferedVariant] = useState(defaultVariant)
-
- useEffect(() => {
- const variantFromCSS = getHomeThemeCssVariable()
-
- if (isCustomWallpaper) {
- setPreferedVariant(defaultVariant)
- } else {
- setPreferedVariant(variantFromCSS || defaultVariant)
- }
- }, [wallpaperLink, binaryCustomWallpaper, isCustomWallpaper, defaultVariant])
-
- return preferedVariant
-}
diff --git a/en/cozy-home/src/hooks/useCustomWallpaper.jsx b/en/cozy-home/src/hooks/useWallpaper.jsx
similarity index 96%
rename from en/cozy-home/src/hooks/useCustomWallpaper.jsx
rename to en/cozy-home/src/hooks/useWallpaper.jsx
index c945ada20..a9ee47014 100644
--- a/en/cozy-home/src/hooks/useCustomWallpaper.jsx
+++ b/en/cozy-home/src/hooks/useWallpaper.jsx
@@ -3,7 +3,7 @@ import homeConfig from 'config/home.json'
import { useClient } from 'cozy-client'
import localForage from 'localforage'
-const useCustomWallpaper = () => {
+const useWallpaper = () => {
const client = useClient()
const [wallpaperLink, setWallpaperLink] = useState(null)
const [fetchStatus, setFetchStatus] = useState('idle')
@@ -61,4 +61,4 @@ const useCustomWallpaper = () => {
}
}
-export default useCustomWallpaper
+export default useWallpaper
diff --git a/en/cozy-home/src/hooks/useWallpaperContext.tsx b/en/cozy-home/src/hooks/useWallpaperContext.tsx
new file mode 100644
index 000000000..161e52a5d
--- /dev/null
+++ b/en/cozy-home/src/hooks/useWallpaperContext.tsx
@@ -0,0 +1,38 @@
+import React from 'react'
+import useWallpaper from './useWallpaper'
+
+const WallPaperContext = React.createContext<
+ WallPaperContextInterface | undefined
+>(undefined)
+
+interface WallPaperContextInterfaceData {
+ wallpaperLink: string | null
+ binaryCustomWallpaper: string | null
+ isCustomWallpaper: boolean
+}
+interface WallPaperContextInterface {
+ data: WallPaperContextInterfaceData
+ fetchStatus: string
+}
+export const WallPaperProvider = ({
+ children
+}: {
+ children: JSX.Element
+}): JSX.Element => {
+ const data = useWallpaper() as WallPaperContextInterface
+ return (
+
+ {children}
+
+ )
+}
+
+export const useWallpaperContext = (): WallPaperContextInterface => {
+ const context = React.useContext(WallPaperContext)
+ if (context === undefined) {
+ throw new Error(
+ 'useWallpaperContext must be used within a WallpaperProvider'
+ )
+ }
+ return context
+}
diff --git a/en/cozy-home/src/styles/app.styl b/en/cozy-home/src/styles/app.styl
index 5c0448d8e..d17db78d7 100644
--- a/en/cozy-home/src/styles/app.styl
+++ b/en/cozy-home/src/styles/app.styl
@@ -24,44 +24,45 @@ body
overflow auto
.App
- // Avoid mix-blend-mode from background-container to be linked to the background color of the body.
+ // Avoid mix-blend-mode from home-custom-background to be linked to the background color of the body.
// Must not be responsive to the theme.
background-color white
- background-repeat no-repeat
- background-size cover
- background-position center
overflow-y auto
+
+ &.custom-wallpaper
+ // black filter effect above the custom wallpaper image
+ &::before
+ content ''
+ position fixed
+ top 0
+ left 0
+ width 100%
+ height 100%
+ background-color rgba(0, 0, 0, .32)
+ backdrop-filter saturate(124%)
+
.corner
z-index var(--zIndex-nav)
margin rem(12) 2rem rem(-44) 0
+
.corner-button
+small-screen()
height 3rem
width 3rem
margin 0
+
+small-screen()
margin 0 0 -3rem
-// black filter effect above the wallpaper image
-.App::before
- content ''
- position fixed
- top 0
- left 0
- width 100%
- height 100%
- background-color rgba(0, 0, 0, .32)
- backdrop-filter saturate(124%)
-
+small-screen()
- .main-view, .background-container
+ .main-view, .home-custom-background
transition transform 200ms ease-out
will-change transform
.App--opened
.main-view
transform scale(1.3)
- .background-container
+ .home-custom-background
transform scale(1.1)
diff --git a/en/cozy-home/src/styles/backgroundContainer.styl b/en/cozy-home/src/styles/backgroundContainer.styl
index 4173c274b..d418da6f5 100644
--- a/en/cozy-home/src/styles/backgroundContainer.styl
+++ b/en/cozy-home/src/styles/backgroundContainer.styl
@@ -1,14 +1,26 @@
-.background-container
- background-position center
- background-repeat no-repeat
- background-size cover
- height 100vh
+.home-background-container
position fixed
+ height 100vh
width 100%
-.background-container-darken
- mix-blend-mode multiply
+ &--light
+ background-color #E9F4FF
-.home-default-partner-background
- background-repeat repeat
- background-size initial
\ No newline at end of file
+ &--dark
+ background-color #142536
+
+.home-default-background
+ &::before
+ content ''
+ position fixed
+ height 100%
+ width 100%
+ background-size 100% 100%
+ background-image url('../assets/images/default-wallpaper.svg')
+ opacity .24
+
+.home-custom-background
+ mix-blend-mode multiply
+ background-position center
+ background-repeat no-repeat
+ background-size cover
diff --git a/en/cozy-home/yarn.lock b/en/cozy-home/yarn.lock
index 81033397f..09620a159 100644
--- a/en/cozy-home/yarn.lock
+++ b/en/cozy-home/yarn.lock
@@ -5904,7 +5904,7 @@ core-util-is@1.0.2, core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=
-cosmiconfig@^5.0.0, cosmiconfig@^5.0.7, cosmiconfig@^5.2.0:
+cosmiconfig@^5.0.0, cosmiconfig@^5.2.0:
version "5.2.1"
resolved "https://registry.yarnpkg.com/cosmiconfig/-/cosmiconfig-5.2.1.tgz#040f726809c591e77a17c0a3626ca45b4f168b1a"
integrity sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==
@@ -9331,22 +9331,6 @@ human-size@^1.1.0:
resolved "https://registry.yarnpkg.com/human-size/-/human-size-1.1.0.tgz#052562be999841c037022c20259990c56ea996f9"
integrity sha1-BSVivpmYQcA3AiwgJZmQxW6plvk=
-husky@1.3.1:
- version "1.3.1"
- resolved "https://registry.yarnpkg.com/husky/-/husky-1.3.1.tgz#26823e399300388ca2afff11cfa8a86b0033fae0"
- integrity sha512-86U6sVVVf4b5NYSZ0yvv88dRgBSSXXmHaiq5pP4KDj5JVzdwKgBjEtUPOm8hcoytezFwbU+7gotXNhpHdystlg==
- dependencies:
- cosmiconfig "^5.0.7"
- execa "^1.0.0"
- find-up "^3.0.0"
- get-stdin "^6.0.0"
- is-ci "^2.0.0"
- pkg-dir "^3.0.0"
- please-upgrade-node "^3.1.1"
- read-pkg "^4.0.1"
- run-node "^1.0.0"
- slash "^2.0.0"
-
hyphenate-style-name@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d"
@@ -12275,9 +12259,9 @@ msgpack5@^4.0.2:
readable-stream "^2.3.6"
safe-buffer "^5.1.2"
-"mui-bottom-sheet@git+https://github.com/cozy/mui-bottom-sheet.git#v1.0.9":
+"mui-bottom-sheet@https://github.com/cozy/mui-bottom-sheet.git#v1.0.9":
version "1.0.8"
- resolved "git+https://github.com/cozy/mui-bottom-sheet.git#3dc4c2a245ab39079bc2f73546bccf80847be14c"
+ resolved "https://github.com/cozy/mui-bottom-sheet.git#3dc4c2a245ab39079bc2f73546bccf80847be14c"
dependencies:
"@juggle/resize-observer" "^3.1.3"
jest-environment-jsdom-sixteen "^1.0.3"
@@ -13316,7 +13300,7 @@ pkginfo@0.3.x, pkginfo@0.x.x:
resolved "https://registry.yarnpkg.com/pkginfo/-/pkginfo-0.3.1.tgz#5b29f6a81f70717142e09e765bbeab97b4f81e21"
integrity sha1-Wyn2qB9wcXFC4J52W76rl7T4HiE=
-please-upgrade-node@^3.0.2, please-upgrade-node@^3.1.1:
+please-upgrade-node@^3.0.2:
version "3.2.0"
resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942"
integrity sha512-gQR3WpIgNIKwBMVLkpMUeR3e1/E1y42bqDQZfql+kDeXd8COYfM8PQA4X6y7a8u9Ua9FHmsrrmirW2vHs45hWg==
@@ -14288,15 +14272,6 @@ read-pkg@^3.0.0:
normalize-package-data "^2.3.2"
path-type "^3.0.0"
-read-pkg@^4.0.1:
- version "4.0.1"
- resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-4.0.1.tgz#963625378f3e1c4d48c85872b5a6ec7d5d093237"
- integrity sha1-ljYlN48+HE1IyFhytabsfV0JMjc=
- dependencies:
- normalize-package-data "^2.3.2"
- parse-json "^4.0.0"
- pify "^3.0.0"
-
read-pkg@^5.2.0:
version "5.2.0"
resolved "https://registry.yarnpkg.com/read-pkg/-/read-pkg-5.2.0.tgz#7bf295438ca5a33e56cd30e053b34ee7250c93cc"
@@ -14973,11 +14948,6 @@ run-async@^2.2.0:
resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455"
integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
-run-node@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/run-node/-/run-node-1.0.0.tgz#46b50b946a2aa2d4947ae1d886e9856fd9cabe5e"
- integrity sha512-kc120TBlQ3mih1LSzdAJXo4xn/GWS2ec0l3S+syHDXP9uRr0JAT8Qd3mdMuyjqCzeZktgP3try92cEgf9Nks8A==
-
run-parallel@^1.1.9:
version "1.2.0"
resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee"
diff --git a/en/search/search_index.json b/en/search/search_index.json
index bca2c50a4..3e27fe2b3 100644
--- a/en/search/search_index.json
+++ b/en/search/search_index.json
@@ -1 +1 @@
-{"config": {"indexing": "full", "lang": ["en"], "min_search_length": 3, "prebuild_index": false, "separator": "[\\s\\-]+"}, "docs": [{"location": "", "text": "Cozy Documentation \u00b6 How-to \u00b6 Find guides for developing apps and connectors and for self-hosting. How to develop apps For Developers How to free data with connectors For Developers How to manipulate data For Developers How to install your own server For Self-Hosting Projects Documentation \u00b6 Cozy Banks Cozy Stack Cozy UI More Projects ... Get in touch \u00b6 Get help from our great community on our forum and on our IRC chat . Of course you can also write an email to our Support team: claude at cozycloud.cc.", "title": "Home"}, {"location": "#cozy-documentation", "text": "", "title": "Cozy Documentation"}, {"location": "#how-to", "text": "Find guides for developing apps and connectors and for self-hosting. How to develop apps For Developers How to free data with connectors For Developers How to manipulate data For Developers How to install your own server For Self-Hosting", "title": "How-to"}, {"location": "#projects-documentation", "text": "Cozy Banks Cozy Stack Cozy UI More Projects ...", "title": "Projects Documentation"}, {"location": "#get-in-touch", "text": "Get help from our great community on our forum and on our IRC chat . Of course you can also write an email to our Support team: claude at cozycloud.cc.", "title": "Get in touch"}, {"location": "privacy/", "text": "Privacy \u00b6 We track usage of our documentation anonymously. You can disable navigation data collection below if you don\u2019t want to participate.", "title": "Privacy"}, {"location": "privacy/#privacy", "text": "We track usage of our documentation anonymously. You can disable navigation data collection below if you don\u2019t want to participate.", "title": "Privacy"}, {"location": "ach/", "text": "ACH \u00b6 Automated Cozy Hydrater (ACH [ax] ) is a CLI that lets you request, create and remove records in your Cozy . Install Usage Examples Import data Import repositories with files Create photo albums with ACH Export data removing the ids Import data from a CSV Generate some files Generate some qualified files with referenced contacts (mespapiers) Install \u00b6 Install ACH using yarn 1 (v1.22.18 or greater) $ yarn global add cozy-ach If you cannot execute ACH after this command, it may be because you do not have the directory where yarn stores its symbolic links in your PATH . Edit it to append the result of yarn global bin . Usage \u00b6 Usage : ACH [ options ] [ command ] Options : - V , -- version output the version number - t -- token [ token ] Token file to use - y -- yes Does not ask for confirmation on sensitive operations - u -- url [ url ] URL of the cozy to use . Defaults to \"http://cozy.localhost:8080\" . ' (default: \"http://cozy.localhost:8080\") - h , -- help output usage information Commands : import < filepath > [ handlebarsOptionsFile ] The file containing the JSON data to import . Defaults to \"example-data.json\" . If the file doesn 't exist in the application, ACH will try to find it inside its data folder. Then the dummy helpers JS file (optional). importDir < directoryPath > The path to the directory content to import . Defaults to \"./DirectoriesToInject\" . generateFiles [ filesCount ] [ dirId ] Generates a given number of small files . ( optional dirId ) drop [ options ] < doctypes ...> Deletes all documents of the provided doctypes . For real . export < doctypes > [ filename ] Exports data from the doctypes ( separated by commas ) to filename downloadFile < fileid > Download the file delete < doctype > < ids ...> Delete document ( s ) updateSettings Update settings token < doctypes ...> Generate token script [ options ] < scriptName > Launch script ls - scripts Lists all built - in scripts , useful for autocompletion batch [ options ] < scriptName > < domainsFile > Launch script Examples \u00b6 Import data \u00b6 $ cat data.json { \"io.cozy.bills\" : [ { \"_id\" : \"eba16106554ca9e23012f83f9c7937c0\" , \"amount\" : 0 .71, \"beneficiary\" : \"Thyrion Lannister\" , \"date\" : \"1455-05-08T22:00:00.000Z\" , \"filename\" : \"20170508_528117465_R17125200206528395_malakoff_mederic.pdf\" , \"fileurl\" : \"https://extranet.braavos-bank.com/espaceClient/sante/tbs/tbsGenererPDF.do?remb=34\" , \"groupAmount\" : 3 .58, \"idPrestation\" : \"528117465_R17125200206528395_412877436\" , \"idReimbursement\" : \"528117465_R17125200206528395\" , \"invoice\" : \"io.cozy.files:ff5864e01f2d20c472f2b0f6531860b7\" , \"isRefund\" : true, \"isThirdPartyPayer\" : true, \"originalAmount\" : 2 .04, \"originalDate\" : \"2017-04-28T22:00:00.000Z\" , \"socialSecurityRefund\" : 1 .33, \"subtype\" : \"Liver transplant\" , \"type\" : \"health_costs\" , \"vendor\" : \"Iron Bank of Braavos\" } , { \"_id\" : \"eba16106554ca9e23012f83f9c793761\" , \"amount\" : 50 , \"beneficiary\" : \"Jamie LANNISTER\" , \"date\" : \"1455-05-17T22:00:00.000Z\" , \"filename\" : \"20170517_528117465_R17137202332136169_malakoff_mederic.pdf\" , \"fileurl\" : \"https://extranet.braavos-bank.com/espaceClient/sante/tbs/tbsGenererPDF.do?remb=33\" , \"groupAmount\" : 175 , \"idPrestation\" : \"528117465_R17137202332136169_415641280\" , \"idReimbursement\" : \"528117465_R17137202332136169\" , \"invoice\" : \"io.cozy.files:c9a4b2104b4a10de543bd574ac9ff9b1\" , \"isRefund\" : true, \"isThirdPartyPayer\" : true, \"originalAmount\" : 108 , \"originalDate\" : \"1455-05-09T22:00:00.000Z\" , \"socialSecurityRefund\" : 7 .22, \"subtype\" : \"Golden hand\" , \"type\" : \"health_costs\" , \"vendor\" : \"Iron Bank of Braavos\" } , { \"_id\" : \"eba16106554ca9e23012f83f9c7936fa\" , \"amount\" : 7 .5, \"beneficiary\" : \"Jamie LANNISTER\" , \"date\" : \"1455-05-21T22:00:00.000Z\" , \"filename\" : \"20170521_528117465_R171401014733001_malakoff_mederic.pdf\" , \"fileurl\" : \"https://extranet.braavos-bank.com/espaceClient/sante/tbs/tbsGenererPDF.do?remb=32\" , \"groupAmount\" : 7 .5, \"idPrestation\" : \"528117465_R171401014733001_416477228\" , \"idReimbursement\" : \"528117465_R171401014733001\" , \"invoice\" : \"io.cozy.files:c9a4b2104b4a10de543bd574ac9fed3a\" , \"isRefund\" : true, \"isThirdPartyPayer\" : false, \"originalAmount\" : 25 , \"originalDate\" : \"1455-05-15T22:00:00.000Z\" , \"socialSecurityRefund\" : 17 .5, \"subtype\" : \"Chiropractor\" , \"type\" : \"health_costs\" , \"vendor\" : \"Iron Bank of Braavos\" } , { \"_id\" : \"eba16106554ca9e23012f83f9c7936dd\" , \"amount\" : 0 .89, \"beneficiary\" : \"Jamie LANNISTER\" , \"date\" : \"2017-07-30T22:00:00.000Z\" , \"filename\" : \"20170730_528117465_R17209200405325685_malakoff_mederic.pdf\" , \"fileurl\" : \"https://extranet.braavos-bank.com/espaceClient/sante/tbs/tbsGenererPDF.do?remb=30\" , \"groupAmount\" : 5 .21, \"idPrestation\" : \"528117465_R17209200405325685_432873233\" , \"idReimbursement\" : \"528117465_R17209200405325685\" , \"invoice\" : \"io.cozy.files:ff5864e01f2d20c472f2b0f6531853ef\" , \"isRefund\" : true, \"isThirdPartyPayer\" : true, \"originalAmount\" : 2 .54, \"originalDate\" : \"2017-07-24T22:00:00.000Z\" , \"socialSecurityRefund\" : 1 .65, \"subtype\" : \"Chemist\" , \"type\" : \"health_costs\" , \"vendor\" : \"Iron Bank of Braavos\" } , { \"_id\" : \"eba16106554ca9e23012f83f9c79311a\" , \"amount\" : 0 .36, \"beneficiary\" : \"Jamie LANNISTER\" , \"date\" : \"2017-08-06T22:00:00.000Z\" , \"filename\" : \"20170806_528117465_R17216201307522910_malakoff_mederic.pdf\" , \"fileurl\" : \"https://extranet.braavos-bank.com/espaceClient/sante/tbs/tbsGenererPDF.do?remb=29\" , \"groupAmount\" : 7 .709999999999999, \"idPrestation\" : \"528117465_R17216201307522910_434482904\" , \"idReimbursement\" : \"528117465_R17216201307522910\" , \"invoice\" : \"io.cozy.files:ff5864e01f2d20c472f2b0f653185344\" , \"isRefund\" : true, \"isThirdPartyPayer\" : true, \"originalAmount\" : 1 .02, \"originalDate\" : \"2017-08-01T22:00:00.000Z\" , \"socialSecurityRefund\" : 0 .66, \"subtype\" : \"Sour \" , \"type\" : \"health_costs\" , \"vendor\" : \"Iron Bank of Braavos\" } ] } $ ACH import data.json If the file doesn\u2019t exist in the application, ACH will try to find it inside its data folder. handlebars \u00b6 Some JSON files use handlebars helpers, for those file, you need to specify the file where the helpers are defined. $ ACH import data/bank/bankData.json data/bank/helpers/bankDummyHelpers.js You can see an example of helpers here . \u2013url param \u00b6 You can import to a remote Cozy with the --url option : $ ACH import data/bank/bankData.json data/bank/helpers/bankDummyHelpers.js --url https://recette.cozy.works serial import \u00b6 By default, ACH imports data in parallel, by batches of 25. It is possible to import serially : $ env ACH_PARALLEL = false ACH import data.json Import directories with files \u00b6 To import a directory into a Cozy, use the importDir command: $ ACH importDir myDirectoryPath # default will be ./DirectoriesToInject All your target directory content will be imported to the root of Cozy Drive following the correct repositories tree. Create photo albums with ACH \u00b6 You can create photo albums from a folder on your disk. $ python scripts/albums-from-dir.py my-photos-directory resulting-albums.json Export data removing the ids \u00b6 By default, exported data contains all _id . Sometimes, you want to strip the ids from the documents you export. Set the environment variable ACH_NO_KEEP_ID to do so : env ACH_NO_KEEP_ID = true ACH export io.cozy.bills --url https://isabelledurand.cozy.rocks ./bills.json Contrary to _id , _rev is stripped by default. To keep the _rev field, set the environment variable ACH_KEEP_REV . Import data from a CSV \u00b6 See the example . Generate some files \u00b6 To create files into a Cozy, use the generateFiles command: $ ACH generateFiles 10 # by default will be at the root of your Drive Options: - -q / --qualify : In order to have a random qualification on your files - -m / --mime : In order to change the default mime of files ( text/plain ) Generate some papers \u00b6 (usefull for MesPapiers) To create qualified files with contacts referenced in a Cozy, use the script papers/createPapers command. ACH script papers/createPapers [ numberFile ] [ folderId ] -t Parameters: - numberFile : Number of papers to create (default: 1) - folderId : ID of the folder where the files will be created. (default: \u2018io.cozy.files.root-dir\u2019) Options: - -t / --token : app/konnector token, required to view files in the MesPapiers app. (Creates the cozyMetadata.createdByApp prop)", "title": "ACH"}, {"location": "ach/#ach", "text": "Automated Cozy Hydrater (ACH [ax] ) is a CLI that lets you request, create and remove records in your Cozy . Install Usage Examples Import data Import repositories with files Create photo albums with ACH Export data removing the ids Import data from a CSV Generate some files Generate some qualified files with referenced contacts (mespapiers)", "title": "ACH"}, {"location": "ach/#install", "text": "Install ACH using yarn 1 (v1.22.18 or greater) $ yarn global add cozy-ach If you cannot execute ACH after this command, it may be because you do not have the directory where yarn stores its symbolic links in your PATH . Edit it to append the result of yarn global bin .", "title": "Install"}, {"location": "ach/#usage", "text": "Usage : ACH [ options ] [ command ] Options : - V , -- version output the version number - t -- token [ token ] Token file to use - y -- yes Does not ask for confirmation on sensitive operations - u -- url [ url ] URL of the cozy to use . Defaults to \"http://cozy.localhost:8080\" . ' (default: \"http://cozy.localhost:8080\") - h , -- help output usage information Commands : import < filepath > [ handlebarsOptionsFile ] The file containing the JSON data to import . Defaults to \"example-data.json\" . If the file doesn 't exist in the application, ACH will try to find it inside its data folder. Then the dummy helpers JS file (optional). importDir < directoryPath > The path to the directory content to import . Defaults to \"./DirectoriesToInject\" . generateFiles [ filesCount ] [ dirId ] Generates a given number of small files . ( optional dirId ) drop [ options ] < doctypes ...> Deletes all documents of the provided doctypes . For real . export < doctypes > [ filename ] Exports data from the doctypes ( separated by commas ) to filename downloadFile < fileid > Download the file delete < doctype > < ids ...> Delete document ( s ) updateSettings Update settings token < doctypes ...> Generate token script [ options ] < scriptName > Launch script ls - scripts Lists all built - in scripts , useful for autocompletion batch [ options ] < scriptName > < domainsFile > Launch script", "title": "Usage"}, {"location": "ach/#examples", "text": "", "title": "Examples"}, {"location": "ach/#import-data", "text": "$ cat data.json { \"io.cozy.bills\" : [ { \"_id\" : \"eba16106554ca9e23012f83f9c7937c0\" , \"amount\" : 0 .71, \"beneficiary\" : \"Thyrion Lannister\" , \"date\" : \"1455-05-08T22:00:00.000Z\" , \"filename\" : \"20170508_528117465_R17125200206528395_malakoff_mederic.pdf\" , \"fileurl\" : \"https://extranet.braavos-bank.com/espaceClient/sante/tbs/tbsGenererPDF.do?remb=34\" , \"groupAmount\" : 3 .58, \"idPrestation\" : \"528117465_R17125200206528395_412877436\" , \"idReimbursement\" : \"528117465_R17125200206528395\" , \"invoice\" : \"io.cozy.files:ff5864e01f2d20c472f2b0f6531860b7\" , \"isRefund\" : true, \"isThirdPartyPayer\" : true, \"originalAmount\" : 2 .04, \"originalDate\" : \"2017-04-28T22:00:00.000Z\" , \"socialSecurityRefund\" : 1 .33, \"subtype\" : \"Liver transplant\" , \"type\" : \"health_costs\" , \"vendor\" : \"Iron Bank of Braavos\" } , { \"_id\" : \"eba16106554ca9e23012f83f9c793761\" , \"amount\" : 50 , \"beneficiary\" : \"Jamie LANNISTER\" , \"date\" : \"1455-05-17T22:00:00.000Z\" , \"filename\" : \"20170517_528117465_R17137202332136169_malakoff_mederic.pdf\" , \"fileurl\" : \"https://extranet.braavos-bank.com/espaceClient/sante/tbs/tbsGenererPDF.do?remb=33\" , \"groupAmount\" : 175 , \"idPrestation\" : \"528117465_R17137202332136169_415641280\" , \"idReimbursement\" : \"528117465_R17137202332136169\" , \"invoice\" : \"io.cozy.files:c9a4b2104b4a10de543bd574ac9ff9b1\" , \"isRefund\" : true, \"isThirdPartyPayer\" : true, \"originalAmount\" : 108 , \"originalDate\" : \"1455-05-09T22:00:00.000Z\" , \"socialSecurityRefund\" : 7 .22, \"subtype\" : \"Golden hand\" , \"type\" : \"health_costs\" , \"vendor\" : \"Iron Bank of Braavos\" } , { \"_id\" : \"eba16106554ca9e23012f83f9c7936fa\" , \"amount\" : 7 .5, \"beneficiary\" : \"Jamie LANNISTER\" , \"date\" : \"1455-05-21T22:00:00.000Z\" , \"filename\" : \"20170521_528117465_R171401014733001_malakoff_mederic.pdf\" , \"fileurl\" : \"https://extranet.braavos-bank.com/espaceClient/sante/tbs/tbsGenererPDF.do?remb=32\" , \"groupAmount\" : 7 .5, \"idPrestation\" : \"528117465_R171401014733001_416477228\" , \"idReimbursement\" : \"528117465_R171401014733001\" , \"invoice\" : \"io.cozy.files:c9a4b2104b4a10de543bd574ac9fed3a\" , \"isRefund\" : true, \"isThirdPartyPayer\" : false, \"originalAmount\" : 25 , \"originalDate\" : \"1455-05-15T22:00:00.000Z\" , \"socialSecurityRefund\" : 17 .5, \"subtype\" : \"Chiropractor\" , \"type\" : \"health_costs\" , \"vendor\" : \"Iron Bank of Braavos\" } , { \"_id\" : \"eba16106554ca9e23012f83f9c7936dd\" , \"amount\" : 0 .89, \"beneficiary\" : \"Jamie LANNISTER\" , \"date\" : \"2017-07-30T22:00:00.000Z\" , \"filename\" : \"20170730_528117465_R17209200405325685_malakoff_mederic.pdf\" , \"fileurl\" : \"https://extranet.braavos-bank.com/espaceClient/sante/tbs/tbsGenererPDF.do?remb=30\" , \"groupAmount\" : 5 .21, \"idPrestation\" : \"528117465_R17209200405325685_432873233\" , \"idReimbursement\" : \"528117465_R17209200405325685\" , \"invoice\" : \"io.cozy.files:ff5864e01f2d20c472f2b0f6531853ef\" , \"isRefund\" : true, \"isThirdPartyPayer\" : true, \"originalAmount\" : 2 .54, \"originalDate\" : \"2017-07-24T22:00:00.000Z\" , \"socialSecurityRefund\" : 1 .65, \"subtype\" : \"Chemist\" , \"type\" : \"health_costs\" , \"vendor\" : \"Iron Bank of Braavos\" } , { \"_id\" : \"eba16106554ca9e23012f83f9c79311a\" , \"amount\" : 0 .36, \"beneficiary\" : \"Jamie LANNISTER\" , \"date\" : \"2017-08-06T22:00:00.000Z\" , \"filename\" : \"20170806_528117465_R17216201307522910_malakoff_mederic.pdf\" , \"fileurl\" : \"https://extranet.braavos-bank.com/espaceClient/sante/tbs/tbsGenererPDF.do?remb=29\" , \"groupAmount\" : 7 .709999999999999, \"idPrestation\" : \"528117465_R17216201307522910_434482904\" , \"idReimbursement\" : \"528117465_R17216201307522910\" , \"invoice\" : \"io.cozy.files:ff5864e01f2d20c472f2b0f653185344\" , \"isRefund\" : true, \"isThirdPartyPayer\" : true, \"originalAmount\" : 1 .02, \"originalDate\" : \"2017-08-01T22:00:00.000Z\" , \"socialSecurityRefund\" : 0 .66, \"subtype\" : \"Sour \" , \"type\" : \"health_costs\" , \"vendor\" : \"Iron Bank of Braavos\" } ] } $ ACH import data.json If the file doesn\u2019t exist in the application, ACH will try to find it inside its data folder.", "title": "Import data"}, {"location": "ach/#handlebars", "text": "Some JSON files use handlebars helpers, for those file, you need to specify the file where the helpers are defined. $ ACH import data/bank/bankData.json data/bank/helpers/bankDummyHelpers.js You can see an example of helpers here .", "title": "handlebars"}, {"location": "ach/#-url-param", "text": "You can import to a remote Cozy with the --url option : $ ACH import data/bank/bankData.json data/bank/helpers/bankDummyHelpers.js --url https://recette.cozy.works", "title": "--url param"}, {"location": "ach/#serial-import", "text": "By default, ACH imports data in parallel, by batches of 25. It is possible to import serially : $ env ACH_PARALLEL = false ACH import data.json", "title": "serial import"}, {"location": "ach/#import-directories-with-files", "text": "To import a directory into a Cozy, use the importDir command: $ ACH importDir myDirectoryPath # default will be ./DirectoriesToInject All your target directory content will be imported to the root of Cozy Drive following the correct repositories tree.", "title": "Import directories with files"}, {"location": "ach/#create-photo-albums-with-ach", "text": "You can create photo albums from a folder on your disk. $ python scripts/albums-from-dir.py my-photos-directory resulting-albums.json", "title": "Create photo albums with ACH"}, {"location": "ach/#export-data-removing-the-ids", "text": "By default, exported data contains all _id . Sometimes, you want to strip the ids from the documents you export. Set the environment variable ACH_NO_KEEP_ID to do so : env ACH_NO_KEEP_ID = true ACH export io.cozy.bills --url https://isabelledurand.cozy.rocks ./bills.json Contrary to _id , _rev is stripped by default. To keep the _rev field, set the environment variable ACH_KEEP_REV .", "title": "Export data removing the ids"}, {"location": "ach/#import-data-from-a-csv", "text": "See the example .", "title": "Import data from a CSV"}, {"location": "ach/#generate-some-files", "text": "To create files into a Cozy, use the generateFiles command: $ ACH generateFiles 10 # by default will be at the root of your Drive Options: - -q / --qualify : In order to have a random qualification on your files - -m / --mime : In order to change the default mime of files ( text/plain )", "title": "Generate some files"}, {"location": "ach/#generate-some-papers", "text": "(usefull for MesPapiers) To create qualified files with contacts referenced in a Cozy, use the script papers/createPapers command. ACH script papers/createPapers [ numberFile ] [ folderId ] -t Parameters: - numberFile : Number of papers to create (default: 1) - folderId : ID of the folder where the files will be created. (default: \u2018io.cozy.files.root-dir\u2019) Options: - -t / --token : app/konnector token, required to view files in the MesPapiers app. (Creates the cozyMetadata.createdByApp prop)", "title": "Generate some papers"}, {"location": "ach/DirectoriesToInject/testFile2/", "text": "", "title": "testFile2"}, {"location": "ach/DirectoriesToInject/Folder/testFile1/", "text": "", "title": "testFile1"}, {"location": "ach/data/bank/", "text": "The fixtures for Banks are in its repository . https://github.com/cozy/cozy-banks/tree/master/test/fixtures", "title": "Index"}, {"location": "ach/e2e/", "text": "E2E flow \u00b6 Create a cozy via Cloudery (or reuse an existing one, see below) Sets passphrase When setting the passphrase, the stack responds with a cookie that is kept for future logins \u26a0\ufe0f Since the passphrase is not hashed properly before being sent to the Cozy), we cannot login to the Cozy afterwards, this is not a real problem since 1) the Cozy is temporary, 2) we already are logged into the Cozy after setting the passphrase To create a usable token for ACH, we use the OAuth flow and reuse the session created after the passphrase is sent. \u2139\ufe0f The cookie jar used for the session is saved, this means that if the test suite is run locally, the Cozy will be reused. \u2139\ufe0f The slug of the Cozy is random and in the form test . Then the ach executable is used to import / export / drop and the output is compared to what is expected. \u26a0\ufe0f E2E tests use a cloudery token accessed via environment variables. It can be found in the password store. If this variable is not set, the e2e test suite will be skipped. export CLOUDERY_TOKEN=$(pass show cozy/e2e-front/manager-token | head -n 1)", "title": "E2E flow"}, {"location": "ach/e2e/#e2e-flow", "text": "Create a cozy via Cloudery (or reuse an existing one, see below) Sets passphrase When setting the passphrase, the stack responds with a cookie that is kept for future logins \u26a0\ufe0f Since the passphrase is not hashed properly before being sent to the Cozy), we cannot login to the Cozy afterwards, this is not a real problem since 1) the Cozy is temporary, 2) we already are logged into the Cozy after setting the passphrase To create a usable token for ACH, we use the OAuth flow and reuse the session created after the passphrase is sent. \u2139\ufe0f The cookie jar used for the session is saved, this means that if the test suite is run locally, the Cozy will be reused. \u2139\ufe0f The slug of the Cozy is random and in the form test . Then the ach executable is used to import / export / drop and the output is compared to what is expected. \u26a0\ufe0f E2E tests use a cloudery token accessed via environment variables. It can be found in the password store. If this variable is not set, the e2e test suite will be skipped. export CLOUDERY_TOKEN=$(pass show cozy/e2e-front/manager-token | head -n 1)", "title": "E2E flow"}, {"location": "ach/examples/data-from-csv/", "text": "Import data from CSV files \u00b6 ACH does not support the import of CSV directly. You need to transform the data into the JSON format understood by ACH You can use ACH to import your data Here the example is from a banking data perspective. Say you banking institutions has provided you data in CSV and you want to import it in your Cozy to see the data in Banks. accounts.csv : contains data on your banking accounts operations.csv : contains data on your banking operations You can look at the parser to see how we transform the CSV data contained in accounts.csv and operations.csv into a format understandable by ACH. THe parser is basic here, the main point of attention here is the reference helper being used to link operations to accounts after accounts have been inserted into the Cozy. \u26a0\ufe0f The parser is very barebone and is just intended as an example. Parsing CSV is much harder than what it seems . You\u2019d be better of with a real CSV parsing library. \u26a0\ufe0f There are many other attributes that can be put on accounts and operations. You can see the docs on operations for more documentation. Usage \u00b6 node parser . js accounts . csv operations . csv > banking - data . json ach import banking - data . json", "title": "Import data from CSV files"}, {"location": "ach/examples/data-from-csv/#import-data-from-csv-files", "text": "ACH does not support the import of CSV directly. You need to transform the data into the JSON format understood by ACH You can use ACH to import your data Here the example is from a banking data perspective. Say you banking institutions has provided you data in CSV and you want to import it in your Cozy to see the data in Banks. accounts.csv : contains data on your banking accounts operations.csv : contains data on your banking operations You can look at the parser to see how we transform the CSV data contained in accounts.csv and operations.csv into a format understandable by ACH. THe parser is basic here, the main point of attention here is the reference helper being used to link operations to accounts after accounts have been inserted into the Cozy. \u26a0\ufe0f The parser is very barebone and is just intended as an example. Parsing CSV is much harder than what it seems . You\u2019d be better of with a real CSV parsing library. \u26a0\ufe0f There are many other attributes that can be put on accounts and operations. You can see the docs on operations for more documentation.", "title": "Import data from CSV files"}, {"location": "ach/examples/data-from-csv/#usage", "text": "node parser . js accounts . csv operations . csv > banking - data . json ach import banking - data . json", "title": "Usage"}, {"location": "babel-preset-cozy-app/", "text": "Babel Preset Cozy App What\u2019s babel-preset-cozy-app? \u00b6 A shareable configuration for Cozy Applications or Scripts. This package is a Babel preset already used by create-cozy-app . To install: yarn add --dev babel-preset-cozy-app Usage with a Create Cozy App projects \u00b6 If you started your project using create-cozy-app , you don\u2019t need to do anything, you should already have a .babelrc configured to used this preset. Usage with other projects \u00b6 If you want to use this preset, you first need to have Babel installed (cf documentation ). Then, in a file named .babelrc (the Babel configuration file), you can use the preset using the following way: { \"presets\" : [ \"cozy-app\" ] } Options \u00b6 node (boolean): false by default \u00b6 By default, this babel preset targets browsers but you can target node by using the node option: { \"presets\" : [ [ \"cozy-app\" , { \"node\" : true }] ] } react (boolean): true by default \u00b6 By default, this babel preset uses the react preset ( babel-preset-react ) but you can disable this behaviour with the react option to false as following: { \"presets\" : [ [ \"cozy-app\" , { \"react\" : false }] ] } transformRegenerator (boolean): true by default (for browsers only) \u00b6 By default, this babel preset uses babel-plugin-transform-runtime to transform regenerator functions on the runtime. But sometimes (not always) it could break CSPs due to some eval usage so you can disable this behaviour with the transformRegenerator option to false as following: { \"presets\" : [ [ \"cozy-app\" , { \"transformRegenerator\" : false }] ] } Lib option \u00b6 When the lib option is activated, import/export nodes are not transpiled. This gives the downstream bundler the ability to prune unused module away. It works by configuring babel-preset-env with {\"modules\": false} . Advanced \u00b6 You can have control on the options passed to babel-preset-env and babel-plugin-transform-runtime : presetEnv will be passed to babel-preset-env transformRuntime will be passed to babel-plugin-transform-runtime { \"presets\" : [ [ \"cozy-app\" , { \"presetEnv\" : { \"modules\" : false }, \"transformRuntime\" : { \"helpers\" : true } }] ] } In this case, we do not want preset-env to touch to import/export and want the inlined Babel helpers to be replaced by imports from babel-runtime . See the options on the official docs : https://babeljs.io/docs/en/babel-preset-env#modules https://babeljs.io/docs/en/babel-plugin-transform-runtime#helpers Community \u00b6 What\u2019s Cozy? \u00b6 Cozy is a platform that brings all your web services in the same private space. With it, your webapps and your devices can share data easily, providing you with a new experience. You can install Cozy on your own hardware where no one\u2019s tracking you. Get in touch \u00b6 You can reach the Cozy Community by: Chatting with us on IRC #cozycloud on Libera.Chat Posting on our Forum Posting issues on the Github repos Say Hi! on Twitter License \u00b6 babel-preset-cozy-app is distributed under the MIT license.", "title": "Babel preset"}, {"location": "babel-preset-cozy-app/#whats-babel-preset-cozy-app", "text": "A shareable configuration for Cozy Applications or Scripts. This package is a Babel preset already used by create-cozy-app . To install: yarn add --dev babel-preset-cozy-app", "title": "What's babel-preset-cozy-app?"}, {"location": "babel-preset-cozy-app/#usage-with-a-create-cozy-app-projects", "text": "If you started your project using create-cozy-app , you don\u2019t need to do anything, you should already have a .babelrc configured to used this preset.", "title": "Usage with a Create Cozy App projects"}, {"location": "babel-preset-cozy-app/#usage-with-other-projects", "text": "If you want to use this preset, you first need to have Babel installed (cf documentation ). Then, in a file named .babelrc (the Babel configuration file), you can use the preset using the following way: { \"presets\" : [ \"cozy-app\" ] }", "title": "Usage with other projects"}, {"location": "babel-preset-cozy-app/#options", "text": "", "title": "Options"}, {"location": "babel-preset-cozy-app/#node-boolean-false-by-default", "text": "By default, this babel preset targets browsers but you can target node by using the node option: { \"presets\" : [ [ \"cozy-app\" , { \"node\" : true }] ] }", "title": "node (boolean): false by default"}, {"location": "babel-preset-cozy-app/#react-boolean-true-by-default", "text": "By default, this babel preset uses the react preset ( babel-preset-react ) but you can disable this behaviour with the react option to false as following: { \"presets\" : [ [ \"cozy-app\" , { \"react\" : false }] ] }", "title": "react (boolean): true by default"}, {"location": "babel-preset-cozy-app/#transformregenerator-boolean-true-by-default-for-browsers-only", "text": "By default, this babel preset uses babel-plugin-transform-runtime to transform regenerator functions on the runtime. But sometimes (not always) it could break CSPs due to some eval usage so you can disable this behaviour with the transformRegenerator option to false as following: { \"presets\" : [ [ \"cozy-app\" , { \"transformRegenerator\" : false }] ] }", "title": "transformRegenerator (boolean): true by default (for browsers only)"}, {"location": "babel-preset-cozy-app/#lib-option", "text": "When the lib option is activated, import/export nodes are not transpiled. This gives the downstream bundler the ability to prune unused module away. It works by configuring babel-preset-env with {\"modules\": false} .", "title": "Lib option"}, {"location": "babel-preset-cozy-app/#advanced", "text": "You can have control on the options passed to babel-preset-env and babel-plugin-transform-runtime : presetEnv will be passed to babel-preset-env transformRuntime will be passed to babel-plugin-transform-runtime { \"presets\" : [ [ \"cozy-app\" , { \"presetEnv\" : { \"modules\" : false }, \"transformRuntime\" : { \"helpers\" : true } }] ] } In this case, we do not want preset-env to touch to import/export and want the inlined Babel helpers to be replaced by imports from babel-runtime . See the options on the official docs : https://babeljs.io/docs/en/babel-preset-env#modules https://babeljs.io/docs/en/babel-plugin-transform-runtime#helpers", "title": "Advanced"}, {"location": "babel-preset-cozy-app/#community", "text": "", "title": "Community"}, {"location": "babel-preset-cozy-app/#whats-cozy", "text": "Cozy is a platform that brings all your web services in the same private space. With it, your webapps and your devices can share data easily, providing you with a new experience. You can install Cozy on your own hardware where no one\u2019s tracking you.", "title": "What's Cozy?"}, {"location": "babel-preset-cozy-app/#get-in-touch", "text": "You can reach the Cozy Community by: Chatting with us on IRC #cozycloud on Libera.Chat Posting on our Forum Posting issues on the Github repos Say Hi! on Twitter", "title": "Get in touch"}, {"location": "babel-preset-cozy-app/#license", "text": "babel-preset-cozy-app is distributed under the MIT license.", "title": "License"}, {"location": "babel-preset-cozy-app/CHANGELOG/", "text": "Change Log \u00b6 All notable changes to this project will be documented in this file. See Conventional Commits for commit guidelines. 2.1.0 (2023-01-31) \u00b6 Features \u00b6 Update cozy-client and cozy-ui ( 6ae3b04 ) 2.0.4 (2022-10-03) \u00b6 Note: Version bump only for package babel-preset-cozy-app 2.0.3 (2022-08-01) \u00b6 Bug Fixes \u00b6 node: Upgrade to Node 16 ( 3a82521 ) 2.0.2 (2022-02-01) \u00b6 Bug Fixes \u00b6 deps: update babel monorepo ( dcc215a ) Handle empty context ( 6258e12 ) 2.0.1 (2021-12-20) \u00b6 Bug Fixes \u00b6 Downgrade babel-core in babel-preset ( 5456544 ) 2.0.0 (2021-12-02) \u00b6 Features \u00b6 Handle Typescript files in eslint and babel configs ( fe658ed ) BREAKING CHANGES \u00b6 upgrade from eslint 5 to eslint 8 upgrade prettier from 1 to 2 you\u2019ll need to run \u2013fix to fix lint issues after the upgrade. Few errors are not auto fixable, you can // disable-next-line if needed 1.12.0 (2021-10-22) \u00b6 Features \u00b6 Remove drive from homeHref ( 97010d3 ) Update preset config to target node 12 ( bae1bcd ) 1.11.0 (2021-02-12) \u00b6 Features \u00b6 Add finance theme ( bb8cf35 ) 1.10.0 (2020-11-23) \u00b6 Features \u00b6 Update babel-preset-cozy-app dependencies ( 0fcccb5 ) Use ^ for dependencies ( fc28de7 ) 1.9.3 (2020-10-01) \u00b6 Note: Version bump only for package babel-preset-cozy-app 1.9.2 (2020-09-15) \u00b6 Bug Fixes \u00b6 Flaky builds due to SyntaxError ( 6b86b76 ) 1.9.1 (2020-08-03) \u00b6 Note: Version bump only for package babel-preset-cozy-app 1.9.0 (2020-07-16) \u00b6 Bug Fixes \u00b6 Call revokeSelf if not the owner of the sharing ( f7afc60 ) Features \u00b6 Update lodash accross all packages ( 6a20128 ) 1.8.1 (2020-02-27) \u00b6 Bug Fixes \u00b6 Revert \u201cMerge pull request #974 from cozy/feat/RemovePropTypes\u201d ( 2d15d78 ) 1.8.0 (2020-02-25) \u00b6 Bug Fixes \u00b6 cozy-harvest-lib: Always show account form when editing an account ( a8718cd ) Features \u00b6 Remove proptype in production mode ( 4287527 ) 1.7.0 (2019-09-05) \u00b6 Features \u00b6 Add account route ( 7986708 ) 1.6.0 (2019-07-19) \u00b6 Features \u00b6 Activate babel helpers by default ( ab62bdb ) Add lib option ( 45469b5 ) Do not let lib add modules:false in Jest ( ee4058c ) 1.5.3 (2019-07-19) \u00b6 Note: Version bump only for package babel-preset-cozy-app 1.5.2 (2019-07-11) \u00b6 Bug Fixes \u00b6 deps: Update dependency lodash to v4.17.13 [SECURITY] ( #648 ) ( 1b36dac ) 1.5.1 (2019-03-18) \u00b6 Bug Fixes \u00b6 babel-preset-cozy-app: Publish validate.js file ( b3c4c5e ) 1.5.0 (2019-03-12) \u00b6 Features \u00b6 Disable a transform that makes React slower ( 035bb4f ) 1.4.0 (2019-03-12) \u00b6 Features \u00b6 Ability to configure transformRegenerator ( 8f928c3 ) Add presetEnv option ( dbd7e49 ) Can disable transformRuntime plugin ( 37ee490 ) Check result when running in CLI ( 791a005 ) Deprecated transformRegenerator option ( 011299f ) 1.3.3 (2019-03-12) \u00b6 Bug Fixes \u00b6 deps: update babel monorepo ( 099cc51 ) 1.3.2 (2019-02-12) \u00b6 Bug Fixes \u00b6 Make babel-preset uses browserslist cozy config ( 3418ac2 ) 1.3.1 (2019-02-11) \u00b6 Bug Fixes \u00b6 Add Android 5 and iOS 10 ( #266 ) ( 1677d25 ) 1.3.0 (2019-01-11) \u00b6 Features \u00b6 babel: Update supported browsers list for Cozy platform ( 8e810e1 ) 1.2.5 (2018-12-28) \u00b6 Note: Version bump only for package babel-preset-cozy-app 1.2.4 (2018-12-26) \u00b6 Note: Version bump only for package babel-preset-cozy-app 1.2.3 (2018-12-17) \u00b6 Note: Version bump only for package babel-preset-cozy-app 1.2.2 (2018-12-10) \u00b6 Note: Version bump only for package babel-preset-cozy-app 1.2.1 (2018-10-02) \u00b6 Note: Version bump only for package babel-preset-cozy-app 1.2.0 (2018-09-25) \u00b6 Bug Fixes \u00b6 \ud83d\udd27 add required @babel /core v7 in cozy-app ( cbce625 ) \ud83d\udd27 remove now deprecated polyfill option ( 63ec309 ) Features \u00b6 \ud83d\udd27 make cozy-app babel 7 compatible ( c2c5a5e ) 1.1.3 (2018-09-21) \u00b6 Note: Version bump only for package babel-preset-cozy-app 1.1.2 (2018-09-21) \u00b6 Note: Version bump only for package babel-preset-cozy-app 1.1.1 (2018-08-22) \u00b6 Note: Version bump only for package babel-preset-cozy-app 1.1.0 (2018-08-09) \u00b6 Features \u00b6 import babel and eslint cozy-app from create-cozy-app ( 0a3ab19 )", "title": "Change Log"}, {"location": "babel-preset-cozy-app/CHANGELOG/#change-log", "text": "All notable changes to this project will be documented in this file. See Conventional Commits for commit guidelines.", "title": "Change Log"}, {"location": "babel-preset-cozy-app/CHANGELOG/#210-2023-01-31", "text": "", "title": "2.1.0 (2023-01-31)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#features", "text": "Update cozy-client and cozy-ui ( 6ae3b04 )", "title": "Features"}, {"location": "babel-preset-cozy-app/CHANGELOG/#204-2022-10-03", "text": "Note: Version bump only for package babel-preset-cozy-app", "title": "2.0.4 (2022-10-03)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#203-2022-08-01", "text": "", "title": "2.0.3 (2022-08-01)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#bug-fixes", "text": "node: Upgrade to Node 16 ( 3a82521 )", "title": "Bug Fixes"}, {"location": "babel-preset-cozy-app/CHANGELOG/#202-2022-02-01", "text": "", "title": "2.0.2 (2022-02-01)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#bug-fixes_1", "text": "deps: update babel monorepo ( dcc215a ) Handle empty context ( 6258e12 )", "title": "Bug Fixes"}, {"location": "babel-preset-cozy-app/CHANGELOG/#201-2021-12-20", "text": "", "title": "2.0.1 (2021-12-20)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#bug-fixes_2", "text": "Downgrade babel-core in babel-preset ( 5456544 )", "title": "Bug Fixes"}, {"location": "babel-preset-cozy-app/CHANGELOG/#200-2021-12-02", "text": "", "title": "2.0.0 (2021-12-02)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#features_1", "text": "Handle Typescript files in eslint and babel configs ( fe658ed )", "title": "Features"}, {"location": "babel-preset-cozy-app/CHANGELOG/#breaking-changes", "text": "upgrade from eslint 5 to eslint 8 upgrade prettier from 1 to 2 you\u2019ll need to run \u2013fix to fix lint issues after the upgrade. Few errors are not auto fixable, you can // disable-next-line if needed", "title": "BREAKING CHANGES"}, {"location": "babel-preset-cozy-app/CHANGELOG/#1120-2021-10-22", "text": "", "title": "1.12.0 (2021-10-22)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#features_2", "text": "Remove drive from homeHref ( 97010d3 ) Update preset config to target node 12 ( bae1bcd )", "title": "Features"}, {"location": "babel-preset-cozy-app/CHANGELOG/#1110-2021-02-12", "text": "", "title": "1.11.0 (2021-02-12)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#features_3", "text": "Add finance theme ( bb8cf35 )", "title": "Features"}, {"location": "babel-preset-cozy-app/CHANGELOG/#1100-2020-11-23", "text": "", "title": "1.10.0 (2020-11-23)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#features_4", "text": "Update babel-preset-cozy-app dependencies ( 0fcccb5 ) Use ^ for dependencies ( fc28de7 )", "title": "Features"}, {"location": "babel-preset-cozy-app/CHANGELOG/#193-2020-10-01", "text": "Note: Version bump only for package babel-preset-cozy-app", "title": "1.9.3 (2020-10-01)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#192-2020-09-15", "text": "", "title": "1.9.2 (2020-09-15)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#bug-fixes_3", "text": "Flaky builds due to SyntaxError ( 6b86b76 )", "title": "Bug Fixes"}, {"location": "babel-preset-cozy-app/CHANGELOG/#191-2020-08-03", "text": "Note: Version bump only for package babel-preset-cozy-app", "title": "1.9.1 (2020-08-03)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#190-2020-07-16", "text": "", "title": "1.9.0 (2020-07-16)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#bug-fixes_4", "text": "Call revokeSelf if not the owner of the sharing ( f7afc60 )", "title": "Bug Fixes"}, {"location": "babel-preset-cozy-app/CHANGELOG/#features_5", "text": "Update lodash accross all packages ( 6a20128 )", "title": "Features"}, {"location": "babel-preset-cozy-app/CHANGELOG/#181-2020-02-27", "text": "", "title": "1.8.1 (2020-02-27)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#bug-fixes_5", "text": "Revert \u201cMerge pull request #974 from cozy/feat/RemovePropTypes\u201d ( 2d15d78 )", "title": "Bug Fixes"}, {"location": "babel-preset-cozy-app/CHANGELOG/#180-2020-02-25", "text": "", "title": "1.8.0 (2020-02-25)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#bug-fixes_6", "text": "cozy-harvest-lib: Always show account form when editing an account ( a8718cd )", "title": "Bug Fixes"}, {"location": "babel-preset-cozy-app/CHANGELOG/#features_6", "text": "Remove proptype in production mode ( 4287527 )", "title": "Features"}, {"location": "babel-preset-cozy-app/CHANGELOG/#170-2019-09-05", "text": "", "title": "1.7.0 (2019-09-05)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#features_7", "text": "Add account route ( 7986708 )", "title": "Features"}, {"location": "babel-preset-cozy-app/CHANGELOG/#160-2019-07-19", "text": "", "title": "1.6.0 (2019-07-19)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#features_8", "text": "Activate babel helpers by default ( ab62bdb ) Add lib option ( 45469b5 ) Do not let lib add modules:false in Jest ( ee4058c )", "title": "Features"}, {"location": "babel-preset-cozy-app/CHANGELOG/#153-2019-07-19", "text": "Note: Version bump only for package babel-preset-cozy-app", "title": "1.5.3 (2019-07-19)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#152-2019-07-11", "text": "", "title": "1.5.2 (2019-07-11)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#bug-fixes_7", "text": "deps: Update dependency lodash to v4.17.13 [SECURITY] ( #648 ) ( 1b36dac )", "title": "Bug Fixes"}, {"location": "babel-preset-cozy-app/CHANGELOG/#151-2019-03-18", "text": "", "title": "1.5.1 (2019-03-18)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#bug-fixes_8", "text": "babel-preset-cozy-app: Publish validate.js file ( b3c4c5e )", "title": "Bug Fixes"}, {"location": "babel-preset-cozy-app/CHANGELOG/#150-2019-03-12", "text": "", "title": "1.5.0 (2019-03-12)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#features_9", "text": "Disable a transform that makes React slower ( 035bb4f )", "title": "Features"}, {"location": "babel-preset-cozy-app/CHANGELOG/#140-2019-03-12", "text": "", "title": "1.4.0 (2019-03-12)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#features_10", "text": "Ability to configure transformRegenerator ( 8f928c3 ) Add presetEnv option ( dbd7e49 ) Can disable transformRuntime plugin ( 37ee490 ) Check result when running in CLI ( 791a005 ) Deprecated transformRegenerator option ( 011299f )", "title": "Features"}, {"location": "babel-preset-cozy-app/CHANGELOG/#133-2019-03-12", "text": "", "title": "1.3.3 (2019-03-12)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#bug-fixes_9", "text": "deps: update babel monorepo ( 099cc51 )", "title": "Bug Fixes"}, {"location": "babel-preset-cozy-app/CHANGELOG/#132-2019-02-12", "text": "", "title": "1.3.2 (2019-02-12)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#bug-fixes_10", "text": "Make babel-preset uses browserslist cozy config ( 3418ac2 )", "title": "Bug Fixes"}, {"location": "babel-preset-cozy-app/CHANGELOG/#131-2019-02-11", "text": "", "title": "1.3.1 (2019-02-11)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#bug-fixes_11", "text": "Add Android 5 and iOS 10 ( #266 ) ( 1677d25 )", "title": "Bug Fixes"}, {"location": "babel-preset-cozy-app/CHANGELOG/#130-2019-01-11", "text": "", "title": "1.3.0 (2019-01-11)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#features_11", "text": "babel: Update supported browsers list for Cozy platform ( 8e810e1 )", "title": "Features"}, {"location": "babel-preset-cozy-app/CHANGELOG/#125-2018-12-28", "text": "Note: Version bump only for package babel-preset-cozy-app", "title": "1.2.5 (2018-12-28)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#124-2018-12-26", "text": "Note: Version bump only for package babel-preset-cozy-app", "title": "1.2.4 (2018-12-26)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#123-2018-12-17", "text": "Note: Version bump only for package babel-preset-cozy-app", "title": "1.2.3 (2018-12-17)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#122-2018-12-10", "text": "Note: Version bump only for package babel-preset-cozy-app", "title": "1.2.2 (2018-12-10)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#121-2018-10-02", "text": "Note: Version bump only for package babel-preset-cozy-app", "title": "1.2.1 (2018-10-02)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#120-2018-09-25", "text": "", "title": "1.2.0 (2018-09-25)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#bug-fixes_12", "text": "\ud83d\udd27 add required @babel /core v7 in cozy-app ( cbce625 ) \ud83d\udd27 remove now deprecated polyfill option ( 63ec309 )", "title": "Bug Fixes"}, {"location": "babel-preset-cozy-app/CHANGELOG/#features_12", "text": "\ud83d\udd27 make cozy-app babel 7 compatible ( c2c5a5e )", "title": "Features"}, {"location": "babel-preset-cozy-app/CHANGELOG/#113-2018-09-21", "text": "Note: Version bump only for package babel-preset-cozy-app", "title": "1.1.3 (2018-09-21)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#112-2018-09-21", "text": "Note: Version bump only for package babel-preset-cozy-app", "title": "1.1.2 (2018-09-21)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#111-2018-08-22", "text": "Note: Version bump only for package babel-preset-cozy-app", "title": "1.1.1 (2018-08-22)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#110-2018-08-09", "text": "", "title": "1.1.0 (2018-08-09)"}, {"location": "babel-preset-cozy-app/CHANGELOG/#features_13", "text": "import babel and eslint cozy-app from create-cozy-app ( 0a3ab19 )", "title": "Features"}, {"location": "commitlint-config-cozy/", "text": "Commitlint Config Cozy \u00b6 Shareable commitlint config enforcing the cozy commit convention Documentations \u00b6 Cozy commit documentation on Cozy Guideline Commitlint How to add it on your project \u00b6 Add the library on your dev dependency ( yarn add commitlint-config-cozy --dev --exact ) Add configuration on your package.json ( see an example ): \"commitlint\" : { \"extends\" : [ \"cozy\" ] } Add verification during a commit with husky (> 1.0.0) on your package.json ( see an example ): \"husky\": { \"hooks\": { \"commit-msg\": \"commitlint -e $GIT_PARAMS\" } } Community \u00b6 What\u2019s Cozy? \u00b6 Cozy is a platform that brings all your web services in the same private space. With it, your webapps and your devices can share data easily, providing you with a new experience. You can install Cozy on your own hardware where no one\u2019s tracking you. Get in touch \u00b6 You can reach the Cozy Community by: Chatting with us on IRC #cozycloud on Libera.Chat Posting on our Forum Posting issues on the Github repos Say Hi! on Twitter Maintainers \u00b6 The maintainer for Commitlint Config Cozy is kosssi ! License \u00b6 commitlint-config-cozy is distributed under the MIT license.", "title": "Commitlint"}, {"location": "commitlint-config-cozy/#commitlint-config-cozy", "text": "Shareable commitlint config enforcing the cozy commit convention", "title": "Commitlint Config Cozy"}, {"location": "commitlint-config-cozy/#documentations", "text": "Cozy commit documentation on Cozy Guideline Commitlint", "title": "Documentations"}, {"location": "commitlint-config-cozy/#how-to-add-it-on-your-project", "text": "Add the library on your dev dependency ( yarn add commitlint-config-cozy --dev --exact ) Add configuration on your package.json ( see an example ): \"commitlint\" : { \"extends\" : [ \"cozy\" ] } Add verification during a commit with husky (> 1.0.0) on your package.json ( see an example ): \"husky\": { \"hooks\": { \"commit-msg\": \"commitlint -e $GIT_PARAMS\" } }", "title": "How to add it on your project"}, {"location": "commitlint-config-cozy/#community", "text": "", "title": "Community"}, {"location": "commitlint-config-cozy/#whats-cozy", "text": "Cozy is a platform that brings all your web services in the same private space. With it, your webapps and your devices can share data easily, providing you with a new experience. You can install Cozy on your own hardware where no one\u2019s tracking you.", "title": "What's Cozy?"}, {"location": "commitlint-config-cozy/#get-in-touch", "text": "You can reach the Cozy Community by: Chatting with us on IRC #cozycloud on Libera.Chat Posting on our Forum Posting issues on the Github repos Say Hi! on Twitter", "title": "Get in touch"}, {"location": "commitlint-config-cozy/#maintainers", "text": "The maintainer for Commitlint Config Cozy is kosssi !", "title": "Maintainers"}, {"location": "commitlint-config-cozy/#license", "text": "commitlint-config-cozy is distributed under the MIT license.", "title": "License"}, {"location": "commitlint-config-cozy/CHANGELOG/", "text": "Change Log \u00b6 All notable changes to this project will be documented in this file. See Conventional Commits for commit guidelines. 0.8.0 (2023-01-31) \u00b6 Features \u00b6 Update cozy-client and cozy-ui ( 6ae3b04 ) 0.7.9 (2022-10-03) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.7.8 (2022-08-01) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.7.7 (2022-05-13) \u00b6 Bug Fixes \u00b6 deps: update commitlint monorepo to v16.2.4 ( 6b17ecb ) 0.7.6 (2022-04-04) \u00b6 Bug Fixes \u00b6 bump @commitlint/cli from 16.1.0 to 16.2.3 ( 2167d5b ) 0.7.5 (2022-02-03) \u00b6 Bug Fixes \u00b6 deps: update dependency jest to v26.6.3 ( f442fff ) 0.7.4 (2022-02-01) \u00b6 Bug Fixes \u00b6 deps: update commitlint monorepo ( d3f4f27 ) 0.7.3 (2022-02-01) \u00b6 Bug Fixes \u00b6 deps: update babel monorepo ( dcc215a ) Handle empty context ( 6258e12 ) 0.7.2 (2021-12-20) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.7.1 (2021-12-02) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.7.0 (2021-10-22) \u00b6 Features \u00b6 Remove drive from homeHref ( 97010d3 ) 0.6.0 (2021-02-12) \u00b6 Features \u00b6 Add finance theme ( bb8cf35 ) 0.5.0 (2020-11-23) \u00b6 Features \u00b6 Update @babel/core and babel-jest ( 352ddc3 ) Update jest ( 3b2c32a ) 0.4.6 (2020-10-01) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.4.5 (2020-09-15) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.4.4 (2020-08-03) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.4.3 (2020-07-16) \u00b6 Bug Fixes \u00b6 Call revokeSelf if not the owner of the sharing ( f7afc60 ) 0.4.2 (2020-02-27) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.4.1 (2020-02-25) \u00b6 Bug Fixes \u00b6 cozy-harvest-lib: Always show account form when editing an account ( a8718cd ) 0.4.0 (2019-09-05) \u00b6 Features \u00b6 Add account route ( 7986708 ) 0.3.27 (2019-07-19) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.26 (2019-07-19) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.25 (2019-07-11) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.24 (2019-03-18) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.23 (2019-03-12) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.22 (2019-03-12) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.21 (2019-03-12) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.20 (2019-03-12) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.19 (2019-02-25) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.18 (2019-02-12) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.17 (2019-02-11) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.16 (2019-01-16) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.15 (2019-01-11) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.14 (2018-12-28) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.13 (2018-12-26) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.12 (2018-12-17) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.11 (2018-12-10) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.10 (2018-11-29) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.9 (2018-10-16) \u00b6 Bug Fixes \u00b6 deps: update commitlint monorepo to v7.2.1 ( 0ee263a ) 0.3.8 (2018-10-11) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.7 (2018-10-09) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.6 (2018-10-02) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.5 (2018-09-27) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.4 (2018-09-25) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.3 (2018-09-25) \u00b6 Bug Fixes \u00b6 add babel-core bridge for v7 ( 18665a8 ), closes /github.com/babel/babel/issues/8206#issuecomment-419705758 use ^7.1.0 for babel-jest issue ( 34b2d14 ) 0.3.2 (2018-09-25) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.1 (2018-09-21) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.3.0 (2018-09-17) \u00b6 Features \u00b6 Add commitlint cli on dependency \u2699\ufe0f ( 8a5652d ) Add limitation on body \ud83d\udccf ( dc33f61 ) 0.2.4 (2018-08-30) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.2.3 (2018-08-22) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.2.2 (2018-08-10) \u00b6 Bug Fixes \u00b6 Commitlint extend should start with @ \ud83d\ude22 ( dc9489f ), closes 40commitlint/resolve-extends/src/index.js#L71 Remove 72 chars limit on body description \ud83d\udd25 ( 5d1edd8 ) 0.2.1 (2018-08-09) \u00b6 Note: Version bump only for package commitlint-config-cozy 0.2.0 (2018-08-09) \u00b6 Features \u00b6 add commitlint-config-cozy package \ud83d\udccf ( b6c7c0e )", "title": "Change Log"}, {"location": "commitlint-config-cozy/CHANGELOG/#change-log", "text": "All notable changes to this project will be documented in this file. See Conventional Commits for commit guidelines.", "title": "Change Log"}, {"location": "commitlint-config-cozy/CHANGELOG/#080-2023-01-31", "text": "", "title": "0.8.0 (2023-01-31)"}, {"location": "commitlint-config-cozy/CHANGELOG/#features", "text": "Update cozy-client and cozy-ui ( 6ae3b04 )", "title": "Features"}, {"location": "commitlint-config-cozy/CHANGELOG/#079-2022-10-03", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.7.9 (2022-10-03)"}, {"location": "commitlint-config-cozy/CHANGELOG/#078-2022-08-01", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.7.8 (2022-08-01)"}, {"location": "commitlint-config-cozy/CHANGELOG/#077-2022-05-13", "text": "", "title": "0.7.7 (2022-05-13)"}, {"location": "commitlint-config-cozy/CHANGELOG/#bug-fixes", "text": "deps: update commitlint monorepo to v16.2.4 ( 6b17ecb )", "title": "Bug Fixes"}, {"location": "commitlint-config-cozy/CHANGELOG/#076-2022-04-04", "text": "", "title": "0.7.6 (2022-04-04)"}, {"location": "commitlint-config-cozy/CHANGELOG/#bug-fixes_1", "text": "bump @commitlint/cli from 16.1.0 to 16.2.3 ( 2167d5b )", "title": "Bug Fixes"}, {"location": "commitlint-config-cozy/CHANGELOG/#075-2022-02-03", "text": "", "title": "0.7.5 (2022-02-03)"}, {"location": "commitlint-config-cozy/CHANGELOG/#bug-fixes_2", "text": "deps: update dependency jest to v26.6.3 ( f442fff )", "title": "Bug Fixes"}, {"location": "commitlint-config-cozy/CHANGELOG/#074-2022-02-01", "text": "", "title": "0.7.4 (2022-02-01)"}, {"location": "commitlint-config-cozy/CHANGELOG/#bug-fixes_3", "text": "deps: update commitlint monorepo ( d3f4f27 )", "title": "Bug Fixes"}, {"location": "commitlint-config-cozy/CHANGELOG/#073-2022-02-01", "text": "", "title": "0.7.3 (2022-02-01)"}, {"location": "commitlint-config-cozy/CHANGELOG/#bug-fixes_4", "text": "deps: update babel monorepo ( dcc215a ) Handle empty context ( 6258e12 )", "title": "Bug Fixes"}, {"location": "commitlint-config-cozy/CHANGELOG/#072-2021-12-20", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.7.2 (2021-12-20)"}, {"location": "commitlint-config-cozy/CHANGELOG/#071-2021-12-02", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.7.1 (2021-12-02)"}, {"location": "commitlint-config-cozy/CHANGELOG/#070-2021-10-22", "text": "", "title": "0.7.0 (2021-10-22)"}, {"location": "commitlint-config-cozy/CHANGELOG/#features_1", "text": "Remove drive from homeHref ( 97010d3 )", "title": "Features"}, {"location": "commitlint-config-cozy/CHANGELOG/#060-2021-02-12", "text": "", "title": "0.6.0 (2021-02-12)"}, {"location": "commitlint-config-cozy/CHANGELOG/#features_2", "text": "Add finance theme ( bb8cf35 )", "title": "Features"}, {"location": "commitlint-config-cozy/CHANGELOG/#050-2020-11-23", "text": "", "title": "0.5.0 (2020-11-23)"}, {"location": "commitlint-config-cozy/CHANGELOG/#features_3", "text": "Update @babel/core and babel-jest ( 352ddc3 ) Update jest ( 3b2c32a )", "title": "Features"}, {"location": "commitlint-config-cozy/CHANGELOG/#046-2020-10-01", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.4.6 (2020-10-01)"}, {"location": "commitlint-config-cozy/CHANGELOG/#045-2020-09-15", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.4.5 (2020-09-15)"}, {"location": "commitlint-config-cozy/CHANGELOG/#044-2020-08-03", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.4.4 (2020-08-03)"}, {"location": "commitlint-config-cozy/CHANGELOG/#043-2020-07-16", "text": "", "title": "0.4.3 (2020-07-16)"}, {"location": "commitlint-config-cozy/CHANGELOG/#bug-fixes_5", "text": "Call revokeSelf if not the owner of the sharing ( f7afc60 )", "title": "Bug Fixes"}, {"location": "commitlint-config-cozy/CHANGELOG/#042-2020-02-27", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.4.2 (2020-02-27)"}, {"location": "commitlint-config-cozy/CHANGELOG/#041-2020-02-25", "text": "", "title": "0.4.1 (2020-02-25)"}, {"location": "commitlint-config-cozy/CHANGELOG/#bug-fixes_6", "text": "cozy-harvest-lib: Always show account form when editing an account ( a8718cd )", "title": "Bug Fixes"}, {"location": "commitlint-config-cozy/CHANGELOG/#040-2019-09-05", "text": "", "title": "0.4.0 (2019-09-05)"}, {"location": "commitlint-config-cozy/CHANGELOG/#features_4", "text": "Add account route ( 7986708 )", "title": "Features"}, {"location": "commitlint-config-cozy/CHANGELOG/#0327-2019-07-19", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.27 (2019-07-19)"}, {"location": "commitlint-config-cozy/CHANGELOG/#0326-2019-07-19", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.26 (2019-07-19)"}, {"location": "commitlint-config-cozy/CHANGELOG/#0325-2019-07-11", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.25 (2019-07-11)"}, {"location": "commitlint-config-cozy/CHANGELOG/#0324-2019-03-18", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.24 (2019-03-18)"}, {"location": "commitlint-config-cozy/CHANGELOG/#0323-2019-03-12", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.23 (2019-03-12)"}, {"location": "commitlint-config-cozy/CHANGELOG/#0322-2019-03-12", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.22 (2019-03-12)"}, {"location": "commitlint-config-cozy/CHANGELOG/#0321-2019-03-12", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.21 (2019-03-12)"}, {"location": "commitlint-config-cozy/CHANGELOG/#0320-2019-03-12", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.20 (2019-03-12)"}, {"location": "commitlint-config-cozy/CHANGELOG/#0319-2019-02-25", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.19 (2019-02-25)"}, {"location": "commitlint-config-cozy/CHANGELOG/#0318-2019-02-12", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.18 (2019-02-12)"}, {"location": "commitlint-config-cozy/CHANGELOG/#0317-2019-02-11", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.17 (2019-02-11)"}, {"location": "commitlint-config-cozy/CHANGELOG/#0316-2019-01-16", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.16 (2019-01-16)"}, {"location": "commitlint-config-cozy/CHANGELOG/#0315-2019-01-11", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.15 (2019-01-11)"}, {"location": "commitlint-config-cozy/CHANGELOG/#0314-2018-12-28", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.14 (2018-12-28)"}, {"location": "commitlint-config-cozy/CHANGELOG/#0313-2018-12-26", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.13 (2018-12-26)"}, {"location": "commitlint-config-cozy/CHANGELOG/#0312-2018-12-17", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.12 (2018-12-17)"}, {"location": "commitlint-config-cozy/CHANGELOG/#0311-2018-12-10", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.11 (2018-12-10)"}, {"location": "commitlint-config-cozy/CHANGELOG/#0310-2018-11-29", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.10 (2018-11-29)"}, {"location": "commitlint-config-cozy/CHANGELOG/#039-2018-10-16", "text": "", "title": "0.3.9 (2018-10-16)"}, {"location": "commitlint-config-cozy/CHANGELOG/#bug-fixes_7", "text": "deps: update commitlint monorepo to v7.2.1 ( 0ee263a )", "title": "Bug Fixes"}, {"location": "commitlint-config-cozy/CHANGELOG/#038-2018-10-11", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.8 (2018-10-11)"}, {"location": "commitlint-config-cozy/CHANGELOG/#037-2018-10-09", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.7 (2018-10-09)"}, {"location": "commitlint-config-cozy/CHANGELOG/#036-2018-10-02", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.6 (2018-10-02)"}, {"location": "commitlint-config-cozy/CHANGELOG/#035-2018-09-27", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.5 (2018-09-27)"}, {"location": "commitlint-config-cozy/CHANGELOG/#034-2018-09-25", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.4 (2018-09-25)"}, {"location": "commitlint-config-cozy/CHANGELOG/#033-2018-09-25", "text": "", "title": "0.3.3 (2018-09-25)"}, {"location": "commitlint-config-cozy/CHANGELOG/#bug-fixes_8", "text": "add babel-core bridge for v7 ( 18665a8 ), closes /github.com/babel/babel/issues/8206#issuecomment-419705758 use ^7.1.0 for babel-jest issue ( 34b2d14 )", "title": "Bug Fixes"}, {"location": "commitlint-config-cozy/CHANGELOG/#032-2018-09-25", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.2 (2018-09-25)"}, {"location": "commitlint-config-cozy/CHANGELOG/#031-2018-09-21", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.3.1 (2018-09-21)"}, {"location": "commitlint-config-cozy/CHANGELOG/#030-2018-09-17", "text": "", "title": "0.3.0 (2018-09-17)"}, {"location": "commitlint-config-cozy/CHANGELOG/#features_5", "text": "Add commitlint cli on dependency \u2699\ufe0f ( 8a5652d ) Add limitation on body \ud83d\udccf ( dc33f61 )", "title": "Features"}, {"location": "commitlint-config-cozy/CHANGELOG/#024-2018-08-30", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.2.4 (2018-08-30)"}, {"location": "commitlint-config-cozy/CHANGELOG/#023-2018-08-22", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.2.3 (2018-08-22)"}, {"location": "commitlint-config-cozy/CHANGELOG/#022-2018-08-10", "text": "", "title": "0.2.2 (2018-08-10)"}, {"location": "commitlint-config-cozy/CHANGELOG/#bug-fixes_9", "text": "Commitlint extend should start with @ \ud83d\ude22 ( dc9489f ), closes 40commitlint/resolve-extends/src/index.js#L71 Remove 72 chars limit on body description \ud83d\udd25 ( 5d1edd8 )", "title": "Bug Fixes"}, {"location": "commitlint-config-cozy/CHANGELOG/#021-2018-08-09", "text": "Note: Version bump only for package commitlint-config-cozy", "title": "0.2.1 (2018-08-09)"}, {"location": "commitlint-config-cozy/CHANGELOG/#020-2018-08-09", "text": "", "title": "0.2.0 (2018-08-09)"}, {"location": "commitlint-config-cozy/CHANGELOG/#features_6", "text": "add commitlint-config-cozy package \ud83d\udccf ( b6c7c0e )", "title": "Features"}, {"location": "cozy-app-publish/", "text": "Cozy App Publish \u00b6 What\u2019s cozy-app-publish? \u00b6 cozy-app-publish is a command line tool that publish a Cozy application to the Cozy registry according to some options. Requirements \u00b6 Node.js version 8 or higher; Install \u00b6 yarn add --dev cozy-app-publish Registry documentation \u00b6 You can find more information about the registry and how to prepare an application to be published in the official registry documentation . Usage via Travis CI (recommended) \u00b6 First of all, don\u2019t forget to build the application: # build the application (in the ./build folder here) yarn build Then, just publish it using the Travis CI workflow: # publish it, REGISTRY_TOKEN should be # encrypted and provided via Travis CI environment # BUILD_COMMIT is your last build commit hash (git rev-parse build) yarn cozy-app-publish \\ --token $REGISTRY_TOKEN \\ --build-commit $BUILD_COMMIT Published version is inferred from the tag set on current commit or the version defined in the manifest version property: If the current commit has no tag associated, then this is a dev version in the form -dev. If the current commit has a beta tag x.y.z-beta.n or a stable tag x.y.z , then this is a beta or stable version and the tag value is used as the version Manual usage (not recommended) \u00b6 First of all, don\u2019t forget to build the application: # build the application (in the ./build folder here) yarn build Then, just publish it using: yarn cozy-app-publish \\ --token $REGISTRY_TOKEN \\ --build-url https://github.com/cozy/cozy-collect/archive/042cef26d9d33ea604fe4364eaab569980b500c9.tar.gz \\ --manual-version 1.0.2-dev.042cef26d9d33ea604fe4364eaab569980b500c9 Publishing a beta version \u00b6 Beta versions are only available through beta channel of the registry and are not automatically deployable on production instances. However a beta tester can force deployment of beta versions of a given (installed) app from Cozy store. Ask your Cozy representative to explain you how to do this. Let\u2019s say you plan to publish version 1.0.2 of your application and want to test it before publishing it to stable. Then you will publish a 1.0.2-beta.1 version, test it, publish other beta versions if some adjustement are needed and when you\u2019re satisfied with the version you will publish a stable version. To publish a beta version: Have the target stable version as the version in your manifest file (eg 1.0.2 in our example). The manifest file always reference stable version. Publish with cozy-app-publish using the beta version like 1.0.2-beta.1 yarn cozy-app-publish \\ --token $REGISTRY_TOKEN \\ --build-url https://github.com/cozy/cozy-collect/archive/042cef26d9d33ea604fe4364eaab569980b500c9.tar.gz \\ --manual-version 1.0.2-beta.1 Publishing a stable version \u00b6 Instances auto-update app versions as soon as they are published as stable. Publishing a new stable version will make it available immediately to all instances (existing and new ones) unless permission changes requiring user\u2019s validation. To publish a stable version, simply use a version in the form x.y.z and it will be considered as stable. Because manifest\u2019s version doesn\u2019t need to be changed between beta and stable, you don\u2019t need to rebuild the application and can publish the exact same app package you built for beta publication yarn cozy-app-publish \\ --token $REGISTRY_TOKEN \\ --build-url https://github.com/cozy/cozy-collect/archive/042cef26d9d33ea604fe4364eaab569980b500c9.tar.gz \\ --manual-version 1.0.2 Options \u00b6 --token (required) \u00b6 The registry editor token. This token must match the editor name and is provided by Cozy Cloud (with the name) in order to use the registry. --build-dir \u00b6 The path to the build folder, relative to the current directory. Since the \u2018standard\u2019 Cozy application builds in the build/ folder, build is the default value. This folder is mainly used to read the application manifest during publishing. --build-url \u00b6 For now, the registry a build archive (.tar.gz file) from an external link to be used in the cozy-stack. In the travis script, this url is computed using the Github trick to get archives from a commit url (but it\u2019s overwritten if provided by this option). For the manual script, we have to provide it. --build-commit \u00b6 Using the travis mode, the archive tarball URL is computed using github and the build commit hash. If you are not on your build branch to publish, you can specify the correct build commit hash using this parameter. --manual-version (required for manual usage only) \u00b6 In the manual mode, we don\u2019t have a way to compute the version like in the Travis mode for example. So we have to provide it using this option. --prepublish \u00b6 Specify custom prepublish hook to manage how the app archive is generated and uploaded. The script must export a asynchronous function which has the following signature: module . exports = async ({ appBuildUrl , appSlug , appType , appVersion , buildCommit , registryUrl , registryEditor , registryToken , spaceName }) => { // ... } This function must return an object containing the same options given as parameter, which can have been updated. For example, you may specifiy a new appBuildUrl in the hook. Here\u2019s a description of the different options: Options Description appBuildUrl The url where the build can be retrieved. For example, http://github.com/cozy/cozy-foo/archives/cozy-foo.tar.gz appSlug The slug of the application, as defined in the manifest. Should not be mutated appType webapp or konnector appVersion App version, as defined in the manifest. Should not be mutated. buildCommit sha of the commit, should not be mutated. registryUrl URL of the Cozy registry, should not be mutated. registryEditor Editor as it appears in the Cozy registry. registryToken Registry Token. See registry documentation . Should not be mutated. spaceName Space name in the Cozy registry. --postpublish \u00b6 Works exactly like the prepublish option, but will be executed after the publication. Multiple hooks and built-in hooks \u00b6 You can specify more than one hook by separating them with a , : cozy-app-publish --prepublish , Some hooks are shipped with cozy-app-publish and can be used by specifying their name: cozy-app-publish --prepublish Downcloud prepublish hook \u00b6 cozy-app-publish --prepublish downcloud This hook allows to upload the app to our downcloud server and sets the appBuildUrl accordingly. In order to upload files to our downcloud server, you will need to generate a new pair of RSA keys, add the private key to your ssh-agent and make sure the corresponding public key is present on the downcloud server. Here\u2019s how to do it: Generate a new key pair with ssh-keygen -t rsa -b 4096 -f id_rsa_downcloud_myapp -C downcloud_myapp_deploy . Communicate the public key to someone who can deposit it on the downcloud server. If you\u2019re running things locally, you\u2019ll want to run ssh-add id_rsa_downcloud_myapp to add it to your ssh-agent. If you\u2019re planing to run this cozy-app-publish on Travis, you\u2019ll want to encrypt that file first . Run travis encrypt-file id_rsa_downcloud_myapp and copy the output. This command also generates a id_rsa_downcloud_myapp.enc . To add the key to Travis\u2019s ssh-agent, add the following lines in the before_install section of your .travis.yml , but don\u2019t forget to paste the output of travis encrypt-file where it\u2019s needed. - if [ \"$TRAVIS_SECURE_ENV_VARS\" != \"false\" ]; then PASTE_TRAVIS_ENCRYPT_OUTPUT_HERE; fi - if [ \"$TRAVIS_SECURE_ENV_VARS\" != \"false\" ]; then eval \"$(ssh-agent -s)\"; fi - if [ \"$TRAVIS_SECURE_ENV_VARS\" != \"false\" ]; then chmod 600 id_rsa_downcloud_myapp; fi - if [ \"$TRAVIS_SECURE_ENV_VARS\" != \"false\" ]; then ssh-add id_rsa_downcloud_myapp; fi We recommend changing the path used for the private key. You can change the -out argument of the command output by travis encrypt-file and the corresponding path\u2019s in the commands above. /tmp/id_rsa_downcloud_myapp is a good place to store this key. You mays also change the -in argument of the same command, and change the path of the file id_rsa_downcloud_myapp.enc to whatever you want. We recomend using ./deploy/id_rsa_downcloud_myapp.enc (don\u2019t forget to move the file as well!). Finally, secure the private key . If you\u2019re using Travis, the key is now stored by Travis so you should delete your local copy. If you\u2019re running things on your machine, make sure the private key doesn\u2019t end up in version control. Mattermost postpublish hook \u00b6 cozy-app-publish --postpublish mattermost Sends a message to a mattermost channel to notify of the app\u2019s deployment. Requires the following options: MATTERMOST_HOOK_URL : You will need to set up a new Incoming Hook . MATTERMOST_CHANNEL : (optional) The name of the channel messages will be posted to or else the default channel of the hook will be used --registry-url \u00b6 The url of the registry, by default it will be https://staging-apps-registry.cozycloud.cc . --space \u00b6 Use this options to provide a specific space name of the registry to publish the application in. By default it will be published in the default space. --verbose \u00b6 To print more logs when using tool (useful for debug). Recommended workflow \u00b6 Day to day \u00b6 Development is done on feature branches that are merged into master , once they are complete. Every time someone commits on master , a new archive is created and uploaded on Downcloud and then published to Cozy Cloud registry. Release workflow \u00b6 A new release branch is created from the current state of master . Let\u2019s say we want to deploy version 1.0.0 of the app, we will create release/1.0.0 . Since we created a new branch, we have to bump the version of master , so we have to create a PR to bump to 1.1.0 everywhere it is necessary. This depends on the app, but most of the time it requires to change the package.json and manifest.webapp versions. The only type of commits allowed on this release branch are bug fixes, that should be made on the release branch. To release a stable or beta version, generally we use directly github and the release creation interface. In this interface, don\u2019t forget to fill in the changelog and to check \u201cprelease\u201d for a beta version. The title of the release must be the released version (ex.: 1.40.0-beta.1 ) Every time bugs are fixed and the version is considered for release, the latest commit is tagged with a prerelease version number, eg. 1.0.0-beta.1 , 1.0.0-beta.2 , etc\u2026 Each of these prereleases is automatically uploaded on downcloud and deployed on instances that are on the beta channel. Once the branch is deemed ready for release, the last commit is tagged with the final version \u2014 1.0.0 in our example. It is then, again, uploaded on downcloud, published on the registry and deployed on specific instances as needed. The release branch is merged back into master so that all the bugfixes aren\u2019t lost. Versions \u00b6 We apply the semver convention: If the release brings only bug fixes, then we should create a patch version. If the release brings at least one feature, then we should create a minor version. If the release changes its application\u2019s permissions, we should create a minor version even if this release is for bug fixes only. Hot Fix \u00b6 If you need to quickly fix a bug in production, then you have to: fetch the latest branch release create a new release branch from there (since this is a bug fix, this is a patch version) fix the bug Make a beta Publish Merge it on master Example: You have to hot fix Drive. The current stable version of Drive is : 1.45.0. Master is on 1.47.0. Then you need to fetch release/1.45.0 Create a branch from this release: git checkout -b release/1.45.1 git commit -m \u201cfix: Bug fix..\u201d git push git tag \u2026", "title": "Publish on the store (app-publish)"}, {"location": "cozy-app-publish/#cozy-app-publish", "text": "", "title": "Cozy App Publish"}, {"location": "cozy-app-publish/#whats-cozy-app-publish", "text": "cozy-app-publish is a command line tool that publish a Cozy application to the Cozy registry according to some options.", "title": "What's cozy-app-publish?"}, {"location": "cozy-app-publish/#requirements", "text": "Node.js version 8 or higher;", "title": "Requirements"}, {"location": "cozy-app-publish/#install", "text": "yarn add --dev cozy-app-publish", "title": "Install"}, {"location": "cozy-app-publish/#registry-documentation", "text": "You can find more information about the registry and how to prepare an application to be published in the official registry documentation .", "title": "Registry documentation"}, {"location": "cozy-app-publish/#usage-via-travis-ci-recommended", "text": "First of all, don\u2019t forget to build the application: # build the application (in the ./build folder here) yarn build Then, just publish it using the Travis CI workflow: # publish it, REGISTRY_TOKEN should be # encrypted and provided via Travis CI environment # BUILD_COMMIT is your last build commit hash (git rev-parse build) yarn cozy-app-publish \\ --token $REGISTRY_TOKEN \\ --build-commit $BUILD_COMMIT Published version is inferred from the tag set on current commit or the version defined in the manifest version property: If the current commit has no tag associated, then this is a dev version in the form -dev. If the current commit has a beta tag x.y.z-beta.n or a stable tag x.y.z , then this is a beta or stable version and the tag value is used as the version", "title": "Usage via Travis CI (recommended)"}, {"location": "cozy-app-publish/#manual-usage-not-recommended", "text": "First of all, don\u2019t forget to build the application: # build the application (in the ./build folder here) yarn build Then, just publish it using: yarn cozy-app-publish \\ --token $REGISTRY_TOKEN \\ --build-url https://github.com/cozy/cozy-collect/archive/042cef26d9d33ea604fe4364eaab569980b500c9.tar.gz \\ --manual-version 1.0.2-dev.042cef26d9d33ea604fe4364eaab569980b500c9", "title": "Manual usage (not recommended)"}, {"location": "cozy-app-publish/#publishing-a-beta-version", "text": "Beta versions are only available through beta channel of the registry and are not automatically deployable on production instances. However a beta tester can force deployment of beta versions of a given (installed) app from Cozy store. Ask your Cozy representative to explain you how to do this. Let\u2019s say you plan to publish version 1.0.2 of your application and want to test it before publishing it to stable. Then you will publish a 1.0.2-beta.1 version, test it, publish other beta versions if some adjustement are needed and when you\u2019re satisfied with the version you will publish a stable version. To publish a beta version: Have the target stable version as the version in your manifest file (eg 1.0.2 in our example). The manifest file always reference stable version. Publish with cozy-app-publish using the beta version like 1.0.2-beta.1 yarn cozy-app-publish \\ --token $REGISTRY_TOKEN \\ --build-url https://github.com/cozy/cozy-collect/archive/042cef26d9d33ea604fe4364eaab569980b500c9.tar.gz \\ --manual-version 1.0.2-beta.1", "title": "Publishing a beta version"}, {"location": "cozy-app-publish/#publishing-a-stable-version", "text": "Instances auto-update app versions as soon as they are published as stable. Publishing a new stable version will make it available immediately to all instances (existing and new ones) unless permission changes requiring user\u2019s validation. To publish a stable version, simply use a version in the form x.y.z and it will be considered as stable. Because manifest\u2019s version doesn\u2019t need to be changed between beta and stable, you don\u2019t need to rebuild the application and can publish the exact same app package you built for beta publication yarn cozy-app-publish \\ --token $REGISTRY_TOKEN \\ --build-url https://github.com/cozy/cozy-collect/archive/042cef26d9d33ea604fe4364eaab569980b500c9.tar.gz \\ --manual-version 1.0.2", "title": "Publishing a stable version"}, {"location": "cozy-app-publish/#options", "text": "", "title": "Options"}, {"location": "cozy-app-publish/#-token-lteditor-tokengt-required", "text": "The registry editor token. This token must match the editor name and is provided by Cozy Cloud (with the name) in order to use the registry.", "title": "--token <editor-token> (required)"}, {"location": "cozy-app-publish/#-build-dir-ltrelative-pathgt", "text": "The path to the build folder, relative to the current directory. Since the \u2018standard\u2019 Cozy application builds in the build/ folder, build is the default value. This folder is mainly used to read the application manifest during publishing.", "title": "--build-dir <relative-path>"}, {"location": "cozy-app-publish/#-build-url-lturlgt", "text": "For now, the registry a build archive (.tar.gz file) from an external link to be used in the cozy-stack. In the travis script, this url is computed using the Github trick to get archives from a commit url (but it\u2019s overwritten if provided by this option). For the manual script, we have to provide it.", "title": "--build-url <url>"}, {"location": "cozy-app-publish/#-build-commit-ltcommit-hashgt", "text": "Using the travis mode, the archive tarball URL is computed using github and the build commit hash. If you are not on your build branch to publish, you can specify the correct build commit hash using this parameter.", "title": "--build-commit <commit-hash>"}, {"location": "cozy-app-publish/#-manual-version-ltversiongt-required-for-manual-usage-only", "text": "In the manual mode, we don\u2019t have a way to compute the version like in the Travis mode for example. So we have to provide it using this option.", "title": "--manual-version <version> (required for manual usage only)"}, {"location": "cozy-app-publish/#-prepublish-ltscript_pathgt", "text": "Specify custom prepublish hook to manage how the app archive is generated and uploaded. The script must export a asynchronous function which has the following signature: module . exports = async ({ appBuildUrl , appSlug , appType , appVersion , buildCommit , registryUrl , registryEditor , registryToken , spaceName }) => { // ... } This function must return an object containing the same options given as parameter, which can have been updated. For example, you may specifiy a new appBuildUrl in the hook. Here\u2019s a description of the different options: Options Description appBuildUrl The url where the build can be retrieved. For example, http://github.com/cozy/cozy-foo/archives/cozy-foo.tar.gz appSlug The slug of the application, as defined in the manifest. Should not be mutated appType webapp or konnector appVersion App version, as defined in the manifest. Should not be mutated. buildCommit sha of the commit, should not be mutated. registryUrl URL of the Cozy registry, should not be mutated. registryEditor Editor as it appears in the Cozy registry. registryToken Registry Token. See registry documentation . Should not be mutated. spaceName Space name in the Cozy registry.", "title": "--prepublish <script_path>"}, {"location": "cozy-app-publish/#-postpublish-ltscript_pathgt", "text": "Works exactly like the prepublish option, but will be executed after the publication.", "title": "--postpublish <script_path>"}, {"location": "cozy-app-publish/#multiple-hooks-and-built-in-hooks", "text": "You can specify more than one hook by separating them with a , : cozy-app-publish --prepublish , Some hooks are shipped with cozy-app-publish and can be used by specifying their name: cozy-app-publish --prepublish ", "title": "Multiple hooks and built-in hooks"}, {"location": "cozy-app-publish/#downcloud-prepublish-hook", "text": "cozy-app-publish --prepublish downcloud This hook allows to upload the app to our downcloud server and sets the appBuildUrl accordingly. In order to upload files to our downcloud server, you will need to generate a new pair of RSA keys, add the private key to your ssh-agent and make sure the corresponding public key is present on the downcloud server. Here\u2019s how to do it: Generate a new key pair with ssh-keygen -t rsa -b 4096 -f id_rsa_downcloud_myapp -C downcloud_myapp_deploy . Communicate the public key to someone who can deposit it on the downcloud server. If you\u2019re running things locally, you\u2019ll want to run ssh-add id_rsa_downcloud_myapp to add it to your ssh-agent. If you\u2019re planing to run this cozy-app-publish on Travis, you\u2019ll want to encrypt that file first . Run travis encrypt-file id_rsa_downcloud_myapp and copy the output. This command also generates a id_rsa_downcloud_myapp.enc . To add the key to Travis\u2019s ssh-agent, add the following lines in the before_install section of your .travis.yml , but don\u2019t forget to paste the output of travis encrypt-file where it\u2019s needed. - if [ \"$TRAVIS_SECURE_ENV_VARS\" != \"false\" ]; then PASTE_TRAVIS_ENCRYPT_OUTPUT_HERE; fi - if [ \"$TRAVIS_SECURE_ENV_VARS\" != \"false\" ]; then eval \"$(ssh-agent -s)\"; fi - if [ \"$TRAVIS_SECURE_ENV_VARS\" != \"false\" ]; then chmod 600 id_rsa_downcloud_myapp; fi - if [ \"$TRAVIS_SECURE_ENV_VARS\" != \"false\" ]; then ssh-add id_rsa_downcloud_myapp; fi We recommend changing the path used for the private key. You can change the -out argument of the command output by travis encrypt-file and the corresponding path\u2019s in the commands above. /tmp/id_rsa_downcloud_myapp is a good place to store this key. You mays also change the -in argument of the same command, and change the path of the file id_rsa_downcloud_myapp.enc to whatever you want. We recomend using ./deploy/id_rsa_downcloud_myapp.enc (don\u2019t forget to move the file as well!). Finally, secure the private key . If you\u2019re using Travis, the key is now stored by Travis so you should delete your local copy. If you\u2019re running things on your machine, make sure the private key doesn\u2019t end up in version control.", "title": "Downcloud prepublish hook"}, {"location": "cozy-app-publish/#mattermost-postpublish-hook", "text": "cozy-app-publish --postpublish mattermost Sends a message to a mattermost channel to notify of the app\u2019s deployment. Requires the following options: MATTERMOST_HOOK_URL : You will need to set up a new Incoming Hook . MATTERMOST_CHANNEL : (optional) The name of the channel messages will be posted to or else the default channel of the hook will be used", "title": "Mattermost postpublish hook"}, {"location": "cozy-app-publish/#-registry-url-lturlgt", "text": "The url of the registry, by default it will be https://staging-apps-registry.cozycloud.cc .", "title": "--registry-url <url>"}, {"location": "cozy-app-publish/#-space-ltspace-namegt", "text": "Use this options to provide a specific space name of the registry to publish the application in. By default it will be published in the default space.", "title": "--space <space-name>"}, {"location": "cozy-app-publish/#-verbose", "text": "To print more logs when using tool (useful for debug).", "title": "--verbose"}, {"location": "cozy-app-publish/#recommended-workflow", "text": "", "title": "Recommended workflow"}, {"location": "cozy-app-publish/#day-to-day", "text": "Development is done on feature branches that are merged into master , once they are complete. Every time someone commits on master , a new archive is created and uploaded on Downcloud and then published to Cozy Cloud registry.", "title": "Day to day"}, {"location": "cozy-app-publish/#release-workflow", "text": "A new release branch is created from the current state of master . Let\u2019s say we want to deploy version 1.0.0 of the app, we will create release/1.0.0 . Since we created a new branch, we have to bump the version of master , so we have to create a PR to bump to 1.1.0 everywhere it is necessary. This depends on the app, but most of the time it requires to change the package.json and manifest.webapp versions. The only type of commits allowed on this release branch are bug fixes, that should be made on the release branch. To release a stable or beta version, generally we use directly github and the release creation interface. In this interface, don\u2019t forget to fill in the changelog and to check \u201cprelease\u201d for a beta version. The title of the release must be the released version (ex.: 1.40.0-beta.1 ) Every time bugs are fixed and the version is considered for release, the latest commit is tagged with a prerelease version number, eg. 1.0.0-beta.1 , 1.0.0-beta.2 , etc\u2026 Each of these prereleases is automatically uploaded on downcloud and deployed on instances that are on the beta channel. Once the branch is deemed ready for release, the last commit is tagged with the final version \u2014 1.0.0 in our example. It is then, again, uploaded on downcloud, published on the registry and deployed on specific instances as needed. The release branch is merged back into master so that all the bugfixes aren\u2019t lost.", "title": "Release workflow"}, {"location": "cozy-app-publish/#versions", "text": "We apply the semver convention: If the release brings only bug fixes, then we should create a patch version. If the release brings at least one feature, then we should create a minor version. If the release changes its application\u2019s permissions, we should create a minor version even if this release is for bug fixes only.", "title": "Versions"}, {"location": "cozy-app-publish/#hot-fix", "text": "If you need to quickly fix a bug in production, then you have to: fetch the latest branch release create a new release branch from there (since this is a bug fix, this is a patch version) fix the bug Make a beta Publish Merge it on master Example: You have to hot fix Drive. The current stable version of Drive is : 1.45.0. Master is on 1.47.0. Then you need to fetch release/1.45.0 Create a branch from this release: git checkout -b release/1.45.1 git commit -m \u201cfix: Bug fix..\u201d git push git tag \u2026", "title": "Hot Fix"}, {"location": "cozy-app-publish/CHANGELOG/", "text": "Change Log \u00b6 All notable changes to this project will be documented in this file. See Conventional Commits for commit guidelines. 0.34.0 (2024-04-10) \u00b6 Features \u00b6 Allow the possibility to override the mode even on Travis CI ( a565a0a ) 0.33.0 (2023-01-31) \u00b6 Features \u00b6 Update cozy-client and cozy-ui ( 6ae3b04 ) 0.32.1 (2022-10-27) \u00b6 Note: Version bump only for package cozy-app-publish 0.32.0 (2022-10-04) \u00b6 Features \u00b6 Prohibits putting only spaces in a document name ( 5568408 ) 0.31.0 (2022-07-05) \u00b6 Features \u00b6 All oauth methods to handle reconection case ( b1a6033 ) 0.30.4 (2022-06-14) \u00b6 Note: Version bump only for package cozy-app-publish 0.30.3 (2022-06-13) \u00b6 Note: Version bump only for package cozy-app-publish 0.30.2 (2022-06-03) \u00b6 Bug Fixes \u00b6 bump tar from 4.4.19 to 6.1.11 ( 128c4a3 ) 0.30.1 (2022-06-02) \u00b6 Note: Version bump only for package cozy-app-publish 0.30.0 (2022-05-25) \u00b6 Bug Fixes \u00b6 bump argparse from 1.0.10 to 2.0.1 ( 832b3db ) Features \u00b6 Remove useVaultClient call in LegacyTriggerManager ( 439e603 ) 0.29.0 (2022-02-03) \u00b6 Bug Fixes \u00b6 deps: update dependency jest to v26.6.3 ( f442fff ) Features \u00b6 Add app parameter to cozy-intent \u2018s openApp method ( 58e0797 ) 0.28.1 (2021-12-02) \u00b6 Note: Version bump only for package cozy-app-publish 0.28.0 (2021-11-03) \u00b6 Features \u00b6 Add verror in cozy-app-publish dependencies ( 653ae83 ) 0.27.2 (2021-10-12) \u00b6 Bug Fixes \u00b6 Fix travis icon on mattermost publish announcement ( 798fac5 ) 0.27.1 (2021-09-03) \u00b6 Bug Fixes \u00b6 Lint cozy-app-publish/README.md ( ad636c5 ) 0.27.0 (2021-02-12) \u00b6 Features \u00b6 Add finance theme ( bb8cf35 ) 0.26.0 (2020-11-23) \u00b6 Features \u00b6 Update jest ( 3b2c32a ) Use ^ for dependencies ( fc28de7 ) 0.25.2 (2020-11-11) \u00b6 Note: Version bump only for package cozy-app-publish 0.25.1 (2020-11-05) \u00b6 Bug Fixes \u00b6 Adjust aligment issues ( efdf056 ) 0.25.0 (2020-08-13) \u00b6 Features \u00b6 Show confirmation prompt before prepublishing ( 3812d94 ) 0.24.1 (2020-08-03) \u00b6 Note: Version bump only for package cozy-app-publish 0.24.0 (2020-07-28) \u00b6 Bug Fixes \u00b6 Clone response since we need to read the text() after reading json() ( 0dd0c3a ) Features \u00b6 Use VError to chain stack traces ( fd3e586 ) 0.23.1 (2020-07-16) \u00b6 Note: Version bump only for package cozy-app-publish 0.23.0 (2020-07-16) \u00b6 Bug Fixes \u00b6 Call revokeSelf if not the owner of the sharing ( f7afc60 ) Features \u00b6 Update lodash accross all packages ( 6a20128 ) 0.22.3 (2020-02-26) \u00b6 Bug Fixes \u00b6 Export src files ( ba1b5c3 ) Import packagejson ( a210b8f ) 0.22.2 (2020-02-25) \u00b6 Note: Version bump only for package cozy-app-publish 0.22.1 (2020-02-24) \u00b6 Bug Fixes \u00b6 Must declare error variable in catch block ( cdd1d42 ) 0.22.0 (2020-02-24) \u00b6 Features \u00b6 Log precise error when failing to require hook ( 3636156 ) 0.21.0 (2020-02-17) \u00b6 Features \u00b6 Ability to send publication message on several channels ( b3d84ab ) Add way to test easily the mattermost hook ( 8d01617 ) Publication message mattermost chan depends on registry chan ( 464430a ) 0.20.3 (2020-02-12) \u00b6 Bug Fixes \u00b6 cozy-app-publish: Mattermost post ( 2f7f986 ) 0.20.2 (2020-01-31) \u00b6 Note: Version bump only for package cozy-app-publish 0.20.1 (2020-01-24) \u00b6 Bug Fixes \u00b6 cozy-app-publish: Handle explicit default space ( dc355cc ) 0.20.0 (2019-11-04) \u00b6 Bug Fixes \u00b6 Translating components ( 1101a66 ) Features \u00b6 Output commit link and travis link in publish message ( 779028e ) 0.19.3 (2019-10-07) \u00b6 Note: Version bump only for package cozy-app-publish 0.19.2 (2019-09-16) \u00b6 Note: Version bump only for package cozy-app-publish 0.19.1 (2019-09-13) \u00b6 Bug Fixes \u00b6 deps: update dependency tar to v4.4.10 ( 5cc8b48 ) 0.19.0 (2019-09-05) \u00b6 Features \u00b6 Add account route ( 7986708 ) 0.18.3 (2019-08-27) \u00b6 Note: Version bump only for package cozy-app-publish 0.18.2 (2019-08-21) \u00b6 Note: Version bump only for package cozy-app-publish 0.18.1 (2019-08-20) \u00b6 Note: Version bump only for package cozy-app-publish 0.18.0 (2019-08-14) \u00b6 Features \u00b6 cozy-app-publish: Add space and application type in matter\u2026 ( #708 ) ( a85a1aa ) cozy-app-publish: Add space and application type in mattermost ( c6b443f ) 0.17.0 (2019-08-13) \u00b6 Features \u00b6 cozy-app-publish: Make mattermost channel optional ( 1fce23d ) 0.16.4 (2019-07-19) \u00b6 Note: Version bump only for package cozy-app-publish 0.16.3 (2019-07-11) \u00b6 Bug Fixes \u00b6 deps: Update dependency lodash to v4.17.13 [SECURITY] ( #648 ) ( 1b36dac ) 0.16.2 (2019-06-25) \u00b6 Bug Fixes \u00b6 cozy-app-publish: Argparse generates null default values ( f9c08c8 ) 0.16.1 (2019-06-21) \u00b6 Bug Fixes \u00b6 cozy-app-publish: Handle snake case cli options ( 5c7da87 ) 0.16.0 (2019-06-18) \u00b6 Bug Fixes \u00b6 Expose FlagSwitcher only in browser context ( f2fafa7 ), closes #402 Features \u00b6 Use argparse ( 8298c62 ) 0.15.0 (2019-03-20) \u00b6 Features \u00b6 app-publish/downcloud: Use space name in remote path ( 22e88c5 ) 0.14.0 (2019-03-20) \u00b6 Features \u00b6 app-publish/downcloud: Use buildDir option ( 89bd5b8 ) 0.13.1 (2019-03-13) \u00b6 Bug Fixes \u00b6 Add lodash as dependency ( a580a78 ) 0.13.0 (2019-03-13) \u00b6 Bug Fixes \u00b6 publish: Typo in help ( 13e6d8b ) Features \u00b6 publish: Let npm warn when using old engine ( 810e9ce ) publish: Tag prefix in travis and manual ( 27b99c1 ) publish: Tags can contain a prefix ( bf59771 ) 0.12.3 (2019-03-13) \u00b6 Note: Version bump only for package cozy-app-publish 0.12.2 (2019-03-12) \u00b6 Note: Version bump only for package cozy-app-publish 0.12.1 (2019-03-07) \u00b6 Note: Version bump only for package cozy-app-publish 0.12.0 (2019-03-05) \u00b6 Bug Fixes \u00b6 Handle errors correctly ( 0769144 ) Features \u00b6 Improve descriptions ( cee1e6f ) yes ( df005ea ) 0.11.1 (2019-02-28) \u00b6 Bug Fixes \u00b6 Use short commit for travis version ( dabb28b ) 0.11.0 (2019-02-28) \u00b6 Bug Fixes \u00b6 Add error handling to CLI main handler ( 2f4b105 ) Reject on process/pipe error ( 35e13d4 ) Features \u00b6 appBuildURL can be provided by prepublish hooks ( c3f09ee ) Auto version in manual mode ( 4cf5065 ) Better error message if custom hook cannot be loaded ( 0f7ceae ) Logs for shasum ( 9190c10 ) Print stack when erroring ( f17de04 ) 0.10.5 (2019-01-29) \u00b6 Note: Version bump only for package cozy-app-publish 0.10.4 (2019-01-21) \u00b6 Note: Version bump only for package cozy-app-publish 0.10.3 (2019-01-10) \u00b6 Bug Fixes \u00b6 Shasum was not following redirects ( 94807ae ) 0.10.2 (2019-01-07) \u00b6 Bug Fixes \u00b6 deps: update dependency chalk to v2.4.2 ( e0921e2 ) 0.10.1 (2019-01-03) \u00b6 Bug Fixes \u00b6 Don\u2019t read publish response stream twice ( a6e7ca7 ) 0.10.0 (2018-12-28) \u00b6 Bug Fixes \u00b6 publish: Catch publishing error ( 63bf575 ) publish: Handle 404 error ( c71f7e6 ) Features \u00b6 publish: Do sha-sum in Node ( de9201d ), closes #68 0.9.1 (2018-12-10) \u00b6 Note: Version bump only for package cozy-app-publish 0.9.0 (2018-10-15) \u00b6 Features \u00b6 app-publish: Remove rundeck postpublish \ud83d\udd25 ( c9c5ffe ) app-publish: Update Mattermost message \ud83d\udcdd ( 8d32a06 ) 0.8.5 (2018-10-11) \u00b6 Note: Version bump only for package cozy-app-publish 0.8.4 (2018-09-27) \u00b6 Note: Version bump only for package cozy-app-publish 0.8.3 (2018-09-25) \u00b6 Note: Version bump only for package cozy-app-publish 0.8.2 (2018-09-25) \u00b6 Bug Fixes \u00b6 add babel-core bridge for v7 ( 18665a8 ), closes /github.com/babel/babel/issues/8206#issuecomment-419705758 0.8.1 (2018-09-21) \u00b6 Note: Version bump only for package cozy-app-publish 0.8.0 (2018-09-18) \u00b6 Features \u00b6 cozy-app-publish: Fail on Travis error \u2728 ( 0307241 ) cozy-app-publish: Throw publish error \u2728 ( 08db1c5 ) 0.7.2 (2018-09-11) \u00b6 Bug Fixes \u00b6 Downcloud folder name \ud83d\ude91 ( c8ac28b ) 0.7.1 (2018-09-07) \u00b6 Bug Fixes \u00b6 Avoid in archive folder \ud83d\ude91 ( 8b09b4b ) 0.7.0 (2018-09-04) \u00b6 Features \u00b6 travis: Throw error on prepublish fail \u2728 ( 7a88817 ) 0.6.0 (2018-08-29) \u00b6 Features \u00b6 cozy-app-publish: Better options check \ud83d\udc6e ( 8f2b33d ) 0.5.5 (2018-08-28) \u00b6 Note: Version bump only for package cozy-app-publish 0.5.4 (2018-08-28) \u00b6 Bug Fixes \u00b6 typo in deploy scripts example in readme ( cf3b558 ) 0.5.3 (2018-08-22) \u00b6 Note: Version bump only for package cozy-app-publish 0.5.2 (2018-08-21) \u00b6 Note: Version bump only for package cozy-app-publish 0.5.1 (2018-08-11) \u00b6 Note: Version bump only for package cozy-app-publish 0.5.0 (2018-08-10) \u00b6 Bug Fixes \u00b6 remove .prettierrc.json from cozy-app-publish ( 1cd528c ) Features \u00b6 import cozy-app-publish as a package ( 403d90d ) Change Log \u00b6 All notable changes to this project will be documented in this file. The format is based on Keep a Changelog and this project adheres to Semantic Versioning . Unreleased \u00b6 Changed \u00b6 none yet Fixed \u00b6 none yet Added \u00b6 disabled attribute for component Removed \u00b6 none yet Deprecated \u00b6 none yet Security \u00b6 none yet v0.3.6 \u00b6 Fixed \u00b6 Make --build-commit usage more priority than the TRAVIS_TAG environment variale v0.3.5 \u00b6 Added \u00b6 Enable --build-url option on Travis mode v0.3.4 \u00b6 Fixed \u00b6 Don\u2019t throw an error on 409 Conflict registry response (version already exists) v0.3.3 \u00b6 Fixed \u00b6 Prefer an option to provided the correct build commit hash: --build-commit $BUILD_COMMIT v0.3.2 \u00b6 Fixed \u00b6 Bug when using BUILD_COMMIT v0.3.1 \u00b6 Changed \u00b6 Use back the TRAVIS_COMMIT for dev versioning Added \u00b6 Hanlde BUILD_COMMIT from environment for dev versioning v0.3.0 \u00b6 Added \u00b6 Add an automatic mode detection according to environment variables Changed \u00b6 Grab editor name directly from the manifest instead of the CLI option The dev version computing in Travis mode use the archive shasum instead of the TRAVIS_COMMIT Removed \u00b6 --on-branch option with git branch checking in travis mode Unused --travis option The --editor option since it\u2019s now using the manifest Pull request checking in travis mode v0.2.0 \u00b6 Changed \u00b6 Now use the registry in production URL Added \u00b6 Handle registry spaces name through --space option v0.1.1 First release \u00b6 Deploy a Cozy application to Cozy Cloud registry", "title": "Change Log"}, {"location": "cozy-app-publish/CHANGELOG/#change-log", "text": "All notable changes to this project will be documented in this file. See Conventional Commits for commit guidelines.", "title": "Change Log"}, {"location": "cozy-app-publish/CHANGELOG/#0340-2024-04-10", "text": "", "title": "0.34.0 (2024-04-10)"}, {"location": "cozy-app-publish/CHANGELOG/#features", "text": "Allow the possibility to override the mode even on Travis CI ( a565a0a )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0330-2023-01-31", "text": "", "title": "0.33.0 (2023-01-31)"}, {"location": "cozy-app-publish/CHANGELOG/#features_1", "text": "Update cozy-client and cozy-ui ( 6ae3b04 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0321-2022-10-27", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.32.1 (2022-10-27)"}, {"location": "cozy-app-publish/CHANGELOG/#0320-2022-10-04", "text": "", "title": "0.32.0 (2022-10-04)"}, {"location": "cozy-app-publish/CHANGELOG/#features_2", "text": "Prohibits putting only spaces in a document name ( 5568408 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0310-2022-07-05", "text": "", "title": "0.31.0 (2022-07-05)"}, {"location": "cozy-app-publish/CHANGELOG/#features_3", "text": "All oauth methods to handle reconection case ( b1a6033 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0304-2022-06-14", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.30.4 (2022-06-14)"}, {"location": "cozy-app-publish/CHANGELOG/#0303-2022-06-13", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.30.3 (2022-06-13)"}, {"location": "cozy-app-publish/CHANGELOG/#0302-2022-06-03", "text": "", "title": "0.30.2 (2022-06-03)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes", "text": "bump tar from 4.4.19 to 6.1.11 ( 128c4a3 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#0301-2022-06-02", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.30.1 (2022-06-02)"}, {"location": "cozy-app-publish/CHANGELOG/#0300-2022-05-25", "text": "", "title": "0.30.0 (2022-05-25)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_1", "text": "bump argparse from 1.0.10 to 2.0.1 ( 832b3db )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#features_4", "text": "Remove useVaultClient call in LegacyTriggerManager ( 439e603 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0290-2022-02-03", "text": "", "title": "0.29.0 (2022-02-03)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_2", "text": "deps: update dependency jest to v26.6.3 ( f442fff )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#features_5", "text": "Add app parameter to cozy-intent \u2018s openApp method ( 58e0797 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0281-2021-12-02", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.28.1 (2021-12-02)"}, {"location": "cozy-app-publish/CHANGELOG/#0280-2021-11-03", "text": "", "title": "0.28.0 (2021-11-03)"}, {"location": "cozy-app-publish/CHANGELOG/#features_6", "text": "Add verror in cozy-app-publish dependencies ( 653ae83 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0272-2021-10-12", "text": "", "title": "0.27.2 (2021-10-12)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_3", "text": "Fix travis icon on mattermost publish announcement ( 798fac5 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#0271-2021-09-03", "text": "", "title": "0.27.1 (2021-09-03)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_4", "text": "Lint cozy-app-publish/README.md ( ad636c5 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#0270-2021-02-12", "text": "", "title": "0.27.0 (2021-02-12)"}, {"location": "cozy-app-publish/CHANGELOG/#features_7", "text": "Add finance theme ( bb8cf35 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0260-2020-11-23", "text": "", "title": "0.26.0 (2020-11-23)"}, {"location": "cozy-app-publish/CHANGELOG/#features_8", "text": "Update jest ( 3b2c32a ) Use ^ for dependencies ( fc28de7 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0252-2020-11-11", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.25.2 (2020-11-11)"}, {"location": "cozy-app-publish/CHANGELOG/#0251-2020-11-05", "text": "", "title": "0.25.1 (2020-11-05)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_5", "text": "Adjust aligment issues ( efdf056 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#0250-2020-08-13", "text": "", "title": "0.25.0 (2020-08-13)"}, {"location": "cozy-app-publish/CHANGELOG/#features_9", "text": "Show confirmation prompt before prepublishing ( 3812d94 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0241-2020-08-03", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.24.1 (2020-08-03)"}, {"location": "cozy-app-publish/CHANGELOG/#0240-2020-07-28", "text": "", "title": "0.24.0 (2020-07-28)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_6", "text": "Clone response since we need to read the text() after reading json() ( 0dd0c3a )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#features_10", "text": "Use VError to chain stack traces ( fd3e586 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0231-2020-07-16", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.23.1 (2020-07-16)"}, {"location": "cozy-app-publish/CHANGELOG/#0230-2020-07-16", "text": "", "title": "0.23.0 (2020-07-16)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_7", "text": "Call revokeSelf if not the owner of the sharing ( f7afc60 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#features_11", "text": "Update lodash accross all packages ( 6a20128 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0223-2020-02-26", "text": "", "title": "0.22.3 (2020-02-26)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_8", "text": "Export src files ( ba1b5c3 ) Import packagejson ( a210b8f )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#0222-2020-02-25", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.22.2 (2020-02-25)"}, {"location": "cozy-app-publish/CHANGELOG/#0221-2020-02-24", "text": "", "title": "0.22.1 (2020-02-24)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_9", "text": "Must declare error variable in catch block ( cdd1d42 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#0220-2020-02-24", "text": "", "title": "0.22.0 (2020-02-24)"}, {"location": "cozy-app-publish/CHANGELOG/#features_12", "text": "Log precise error when failing to require hook ( 3636156 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0210-2020-02-17", "text": "", "title": "0.21.0 (2020-02-17)"}, {"location": "cozy-app-publish/CHANGELOG/#features_13", "text": "Ability to send publication message on several channels ( b3d84ab ) Add way to test easily the mattermost hook ( 8d01617 ) Publication message mattermost chan depends on registry chan ( 464430a )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0203-2020-02-12", "text": "", "title": "0.20.3 (2020-02-12)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_10", "text": "cozy-app-publish: Mattermost post ( 2f7f986 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#0202-2020-01-31", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.20.2 (2020-01-31)"}, {"location": "cozy-app-publish/CHANGELOG/#0201-2020-01-24", "text": "", "title": "0.20.1 (2020-01-24)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_11", "text": "cozy-app-publish: Handle explicit default space ( dc355cc )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#0200-2019-11-04", "text": "", "title": "0.20.0 (2019-11-04)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_12", "text": "Translating components ( 1101a66 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#features_14", "text": "Output commit link and travis link in publish message ( 779028e )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0193-2019-10-07", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.19.3 (2019-10-07)"}, {"location": "cozy-app-publish/CHANGELOG/#0192-2019-09-16", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.19.2 (2019-09-16)"}, {"location": "cozy-app-publish/CHANGELOG/#0191-2019-09-13", "text": "", "title": "0.19.1 (2019-09-13)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_13", "text": "deps: update dependency tar to v4.4.10 ( 5cc8b48 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#0190-2019-09-05", "text": "", "title": "0.19.0 (2019-09-05)"}, {"location": "cozy-app-publish/CHANGELOG/#features_15", "text": "Add account route ( 7986708 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0183-2019-08-27", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.18.3 (2019-08-27)"}, {"location": "cozy-app-publish/CHANGELOG/#0182-2019-08-21", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.18.2 (2019-08-21)"}, {"location": "cozy-app-publish/CHANGELOG/#0181-2019-08-20", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.18.1 (2019-08-20)"}, {"location": "cozy-app-publish/CHANGELOG/#0180-2019-08-14", "text": "", "title": "0.18.0 (2019-08-14)"}, {"location": "cozy-app-publish/CHANGELOG/#features_16", "text": "cozy-app-publish: Add space and application type in matter\u2026 ( #708 ) ( a85a1aa ) cozy-app-publish: Add space and application type in mattermost ( c6b443f )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0170-2019-08-13", "text": "", "title": "0.17.0 (2019-08-13)"}, {"location": "cozy-app-publish/CHANGELOG/#features_17", "text": "cozy-app-publish: Make mattermost channel optional ( 1fce23d )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0164-2019-07-19", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.16.4 (2019-07-19)"}, {"location": "cozy-app-publish/CHANGELOG/#0163-2019-07-11", "text": "", "title": "0.16.3 (2019-07-11)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_14", "text": "deps: Update dependency lodash to v4.17.13 [SECURITY] ( #648 ) ( 1b36dac )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#0162-2019-06-25", "text": "", "title": "0.16.2 (2019-06-25)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_15", "text": "cozy-app-publish: Argparse generates null default values ( f9c08c8 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#0161-2019-06-21", "text": "", "title": "0.16.1 (2019-06-21)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_16", "text": "cozy-app-publish: Handle snake case cli options ( 5c7da87 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#0160-2019-06-18", "text": "", "title": "0.16.0 (2019-06-18)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_17", "text": "Expose FlagSwitcher only in browser context ( f2fafa7 ), closes #402", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#features_18", "text": "Use argparse ( 8298c62 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0150-2019-03-20", "text": "", "title": "0.15.0 (2019-03-20)"}, {"location": "cozy-app-publish/CHANGELOG/#features_19", "text": "app-publish/downcloud: Use space name in remote path ( 22e88c5 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0140-2019-03-20", "text": "", "title": "0.14.0 (2019-03-20)"}, {"location": "cozy-app-publish/CHANGELOG/#features_20", "text": "app-publish/downcloud: Use buildDir option ( 89bd5b8 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0131-2019-03-13", "text": "", "title": "0.13.1 (2019-03-13)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_18", "text": "Add lodash as dependency ( a580a78 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#0130-2019-03-13", "text": "", "title": "0.13.0 (2019-03-13)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_19", "text": "publish: Typo in help ( 13e6d8b )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#features_21", "text": "publish: Let npm warn when using old engine ( 810e9ce ) publish: Tag prefix in travis and manual ( 27b99c1 ) publish: Tags can contain a prefix ( bf59771 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0123-2019-03-13", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.12.3 (2019-03-13)"}, {"location": "cozy-app-publish/CHANGELOG/#0122-2019-03-12", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.12.2 (2019-03-12)"}, {"location": "cozy-app-publish/CHANGELOG/#0121-2019-03-07", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.12.1 (2019-03-07)"}, {"location": "cozy-app-publish/CHANGELOG/#0120-2019-03-05", "text": "", "title": "0.12.0 (2019-03-05)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_20", "text": "Handle errors correctly ( 0769144 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#features_22", "text": "Improve descriptions ( cee1e6f ) yes ( df005ea )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0111-2019-02-28", "text": "", "title": "0.11.1 (2019-02-28)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_21", "text": "Use short commit for travis version ( dabb28b )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#0110-2019-02-28", "text": "", "title": "0.11.0 (2019-02-28)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_22", "text": "Add error handling to CLI main handler ( 2f4b105 ) Reject on process/pipe error ( 35e13d4 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#features_23", "text": "appBuildURL can be provided by prepublish hooks ( c3f09ee ) Auto version in manual mode ( 4cf5065 ) Better error message if custom hook cannot be loaded ( 0f7ceae ) Logs for shasum ( 9190c10 ) Print stack when erroring ( f17de04 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#0105-2019-01-29", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.10.5 (2019-01-29)"}, {"location": "cozy-app-publish/CHANGELOG/#0104-2019-01-21", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.10.4 (2019-01-21)"}, {"location": "cozy-app-publish/CHANGELOG/#0103-2019-01-10", "text": "", "title": "0.10.3 (2019-01-10)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_23", "text": "Shasum was not following redirects ( 94807ae )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#0102-2019-01-07", "text": "", "title": "0.10.2 (2019-01-07)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_24", "text": "deps: update dependency chalk to v2.4.2 ( e0921e2 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#0101-2019-01-03", "text": "", "title": "0.10.1 (2019-01-03)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_25", "text": "Don\u2019t read publish response stream twice ( a6e7ca7 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#0100-2018-12-28", "text": "", "title": "0.10.0 (2018-12-28)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_26", "text": "publish: Catch publishing error ( 63bf575 ) publish: Handle 404 error ( c71f7e6 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#features_24", "text": "publish: Do sha-sum in Node ( de9201d ), closes #68", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#091-2018-12-10", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.9.1 (2018-12-10)"}, {"location": "cozy-app-publish/CHANGELOG/#090-2018-10-15", "text": "", "title": "0.9.0 (2018-10-15)"}, {"location": "cozy-app-publish/CHANGELOG/#features_25", "text": "app-publish: Remove rundeck postpublish \ud83d\udd25 ( c9c5ffe ) app-publish: Update Mattermost message \ud83d\udcdd ( 8d32a06 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#085-2018-10-11", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.8.5 (2018-10-11)"}, {"location": "cozy-app-publish/CHANGELOG/#084-2018-09-27", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.8.4 (2018-09-27)"}, {"location": "cozy-app-publish/CHANGELOG/#083-2018-09-25", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.8.3 (2018-09-25)"}, {"location": "cozy-app-publish/CHANGELOG/#082-2018-09-25", "text": "", "title": "0.8.2 (2018-09-25)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_27", "text": "add babel-core bridge for v7 ( 18665a8 ), closes /github.com/babel/babel/issues/8206#issuecomment-419705758", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#081-2018-09-21", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.8.1 (2018-09-21)"}, {"location": "cozy-app-publish/CHANGELOG/#080-2018-09-18", "text": "", "title": "0.8.0 (2018-09-18)"}, {"location": "cozy-app-publish/CHANGELOG/#features_26", "text": "cozy-app-publish: Fail on Travis error \u2728 ( 0307241 ) cozy-app-publish: Throw publish error \u2728 ( 08db1c5 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#072-2018-09-11", "text": "", "title": "0.7.2 (2018-09-11)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_28", "text": "Downcloud folder name \ud83d\ude91 ( c8ac28b )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#071-2018-09-07", "text": "", "title": "0.7.1 (2018-09-07)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_29", "text": "Avoid in archive folder \ud83d\ude91 ( 8b09b4b )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#070-2018-09-04", "text": "", "title": "0.7.0 (2018-09-04)"}, {"location": "cozy-app-publish/CHANGELOG/#features_27", "text": "travis: Throw error on prepublish fail \u2728 ( 7a88817 )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#060-2018-08-29", "text": "", "title": "0.6.0 (2018-08-29)"}, {"location": "cozy-app-publish/CHANGELOG/#features_28", "text": "cozy-app-publish: Better options check \ud83d\udc6e ( 8f2b33d )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#055-2018-08-28", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.5.5 (2018-08-28)"}, {"location": "cozy-app-publish/CHANGELOG/#054-2018-08-28", "text": "", "title": "0.5.4 (2018-08-28)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_30", "text": "typo in deploy scripts example in readme ( cf3b558 )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#053-2018-08-22", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.5.3 (2018-08-22)"}, {"location": "cozy-app-publish/CHANGELOG/#052-2018-08-21", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.5.2 (2018-08-21)"}, {"location": "cozy-app-publish/CHANGELOG/#051-2018-08-11", "text": "Note: Version bump only for package cozy-app-publish", "title": "0.5.1 (2018-08-11)"}, {"location": "cozy-app-publish/CHANGELOG/#050-2018-08-10", "text": "", "title": "0.5.0 (2018-08-10)"}, {"location": "cozy-app-publish/CHANGELOG/#bug-fixes_31", "text": "remove .prettierrc.json from cozy-app-publish ( 1cd528c )", "title": "Bug Fixes"}, {"location": "cozy-app-publish/CHANGELOG/#features_29", "text": "import cozy-app-publish as a package ( 403d90d )", "title": "Features"}, {"location": "cozy-app-publish/CHANGELOG/#change-log_1", "text": "All notable changes to this project will be documented in this file. The format is based on Keep a Changelog and this project adheres to Semantic Versioning .", "title": "Change Log"}, {"location": "cozy-app-publish/CHANGELOG/#unreleased", "text": "", "title": "Unreleased"}, {"location": "cozy-app-publish/CHANGELOG/#changed", "text": "none yet", "title": "Changed"}, {"location": "cozy-app-publish/CHANGELOG/#fixed", "text": "none yet", "title": "Fixed"}, {"location": "cozy-app-publish/CHANGELOG/#added", "text": "disabled attribute for component", "title": "Added"}, {"location": "cozy-app-publish/CHANGELOG/#removed", "text": "none yet", "title": "Removed"}, {"location": "cozy-app-publish/CHANGELOG/#deprecated", "text": "none yet", "title": "Deprecated"}, {"location": "cozy-app-publish/CHANGELOG/#security", "text": "none yet", "title": "Security"}, {"location": "cozy-app-publish/CHANGELOG/#v036", "text": "", "title": "v0.3.6"}, {"location": "cozy-app-publish/CHANGELOG/#fixed_1", "text": "Make --build-commit usage more priority than the TRAVIS_TAG environment variale", "title": "Fixed"}, {"location": "cozy-app-publish/CHANGELOG/#v035", "text": "", "title": "v0.3.5"}, {"location": "cozy-app-publish/CHANGELOG/#added_1", "text": "Enable --build-url option on Travis mode", "title": "Added"}, {"location": "cozy-app-publish/CHANGELOG/#v034", "text": "", "title": "v0.3.4"}, {"location": "cozy-app-publish/CHANGELOG/#fixed_2", "text": "Don\u2019t throw an error on 409 Conflict registry response (version already exists)", "title": "Fixed"}, {"location": "cozy-app-publish/CHANGELOG/#v033", "text": "", "title": "v0.3.3"}, {"location": "cozy-app-publish/CHANGELOG/#fixed_3", "text": "Prefer an option to provided the correct build commit hash: --build-commit $BUILD_COMMIT", "title": "Fixed"}, {"location": "cozy-app-publish/CHANGELOG/#v032", "text": "", "title": "v0.3.2"}, {"location": "cozy-app-publish/CHANGELOG/#fixed_4", "text": "Bug when using BUILD_COMMIT", "title": "Fixed"}, {"location": "cozy-app-publish/CHANGELOG/#v031", "text": "", "title": "v0.3.1"}, {"location": "cozy-app-publish/CHANGELOG/#changed_1", "text": "Use back the TRAVIS_COMMIT for dev versioning", "title": "Changed"}, {"location": "cozy-app-publish/CHANGELOG/#added_2", "text": "Hanlde BUILD_COMMIT from environment for dev versioning", "title": "Added"}, {"location": "cozy-app-publish/CHANGELOG/#v030", "text": "", "title": "v0.3.0"}, {"location": "cozy-app-publish/CHANGELOG/#added_3", "text": "Add an automatic mode detection according to environment variables", "title": "Added"}, {"location": "cozy-app-publish/CHANGELOG/#changed_2", "text": "Grab editor name directly from the manifest instead of the CLI option The dev version computing in Travis mode use the archive shasum instead of the TRAVIS_COMMIT", "title": "Changed"}, {"location": "cozy-app-publish/CHANGELOG/#removed_1", "text": "--on-branch option with git branch checking in travis mode Unused --travis option The --editor option since it\u2019s now using the manifest Pull request checking in travis mode", "title": "Removed"}, {"location": "cozy-app-publish/CHANGELOG/#v020", "text": "", "title": "v0.2.0"}, {"location": "cozy-app-publish/CHANGELOG/#changed_3", "text": "Now use the registry in production URL", "title": "Changed"}, {"location": "cozy-app-publish/CHANGELOG/#added_4", "text": "Handle registry spaces name through --space option", "title": "Added"}, {"location": "cozy-app-publish/CHANGELOG/#v011-first-release", "text": "Deploy a Cozy application to Cozy Cloud registry", "title": "v0.1.1 First release"}, {"location": "cozy-apps-registry/", "text": "cozy-apps-registry \u00b6 What\u2019s Cozy? \u00b6 Cozy is a platform that brings all your web services in the same private space. With it, your webapps and your devices can share data easily, providing you with a new experience. You can install Cozy on your own hardware where no one\u2019s tracking you. Table of contents \u00b6 cozy-apps-registry What\u2019s Cozy? Table of contents What about this repository? How to develop with a cozy-apps-registry working in local environment 1) Install and configure the local cozy-apps-registry 2) Configure the registry with cozy-registry.yml 3) Run the registry to serve the apps 4) Create an editor 5) Configure cozy-stack with the registry Publish your application on the registry 1) Define your application manifest Properties meaning (reference) Available manifest\u2019s features list : Translated manifest fields Application terms Konnectors folders handling Konnectors fields property Konnectors message property Categories and Data types 2) Add a new application in the registry Our official apps registry Custom registry 3) Add a new version of a registered application Via cozy-app-publish (highly recommanded) Via curl Spaces & Virtual Spaces Spaces Create a space Remove a space Virtual Spaces Automation (CI) Access control and tokens Maintenance Import/export Application confidence grade / labelling Universal links Configuration Config file Files Usage Budget-Insight web auth Community What about this repository? \u00b6 The cozy-apps-registry is a go project that implements the registry API described to work with the cozy-stack . To work properly, it requires: Go >= 1.18 Couchdb >= 3.2 Redis Openstack Object Storage (Swift) How to develop with a cozy-apps-registry working in local environment \u00b6 Before starting, you will need to have a couchdb running already. That can be the one used by the local cozy-stack if you have one. For this tutorial, couchdb will be running on the default port 5984. You also must have redis and an OpenStack Object Storage (Swift) up and running. You can follow install instructions on the official website 1) Install and configure the local cozy-apps-registry \u00b6 Since this is a golang project, you can install it using go with the followed command: go get -u github.com/cozy/cozy-apps-registry cd $GOPATH /src/github.com/cozy/cozy-apps-registry/ Then you will need a session secret key to run the registry (this key will be store in the sessionsecret.key file of your working directory) using a password: cozy-apps-registry gen-session-secret --passphrase sessionsecret.key This password is important, you will need it to run the cozy-apps-registry again later. If you lose it, you will have to start again these steps. 2) Configure the registry with cozy-registry.yml \u00b6 Before running the registry, you have to configure it correctly. Don\u2019t worry, here is the yaml file to copy and paste in your cozy-registry.yml (should be in the root folder of cozy-apps-registry/ ): You can find an example of this configuration file at the root of the directory. # server host (serve command) - flag --host host : \"localhost\" # server port (serve command) - flag --port port : 8081 couchdb : # CouchDB server url - flag --couchdb-url url : http://localhost:5984 # CouchDB user - flag --couchdb-user user : '' # CouchDB password - flag --couchdb-password password : '' # CouchDB prefix for the registries databases - flag --couchdb-prefix prefix : registry1 swift : # Swift auth URL (provided by keystone) auth_url : http://172.28.128.3/identity/v3 # Swift username username : admin # Swift password api_key : secret # Endpoint type (public/admin/internal) endpointy_type : public # Project name tenant : demo # Swift domain domain : default # Path to the session secret file containing the master secret to generate # session token. # # Should be generated with the \"gen-session-secret\" command. session-secret : sessionsecret.key Feel free to change it if some configurations change in your case (the couchdb user, the server parameters or the databases prefix for example). Notices: Here the generated session token (step 1) is stored in the sessionsecret.key file of the working directory, this is so the value of the property session-secret at the end of the configuration file. By default, the local couchdb allow all admin accesses without creating users, so there is no user and password here. But if an admin user has been created, you have to use the properties user and password in the couchdb part to provide these informations. It\u2019s also possible to use env variables for configuration. You can take the key from the configuration file and add the COZY_REGISTRY prefix. For example, you can run: COZY_REGISTRY_PORT = 8081 cozy-apps-registry serve There is also the REGISTRY_SESSION_PASS env variable for the password for the session secret. 3) Run the registry to serve the apps \u00b6 Run the registry using this followed command (here our configuration file is a cozy-registry.yml in the current working directory): cozy-apps-registry serve -c cozy-registry.yml At this step, you should have a cozy-apps-registry running and ready for the development. If you runnig the registry for the first time you can see the next steps to create a new editor and to configure your local cozy-stack to run with this new registry. The -c options is always mandatory if you want to specify a config file like here. 4) Create an editor \u00b6 This step is required to submit new applications in the registry. In another terminal, run these commands to create an editor (the one that will submit the application(s)) and generate an access token: cozy-apps-registry add-editor Cozy -c cozy-registry.yml cozy-apps-registry gen-token --master Cozy -c cozy-registry.yml Here we go, you have now an registry ready and running on the 8081 port. The -c options is always mandatory if you want to specify a config file like here. 5) Configure cozy-stack with the registry \u00b6 On the cozy-stack , you have to add the new registry in the stack configuration file cozy.yaml (registries property): ... registries : default : - http://localhost:8081/ ... Now restart your local cozy-stack to take this new configuration in consideration (stop and run again cozy-stack serve ) and you\u2019re ready to work with the cozy-apps-registry ! Publish your application on the registry \u00b6 If you need more details about the registry you can go to the official registry documentation Important: In this whole documentation, by the term application , we mean a web application or a konnector. Indeed, for the registry, all entities are applications and they can be either webapp or konnector type. 1) Define your application manifest \u00b6 To be publishable, your application requires some informations in its manifest.webapp , the manifest of a Cozy application. You can find an example of manifest for an application in Cozy-Drive and one for a konnector in cozy-konnector-trainline . Most properties are common to both applications and konnectors but platforms, screenshots, services, routes and intents are only used in applications. Properties oauth, data_types, doctypes, fields, frequency, language, messages, parameters, time_interval, uuid and vendor_link ar only used in konnectors. Properties meaning (reference) \u00b6 Here are all properties meaning for the manifest file (for webapp and konnectors) sorted alphabetically: Field Description aggregator Object containing aggregator data. Typically { accountId: 'aggregator-service' } . categories array of categories for your apps (see authorized categories), it will be ['others'] by default if empty data_types (konnector specific) Array of the data type the konnector will manage developer name and url for the developer editor the editor\u2019s name to display on the cozy-bar ( REQUIRED ) fields (konnector specific) JSON object describing the fields need by the konnector ( except folder path ). Used to generate a form. See below folders (konnector specific) A list of folders required by the konnector to store files according to datatype (see the specific documentation below ) frequency (konnector specific) A human readable value between monthly , weekly , daily , hourly , indicating the interval of time between two runs of the konnector. Default: weekly . icon path to the icon for the home (path in the build) intents (application specific) a list of intents provided by this app (see cozy-stack intents doc for more details) langs Languages available in your app (can be different from locales) language (konnector specific) the konnector development language used (ex: node ) license the SPDX license identifier locales an object with language slug as property, each name property is an object of localized informations (see the second part below) manifest_version The current manifest version used. This is a versioning for the manifest and allow better retrocompatiblity when processing app manifest messages (konnector specific) Array of message identifiers, which can be used by application to display information at known areas. See example below . mobile (application specific) JSON object containing information about app\u2019s mobile version (see cozy-stack routes doc for more details) name the name to display on the home ( REQUIRED ) name_prefix the prefix to display with the name oauth (konnector specific) JSON object containing oAuth information, like scope . If a manifest provides an oauth property, it is considered as an OAuth konnector. Note: scope can be a string or an array. If it is an array, its values will be joined with a space. A false or null value in scope will remove any scope parameter in the request sent to the oauth provider. parameters (konnector specific) Additional parameters which should be passed to the konnector. Used for example for bank konnectors to pass a bankId parameter. partnership an object to provide informations (to display in the Store for example) about a partnership related to the application ( icon description , name and domain ). It can also be used to trigger alternative konnector connection policies for some vendors (see the budget-insight konnector policy in cozy-harvest ). permissions a map of permissions needed by the app (see see cozy-stack permissions doc for more details) platforms (application specific) List of objects for platform native applications. For now there are only two properties: type (i.e. 'ios' or 'linux' ) and the optional url to reach this application page. routes (application specific) a map of routes for the app (see cozy-stack routes doc for more details) ( REQUIRED ) screenshots an array of paths to the screenshots of the application (paths in the build) services (application specific) a map of the services associated with the app (see cozy-stack services doc for more details) slug the default slug that should never change (alpha-numeric lowercase) ( REQUIRED ) source where the files of the app can be downloaded (by default it will look for the branch build ) terms an object defining properties for terms that need to be displayed/accepted by the user when installing the application ( more-info-below ) time_interval (konnector specific) By defaults, konnector triggers are scheduled randomly between 00:00 AM and 05:00 AM. Those two values can be overwritten thanks to this property, by passing an array containing two values: first is the interval start hour, second is the interval end hour. Example: [15, 21] will randomly schedule the konnector trigger between 15:00 (03:00 PM) and 21:00 (09:00 PM). The time zone used is GMT. type type of application ( konnector or webapp ) ( REQUIRED ) version the current version number ( REQUIRED ) vendor_link (konnector specific) URL to editor or service website qualification_labels (konnector specific) Array of one or more labels from the Cozy Client\u2019s qualifications list to associate with the files the konnector will receive from the website. features (konnector specific) Array of features added in the konnector from the list below. Available manifest\u2019s features list : \u00b6 2FA Two Factors identification. BILLS Import bills documents, doctype \u201cio.cozy.bills\u201d. FILES Import files documents, doctype \u201cio.cozy.files\u201d. CAPTCHA_RESOLUTION The konnector using a captcha resolution process. CARBON_COPY The konnector import legally true copy of the original files. DOC_QUALIFICATION The konnector uses the first version of files qualifications, you may stumble upon on some konnectors wich hasn\u2019t been treated. DOC_QUALIFICATION_V2 The konnector uses new version (last one for now) of files qualifications. ELECTRONIC_SAFE Files comes from a known electronic safe. HEALTH The konnector treat health documents HTML_TO_PDF The konnector needs to convert HTML page(s) to make pdf files. IDENTITY The konnector create identity(ies) for doctype \u201cio.cozy.identities\u201d LOGIN_OK The konnector deactivate the auto-notification METADATA_DEDUP The konnector uses a fileIdAttribute as detection to avoid deduplication. VENDOR_REF The konnector uses. SENTRY_V2 The konnector had been migrated (or packaged) to sentry V2 (errors.cozycloud.cc) Notices: All images paths ( icon , partnership.icon and screenshots ) should be relative to the build directory. For example, here, the icon.svg is stored in the build root directory and all screenshots are store in a folder screenshots in the build directory. Therefore, if you use a bundler (like webpack) be sure to know exactly where the bundler will store these assets in the build directory (and change it in the manifest if needed). All properties in locales objects will override the matched property of the main manifest.webapp body, if a property is not found in locales it will fallback to the main body one. We use to have the en locale as default one if the one wanted by the user doesn\u2019t exist. Be sure to have, at least, that locale complete with the name and all descriptions. In your build files, this manifest.webapp file must be at the root. Translated manifest fields \u00b6 Here are the properties that you can override using locales (we recommand to automatically build these properties according to your locales files if you\u2019re using a translating tool like transifex ): name , the app\u2019s name short_description , short description of what the app do long_description , longer and more complete description of the app behaviour changes , description of your new version of the konnector or all changes since the last version fields , An object containing translations for fields. screenshots folders { \"fields\" : { \"email\" : { \"type\" : \"email\" } }, \"locales\" : { \"en\" : { \"short_description\" : \"Collect your Orange's bills\" , \"fields\" : { \"email\" : { \"label\" : \"Identifier (your email)\" } } }, \"fr\" : { \"short_description\" : \"R\u00e9cup\u00e8re vos factures Orange\" , \"fields\" : { \"email\" : { \"label\" : \"Identifiant (votre adresse mail)\" } } } } } Application terms \u00b6 You can provide a related terms property if you want to display and make the user accept some terms (ToS for example) just before installing the application. Here are all properties allowed and used: url , the URL of the terms/contract to redirect the user to ( REQUIRED ) version : A specific version of the terms, we need it handle terms updates and ask the user again to accept the update. The special characters [*+~.()'\"!:@] are not allowed here. ( REQUIRED ) id : An id for the terms. When accepting terms, we store in io.cozy.terms , a document containing the id and version so that we know which terms have been accepted, and show the user a modal if the terms have not been accepted yet. The special characters [*+~.()'\"!:@] are not allowed here. ( REQUIRED ) Konnectors folders handling \u00b6 The folders property is a list of objects with these following properties: defaultDir : ( REQUIRED ) The default root directory of your folder. In this folder will automatically be created a subfolder with the konnector name and into this latter a subfolder with the account name to store the related files. Here you can use some variables in the path like the following: $administrative : Folder which will receive all administrative related files (bills, contracts, invoices\u2026) $photos : Folder which will receive all photos $konnector : The name of the konnector All paths provided using defaultDir will be the root directory, not the final folder which will receive the files. For example, if you set $photos , the final folder will be $photos/$konnector/$account in order to keep them always sorted by konnectors and accounts. Konnectors fields property \u00b6 The fields property is a JSON object describing the input fields needed to generate the konnector\u2019s configuration form. A typical example will be: { \"fields\" : { \"identifier\" : { \"type\" : \"text\" }, \"secret\" : { \"type\" : \"password\" } } } The keys of the fields object are the name/id of the fields. They will be passed as parameters to the konnector at every run. Each fields may also have the following properties: Property Description identifier (Boolean) indicating if the field is the main identifier. By default, the login field is the identifier. Default value is false and there can be only one identifier advanced Indicates if the field should be displayed in the \u201cadvanced\u201d area of the form (default: false ) default Default value. It can a string for a text field, or an object for a select field ( \"default\": {\"value\": \"foo\",\"name\": \"bar\"}, ) description Field description, as a locale key. label Predefined label. This value must match a locale key provided by Cozy-Home. Example: With label: \"identifier\" , Cozy-Home will use the locale key account.form.label.identifier . Translations for these fields use the locales property in the manifest. max Maximum length of the value (number of characters) min Minimum length of the value (number of characters) options When the field is a dropdown, list of available options pattern Define a regex used to validate the field. isRequired Boolean indicating if the field is required or not (default true ) type Required . Field type from dropdown , email , hidden , password , text , checkbox . Konnectors message property \u00b6 Messages are a common way to provide custom information to display in application. An app like cozy-home should have some specific area to display custom messages provided by the konnector. Example: // The final example will be available after the implementation of the whole mechanism, // but here is the global idea: { installSuccess && < p >{ t ( 'home.konnector.install.success.message' )} p > } { installSuccess && konnector . manifest . messages . includes ( 'success_message' ) && < p >{ t ( 'konnector.manifest.locales.messages.success_message' )} } Categories and Data types \u00b6 Categories are slugs from the following list: banking clouds cozy education energy finance health host_provider insurance isp mes_infos online_services partners press pro productivity ptnb public_service shopping social tech telecom transport Data types are slugs from the following list: activity appointment bankTransactions bankAccounts bill bloodPressure calendar certificate commit consumption contact contract courseMaterial document event family geopoint heartbeat home phonecommunicationlog podcast profile refund sinister sleepTime stepsNumber temperature travelDate tweet videostream weight 2) Add a new application in the registry \u00b6 Our official apps registry \u00b6 Official registry URL: https://apps-registry.cozycloud.cc In order to use our official repository, you need a token for a specific editor. To do so, contact us directly at the address contact@cozycloud.cc with a mail using the following title prefix: [registry] and provide us these folowing information (not changeable after): - slug of your application - editor name that you want We will provide you with the correct token. Custom registry \u00b6 See the details below to know how to add a new application in a custom cozy-apps-registry instance (local or not). Prequisites : - For this step, you will need your editor token access generated when you created your editor (see below ). You have to replace all {{EDITOR_TOKEN}} in this documentation by this token. - The communication with the registry is done through HTTP requests for now. So we will use the curl command line tool to register our application here. Now you can add your application in the registry. This step is splitted in two septs: - Add a new application (without versions) - Add a version of the application A new application without registered version won\u2019t be displayed by the cozy-store application . To add a new application, you have to do a POST request which all the informations needed to the route registryAddress/registry with registryAddress your registry address (for example here http://localhost:8081 ). Let\u2019s add the Collect application as example: # {{EDITOR_TOKEN}} -> your generated editor access token curl -X \"POST\" \"http://localhost:8081/registry\" \\ -H \"Authorization: Token {{EDITOR_TOKEN}}\" \\ -H \"Content-Type: application/json\" \\ -d $'{ \"slug\": \"collect\", \"type\": \"webapp\", \"editor\": \"{{EDITOR}}\" }' Field Description slug your application unique ID type kind of application (it can be only webapp or konnector ) editor Name of the editor matching the {{EDITOR_TOKEN}} Here the slug is the unique ID of the application in the registry, so it can\u2019t be changed after the application is already registered. 3) Add a new version of a registered application \u00b6 Please note that an application bundle cannot be larger than 20MB (hardcoded value). This limitation has been implemented to encourage better web application development practices because in general the larger the application bundle is, the worst the performance and user experience will be. Via cozy-app-publish (highly recommanded) \u00b6 Here we will show the classical way to add a version using the manual mode of cozy-app-publish as reference. But you may need to look at the Automation CI part of this documentation instead. Prequisites : For this step, you will need your editor token access generated when you created your editor (see below ). You have to replace all {{EDITOR_TOKEN}} in this documentation by this token. Don\u2019t forget to build your application first (run yarn build ), cozy-app-publish will read the manifest from your build Firstly, install the cozy-app-publish package using yarn or npm : yarn add cozy-app-publish --dev You can also install the package as a global package, but don\u2019t forget to update it frequently Then use it to publish your application, here is an example for collect : yarn cozy-app-publish \\ --token {{ EDITOR_TOKEN }} \\ --build-url https://github.com/cozy/cozy-collect/archive/042cef26d9d33ea604fe4364eaab569980b500c9.tar.gz \\ --manual-version 1.0.2-dev.042cef26d9d33ea604fe4364eaab569980b500c9 If you need more information about this tool, you can go to the official cozy-app-publish documentation . Via curl \u00b6 Here we will show the classical way to add a version using curl as reference. But you may need to look at our dedicated tool cozy-app-publish or the Automation CI part of this documentation instead. Prequisites : - For this step, you will need your editor token access generated when you created your editor (see below ). You have to replace all {{EDITOR_TOKEN}} in this documentation by this token. - The communication with the registry is done through HTTP requests for now. So we will use the curl command line tool to register our application here. To add a new version for a registered application, you have to do a POST request with all needed information to the route registryAddress/registry/:appSlug to publish in default space or registryAddress/:space/registry/:appSlug for a named space (see Spaces & Virtual Spaces below) with registryAddress your registry address (for example here http://localhost:8081 ), :appName your application slug (here drive ) and :space your registry space. Let\u2019s add the version 1.0.1 of the Collect application for example: # {{EDITOR_TOKEN}} -> your generated editor access token curl -X \"POST\" \"http://localhost:8081/registry/collect\" \\ -H \"Authorization: Token {{EDITOR_TOKEN}}\" \\ -H \"Content-Type: application/json\" \\ -d $'{ \"url\": \"https://github.com/cozy/cozy-collect/archive/1.0.1.tar.gz\", \"sha256\": \"96212bf53ab618808da0a92c7b6d9f2867b1f9487ba7c1c29606826b107041b5\", \"version\": \"1.0.1\", }' Field Description url the archive source of your application, it will be downloaded and checked with the sha256 property sha256 the sha256 hash of your source archive matching the archive in url (see the notice below) version version of the application, must match the one in the manifest (see the notice below) Important notices: The version must match the one in the manifest.webapp file for stable release. For beta (X.X.X-betaX) or dev releases (X.X.X-dev.hash256), the version before the cyphen must match the one in the manifest.webapp . If version starts with the v letter (like v1.2.3 ), then the v letter is silently stripped from version, allowing you to simply publish according to tag name if your tags are labelled vx.y.z . For better integrity, the sha256 provided must match the sha256 of the archive provided in url . If it\u2019s not the case, that will be considered as an error and the version won\u2019t be registered. Spaces & Virtual Spaces \u00b6 Spaces \u00b6 You can divide your applications between several isolated places, called spaces . When an application and its versions are published in a space , they are only reachable in that one (you can consider a space like a entire sub-part of the registry). It is espacially useful for splitting up applications by logical topics. Most of the CLI and API endpoints have a space option. You can refer to the documentation or CLI help to view all available parameters. Create a space \u00b6 Spaces are defined in the config file and are automatically created during registry launching. Add a space entry, followed by your spaces names, and let the registry do the work: spaces : __default__ myspace foospace Remove a space \u00b6 To remove a space, you have to clean all the remaining apps & versions before removing the space entry name. A CLI is available for the job: $ cozy-apps-registry rm-space Example: $ cozy-apps-registry rm-space foobar Warning: You are going to remove space foobar and all its applications. This action is irreversible. Please enter the space name to confirm: foobar Removing app1/0.7.3-dev.f26bf2b8db3da459071a074a1367ce36e78bb34c Removing app1/0.7.3-dev.cf1efba4c1b6dd08bb5857f5752790f0d2663d6d Removing app1/0.7.3-dev.0bbd57a6ce50af82cfbefb8c231fbfe04516e742 Removing app1/0.7.3-dev.21338229a0c2317dc0f3b94e92b22a367f84c537 Removing app1/0.7.3-dev.08ab3624136fb70dc996003aebc3049af51f7438 Removing app1/0.7.3-dev.4e9d174a3b01acaf8a44b561455efc3f34871142 Removing app1/0.7.3-dev.b2654bf00be393aa611fcbb7f70a8ef671895a84 Removing app1/0.7.3-dev.860861868a5dfe294c7120d81fa9feb5387bb57f Removing app2/0.1.9-dev.954dac9e12e080d591cb76591c311611fed1bea9 You can now delete the name from your config file. Virtual Spaces \u00b6 A virtual space is necessarily built over an existing space . It allows to filter by selecting or rejecting applications available on the underlying space. Please note that it is not possible to publish applications or versions on a virtual space . It is possible to change the name of an application in the virtual space, without changing it in the underlying space, with the cozy-apps-registry overwrite-app-name command. The same thing is possible for the icon with cozy-apps-registry overwrite-app-icon . And the maintenance status can also be changed in the virtual space with the cozy-apps-registry maintenance commands. That\u2019s all for the moment. Automation (CI) \u00b6 The following tutorial explains how to connect your continuous integration based on Travis to automatically publish new versions on the apps registry. In this tutorial, we assume: you have a token allowing you to publish applications for your editor : {{EDITOR_TOKEN}} you are working on a repository plugged on travis and named on github myname/cozy-example You first need to add the token to your travis configuration file .travis.yml . To do so, you need the travis utility to encrypt its value. $ travis encrypt REGISTRY_TOKEN ={{ EDITOR_TOKEN }} -r myname/cozy-example --org Please add the following to your .travis.yml file: secure: \"jUAjk..LOOOOONG_ENCRYPTED_STRING.....jdk89=\" Like said, you need to add this block of ciphered data in the .travis.yml (if it\u2019s not already done automatically). This will allow you to use the REGISTRY_TOKEN variable in your deployment script. Then, you can add the publish script in your package.json in order to be used by Travis: ... \"publish:cozy\" : \"git fetch origin ${DEPLOY_BRANCH:-build}:${DEPLOY_BRANCH:-build} && cozy-app-publish --token $REGISTRY_TOKEN --build-commit $(git rev-parse ${DEPLOY_BRANCH:-build})\" ... This script will fetch your last commit from the build branch to publish to the registry. If you push a tag, be sure to wait the last build branch Travis build finished in order to have the real last commit to publish. Finally, you can add this script to your .travis.yml to publish your app using our publishing tool cozy-app-publish during the deploy process: ... before_deploy: - yarn add cozy-app-publish deploy: - provider: script repo: myname/cozy-example skip-cleanup: true script: export DEPLOY_BRANCH=build && yarn deploy && yarn publish:cozy on: branch: master - provider: script repo: myname/cozy-example skip-cleanup: true script: export DEPLOY_BRANCH=build && yarn publish:cozy on: tags: true ... Important notices: A commit push to the branch master will publish your application in the dev channel of the registry. A tag push (Github release) will publish a stable version (ex: 1.0.0 ) or a beta version (ex: 1.0.1-beta2 ) to the registry (automatically handled by the registry). cozy-app-publish will use the github archive URL computing to get the application tarball. If your applicaiton is not on Github, you may need to use the manual mode of the command. Access control and tokens \u00b6 The read-only routes of the registry are all public and do not require any access-control. However routes allowing to create applications and versions have access-control policies associated to them. The registry has two types of access permissions, that are associated to two different tokens: editor tokens : these tokens give access to the publication of new versions on the registry, for a specific editor name, at these conditions: the version\u2019s application must already exist in the registry the version\u2019s application must have the same \u201ceditor\u201d value as the token master tokens : these tokens are allowed to create and register new applications on the registry, and associate them with an existing editor name. They also have the same accesses as the editor tokens. Editor tokens can be specific to one or more applications names that they are allowed to publish. In order to create tokens, the binary offers a gen-token command-line. Here are some examples to illustrates some usages: # Generating tokens # generate an editor token for the editor \"cozy\", for any application $ cozy-apps-registry gen-token cozy # generate an editor token for the editor \"cozy\" expiring after 30 days $ cozy-apps-registry gen-token cozy --max-age 30d # generate an editor token for the editor \"cozy\" for application \"collect\" and \"drive\" $ cozy-apps-registry gen-token cozy --apps collect,drive # generate a master token associated with the editor \"cozy\" expiring after 30 days $ cozy-apps-registry gen-token cozy --master --max-age 30d # Verifying tokens # verify the editor token \"XXX\" for the editor \"cozy\" $ cozy-apps-registry verify-token cozy \"XXX\" # verify the master token \"XXX\" associated with the editor \"cozy\" $ cozy-apps-registry verify-token cozy \"XXX\" --master # Revoking tokens # revoke all editors tokens for the cozy editor $ cozy-apps-registry revoke-tokens cozy # revoke all master tokens associated with the cozy editor $ cozy-apps-registry revoke-tokens cozy --master Maintenance \u00b6 In order to set/unset an application into maintenance mode, the binary offers a maintenance command-line. Here are some examples of how to use it: # Activate maintenance mode for the application 'bank' of space 'myspace' # Available flagged options: # --infra specify a maintenance specific to our infra # --no-manual-exec specify a maintenance disallowing manual execution # --short specify a short maintenance $ cozy-apps-registry maintenance activate bank --space myspace # Deactivate maintenance mode for the application 'bank' of space 'myspace' $ cozy-apps-registry maintenance deactivate bank --space myspace Or using a cURL request and a master token: curl -XPUT \\ -H \"Authorization: Token $COZY_REGISTRY_ADMIN_TOKEN \" \\ -H \"Content-Type: application/json\" \\ -d '{\"flag_infra_maintenance\": false,\"flag_short_maintenance\": false,\"flag_disallow_manual_exec\": false,\"messages\": {\"fr\": {\"long_message\": \"Bla bla bla\",\"short_message\": \"Bla\"},\"en\": {\"long_message\": \"Yadi yadi yada\",\"short_message\": \"Yada\"}}}' \\ https://apps-registry.cozycloud.cc/myspace/registry/maintenance/bank/activate curl -XPUT \\ -H \"Authorization: Token $COZY_REGISTRY_ADMIN_TOKEN \" \\ https://apps-registry.cozycloud.cc/registry/maintenance/bank/deactivate Import/export \u00b6 CouchDB & Swift can be exported into a single archive with cozy-apps-registry export . Registry data are exported as below: registry/couchdb/{db}/{uuid}.json : CouchDB document exported as JSON registry/swift/{file/path} : Swift document, with the following tar custom metadata COZY.content-type : associated content type The generated archive can be imported with cozy-apps-registry import -d . The -d option will drop CouchDB databases and Swift containers related to declared spaces on the registry configuration. Application confidence grade / labelling \u00b6 The confidence grade of an applications can be specified by specifying the data_usage_commitment and data_usage_commitment_by fields of the application document. Possible values for these properties are: data_usage_commitment : specify a technical commitment from the application editor: user_ciphered : technical commitment that the user\u2019s data is encrypted and can only be known by him. user_reserved : commitment that the data is only used for the user, to directly offer its service. none : no commitment data_usage_commitment_by : specify what entity is taking the commitment: cozy : the commitment is taken by cozy editor : the commitment is taken by the application\u2019s editor none : no commitment is taken To do that, a command line and admin API are available, and be used as follow: $ cozy-apps-registry modify-app banks --space my_space --data-usage-commitment user_reserved --data-usage-commitment-by editor Or using a cURL request and a master token: curl -XPATCH \\ -H\"Authorization: Token $COZY_REGISTRY_ADMIN_TOKEN\" \\ -H\"Content-Type: application/json\" \\ -d'{\"data_usage_commitment\": \"user_reserved\", \"data_usage_commitment_by\": \"editor\"} https://apps-registry.cozycloud.cc/my_space/registry/banks Universal links \u00b6 The registry can manage Universal links . Configuration \u00b6 Config file \u00b6 Each space holds its own files. The space determination is based on the request host, so you must bind a domain to a space in the config file. domain_space : mycloud.com : \"__default__\" cloud.foobar.com : \"foobar\" Files \u00b6 Place your files (e.g apple-app-site-association ) in the space container. The file must be prepended with universallink/ For the foobar space and file apple-app-site-association , the file has to be named universallink/apple-app-site-association and placed in the foobar container Usage \u00b6 The following endpoint is available to get any file: http:///.well-known/:filename You can now query your endpoint to get your file: curl -X GET http://cloud.foobar.com/.well-known/apple-app-site-association { \"applinks\" : { \"apps\" : [] , \"details\" : [ { \"appID\" : \"3AKXFMV43J.io.cozy.drive.mobile\" , \"paths\" : [ \"/drive\" ] } , { \"appID\" : \"3AKXFMV43J.io.cozy.banks.mobile\" , \"paths\" : [ \"/banks\" ] } , { \"appID\" : \"3AKXFMV43J.io.cozy.photos.mobile\" , \"paths\" : [ \"/photos\" ] } ] } } Budget-Insight web auth \u00b6 For some banks integration (Paypal, Orange Bank, Revolut\u2026), Budget-Insight need something similar to universal link because they expect a static domain for fallback but there is a specific domain per Cozy instance. In contrast with universal links, query parameters (provided by BI) are propagated to the final fallback redirection. http:///biwebauth?fallback=http%3A%2F%2Fa.cozy%3Ffoo%3Dfoo&bar=bar redirect to http://a.cozy?foo=foo&bar=bar , merging fallback provided query parameters ( foo=foo ) with webauth provided ones ( bar=bar ). Community \u00b6 You can reach the Cozy Community by: Chatting with us on IRC #cozycloud on Libera.Chat Posting on our Forum Posting issues on the Github repos Say Hi! on Twitter", "title": "Registry server"}, {"location": "cozy-apps-registry/#cozy-apps-registry", "text": "", "title": "cozy-apps-registry"}, {"location": "cozy-apps-registry/#whats-cozy", "text": "Cozy is a platform that brings all your web services in the same private space. With it, your webapps and your devices can share data easily, providing you with a new experience. You can install Cozy on your own hardware where no one\u2019s tracking you.", "title": "What's Cozy?"}, {"location": "cozy-apps-registry/#table-of-contents", "text": "cozy-apps-registry What\u2019s Cozy? Table of contents What about this repository? How to develop with a cozy-apps-registry working in local environment 1) Install and configure the local cozy-apps-registry 2) Configure the registry with cozy-registry.yml 3) Run the registry to serve the apps 4) Create an editor 5) Configure cozy-stack with the registry Publish your application on the registry 1) Define your application manifest Properties meaning (reference) Available manifest\u2019s features list : Translated manifest fields Application terms Konnectors folders handling Konnectors fields property Konnectors message property Categories and Data types 2) Add a new application in the registry Our official apps registry Custom registry 3) Add a new version of a registered application Via cozy-app-publish (highly recommanded) Via curl Spaces & Virtual Spaces Spaces Create a space Remove a space Virtual Spaces Automation (CI) Access control and tokens Maintenance Import/export Application confidence grade / labelling Universal links Configuration Config file Files Usage Budget-Insight web auth Community", "title": "Table of contents"}, {"location": "cozy-apps-registry/#what-about-this-repository", "text": "The cozy-apps-registry is a go project that implements the registry API described to work with the cozy-stack . To work properly, it requires: Go >= 1.18 Couchdb >= 3.2 Redis Openstack Object Storage (Swift)", "title": "What about this repository?"}, {"location": "cozy-apps-registry/#how-to-develop-with-a-cozy-apps-registry-working-in-local-environment", "text": "Before starting, you will need to have a couchdb running already. That can be the one used by the local cozy-stack if you have one. For this tutorial, couchdb will be running on the default port 5984. You also must have redis and an OpenStack Object Storage (Swift) up and running. You can follow install instructions on the official website", "title": "How to develop with a cozy-apps-registry working in local environment"}, {"location": "cozy-apps-registry/#1-install-and-configure-the-local-cozy-apps-registry", "text": "Since this is a golang project, you can install it using go with the followed command: go get -u github.com/cozy/cozy-apps-registry cd $GOPATH /src/github.com/cozy/cozy-apps-registry/ Then you will need a session secret key to run the registry (this key will be store in the sessionsecret.key file of your working directory) using a password: cozy-apps-registry gen-session-secret --passphrase sessionsecret.key This password is important, you will need it to run the cozy-apps-registry again later. If you lose it, you will have to start again these steps.", "title": "1) Install and configure the local cozy-apps-registry"}, {"location": "cozy-apps-registry/#2-configure-the-registry-with-cozy-registryyml", "text": "Before running the registry, you have to configure it correctly. Don\u2019t worry, here is the yaml file to copy and paste in your cozy-registry.yml (should be in the root folder of cozy-apps-registry/ ): You can find an example of this configuration file at the root of the directory. # server host (serve command) - flag --host host : \"localhost\" # server port (serve command) - flag --port port : 8081 couchdb : # CouchDB server url - flag --couchdb-url url : http://localhost:5984 # CouchDB user - flag --couchdb-user user : '' # CouchDB password - flag --couchdb-password password : '' # CouchDB prefix for the registries databases - flag --couchdb-prefix prefix : registry1 swift : # Swift auth URL (provided by keystone) auth_url : http://172.28.128.3/identity/v3 # Swift username username : admin # Swift password api_key : secret # Endpoint type (public/admin/internal) endpointy_type : public # Project name tenant : demo # Swift domain domain : default # Path to the session secret file containing the master secret to generate # session token. # # Should be generated with the \"gen-session-secret\" command. session-secret : sessionsecret.key Feel free to change it if some configurations change in your case (the couchdb user, the server parameters or the databases prefix for example). Notices: Here the generated session token (step 1) is stored in the sessionsecret.key file of the working directory, this is so the value of the property session-secret at the end of the configuration file. By default, the local couchdb allow all admin accesses without creating users, so there is no user and password here. But if an admin user has been created, you have to use the properties user and password in the couchdb part to provide these informations. It\u2019s also possible to use env variables for configuration. You can take the key from the configuration file and add the COZY_REGISTRY prefix. For example, you can run: COZY_REGISTRY_PORT = 8081 cozy-apps-registry serve There is also the REGISTRY_SESSION_PASS env variable for the password for the session secret.", "title": "2) Configure the registry with cozy-registry.yml"}, {"location": "cozy-apps-registry/#3-run-the-registry-to-serve-the-apps", "text": "Run the registry using this followed command (here our configuration file is a cozy-registry.yml in the current working directory): cozy-apps-registry serve -c cozy-registry.yml At this step, you should have a cozy-apps-registry running and ready for the development. If you runnig the registry for the first time you can see the next steps to create a new editor and to configure your local cozy-stack to run with this new registry. The -c options is always mandatory if you want to specify a config file like here.", "title": "3) Run the registry to serve the apps"}, {"location": "cozy-apps-registry/#4-create-an-editor", "text": "This step is required to submit new applications in the registry. In another terminal, run these commands to create an editor (the one that will submit the application(s)) and generate an access token: cozy-apps-registry add-editor Cozy -c cozy-registry.yml cozy-apps-registry gen-token --master Cozy -c cozy-registry.yml Here we go, you have now an registry ready and running on the 8081 port. The -c options is always mandatory if you want to specify a config file like here.", "title": "4) Create an editor"}, {"location": "cozy-apps-registry/#5-configure-cozy-stack-with-the-registry", "text": "On the cozy-stack , you have to add the new registry in the stack configuration file cozy.yaml (registries property): ... registries : default : - http://localhost:8081/ ... Now restart your local cozy-stack to take this new configuration in consideration (stop and run again cozy-stack serve ) and you\u2019re ready to work with the cozy-apps-registry !", "title": "5) Configure cozy-stack with the registry"}, {"location": "cozy-apps-registry/#publish-your-application-on-the-registry", "text": "If you need more details about the registry you can go to the official registry documentation Important: In this whole documentation, by the term application , we mean a web application or a konnector. Indeed, for the registry, all entities are applications and they can be either webapp or konnector type.", "title": "Publish your application on the registry"}, {"location": "cozy-apps-registry/#1-define-your-application-manifest", "text": "To be publishable, your application requires some informations in its manifest.webapp , the manifest of a Cozy application. You can find an example of manifest for an application in Cozy-Drive and one for a konnector in cozy-konnector-trainline . Most properties are common to both applications and konnectors but platforms, screenshots, services, routes and intents are only used in applications. Properties oauth, data_types, doctypes, fields, frequency, language, messages, parameters, time_interval, uuid and vendor_link ar only used in konnectors.", "title": "1) Define your application manifest"}, {"location": "cozy-apps-registry/#properties-meaning-reference", "text": "Here are all properties meaning for the manifest file (for webapp and konnectors) sorted alphabetically: Field Description aggregator Object containing aggregator data. Typically { accountId: 'aggregator-service' } . categories array of categories for your apps (see authorized categories), it will be ['others'] by default if empty data_types (konnector specific) Array of the data type the konnector will manage developer name and url for the developer editor the editor\u2019s name to display on the cozy-bar ( REQUIRED ) fields (konnector specific) JSON object describing the fields need by the konnector ( except folder path ). Used to generate a form. See below folders (konnector specific) A list of folders required by the konnector to store files according to datatype (see the specific documentation below ) frequency (konnector specific) A human readable value between monthly , weekly , daily , hourly , indicating the interval of time between two runs of the konnector. Default: weekly . icon path to the icon for the home (path in the build) intents (application specific) a list of intents provided by this app (see cozy-stack intents doc for more details) langs Languages available in your app (can be different from locales) language (konnector specific) the konnector development language used (ex: node ) license the SPDX license identifier locales an object with language slug as property, each name property is an object of localized informations (see the second part below) manifest_version The current manifest version used. This is a versioning for the manifest and allow better retrocompatiblity when processing app manifest messages (konnector specific) Array of message identifiers, which can be used by application to display information at known areas. See example below . mobile (application specific) JSON object containing information about app\u2019s mobile version (see cozy-stack routes doc for more details) name the name to display on the home ( REQUIRED ) name_prefix the prefix to display with the name oauth (konnector specific) JSON object containing oAuth information, like scope . If a manifest provides an oauth property, it is considered as an OAuth konnector. Note: scope can be a string or an array. If it is an array, its values will be joined with a space. A false or null value in scope will remove any scope parameter in the request sent to the oauth provider. parameters (konnector specific) Additional parameters which should be passed to the konnector. Used for example for bank konnectors to pass a bankId parameter. partnership an object to provide informations (to display in the Store for example) about a partnership related to the application ( icon description , name and domain ). It can also be used to trigger alternative konnector connection policies for some vendors (see the budget-insight konnector policy in cozy-harvest ). permissions a map of permissions needed by the app (see see cozy-stack permissions doc for more details) platforms (application specific) List of objects for platform native applications. For now there are only two properties: type (i.e. 'ios' or 'linux' ) and the optional url to reach this application page. routes (application specific) a map of routes for the app (see cozy-stack routes doc for more details) ( REQUIRED ) screenshots an array of paths to the screenshots of the application (paths in the build) services (application specific) a map of the services associated with the app (see cozy-stack services doc for more details) slug the default slug that should never change (alpha-numeric lowercase) ( REQUIRED ) source where the files of the app can be downloaded (by default it will look for the branch build ) terms an object defining properties for terms that need to be displayed/accepted by the user when installing the application ( more-info-below ) time_interval (konnector specific) By defaults, konnector triggers are scheduled randomly between 00:00 AM and 05:00 AM. Those two values can be overwritten thanks to this property, by passing an array containing two values: first is the interval start hour, second is the interval end hour. Example: [15, 21] will randomly schedule the konnector trigger between 15:00 (03:00 PM) and 21:00 (09:00 PM). The time zone used is GMT. type type of application ( konnector or webapp ) ( REQUIRED ) version the current version number ( REQUIRED ) vendor_link (konnector specific) URL to editor or service website qualification_labels (konnector specific) Array of one or more labels from the Cozy Client\u2019s qualifications list to associate with the files the konnector will receive from the website. features (konnector specific) Array of features added in the konnector from the list below.", "title": "Properties meaning (reference)"}, {"location": "cozy-apps-registry/#available-manifests-features-list", "text": "2FA Two Factors identification. BILLS Import bills documents, doctype \u201cio.cozy.bills\u201d. FILES Import files documents, doctype \u201cio.cozy.files\u201d. CAPTCHA_RESOLUTION The konnector using a captcha resolution process. CARBON_COPY The konnector import legally true copy of the original files. DOC_QUALIFICATION The konnector uses the first version of files qualifications, you may stumble upon on some konnectors wich hasn\u2019t been treated. DOC_QUALIFICATION_V2 The konnector uses new version (last one for now) of files qualifications. ELECTRONIC_SAFE Files comes from a known electronic safe. HEALTH The konnector treat health documents HTML_TO_PDF The konnector needs to convert HTML page(s) to make pdf files. IDENTITY The konnector create identity(ies) for doctype \u201cio.cozy.identities\u201d LOGIN_OK The konnector deactivate the auto-notification METADATA_DEDUP The konnector uses a fileIdAttribute as detection to avoid deduplication. VENDOR_REF The konnector uses. SENTRY_V2 The konnector had been migrated (or packaged) to sentry V2 (errors.cozycloud.cc) Notices: All images paths ( icon , partnership.icon and screenshots ) should be relative to the build directory. For example, here, the icon.svg is stored in the build root directory and all screenshots are store in a folder screenshots in the build directory. Therefore, if you use a bundler (like webpack) be sure to know exactly where the bundler will store these assets in the build directory (and change it in the manifest if needed). All properties in locales objects will override the matched property of the main manifest.webapp body, if a property is not found in locales it will fallback to the main body one. We use to have the en locale as default one if the one wanted by the user doesn\u2019t exist. Be sure to have, at least, that locale complete with the name and all descriptions. In your build files, this manifest.webapp file must be at the root.", "title": "Available manifest\u2019s features list :"}, {"location": "cozy-apps-registry/#translated-manifest-fields", "text": "Here are the properties that you can override using locales (we recommand to automatically build these properties according to your locales files if you\u2019re using a translating tool like transifex ): name , the app\u2019s name short_description , short description of what the app do long_description , longer and more complete description of the app behaviour changes , description of your new version of the konnector or all changes since the last version fields , An object containing translations for fields. screenshots folders { \"fields\" : { \"email\" : { \"type\" : \"email\" } }, \"locales\" : { \"en\" : { \"short_description\" : \"Collect your Orange's bills\" , \"fields\" : { \"email\" : { \"label\" : \"Identifier (your email)\" } } }, \"fr\" : { \"short_description\" : \"R\u00e9cup\u00e8re vos factures Orange\" , \"fields\" : { \"email\" : { \"label\" : \"Identifiant (votre adresse mail)\" } } } } }", "title": "Translated manifest fields"}, {"location": "cozy-apps-registry/#application-terms", "text": "You can provide a related terms property if you want to display and make the user accept some terms (ToS for example) just before installing the application. Here are all properties allowed and used: url , the URL of the terms/contract to redirect the user to ( REQUIRED ) version : A specific version of the terms, we need it handle terms updates and ask the user again to accept the update. The special characters [*+~.()'\"!:@] are not allowed here. ( REQUIRED ) id : An id for the terms. When accepting terms, we store in io.cozy.terms , a document containing the id and version so that we know which terms have been accepted, and show the user a modal if the terms have not been accepted yet. The special characters [*+~.()'\"!:@] are not allowed here. ( REQUIRED )", "title": "Application terms"}, {"location": "cozy-apps-registry/#konnectors-folders-handling", "text": "The folders property is a list of objects with these following properties: defaultDir : ( REQUIRED ) The default root directory of your folder. In this folder will automatically be created a subfolder with the konnector name and into this latter a subfolder with the account name to store the related files. Here you can use some variables in the path like the following: $administrative : Folder which will receive all administrative related files (bills, contracts, invoices\u2026) $photos : Folder which will receive all photos $konnector : The name of the konnector All paths provided using defaultDir will be the root directory, not the final folder which will receive the files. For example, if you set $photos , the final folder will be $photos/$konnector/$account in order to keep them always sorted by konnectors and accounts.", "title": "Konnectors folders handling"}, {"location": "cozy-apps-registry/#konnectors-fields-property", "text": "The fields property is a JSON object describing the input fields needed to generate the konnector\u2019s configuration form. A typical example will be: { \"fields\" : { \"identifier\" : { \"type\" : \"text\" }, \"secret\" : { \"type\" : \"password\" } } } The keys of the fields object are the name/id of the fields. They will be passed as parameters to the konnector at every run. Each fields may also have the following properties: Property Description identifier (Boolean) indicating if the field is the main identifier. By default, the login field is the identifier. Default value is false and there can be only one identifier advanced Indicates if the field should be displayed in the \u201cadvanced\u201d area of the form (default: false ) default Default value. It can a string for a text field, or an object for a select field ( \"default\": {\"value\": \"foo\",\"name\": \"bar\"}, ) description Field description, as a locale key. label Predefined label. This value must match a locale key provided by Cozy-Home. Example: With label: \"identifier\" , Cozy-Home will use the locale key account.form.label.identifier . Translations for these fields use the locales property in the manifest. max Maximum length of the value (number of characters) min Minimum length of the value (number of characters) options When the field is a dropdown, list of available options pattern Define a regex used to validate the field. isRequired Boolean indicating if the field is required or not (default true ) type Required . Field type from dropdown , email , hidden , password , text , checkbox .", "title": "Konnectors fields property"}, {"location": "cozy-apps-registry/#konnectors-message-property", "text": "Messages are a common way to provide custom information to display in application. An app like cozy-home should have some specific area to display custom messages provided by the konnector. Example: // The final example will be available after the implementation of the whole mechanism, // but here is the global idea: { installSuccess && < p >{ t ( 'home.konnector.install.success.message' )} p > } { installSuccess && konnector . manifest . messages . includes ( 'success_message' ) && < p >{ t ( 'konnector.manifest.locales.messages.success_message' )} }", "title": "Konnectors message property"}, {"location": "cozy-apps-registry/#categories-and-data-types", "text": "Categories are slugs from the following list: banking clouds cozy education energy finance health host_provider insurance isp mes_infos online_services partners press pro productivity ptnb public_service shopping social tech telecom transport Data types are slugs from the following list: activity appointment bankTransactions bankAccounts bill bloodPressure calendar certificate commit consumption contact contract courseMaterial document event family geopoint heartbeat home phonecommunicationlog podcast profile refund sinister sleepTime stepsNumber temperature travelDate tweet videostream weight", "title": "Categories and Data types"}, {"location": "cozy-apps-registry/#2-add-a-new-application-in-the-registry", "text": "", "title": "2) Add a new application in the registry"}, {"location": "cozy-apps-registry/#our-official-apps-registry", "text": "Official registry URL: https://apps-registry.cozycloud.cc In order to use our official repository, you need a token for a specific editor. To do so, contact us directly at the address contact@cozycloud.cc with a mail using the following title prefix: [registry] and provide us these folowing information (not changeable after): - slug of your application - editor name that you want We will provide you with the correct token.", "title": "Our official apps registry"}, {"location": "cozy-apps-registry/#custom-registry", "text": "See the details below to know how to add a new application in a custom cozy-apps-registry instance (local or not). Prequisites : - For this step, you will need your editor token access generated when you created your editor (see below ). You have to replace all {{EDITOR_TOKEN}} in this documentation by this token. - The communication with the registry is done through HTTP requests for now. So we will use the curl command line tool to register our application here. Now you can add your application in the registry. This step is splitted in two septs: - Add a new application (without versions) - Add a version of the application A new application without registered version won\u2019t be displayed by the cozy-store application . To add a new application, you have to do a POST request which all the informations needed to the route registryAddress/registry with registryAddress your registry address (for example here http://localhost:8081 ). Let\u2019s add the Collect application as example: # {{EDITOR_TOKEN}} -> your generated editor access token curl -X \"POST\" \"http://localhost:8081/registry\" \\ -H \"Authorization: Token {{EDITOR_TOKEN}}\" \\ -H \"Content-Type: application/json\" \\ -d $'{ \"slug\": \"collect\", \"type\": \"webapp\", \"editor\": \"{{EDITOR}}\" }' Field Description slug your application unique ID type kind of application (it can be only webapp or konnector ) editor Name of the editor matching the {{EDITOR_TOKEN}} Here the slug is the unique ID of the application in the registry, so it can\u2019t be changed after the application is already registered.", "title": "Custom registry"}, {"location": "cozy-apps-registry/#3-add-a-new-version-of-a-registered-application", "text": "Please note that an application bundle cannot be larger than 20MB (hardcoded value). This limitation has been implemented to encourage better web application development practices because in general the larger the application bundle is, the worst the performance and user experience will be.", "title": "3) Add a new version of a registered application"}, {"location": "cozy-apps-registry/#via-cozy-app-publish-highly-recommanded", "text": "Here we will show the classical way to add a version using the manual mode of cozy-app-publish as reference. But you may need to look at the Automation CI part of this documentation instead. Prequisites : For this step, you will need your editor token access generated when you created your editor (see below ). You have to replace all {{EDITOR_TOKEN}} in this documentation by this token. Don\u2019t forget to build your application first (run yarn build ), cozy-app-publish will read the manifest from your build Firstly, install the cozy-app-publish package using yarn or npm : yarn add cozy-app-publish --dev You can also install the package as a global package, but don\u2019t forget to update it frequently Then use it to publish your application, here is an example for collect : yarn cozy-app-publish \\ --token {{ EDITOR_TOKEN }} \\ --build-url https://github.com/cozy/cozy-collect/archive/042cef26d9d33ea604fe4364eaab569980b500c9.tar.gz \\ --manual-version 1.0.2-dev.042cef26d9d33ea604fe4364eaab569980b500c9 If you need more information about this tool, you can go to the official cozy-app-publish documentation .", "title": "Via cozy-app-publish (highly recommanded)"}, {"location": "cozy-apps-registry/#via-curl", "text": "Here we will show the classical way to add a version using curl as reference. But you may need to look at our dedicated tool cozy-app-publish or the Automation CI part of this documentation instead. Prequisites : - For this step, you will need your editor token access generated when you created your editor (see below ). You have to replace all {{EDITOR_TOKEN}} in this documentation by this token. - The communication with the registry is done through HTTP requests for now. So we will use the curl command line tool to register our application here. To add a new version for a registered application, you have to do a POST request with all needed information to the route registryAddress/registry/:appSlug to publish in default space or registryAddress/:space/registry/:appSlug for a named space (see Spaces & Virtual Spaces below) with registryAddress your registry address (for example here http://localhost:8081 ), :appName your application slug (here drive ) and :space your registry space. Let\u2019s add the version 1.0.1 of the Collect application for example: # {{EDITOR_TOKEN}} -> your generated editor access token curl -X \"POST\" \"http://localhost:8081/registry/collect\" \\ -H \"Authorization: Token {{EDITOR_TOKEN}}\" \\ -H \"Content-Type: application/json\" \\ -d $'{ \"url\": \"https://github.com/cozy/cozy-collect/archive/1.0.1.tar.gz\", \"sha256\": \"96212bf53ab618808da0a92c7b6d9f2867b1f9487ba7c1c29606826b107041b5\", \"version\": \"1.0.1\", }' Field Description url the archive source of your application, it will be downloaded and checked with the sha256 property sha256 the sha256 hash of your source archive matching the archive in url (see the notice below) version version of the application, must match the one in the manifest (see the notice below) Important notices: The version must match the one in the manifest.webapp file for stable release. For beta (X.X.X-betaX) or dev releases (X.X.X-dev.hash256), the version before the cyphen must match the one in the manifest.webapp . If version starts with the v letter (like v1.2.3 ), then the v letter is silently stripped from version, allowing you to simply publish according to tag name if your tags are labelled vx.y.z . For better integrity, the sha256 provided must match the sha256 of the archive provided in url . If it\u2019s not the case, that will be considered as an error and the version won\u2019t be registered.", "title": "Via curl"}, {"location": "cozy-apps-registry/#spaces-virtual-spaces", "text": "", "title": "Spaces & Virtual Spaces"}, {"location": "cozy-apps-registry/#spaces", "text": "You can divide your applications between several isolated places, called spaces . When an application and its versions are published in a space , they are only reachable in that one (you can consider a space like a entire sub-part of the registry). It is espacially useful for splitting up applications by logical topics. Most of the CLI and API endpoints have a space option. You can refer to the documentation or CLI help to view all available parameters.", "title": "Spaces"}, {"location": "cozy-apps-registry/#create-a-space", "text": "Spaces are defined in the config file and are automatically created during registry launching. Add a space entry, followed by your spaces names, and let the registry do the work: spaces : __default__ myspace foospace", "title": "Create a space"}, {"location": "cozy-apps-registry/#remove-a-space", "text": "To remove a space, you have to clean all the remaining apps & versions before removing the space entry name. A CLI is available for the job: $ cozy-apps-registry rm-space Example: $ cozy-apps-registry rm-space foobar Warning: You are going to remove space foobar and all its applications. This action is irreversible. Please enter the space name to confirm: foobar Removing app1/0.7.3-dev.f26bf2b8db3da459071a074a1367ce36e78bb34c Removing app1/0.7.3-dev.cf1efba4c1b6dd08bb5857f5752790f0d2663d6d Removing app1/0.7.3-dev.0bbd57a6ce50af82cfbefb8c231fbfe04516e742 Removing app1/0.7.3-dev.21338229a0c2317dc0f3b94e92b22a367f84c537 Removing app1/0.7.3-dev.08ab3624136fb70dc996003aebc3049af51f7438 Removing app1/0.7.3-dev.4e9d174a3b01acaf8a44b561455efc3f34871142 Removing app1/0.7.3-dev.b2654bf00be393aa611fcbb7f70a8ef671895a84 Removing app1/0.7.3-dev.860861868a5dfe294c7120d81fa9feb5387bb57f Removing app2/0.1.9-dev.954dac9e12e080d591cb76591c311611fed1bea9 You can now delete the name from your config file.", "title": "Remove a space"}, {"location": "cozy-apps-registry/#virtual-spaces", "text": "A virtual space is necessarily built over an existing space . It allows to filter by selecting or rejecting applications available on the underlying space. Please note that it is not possible to publish applications or versions on a virtual space . It is possible to change the name of an application in the virtual space, without changing it in the underlying space, with the cozy-apps-registry overwrite-app-name command. The same thing is possible for the icon with cozy-apps-registry overwrite-app-icon . And the maintenance status can also be changed in the virtual space with the cozy-apps-registry maintenance commands. That\u2019s all for the moment.", "title": "Virtual Spaces"}, {"location": "cozy-apps-registry/#automation-ci", "text": "The following tutorial explains how to connect your continuous integration based on Travis to automatically publish new versions on the apps registry. In this tutorial, we assume: you have a token allowing you to publish applications for your editor : {{EDITOR_TOKEN}} you are working on a repository plugged on travis and named on github myname/cozy-example You first need to add the token to your travis configuration file .travis.yml . To do so, you need the travis utility to encrypt its value. $ travis encrypt REGISTRY_TOKEN ={{ EDITOR_TOKEN }} -r myname/cozy-example --org Please add the following to your .travis.yml file: secure: \"jUAjk..LOOOOONG_ENCRYPTED_STRING.....jdk89=\" Like said, you need to add this block of ciphered data in the .travis.yml (if it\u2019s not already done automatically). This will allow you to use the REGISTRY_TOKEN variable in your deployment script. Then, you can add the publish script in your package.json in order to be used by Travis: ... \"publish:cozy\" : \"git fetch origin ${DEPLOY_BRANCH:-build}:${DEPLOY_BRANCH:-build} && cozy-app-publish --token $REGISTRY_TOKEN --build-commit $(git rev-parse ${DEPLOY_BRANCH:-build})\" ... This script will fetch your last commit from the build branch to publish to the registry. If you push a tag, be sure to wait the last build branch Travis build finished in order to have the real last commit to publish. Finally, you can add this script to your .travis.yml to publish your app using our publishing tool cozy-app-publish during the deploy process: ... before_deploy: - yarn add cozy-app-publish deploy: - provider: script repo: myname/cozy-example skip-cleanup: true script: export DEPLOY_BRANCH=build && yarn deploy && yarn publish:cozy on: branch: master - provider: script repo: myname/cozy-example skip-cleanup: true script: export DEPLOY_BRANCH=build && yarn publish:cozy on: tags: true ... Important notices: A commit push to the branch master will publish your application in the dev channel of the registry. A tag push (Github release) will publish a stable version (ex: 1.0.0 ) or a beta version (ex: 1.0.1-beta2 ) to the registry (automatically handled by the registry). cozy-app-publish will use the github archive URL computing to get the application tarball. If your applicaiton is not on Github, you may need to use the manual mode of the command.", "title": "Automation (CI)"}, {"location": "cozy-apps-registry/#access-control-and-tokens", "text": "The read-only routes of the registry are all public and do not require any access-control. However routes allowing to create applications and versions have access-control policies associated to them. The registry has two types of access permissions, that are associated to two different tokens: editor tokens : these tokens give access to the publication of new versions on the registry, for a specific editor name, at these conditions: the version\u2019s application must already exist in the registry the version\u2019s application must have the same \u201ceditor\u201d value as the token master tokens : these tokens are allowed to create and register new applications on the registry, and associate them with an existing editor name. They also have the same accesses as the editor tokens. Editor tokens can be specific to one or more applications names that they are allowed to publish. In order to create tokens, the binary offers a gen-token command-line. Here are some examples to illustrates some usages: # Generating tokens # generate an editor token for the editor \"cozy\", for any application $ cozy-apps-registry gen-token cozy # generate an editor token for the editor \"cozy\" expiring after 30 days $ cozy-apps-registry gen-token cozy --max-age 30d # generate an editor token for the editor \"cozy\" for application \"collect\" and \"drive\" $ cozy-apps-registry gen-token cozy --apps collect,drive # generate a master token associated with the editor \"cozy\" expiring after 30 days $ cozy-apps-registry gen-token cozy --master --max-age 30d # Verifying tokens # verify the editor token \"XXX\" for the editor \"cozy\" $ cozy-apps-registry verify-token cozy \"XXX\" # verify the master token \"XXX\" associated with the editor \"cozy\" $ cozy-apps-registry verify-token cozy \"XXX\" --master # Revoking tokens # revoke all editors tokens for the cozy editor $ cozy-apps-registry revoke-tokens cozy # revoke all master tokens associated with the cozy editor $ cozy-apps-registry revoke-tokens cozy --master", "title": "Access control and tokens"}, {"location": "cozy-apps-registry/#maintenance", "text": "In order to set/unset an application into maintenance mode, the binary offers a maintenance command-line. Here are some examples of how to use it: # Activate maintenance mode for the application 'bank' of space 'myspace' # Available flagged options: # --infra specify a maintenance specific to our infra # --no-manual-exec specify a maintenance disallowing manual execution # --short specify a short maintenance $ cozy-apps-registry maintenance activate bank --space myspace # Deactivate maintenance mode for the application 'bank' of space 'myspace' $ cozy-apps-registry maintenance deactivate bank --space myspace Or using a cURL request and a master token: curl -XPUT \\ -H \"Authorization: Token $COZY_REGISTRY_ADMIN_TOKEN \" \\ -H \"Content-Type: application/json\" \\ -d '{\"flag_infra_maintenance\": false,\"flag_short_maintenance\": false,\"flag_disallow_manual_exec\": false,\"messages\": {\"fr\": {\"long_message\": \"Bla bla bla\",\"short_message\": \"Bla\"},\"en\": {\"long_message\": \"Yadi yadi yada\",\"short_message\": \"Yada\"}}}' \\ https://apps-registry.cozycloud.cc/myspace/registry/maintenance/bank/activate curl -XPUT \\ -H \"Authorization: Token $COZY_REGISTRY_ADMIN_TOKEN \" \\ https://apps-registry.cozycloud.cc/registry/maintenance/bank/deactivate", "title": "Maintenance"}, {"location": "cozy-apps-registry/#importexport", "text": "CouchDB & Swift can be exported into a single archive with cozy-apps-registry export . Registry data are exported as below: registry/couchdb/{db}/{uuid}.json : CouchDB document exported as JSON registry/swift/{file/path} : Swift document, with the following tar custom metadata COZY.content-type : associated content type The generated archive can be imported with cozy-apps-registry import -d . The -d option will drop CouchDB databases and Swift containers related to declared spaces on the registry configuration.", "title": "Import/export"}, {"location": "cozy-apps-registry/#application-confidence-grade-labelling", "text": "The confidence grade of an applications can be specified by specifying the data_usage_commitment and data_usage_commitment_by fields of the application document. Possible values for these properties are: data_usage_commitment : specify a technical commitment from the application editor: user_ciphered : technical commitment that the user\u2019s data is encrypted and can only be known by him. user_reserved : commitment that the data is only used for the user, to directly offer its service. none : no commitment data_usage_commitment_by : specify what entity is taking the commitment: cozy : the commitment is taken by cozy editor : the commitment is taken by the application\u2019s editor none : no commitment is taken To do that, a command line and admin API are available, and be used as follow: $ cozy-apps-registry modify-app banks --space my_space --data-usage-commitment user_reserved --data-usage-commitment-by editor Or using a cURL request and a master token: curl -XPATCH \\ -H\"Authorization: Token $COZY_REGISTRY_ADMIN_TOKEN\" \\ -H\"Content-Type: application/json\" \\ -d'{\"data_usage_commitment\": \"user_reserved\", \"data_usage_commitment_by\": \"editor\"} https://apps-registry.cozycloud.cc/my_space/registry/banks", "title": "Application confidence grade / labelling"}, {"location": "cozy-apps-registry/#universal-links", "text": "The registry can manage Universal links .", "title": "Universal links"}, {"location": "cozy-apps-registry/#configuration", "text": "", "title": "Configuration"}, {"location": "cozy-apps-registry/#config-file", "text": "Each space holds its own files. The space determination is based on the request host, so you must bind a domain to a space in the config file. domain_space : mycloud.com : \"__default__\" cloud.foobar.com : \"foobar\"", "title": "Config file"}, {"location": "cozy-apps-registry/#files", "text": "Place your files (e.g apple-app-site-association ) in the space container. The file must be prepended with universallink/ For the foobar space and file apple-app-site-association , the file has to be named universallink/apple-app-site-association and placed in the foobar container", "title": "Files"}, {"location": "cozy-apps-registry/#usage", "text": "The following endpoint is available to get any file: http:///.well-known/:filename You can now query your endpoint to get your file: curl -X GET http://cloud.foobar.com/.well-known/apple-app-site-association { \"applinks\" : { \"apps\" : [] , \"details\" : [ { \"appID\" : \"3AKXFMV43J.io.cozy.drive.mobile\" , \"paths\" : [ \"/drive\" ] } , { \"appID\" : \"3AKXFMV43J.io.cozy.banks.mobile\" , \"paths\" : [ \"/banks\" ] } , { \"appID\" : \"3AKXFMV43J.io.cozy.photos.mobile\" , \"paths\" : [ \"/photos\" ] } ] } }", "title": "Usage"}, {"location": "cozy-apps-registry/#budget-insight-web-auth", "text": "For some banks integration (Paypal, Orange Bank, Revolut\u2026), Budget-Insight need something similar to universal link because they expect a static domain for fallback but there is a specific domain per Cozy instance. In contrast with universal links, query parameters (provided by BI) are propagated to the final fallback redirection. http:///biwebauth?fallback=http%3A%2F%2Fa.cozy%3Ffoo%3Dfoo&bar=bar redirect to http://a.cozy?foo=foo&bar=bar , merging fallback provided query parameters ( foo=foo ) with webauth provided ones ( bar=bar ).", "title": "Budget-Insight web auth"}, {"location": "cozy-apps-registry/#community", "text": "You can reach the Cozy Community by: Chatting with us on IRC #cozycloud on Libera.Chat Posting on our Forum Posting issues on the Github repos Say Hi! on Twitter", "title": "Community"}, {"location": "cozy-apps-registry/CONTRIBUTING/", "text": "How to contribute to the Cozy Registry v3? \u00b6 Thank you for your interest in contributing to Cozy! There are many ways to contribute, and we appreciate all of them. Security Issues \u00b6 If you discover a security issue, please bring it to their attention right away! Please DO NOT file a public issue, instead send your report privately to security AT cozycloud DOT cc. Security reports are greatly appreciated and we will publicly thank you for it. We currently do not offer a paid security bounty program, but are not ruling it out in the future. Bug Reports \u00b6 While bugs are unfortunate, they\u2019re a reality in software. We can\u2019t fix what we don\u2019t know about, so please report liberally. If you\u2019re not sure if something is a bug or not, feel free to file a bug anyway. Opening an issue is as easy as following this link and filling out the fields. Here are some things you can write about your bug: A short summary What did you try, step by step? What did you expect? What did happen instead? What is the version of the Cozy Stack? Pull Requests \u00b6 Workflow \u00b6 Pull requests are the primary mechanism we use to change Cozy. GitHub itself has some great documentation on using the Pull Request feature. We use the \u2018fork and pull\u2019 model described there. Step 1: Fork \u00b6 Fork the project on GitHub and check out your copy locally: $ git clone https://github.com/cozy/cozy-apps-registry.git $ cd cozy-apps-registry $ git remote add fork git://github.com/username/cozy-apps-registry.git Step 2: Branch \u00b6 Create a branch and start hacking: $ git checkout -b my-branch -t origin/master Step 3: Code \u00b6 Well, I think you know how to do that. Just be sure to follow the coding guidelines from the Go community (gofmt, Effective Go , comment the code, etc.). Step 4: Test \u00b6 Don\u2019t forget to add tests and be sure they are green: $ go test -v Step 5: Commit \u00b6 Writing good commit messages is important. A commit message should describe what changed and why. Step 6: Rebase \u00b6 Use git pull --rebase , or git rebase (but not git merge ), to sync your work from time to time: $ git pull origin master --rebase Step 7: Push \u00b6 $ git push fork my-branch Go to https://github.com/username/cozy-apps-registry and select your branch. Click the \u2018Pull Request\u2019 button and fill out the form. Pull requests are usually reviewed within a few days. If there are comments to address, apply your changes in a separate commit and push that to your branch. Community \u00b6 You can help us by making our community even more vibrant. For example, you can write a blog post, take some videos, answer the questions on the forum , organize new meetups, and speak about what you like in Cozy!", "title": "CONTRIBUTING"}, {"location": "cozy-apps-registry/CONTRIBUTING/#how-to-contribute-to-the-cozy-registry-v3", "text": "Thank you for your interest in contributing to Cozy! There are many ways to contribute, and we appreciate all of them.", "title": "How to contribute to the Cozy Registry v3?"}, {"location": "cozy-apps-registry/CONTRIBUTING/#security-issues", "text": "If you discover a security issue, please bring it to their attention right away! Please DO NOT file a public issue, instead send your report privately to security AT cozycloud DOT cc. Security reports are greatly appreciated and we will publicly thank you for it. We currently do not offer a paid security bounty program, but are not ruling it out in the future.", "title": "Security Issues"}, {"location": "cozy-apps-registry/CONTRIBUTING/#bug-reports", "text": "While bugs are unfortunate, they\u2019re a reality in software. We can\u2019t fix what we don\u2019t know about, so please report liberally. If you\u2019re not sure if something is a bug or not, feel free to file a bug anyway. Opening an issue is as easy as following this link and filling out the fields. Here are some things you can write about your bug: A short summary What did you try, step by step? What did you expect? What did happen instead? What is the version of the Cozy Stack?", "title": "Bug Reports"}, {"location": "cozy-apps-registry/CONTRIBUTING/#pull-requests", "text": "", "title": "Pull Requests"}, {"location": "cozy-apps-registry/CONTRIBUTING/#workflow", "text": "Pull requests are the primary mechanism we use to change Cozy. GitHub itself has some great documentation on using the Pull Request feature. We use the \u2018fork and pull\u2019 model described there.", "title": "Workflow"}, {"location": "cozy-apps-registry/CONTRIBUTING/#step-1-fork", "text": "Fork the project on GitHub and check out your copy locally: $ git clone https://github.com/cozy/cozy-apps-registry.git $ cd cozy-apps-registry $ git remote add fork git://github.com/username/cozy-apps-registry.git", "title": "Step 1: Fork"}, {"location": "cozy-apps-registry/CONTRIBUTING/#step-2-branch", "text": "Create a branch and start hacking: $ git checkout -b my-branch -t origin/master", "title": "Step 2: Branch"}, {"location": "cozy-apps-registry/CONTRIBUTING/#step-3-code", "text": "Well, I think you know how to do that. Just be sure to follow the coding guidelines from the Go community (gofmt, Effective Go , comment the code, etc.).", "title": "Step 3: Code"}, {"location": "cozy-apps-registry/CONTRIBUTING/#step-4-test", "text": "Don\u2019t forget to add tests and be sure they are green: $ go test -v", "title": "Step 4: Test"}, {"location": "cozy-apps-registry/CONTRIBUTING/#step-5-commit", "text": "Writing good commit messages is important. A commit message should describe what changed and why.", "title": "Step 5: Commit"}, {"location": "cozy-apps-registry/CONTRIBUTING/#step-6-rebase", "text": "Use git pull --rebase , or git rebase (but not git merge ), to sync your work from time to time: $ git pull origin master --rebase", "title": "Step 6: Rebase"}, {"location": "cozy-apps-registry/CONTRIBUTING/#step-7-push", "text": "$ git push fork my-branch Go to https://github.com/username/cozy-apps-registry and select your branch. Click the \u2018Pull Request\u2019 button and fill out the form. Pull requests are usually reviewed within a few days. If there are comments to address, apply your changes in a separate commit and push that to your branch.", "title": "Step 7: Push"}, {"location": "cozy-apps-registry/CONTRIBUTING/#community", "text": "You can help us by making our community even more vibrant. For example, you can write a blog post, take some videos, answer the questions on the forum , organize new meetups, and speak about what you like in Cozy!", "title": "Community"}, {"location": "cozy-banks/", "text": "Cozy Banks \u00b6 Cozy Banks is the personal financial management application available on Cozy. It helps you gain understanding of your personal finances, and much more . As the first digital home on the market, Cozy helps all users with applications and connectors regain control, streamline and maximize their digital lives. With Cozy Banks, you can easily: Have all your bank accounts in one place Get an comprehensive overview of all your expenses with one-click access to your bills Directly access your health insurance reimbursements Enjoy all the features for free Developing Account Types Bills Matching Brand Dictionnary Categorization Category Code Conventions Credentials Data Fetching Demo Notification Override Cordova Config Perfs Services Tracking Feature requests Feature requests \u00b6 We love getting feedback, do not hesitate if you have any. Please use the forum for any feature requests.", "title": "Cozy Banks"}, {"location": "cozy-banks/#cozy-banks", "text": "Cozy Banks is the personal financial management application available on Cozy. It helps you gain understanding of your personal finances, and much more . As the first digital home on the market, Cozy helps all users with applications and connectors regain control, streamline and maximize their digital lives. With Cozy Banks, you can easily: Have all your bank accounts in one place Get an comprehensive overview of all your expenses with one-click access to your bills Directly access your health insurance reimbursements Enjoy all the features for free Developing Account Types Bills Matching Brand Dictionnary Categorization Category Code Conventions Credentials Data Fetching Demo Notification Override Cordova Config Perfs Services Tracking Feature requests", "title": "Cozy Banks"}, {"location": "cozy-banks/#feature-requests", "text": "We love getting feedback, do not hesitate if you have any. Please use the forum for any feature requests.", "title": "Feature requests"}, {"location": "cozy-banks/CHANGELOG/", "text": "1.59.0 \u00b6 1.58.0 \u00b6 \u2728 Features \u00b6 Use redux store for save all brands Use optimize query for get triggers without jobs \ud83d\udc1b Bug Fixes \u00b6 No chips for Konnectors under maintenance In order to display correctly the KonnectorChip and don\u2019t propose the installation of a clisk if it\u2019s already connected \ud83d\udd27 Tech \u00b6 Retrieving connectors via the registry in addition to the JSON file 1.57.0 \u00b6 \u2728 Features \u00b6 Upgrade cozy-scripts from 6.3.0 to 8.1.1 \ud83d\udc1b Bug Fixes \u00b6 Transaction modale closed by itself on some mobile devices Fields in Intent modals must be clickable 1.56.0 \u00b6 \u2728 Features \u00b6 Hide KonnectorChip by flag for health category Hide BillChip by flag for health category Remove native link and icon from manifest \ud83d\udc1b Bug Fixes \u00b6 Transaction modale closed by itself on some mobile devices \ud83d\udd27 Tech \u00b6 Remove logs with unnecessary or sensitive data 1.55.0 \u00b6 \u2728 Features \u00b6 Update cozy-bar to get fixed cloud icon position Save imported transactions count Update Success modal to specify number of successfully imported operations Add balancesNotifications to io.cozy.bank.settings Add current balance for each account in io.cozy.bank.settings when onOperationOrBillCreate service run. \ud83d\udc1b Bug Fixes \u00b6 French wording for import success title Email notification for balance greater wasn\u2019t using the right title Reduction of the number of BalanceLower & BalanceGreater notifications \ud83d\udd27 Tech \u00b6 Add import service documentation 1.54.0 \u00b6 \ud83d\udc1b Bug Fixes \u00b6 Import accounts with a normalized number Prevent fallback on sub-optimal index for in-progress jobs query. \ud83d\udd27 Tech \u00b6 Notifications are compatible with the new Cozy app 1.53.0 \u00b6 \u2728 Features \u00b6 Export your bank\u2019s data in csv format via the Settings page Import bank data from Cozy bank export file ( csv format) via the Settings page Rework renderExtraRoutesWithoutLayout AppRoute method Allow grouping bank accounts by institution labels in Settings \ud83d\udc1b Bug Fixes \u00b6 The service onOperationOrBillCreate was failing with a CozyStackClient.collection() called without a doctype error. Bank accounts imported via the import service are grouped by their institution label in the Settings\u202f>\u202fAccounts tab \ud83d\udd27 Tech \u00b6 Remove direct dependency to cozy-stack-client Bump cozy-stack-client from 35.3.1 to 35.6.0 Bump cozy-pouch-link from 35.3.1 to 35.6.0 Services launched via the CLI use a CozyClient instance with appMetadata 1.52.0 \u00b6 \u2728 Features \u00b6 Update cozy-bar from 8.11.2 to 8.14.0 \ud83d\udc1b Bug Fixes \u00b6 When a connector needs to be updated, it no longer impacts the add bank connector buttons The recurrence service should not modify transactions already associated with a recurrence Use absolute links for analysis tabs Right arrow on advanced filter in category page was not clickable \ud83d\udd27 Tech \u00b6 Clarified recurrence service functions and variables names Add better log for services More specific log for doTransactionsMatching and doBillsMatching in onOperationOrBillCreate Improved performance of transactions filtering in the recurrence service 1.51.0 \u00b6 \u2728 Features \u00b6 The stats service is no longer useful, we can remove it from the manifest and delete the deprecated code Update React Router to v6 Update cozy-authentication from 2.1.0 to 2.12.1 \ud83d\udc1b Bug Fixes \u00b6 Fix bad display of settings menu \ud83d\udd27 Tech \u00b6 Remove cozy-client-js assets 1.50.0 \u00b6 \u2728 Features \u00b6 Upgrade cozy-ui from 75.4.0 to 79.0.0 Upgrade cozy-client from 33.2.0 to 34.5.0 Upgrade cozy-stack-client from 33.2.0 to 34.1.5 Upgrade cozy-pouch-link from 33.2.0 to 34.5.0 Upgrade cozy-device-helper from 2.1.0 to 2.6.0 Upgrade cozy-harvest-lib from 9.32.4 to 10.0.0 \ud83d\udc1b Bug Fixes \u00b6 Exclude virtual accounts from the counter on the balance page Localize account and group labels in notification settings 1.49.0 \u00b6 \u2728 Features \u00b6 upgrade cozy-bar and cozy-intent to 8.11/2.7 \ud83d\udc1b Bug Fixes \u00b6 update icon-banks svg file 1.48.0 \u00b6 \ud83d\udd27 Tech \u00b6 Use warn log instead of info for konnectorAlerts service \ud83d\udc1b Bug Fixes \u00b6 KonnectorAlerts notification onSuccess is async 1.47.1 \u00b6 \u2728 Features \u00b6 Upgrade cozy-harvest-lib to 9.32.3 : Use OAuthService in KonnectorAccountTabs Use OAuthService in OAuthForm Update wording for Bank disconnect dialog close button Add independent confirm dialog Use independant OAuth window Better locale for delete BI connection confirmation button Follow current trigger jobs even after the first load Only update cozy-client store when refreshing contracts Do not unsubscribe all realtime events Prevent createTemporaryToken to updateCache twice at the same time upgrade cozy-realtime to 4.2.9 to get the sendNotification method Upgrade cozy-bar from 8.9.3 to 8.9.4 Add konnector slug in fake trigger passed to onLoginSuccess Add realtime update of cozy accounts Add the virtual reimbursement accounts to the account switch Add the account switch to the reimbursement page Do not display success or error toast for webhooks other than CONNECTION_SYNCED \ud83d\udc1b Bug Fixes \u00b6 Do not display an error icon for all accounts with the same slug Ignore account delete and account disabled jobs for import success message Remove import in progress in the end of the connector job Use CozyClient.saveAll() instead of Document.updateAll() from deprecated cozy-doctypes to avoid CouchDB errors with attributes starting with an underscore (#2547) Swap providers to make some Harvest dialogs match the theme Handles accounts created after bi webhooks on contract synchronization Fix notifications issues on the b2c app Don\u2019t register the flag plugin twice Wrong locale on BI connection removal https://github.com/cozy/cozy-libs/commit/ed2f352467da5f36ef1753de5578f156bb2a1ffb Update cozy accounts when removed from cozy-stack after BI connection removal from BI webview Reverts \u201cInclude virtual accounts in the account total count in balance details\u201d Exclude virtual accounts from the account count in balance details Do not show any account when none is selected in balance details Always show the action column since tags are always enabled Handles accounts created after bi webhooks on contract synchronization \ud83d\udd27 Tech \u00b6 Add more logs around LateHealthReimbursement onSuccess method 1.47.0 \u00b6 \u2728 Features \u00b6 Add wait job New OAuthWrapperCompProps in TriggerManager Preserve selected tags when navigating in categories Don\u2019t notify users about very old konnector run failures (i.e. older than 7 days and 15 minutes which is the maximum delay between the last failure and the scheduled 7 days reminder). Remove flag for Tags feature \ud83d\udc1b Bug Fixes \u00b6 Add and remove tags at the same time on a transaction Fix blank block within the flagship app for the cozy-bar Prevent scheduling konnectorAlerts triggers in the past which would be executed right away by cozy-stack ending up sending multiple notifications to the user about the failed konnector run. Include virtual accounts in the account total count in balance details Log event only when hiding incomes and not when unhiding them 1.46.0 \u00b6 \u2728 Features \u00b6 Optimization of the Mango query to get first / last date for an account No more 404 call to manifest.json Add new event and page loggers for tags Add a new switch to toggle hiding amounts in mobile notifications \ud83d\udc1b Bug Fixes \u00b6 Revert cozy-script to deduplicate CSS files Harvest: Hide BIContractActivationWindow behind the bi webview flag 1.45.0 \u00b6 \u2728 Features \u00b6 Add tags on transactions Add a tab in the settings to list all the tags Add a modal to filter by Tags on the analysis page Upgrade cozy-ui from 69.3.0 to 74.3.0 Add a page for managing a given tag Optimization of the Mango query to get first / last date for an account \ud83d\udc1b Bug Fixes \u00b6 Fix recurrence service that was triggering itself in an infinite loop [PR] Fix typo in French translation [PR] Transactions actions style on mobile Notifications based on transactions changes will only be sent once, even if the transaction is modified after the first trigger [PR] Update trigger without fetch policy in AccountModal, while reconnecting a konnector Update cozy-harvest-lib 9.15.1 : Update trigger while status changed [PR] Update trigger without fetch policy in AccountModal, while reconnecting a konnector [PR] Prevent recurrence service from running until we figure out why it is triggering itself in an infinite loop [PR] \ud83d\udd27 Tech \u00b6 Remove dev dependency to cozy-ach [PR] 1.44.0 \u00b6 \u2728 Features \u00b6 Update cozy-stack-client and cozy-pouch-link to sync with cozy-client version Use DropdownText comp instead of custom in AccountSwitch Update cozy-harvest-lib 9.8.0 : Add reconnect to bi Webviews [PR] 9.10.1 : Add custom intentsApi prop to TriggerManager [PR] 9.11.1 : Add sync date on ContractItem and overrides ability in AccountModal [PR] and [PR] 9.12.0 : Do not show Popup when intentsApi parameter is given [PR] 9.12.2 : Do not pre encode oauth url [PR] and Do not show popup when intentsApi is given [PR] 9.12.3 : Do not double encode oauth url [PR] 9.14.1 : Change RedirectToAccountFormButton label & size [PR] 9.15.1 : Update trigger while status changed [PR] 9.16.0 : Allow EditAccountModal to have intentsApi ( 43c5910 ) Now open the BI manage webview to the correct connection id ( 2f3da74 ) 9.17.0 : All oauth methods to handle reconection case ( b1a6033 ) Do not show identifiers with bi Webviews ( 58e1bb1 ) 9.18.0 : Add error message display in OAuthForm component ( f29b3c4 ) Handle user dismiss in Oauth window ( a6dcba8 ) 9.22.2 : feat: Allow disabled banks to be clickable 9.23.2 : Add BI aggregator releationship to BI accounts 9.25.0 : Now OAuth popup/inAppBrowser wait for login success to hide 9.26.1 : Use BI account creation webview to handle account synchronization RefreshContracts now updates contracts in realtime Disable account line in import group panel to prevent accessing an account not yet ready Change wording for toast message when importing data from a bank is completed Remove icon on ReconnectTriggerButton Add intentsApi prop to HarvestBankAccountSettings Add a spinner in OAuth popup/InAppBrowser after OAuth redirection \ud83d\udc1b Bug Fixes \u00b6 Fix App Amirale UI issues by updating cozy-ui [PR] Update trigger without fetch policy in AccountModal, while reconnecting a konnector [PR] Use the right color for input text Colors when importing account Prevent recurrence service from running until we figure out why it is triggering itself in an infinite loop [PR] Do not allways show the same bank in BI webview Do fail the connector for banks with multiple bank ids Update cozy-client to 32.2.7 : Lodash.merge is not creating a new object PR fix temporary token cache when beginning with an empty cache PR Breaking changes are not supposed to affect cozy-banks Update cozy-harvest-lib 9.12.2 : Do not pre encode oauth url PR and Do not show popup when intentsApi is given PR 9.12.3 : Do not double encode oauth url PR Prevent recurrence service from running until we figure out why it is triggering itself in an infinite loop [PR] Do not allways show the same bank in BI webview Do fail the connector for banks with multiple bank ids Update cozy-client to 32.2.6 : fix temporary token cache when beginning with an empty cache PR Breaking changes are not supposed to affect cozy-banks Invalidate temporary token cache when there is a change of BI user OauthWindowInAppBrowser re-render 9.12.2 : Do not pre encode oauth url PR and Do not show popup when intentsApi is given PR Harvest 9.25.0: Remove an BI webview reconnection step Remove an unused request to BI api to be faster 9.26.6 : Better handling of duplicate accounts : locale + realtime in bank accounts Display the resulting account in the Settings screen after an account creation (with realtime) Update cozy-harvest-lib 9.14.1 Update cozy-client to 32.2.6 \ud83d\udd27 Tech \u00b6 Extract import of AccountModalContent in HarvestAccountModal to be able to override it easily 1.43.1 \u00b6 \ud83d\udc1b Bug Fixes \u00b6 Fix services that were broken due to latest cozy-client update [PR] 1.43.0 \u00b6 \u2728 Features \u00b6 Change Sentry url + add instance in tags context Upgrade cozy-client to get ability to force HTTPs fetches when window.cozy.isSecureProtocol is true CozyClient can be used in a node env [PR] Fix App Amirale localhost dev server issues by updating cozy-scripts [PR] \ud83d\udc1b Bug Fixes \u00b6 cozy-harvest-lib 9.4.0 : Get correct bi mapping for bnp_es and cic_es PR Remove useVaultClient call in LegacyTriggerManager PR TriggerManager OAuthForm wrapper PR Upgrade cozy-ui to 67.0.2 to get bugfix on Matomo tracking Fix deprecated bundles help french translation \ud83d\udd27 Tech \u00b6 Update cozy packages 1.42.0 \u00b6 \u2728 Features \u00b6 Update cozy-client and cozy-stack-client to 27.17.0 Update cozy-harvest-lib to 7.3.1 \ud83d\udd27 Tech \u00b6 Remove the creation of an Android version of the application 1.41.0 \u00b6 \ud83d\udc1b Bug Fixes \u00b6 Transactions page indicated isDesktop undefined when changing month in the date selector Reimbursements shows correct datas even if coming from the home page \ud83d\udd27 Tech \u00b6 Refactor of Reimbursements from class component to functional component Update documentation to install and start project 1.40.0 \u00b6 \u2728 Features \u00b6 cozy-harvest-lib 6.15.0 : get support email according to the contect PR \ud83d\udc1b Bug Fixes \u00b6 Scheduled notification are created only if a notification will be sent in the next day, and only if there is no already notification in the futur Notifications for errored connector are now sent at 5am local time (UTC for cozy servers) instead of 6am Scheduling notifications if sending is between 10pm and 5am local time (UTC for cozy servers) instead of 11pm and 6am Reimbursment panel was not correctly displaying the transactions Switching to /analysis/categories from \u201creimbursment virutal group\u201d no longer leads to empty page Get reimbursements data for transactions fetched on the homepage. This fixes reimbursements group. \ud83d\udd27 Tech \u00b6 1.39.0 \u00b6 \u2728 Features \u00b6 Scheduling notifications if sending is between 11pm and 6am Notifications for errored connector are now sent at 6am instead of 8am Show alert message when a request failed (allows to reload the app) \ud83d\udc1b Bug Fixes \u00b6 Show empty page title only for mobile Reimbursement block is visible again on the balance page if it is shown first Show operations by date and by account (and not the reverse) in group details Fix colors Alerter component and alert message displayed several times 1.38.0 \u00b6 \u2728 Features \u00b6 Alert notifications for KO connectors link to the accounts page in the settings Change wording push content notification Change EUR by \u20ac Replace \u2018.\u2019 in amount by \u2018,\u2019 Capitalize each transaction label word Show by line 50 char max Example if the label from transaction is Salaire du mois de Septembre 2021 (01/09/2021) with an amount 1234.56 so we display that: Salaire Du Mois De Septembre 2021 (01/0 : 1234,56\u20ac Color change for the recurrence edition modal \ud83d\udd27 Tech \u00b6 Refactor for RecurrencePage and split component into different files 1.37.0 \u00b6 \u2728 Features \u00b6 Add notifications at +3 and +7 days for banking connectors, if the connector is in an actionable error Recurrency service: allows to attach transactions whose amount is between 2 extremes of amounts in the existing recurrences (+/- 5% by default). This percentage is configurable with the flag banks.recurrency.percentage-amounts-accepted . Example for 10% set 0.1 \ud83d\udc1b Bug Fixes \u00b6 Fix Month / Year selection on iOS in Analysis Page Fix no data displayed in Analysis Page on iOS Fix Accordion border color and SelectDates text color \ud83d\udd27 Tech \u00b6 Move / Refactor / Split CategoriesHeader component Split bundle into 3 chunks: main, vendor and cozy-bar Update Cozy App Publish (Fix travis icon on mattermost publish announcement) 1.36.0 \u00b6 \u2728 Features \u00b6 Add latest transaction amount value in recurrences Futur balances shows latest transaction amount \ud83d\udc1b Bug Fixes \u00b6 Update cozy-ui to 52.0.0 to reduce the size of the bundle Exclude some modules to reduce the size of the bundle \u2018node-forge\u2019, \u2018node-jose\u2019, \u2018tldjs\u2019 Remove third level import from Mui in HistoryChart fix undefined var in the categ service Transaction Label is now truncated if too long in the Transaction details modal Fix Search Link when clicking on the magnifying glasse if label contained an \u201c/\u201d \ud83d\udd27 Tech \u00b6 Add recurrence test for not same account scenario + refactor other recurrence tests Use CozyClient links instead of StackClient in removeAccountFromGroups 1.35.0 \u00b6 \u2728 Features \u00b6 Optimization of the database on mobile (addition of the indexeddb adapter). For old users, a modal appears and allows to launch the data migration. Update cozy-pouch-link to 24.3.2 to be able to migrates database on mobile to indexeddb Remove minimum limit to find recurrence Recurrence creation process will always try to update existing bundle before creating some Ability to update old recurrences and create new ones in the same batch Change recurrence lookback date limit from 90 to 100 days Selection mode to change the category of several transactions at once Update cozy-harvest-lib to 6.6.0 to get the correct BI slug for palatine bank Change migration modal wording \ud83d\udc1b Bug Fixes \u00b6 Error when removing a group on desktop and mobile Correct minimum date is used to create recurrence Fix warming queries with null applicationDate selector \ud83d\udd27 Tech \u00b6 Add pouchdb-adapter-idb and pouchdb-adapter-indexeddb v7.2.2 Extract component from GroupSettings Groups are not filtered anymore to exclude undefined one in AccountSwitch Remove updateOrCreateGroup() to remove router from dependencies Only deep import for lodash Add logs to better debugging recurrence 1.34.0 \u00b6 \u2728 Features \u00b6 Remove balance from transaction header Add checkbox icon button to activate selection mode in transactions page and search page Improve ui for no result in search page Recategorizing multiple transactions is much faster with better performance Optimize transactions queries by changing indexes order Separates notifications content by a return to line Update cozy-ui to 51.4.0 Update cozy-harvest-lib to 6.4.0 Update cozy-client and cozy-pouch-link to 24.1.0 to fix queryAll bug and destroy on Pouch Update cozy-stack-client to 24.0.0 \ud83d\udc1b Bug Fixes \u00b6 Checkbox horizontal position for selectionning rows in desktop Hide owner field in account configuration when Contacts app is not installed Deactivates selection mode when leaving an account page First transactions are no longer trimmed on the balance page on tablet Missing colors for categories in the chart on the analysis page The analysis page correctly retrieves information when viewing all accounts Prevent render loop after login if a pin had been set Render pin setting row in configuration even when no pin has been set yet Autogroups and LinkMyselfToAccount services crashed if configuration settings had not been saved yet Median function in Recurrence returns the correct median Reassigned transactions are displayed in the correct period according to the selected period On mobile, account settings page doesn\u2019t loop after removing an account Checkbox in transaction row are no longer trimmed Transactions are no longer selectable in the projected expenses page Planned transactions page shows transactions correctly on tablet \ud83d\udd27 Tech \u00b6 To facilitate overriding about notifications and standardize their entry point, a bit refactoring was necessary: Move CategoryBudget to notifications folder Move lang and dictRequire to utils/lang Ability to run the push notifications debug server from the CLI Add some documentation to develop for android Extract HeaderInfoCard from PlannedTransactionsPage Extract PlannedTransactionsPage header in its own component", "title": "1.59.0"}, {"location": "cozy-banks/CHANGELOG/#1590", "text": "", "title": "1.59.0"}, {"location": "cozy-banks/CHANGELOG/#1580", "text": "", "title": "1.58.0"}, {"location": "cozy-banks/CHANGELOG/#features", "text": "Use redux store for save all brands Use optimize query for get triggers without jobs", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes", "text": "No chips for Konnectors under maintenance In order to display correctly the KonnectorChip and don\u2019t propose the installation of a clisk if it\u2019s already connected", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#tech", "text": "Retrieving connectors via the registry in addition to the JSON file", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1570", "text": "", "title": "1.57.0"}, {"location": "cozy-banks/CHANGELOG/#features_1", "text": "Upgrade cozy-scripts from 6.3.0 to 8.1.1", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_1", "text": "Transaction modale closed by itself on some mobile devices Fields in Intent modals must be clickable", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#1560", "text": "", "title": "1.56.0"}, {"location": "cozy-banks/CHANGELOG/#features_2", "text": "Hide KonnectorChip by flag for health category Hide BillChip by flag for health category Remove native link and icon from manifest", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_2", "text": "Transaction modale closed by itself on some mobile devices", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#tech_1", "text": "Remove logs with unnecessary or sensitive data", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1550", "text": "", "title": "1.55.0"}, {"location": "cozy-banks/CHANGELOG/#features_3", "text": "Update cozy-bar to get fixed cloud icon position Save imported transactions count Update Success modal to specify number of successfully imported operations Add balancesNotifications to io.cozy.bank.settings Add current balance for each account in io.cozy.bank.settings when onOperationOrBillCreate service run.", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_3", "text": "French wording for import success title Email notification for balance greater wasn\u2019t using the right title Reduction of the number of BalanceLower & BalanceGreater notifications", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#tech_2", "text": "Add import service documentation", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1540", "text": "", "title": "1.54.0"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_4", "text": "Import accounts with a normalized number Prevent fallback on sub-optimal index for in-progress jobs query.", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#tech_3", "text": "Notifications are compatible with the new Cozy app", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1530", "text": "", "title": "1.53.0"}, {"location": "cozy-banks/CHANGELOG/#features_4", "text": "Export your bank\u2019s data in csv format via the Settings page Import bank data from Cozy bank export file ( csv format) via the Settings page Rework renderExtraRoutesWithoutLayout AppRoute method Allow grouping bank accounts by institution labels in Settings", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_5", "text": "The service onOperationOrBillCreate was failing with a CozyStackClient.collection() called without a doctype error. Bank accounts imported via the import service are grouped by their institution label in the Settings\u202f>\u202fAccounts tab", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#tech_4", "text": "Remove direct dependency to cozy-stack-client Bump cozy-stack-client from 35.3.1 to 35.6.0 Bump cozy-pouch-link from 35.3.1 to 35.6.0 Services launched via the CLI use a CozyClient instance with appMetadata", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1520", "text": "", "title": "1.52.0"}, {"location": "cozy-banks/CHANGELOG/#features_5", "text": "Update cozy-bar from 8.11.2 to 8.14.0", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_6", "text": "When a connector needs to be updated, it no longer impacts the add bank connector buttons The recurrence service should not modify transactions already associated with a recurrence Use absolute links for analysis tabs Right arrow on advanced filter in category page was not clickable", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#tech_5", "text": "Clarified recurrence service functions and variables names Add better log for services More specific log for doTransactionsMatching and doBillsMatching in onOperationOrBillCreate Improved performance of transactions filtering in the recurrence service", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1510", "text": "", "title": "1.51.0"}, {"location": "cozy-banks/CHANGELOG/#features_6", "text": "The stats service is no longer useful, we can remove it from the manifest and delete the deprecated code Update React Router to v6 Update cozy-authentication from 2.1.0 to 2.12.1", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_7", "text": "Fix bad display of settings menu", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#tech_6", "text": "Remove cozy-client-js assets", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1500", "text": "", "title": "1.50.0"}, {"location": "cozy-banks/CHANGELOG/#features_7", "text": "Upgrade cozy-ui from 75.4.0 to 79.0.0 Upgrade cozy-client from 33.2.0 to 34.5.0 Upgrade cozy-stack-client from 33.2.0 to 34.1.5 Upgrade cozy-pouch-link from 33.2.0 to 34.5.0 Upgrade cozy-device-helper from 2.1.0 to 2.6.0 Upgrade cozy-harvest-lib from 9.32.4 to 10.0.0", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_8", "text": "Exclude virtual accounts from the counter on the balance page Localize account and group labels in notification settings", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#1490", "text": "", "title": "1.49.0"}, {"location": "cozy-banks/CHANGELOG/#features_8", "text": "upgrade cozy-bar and cozy-intent to 8.11/2.7", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_9", "text": "update icon-banks svg file", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#1480", "text": "", "title": "1.48.0"}, {"location": "cozy-banks/CHANGELOG/#tech_7", "text": "Use warn log instead of info for konnectorAlerts service", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_10", "text": "KonnectorAlerts notification onSuccess is async", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#1471", "text": "", "title": "1.47.1"}, {"location": "cozy-banks/CHANGELOG/#features_9", "text": "Upgrade cozy-harvest-lib to 9.32.3 : Use OAuthService in KonnectorAccountTabs Use OAuthService in OAuthForm Update wording for Bank disconnect dialog close button Add independent confirm dialog Use independant OAuth window Better locale for delete BI connection confirmation button Follow current trigger jobs even after the first load Only update cozy-client store when refreshing contracts Do not unsubscribe all realtime events Prevent createTemporaryToken to updateCache twice at the same time upgrade cozy-realtime to 4.2.9 to get the sendNotification method Upgrade cozy-bar from 8.9.3 to 8.9.4 Add konnector slug in fake trigger passed to onLoginSuccess Add realtime update of cozy accounts Add the virtual reimbursement accounts to the account switch Add the account switch to the reimbursement page Do not display success or error toast for webhooks other than CONNECTION_SYNCED", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_11", "text": "Do not display an error icon for all accounts with the same slug Ignore account delete and account disabled jobs for import success message Remove import in progress in the end of the connector job Use CozyClient.saveAll() instead of Document.updateAll() from deprecated cozy-doctypes to avoid CouchDB errors with attributes starting with an underscore (#2547) Swap providers to make some Harvest dialogs match the theme Handles accounts created after bi webhooks on contract synchronization Fix notifications issues on the b2c app Don\u2019t register the flag plugin twice Wrong locale on BI connection removal https://github.com/cozy/cozy-libs/commit/ed2f352467da5f36ef1753de5578f156bb2a1ffb Update cozy accounts when removed from cozy-stack after BI connection removal from BI webview Reverts \u201cInclude virtual accounts in the account total count in balance details\u201d Exclude virtual accounts from the account count in balance details Do not show any account when none is selected in balance details Always show the action column since tags are always enabled Handles accounts created after bi webhooks on contract synchronization", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#tech_8", "text": "Add more logs around LateHealthReimbursement onSuccess method", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1470", "text": "", "title": "1.47.0"}, {"location": "cozy-banks/CHANGELOG/#features_10", "text": "Add wait job New OAuthWrapperCompProps in TriggerManager Preserve selected tags when navigating in categories Don\u2019t notify users about very old konnector run failures (i.e. older than 7 days and 15 minutes which is the maximum delay between the last failure and the scheduled 7 days reminder). Remove flag for Tags feature", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_12", "text": "Add and remove tags at the same time on a transaction Fix blank block within the flagship app for the cozy-bar Prevent scheduling konnectorAlerts triggers in the past which would be executed right away by cozy-stack ending up sending multiple notifications to the user about the failed konnector run. Include virtual accounts in the account total count in balance details Log event only when hiding incomes and not when unhiding them", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#1460", "text": "", "title": "1.46.0"}, {"location": "cozy-banks/CHANGELOG/#features_11", "text": "Optimization of the Mango query to get first / last date for an account No more 404 call to manifest.json Add new event and page loggers for tags Add a new switch to toggle hiding amounts in mobile notifications", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_13", "text": "Revert cozy-script to deduplicate CSS files Harvest: Hide BIContractActivationWindow behind the bi webview flag", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#1450", "text": "", "title": "1.45.0"}, {"location": "cozy-banks/CHANGELOG/#features_12", "text": "Add tags on transactions Add a tab in the settings to list all the tags Add a modal to filter by Tags on the analysis page Upgrade cozy-ui from 69.3.0 to 74.3.0 Add a page for managing a given tag Optimization of the Mango query to get first / last date for an account", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_14", "text": "Fix recurrence service that was triggering itself in an infinite loop [PR] Fix typo in French translation [PR] Transactions actions style on mobile Notifications based on transactions changes will only be sent once, even if the transaction is modified after the first trigger [PR] Update trigger without fetch policy in AccountModal, while reconnecting a konnector Update cozy-harvest-lib 9.15.1 : Update trigger while status changed [PR] Update trigger without fetch policy in AccountModal, while reconnecting a konnector [PR] Prevent recurrence service from running until we figure out why it is triggering itself in an infinite loop [PR]", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#tech_9", "text": "Remove dev dependency to cozy-ach [PR]", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1440", "text": "", "title": "1.44.0"}, {"location": "cozy-banks/CHANGELOG/#features_13", "text": "Update cozy-stack-client and cozy-pouch-link to sync with cozy-client version Use DropdownText comp instead of custom in AccountSwitch Update cozy-harvest-lib 9.8.0 : Add reconnect to bi Webviews [PR] 9.10.1 : Add custom intentsApi prop to TriggerManager [PR] 9.11.1 : Add sync date on ContractItem and overrides ability in AccountModal [PR] and [PR] 9.12.0 : Do not show Popup when intentsApi parameter is given [PR] 9.12.2 : Do not pre encode oauth url [PR] and Do not show popup when intentsApi is given [PR] 9.12.3 : Do not double encode oauth url [PR] 9.14.1 : Change RedirectToAccountFormButton label & size [PR] 9.15.1 : Update trigger while status changed [PR] 9.16.0 : Allow EditAccountModal to have intentsApi ( 43c5910 ) Now open the BI manage webview to the correct connection id ( 2f3da74 ) 9.17.0 : All oauth methods to handle reconection case ( b1a6033 ) Do not show identifiers with bi Webviews ( 58e1bb1 ) 9.18.0 : Add error message display in OAuthForm component ( f29b3c4 ) Handle user dismiss in Oauth window ( a6dcba8 ) 9.22.2 : feat: Allow disabled banks to be clickable 9.23.2 : Add BI aggregator releationship to BI accounts 9.25.0 : Now OAuth popup/inAppBrowser wait for login success to hide 9.26.1 : Use BI account creation webview to handle account synchronization RefreshContracts now updates contracts in realtime Disable account line in import group panel to prevent accessing an account not yet ready Change wording for toast message when importing data from a bank is completed Remove icon on ReconnectTriggerButton Add intentsApi prop to HarvestBankAccountSettings Add a spinner in OAuth popup/InAppBrowser after OAuth redirection", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_15", "text": "Fix App Amirale UI issues by updating cozy-ui [PR] Update trigger without fetch policy in AccountModal, while reconnecting a konnector [PR] Use the right color for input text Colors when importing account Prevent recurrence service from running until we figure out why it is triggering itself in an infinite loop [PR] Do not allways show the same bank in BI webview Do fail the connector for banks with multiple bank ids Update cozy-client to 32.2.7 : Lodash.merge is not creating a new object PR fix temporary token cache when beginning with an empty cache PR Breaking changes are not supposed to affect cozy-banks Update cozy-harvest-lib 9.12.2 : Do not pre encode oauth url PR and Do not show popup when intentsApi is given PR 9.12.3 : Do not double encode oauth url PR Prevent recurrence service from running until we figure out why it is triggering itself in an infinite loop [PR] Do not allways show the same bank in BI webview Do fail the connector for banks with multiple bank ids Update cozy-client to 32.2.6 : fix temporary token cache when beginning with an empty cache PR Breaking changes are not supposed to affect cozy-banks Invalidate temporary token cache when there is a change of BI user OauthWindowInAppBrowser re-render 9.12.2 : Do not pre encode oauth url PR and Do not show popup when intentsApi is given PR Harvest 9.25.0: Remove an BI webview reconnection step Remove an unused request to BI api to be faster 9.26.6 : Better handling of duplicate accounts : locale + realtime in bank accounts Display the resulting account in the Settings screen after an account creation (with realtime) Update cozy-harvest-lib 9.14.1 Update cozy-client to 32.2.6", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#tech_10", "text": "Extract import of AccountModalContent in HarvestAccountModal to be able to override it easily", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1431", "text": "", "title": "1.43.1"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_16", "text": "Fix services that were broken due to latest cozy-client update [PR]", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#1430", "text": "", "title": "1.43.0"}, {"location": "cozy-banks/CHANGELOG/#features_14", "text": "Change Sentry url + add instance in tags context Upgrade cozy-client to get ability to force HTTPs fetches when window.cozy.isSecureProtocol is true CozyClient can be used in a node env [PR] Fix App Amirale localhost dev server issues by updating cozy-scripts [PR]", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_17", "text": "cozy-harvest-lib 9.4.0 : Get correct bi mapping for bnp_es and cic_es PR Remove useVaultClient call in LegacyTriggerManager PR TriggerManager OAuthForm wrapper PR Upgrade cozy-ui to 67.0.2 to get bugfix on Matomo tracking Fix deprecated bundles help french translation", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#tech_11", "text": "Update cozy packages", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1420", "text": "", "title": "1.42.0"}, {"location": "cozy-banks/CHANGELOG/#features_15", "text": "Update cozy-client and cozy-stack-client to 27.17.0 Update cozy-harvest-lib to 7.3.1", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#tech_12", "text": "Remove the creation of an Android version of the application", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1410", "text": "", "title": "1.41.0"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_18", "text": "Transactions page indicated isDesktop undefined when changing month in the date selector Reimbursements shows correct datas even if coming from the home page", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#tech_13", "text": "Refactor of Reimbursements from class component to functional component Update documentation to install and start project", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1400", "text": "", "title": "1.40.0"}, {"location": "cozy-banks/CHANGELOG/#features_16", "text": "cozy-harvest-lib 6.15.0 : get support email according to the contect PR", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_19", "text": "Scheduled notification are created only if a notification will be sent in the next day, and only if there is no already notification in the futur Notifications for errored connector are now sent at 5am local time (UTC for cozy servers) instead of 6am Scheduling notifications if sending is between 10pm and 5am local time (UTC for cozy servers) instead of 11pm and 6am Reimbursment panel was not correctly displaying the transactions Switching to /analysis/categories from \u201creimbursment virutal group\u201d no longer leads to empty page Get reimbursements data for transactions fetched on the homepage. This fixes reimbursements group.", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#tech_14", "text": "", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1390", "text": "", "title": "1.39.0"}, {"location": "cozy-banks/CHANGELOG/#features_17", "text": "Scheduling notifications if sending is between 11pm and 6am Notifications for errored connector are now sent at 6am instead of 8am Show alert message when a request failed (allows to reload the app)", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_20", "text": "Show empty page title only for mobile Reimbursement block is visible again on the balance page if it is shown first Show operations by date and by account (and not the reverse) in group details Fix colors Alerter component and alert message displayed several times", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#1380", "text": "", "title": "1.38.0"}, {"location": "cozy-banks/CHANGELOG/#features_18", "text": "Alert notifications for KO connectors link to the accounts page in the settings Change wording push content notification Change EUR by \u20ac Replace \u2018.\u2019 in amount by \u2018,\u2019 Capitalize each transaction label word Show by line 50 char max Example if the label from transaction is Salaire du mois de Septembre 2021 (01/09/2021) with an amount 1234.56 so we display that: Salaire Du Mois De Septembre 2021 (01/0 : 1234,56\u20ac Color change for the recurrence edition modal", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#tech_15", "text": "Refactor for RecurrencePage and split component into different files", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1370", "text": "", "title": "1.37.0"}, {"location": "cozy-banks/CHANGELOG/#features_19", "text": "Add notifications at +3 and +7 days for banking connectors, if the connector is in an actionable error Recurrency service: allows to attach transactions whose amount is between 2 extremes of amounts in the existing recurrences (+/- 5% by default). This percentage is configurable with the flag banks.recurrency.percentage-amounts-accepted . Example for 10% set 0.1", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_21", "text": "Fix Month / Year selection on iOS in Analysis Page Fix no data displayed in Analysis Page on iOS Fix Accordion border color and SelectDates text color", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#tech_16", "text": "Move / Refactor / Split CategoriesHeader component Split bundle into 3 chunks: main, vendor and cozy-bar Update Cozy App Publish (Fix travis icon on mattermost publish announcement)", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1360", "text": "", "title": "1.36.0"}, {"location": "cozy-banks/CHANGELOG/#features_20", "text": "Add latest transaction amount value in recurrences Futur balances shows latest transaction amount", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_22", "text": "Update cozy-ui to 52.0.0 to reduce the size of the bundle Exclude some modules to reduce the size of the bundle \u2018node-forge\u2019, \u2018node-jose\u2019, \u2018tldjs\u2019 Remove third level import from Mui in HistoryChart fix undefined var in the categ service Transaction Label is now truncated if too long in the Transaction details modal Fix Search Link when clicking on the magnifying glasse if label contained an \u201c/\u201d", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#tech_17", "text": "Add recurrence test for not same account scenario + refactor other recurrence tests Use CozyClient links instead of StackClient in removeAccountFromGroups", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1350", "text": "", "title": "1.35.0"}, {"location": "cozy-banks/CHANGELOG/#features_21", "text": "Optimization of the database on mobile (addition of the indexeddb adapter). For old users, a modal appears and allows to launch the data migration. Update cozy-pouch-link to 24.3.2 to be able to migrates database on mobile to indexeddb Remove minimum limit to find recurrence Recurrence creation process will always try to update existing bundle before creating some Ability to update old recurrences and create new ones in the same batch Change recurrence lookback date limit from 90 to 100 days Selection mode to change the category of several transactions at once Update cozy-harvest-lib to 6.6.0 to get the correct BI slug for palatine bank Change migration modal wording", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_23", "text": "Error when removing a group on desktop and mobile Correct minimum date is used to create recurrence Fix warming queries with null applicationDate selector", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#tech_18", "text": "Add pouchdb-adapter-idb and pouchdb-adapter-indexeddb v7.2.2 Extract component from GroupSettings Groups are not filtered anymore to exclude undefined one in AccountSwitch Remove updateOrCreateGroup() to remove router from dependencies Only deep import for lodash Add logs to better debugging recurrence", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/CHANGELOG/#1340", "text": "", "title": "1.34.0"}, {"location": "cozy-banks/CHANGELOG/#features_22", "text": "Remove balance from transaction header Add checkbox icon button to activate selection mode in transactions page and search page Improve ui for no result in search page Recategorizing multiple transactions is much faster with better performance Optimize transactions queries by changing indexes order Separates notifications content by a return to line Update cozy-ui to 51.4.0 Update cozy-harvest-lib to 6.4.0 Update cozy-client and cozy-pouch-link to 24.1.0 to fix queryAll bug and destroy on Pouch Update cozy-stack-client to 24.0.0", "title": "\u2728 Features"}, {"location": "cozy-banks/CHANGELOG/#bug-fixes_24", "text": "Checkbox horizontal position for selectionning rows in desktop Hide owner field in account configuration when Contacts app is not installed Deactivates selection mode when leaving an account page First transactions are no longer trimmed on the balance page on tablet Missing colors for categories in the chart on the analysis page The analysis page correctly retrieves information when viewing all accounts Prevent render loop after login if a pin had been set Render pin setting row in configuration even when no pin has been set yet Autogroups and LinkMyselfToAccount services crashed if configuration settings had not been saved yet Median function in Recurrence returns the correct median Reassigned transactions are displayed in the correct period according to the selected period On mobile, account settings page doesn\u2019t loop after removing an account Checkbox in transaction row are no longer trimmed Transactions are no longer selectable in the projected expenses page Planned transactions page shows transactions correctly on tablet", "title": "\ud83d\udc1b Bug Fixes"}, {"location": "cozy-banks/CHANGELOG/#tech_19", "text": "To facilitate overriding about notifications and standardize their entry point, a bit refactoring was necessary: Move CategoryBudget to notifications folder Move lang and dictRequire to utils/lang Ability to run the push notifications debug server from the CLI Add some documentation to develop for android Extract HeaderInfoCard from PlannedTransactionsPage Extract PlannedTransactionsPage header in its own component", "title": "\ud83d\udd27 Tech"}, {"location": "cozy-banks/docs/account-types/", "text": "Account types \u00b6 Here is the complete list of the account types managed by the app: Asset Bank Capitalisation Cash Checkings ConsumerCredit CreditCard Credit Card Deposit Joint Liability LifeInsurance Loan Madelin Market Mortgage PEA PEE RevolvingCredit RSP Savings Other Unkown None Credit card Perco Perp Article83 Mapping \u00b6 Some types are dynamically mapped to other types: Original type Mapped type `Article83` `LongTermSavings` `LifeInsurance` `Madelin` `Market` `Mortgage` `PEA` `PEE` `Perco` `Perp` `RSP` `Asset` `Business` `Capitalisation` `Liability` `Bank` `Checkings` `Cash` `Deposit` `ConsumerCredit` `Loan` `RevolvingCredit` `Credit card` `CreditCard` `None` `Other` `Unkown`", "title": "Account types"}, {"location": "cozy-banks/docs/account-types/#account-types", "text": "Here is the complete list of the account types managed by the app: Asset Bank Capitalisation Cash Checkings ConsumerCredit CreditCard Credit Card Deposit Joint Liability LifeInsurance Loan Madelin Market Mortgage PEA PEE RevolvingCredit RSP Savings Other Unkown None Credit card Perco Perp Article83", "title": "Account types"}, {"location": "cozy-banks/docs/account-types/#mapping", "text": "Some types are dynamically mapped to other types: Original type Mapped type `Article83` `LongTermSavings` `LifeInsurance` `Madelin` `Market` `Mortgage` `PEA` `PEE` `Perco` `Perp` `RSP` `Asset` `Business` `Capitalisation` `Liability` `Bank` `Checkings` `Cash` `Deposit` `ConsumerCredit` `Loan` `RevolvingCredit` `Credit card` `CreditCard` `None` `Other` `Unkown`", "title": "Mapping"}, {"location": "cozy-banks/docs/bills-matching/", "text": "Bills/transactions matching algorithm \u00b6 The matching algorithm is in charge of finding matchings between io.cozy.bills and io.cozy.bank.operations documents. This document explains how the matching algorithm works. What are matchings? \u00b6 Matchings are links that can be made between io.cozy.bills and io.cozy.bank.operations documents. For example, if the user ordered something on Amazon, his Amazon connector will import a io.cozy.bills document representing this order, and his banking connector will import a io.cozy.bank.operations representing the bank transaction associated to this order. In banks\u2019 UI, it is used to show a CTA with the transaction on which the user can click to show the linked bill PDF without leaving banks app. The Linker \u00b6 The algorithm is held by the Linker , and more precisely its linkBillsToOperations method. This method takes 3 parameters: An array of io.cozy.bills objects An array of io.cozy.bank.operations objects An options object The options object can contain the following properties: amountLowerDelta : defaults to 0.001 amountUpperDelta : defaults to 0.001 dateLowerDelta : defaults to 15 (days) dateUpperDelta : defaults to 29 (days) These options will determine the default date and amount windows in which a transaction should be to match with a bill. General flow \u00b6 When called, this method will do the following (each part will be explained in details after): Filter bills that are declared as third party payer: these bills have no matching transation since it has been paid by somebody else Then for each bill: Try to find a matching debit transaction (amount < 0) Try to find a matching credit transaction (amount > 0) if the bill is a refund Try to combine bills that didn\u2019t match anything to see if they match something when combined Update transactions that matched in database Finding debit and credit operations for a bill \u00b6 The algorithm is globally the same to find a debit or a credit operation for a bill, but there are some differences at some steps. Each step is explained below. Find neighboring transactions \u00b6 First, we look for transactions that are \u00ab neighbors \u00bb of the bill. It means the ones that fits in the amount and date windows of the bill. The date window is [bill date - dateLowerDelta; bill date + dateUpperDelta] . Where: bill date is bill.date if we are looking for a credit; bill.originalDate with a fallback on bill.date if we are looking for a debit dateLowerDelta is bill.matchingCriterias.dateLowerDelta if it exists, options.dateLowerDelta otherwise dateUpperDelta is bill.matchingCriterias.dateUpperDelta if it exists, options.dateUpperDelta otherwise The amount window is [bill amount - amountLowerDelta; bill amount + amountUpperDelta] . Where: bill amount is bill.groupAmount with a fallback on bill.amount if we are looking for a credit; -bill.originalAmount with a fallback on -bill.amount if we are looking for a debit amountLowerDelta is bill.matchingCriterias.amountLowerDelta if it exists, options.minAmoutDelta otherwise amountUpperDelta is bill.matchingCriterias.amountUpperDelta if it exists, options.maxAmoutDelta otherwise All transactions that matches these two criterias are kept. Apply filters to neighboring transactions \u00b6 There are other filters a transaction must pass to match with a bill. Category \u00b6 Health bills are a little special because they can only match with health transactions. So if the bill is an health bill, we keep only health transactions. Otherwise, we keep all but health transactions. You can pass a allowUncategorized option to the algorithm, in which case uncategorized transactions will also be able to match bills. Reimbursements \u00b6 This filter is applied only if we are looking for a debit transactions. If we try to link a bill as a reimbursement to a debit transaction, we check that the bill\u2019s amount and transaction\u2019s reimbursements sum does not overflows the transaction\u2019s amount. Label regex \u00b6 This filter is applied only if we are looking for a credit transaction or if the bill is not of health type. This filter checks if a transaction matches a regex that is built upon the bill\u2019s properties. Here is how the regexp is built: If the bill has a matchingCriterias.labelRegex property, this is used Otherwise we try to get the brand corresponding to the bill\u2019s vendor in our brands dictionary . If it exists, we use its regexp property Otherwise, we create a regexp containing the bill\u2019s vendor Lastly, if the bill has no vendor, we can\u2019t do anything and the filter will be false for every transaction and the bill will not match any transaction Sort remaining transactions \u00b6 A score is given to the remaining transactions according to their \u00ab distance \u00bb to the bill\u2019s date and amount. The closest one wins and continues through the algorithm. Link bills to debit and credit transactions \u00b6 When transactions were found for a given bill, we need to link the bill to them, either as a bill or as a reimbursement . When a bill matched with a transaction (debit or credit), it is added to the transaction\u2019s bills array. When a bill matched with a debit and a credit transactions, it is also added to the debit transaction\u2019s reimbursements array. A last safety net is applied by checking if adding the bill to the transaction would make the bills sum overflowing the transaction amount or not. It it overflows, the bill is not added. For the bills property, a removed bill will be ignored. But for the reimbursements property, since we don\u2019t fetch the bill because the amount is already present in the transaction, a removed bill will not be ignored. Bills combinations \u00b6 Sometimes, bills need to be combined to match with a debit transaction. It is generally the case for health bills. For example, when your paid multiple medical procedures with a single transaction. It will generate multiple bills for a single debit transaction. In this case, we try to combine bills and find debit transaction for them. This combination process is not required to find debit transaction because in that case the bill\u2019s groupAmount (see io.cozy.bills documentation ) can be used. The bills that are candidates to be combined are the ones that: Didn\u2019t match with a debit transaction Are health costs or are from a vendor that groups bills These bills are then grouped by date and vendor, so we don\u2019t mix bills that have nothing in common. Then all possible combinations are generated for each group. For each combination, a \u00ab meta bill \u00bb is created from the grouped bills and this meta bill is passed in the matching algorithm to find a debit transaction that matches with it. If a transaction is found, then all the bills making the meta bill are linked to it using the same logic as before.", "title": "Bills/transactions matching algorithm"}, {"location": "cozy-banks/docs/bills-matching/#billstransactions-matching-algorithm", "text": "The matching algorithm is in charge of finding matchings between io.cozy.bills and io.cozy.bank.operations documents. This document explains how the matching algorithm works.", "title": "Bills/transactions matching algorithm"}, {"location": "cozy-banks/docs/bills-matching/#what-are-matchings", "text": "Matchings are links that can be made between io.cozy.bills and io.cozy.bank.operations documents. For example, if the user ordered something on Amazon, his Amazon connector will import a io.cozy.bills document representing this order, and his banking connector will import a io.cozy.bank.operations representing the bank transaction associated to this order. In banks\u2019 UI, it is used to show a CTA with the transaction on which the user can click to show the linked bill PDF without leaving banks app.", "title": "What are matchings?"}, {"location": "cozy-banks/docs/bills-matching/#the-linker", "text": "The algorithm is held by the Linker , and more precisely its linkBillsToOperations method. This method takes 3 parameters: An array of io.cozy.bills objects An array of io.cozy.bank.operations objects An options object The options object can contain the following properties: amountLowerDelta : defaults to 0.001 amountUpperDelta : defaults to 0.001 dateLowerDelta : defaults to 15 (days) dateUpperDelta : defaults to 29 (days) These options will determine the default date and amount windows in which a transaction should be to match with a bill.", "title": "The Linker"}, {"location": "cozy-banks/docs/bills-matching/#general-flow", "text": "When called, this method will do the following (each part will be explained in details after): Filter bills that are declared as third party payer: these bills have no matching transation since it has been paid by somebody else Then for each bill: Try to find a matching debit transaction (amount < 0) Try to find a matching credit transaction (amount > 0) if the bill is a refund Try to combine bills that didn\u2019t match anything to see if they match something when combined Update transactions that matched in database", "title": "General flow"}, {"location": "cozy-banks/docs/bills-matching/#finding-debit-and-credit-operations-for-a-bill", "text": "The algorithm is globally the same to find a debit or a credit operation for a bill, but there are some differences at some steps. Each step is explained below.", "title": "Finding debit and credit operations for a bill"}, {"location": "cozy-banks/docs/bills-matching/#find-neighboring-transactions", "text": "First, we look for transactions that are \u00ab neighbors \u00bb of the bill. It means the ones that fits in the amount and date windows of the bill. The date window is [bill date - dateLowerDelta; bill date + dateUpperDelta] . Where: bill date is bill.date if we are looking for a credit; bill.originalDate with a fallback on bill.date if we are looking for a debit dateLowerDelta is bill.matchingCriterias.dateLowerDelta if it exists, options.dateLowerDelta otherwise dateUpperDelta is bill.matchingCriterias.dateUpperDelta if it exists, options.dateUpperDelta otherwise The amount window is [bill amount - amountLowerDelta; bill amount + amountUpperDelta] . Where: bill amount is bill.groupAmount with a fallback on bill.amount if we are looking for a credit; -bill.originalAmount with a fallback on -bill.amount if we are looking for a debit amountLowerDelta is bill.matchingCriterias.amountLowerDelta if it exists, options.minAmoutDelta otherwise amountUpperDelta is bill.matchingCriterias.amountUpperDelta if it exists, options.maxAmoutDelta otherwise All transactions that matches these two criterias are kept.", "title": "Find neighboring transactions"}, {"location": "cozy-banks/docs/bills-matching/#apply-filters-to-neighboring-transactions", "text": "There are other filters a transaction must pass to match with a bill.", "title": "Apply filters to neighboring transactions"}, {"location": "cozy-banks/docs/bills-matching/#category", "text": "Health bills are a little special because they can only match with health transactions. So if the bill is an health bill, we keep only health transactions. Otherwise, we keep all but health transactions. You can pass a allowUncategorized option to the algorithm, in which case uncategorized transactions will also be able to match bills.", "title": "Category"}, {"location": "cozy-banks/docs/bills-matching/#reimbursements", "text": "This filter is applied only if we are looking for a debit transactions. If we try to link a bill as a reimbursement to a debit transaction, we check that the bill\u2019s amount and transaction\u2019s reimbursements sum does not overflows the transaction\u2019s amount.", "title": "Reimbursements"}, {"location": "cozy-banks/docs/bills-matching/#label-regex", "text": "This filter is applied only if we are looking for a credit transaction or if the bill is not of health type. This filter checks if a transaction matches a regex that is built upon the bill\u2019s properties. Here is how the regexp is built: If the bill has a matchingCriterias.labelRegex property, this is used Otherwise we try to get the brand corresponding to the bill\u2019s vendor in our brands dictionary . If it exists, we use its regexp property Otherwise, we create a regexp containing the bill\u2019s vendor Lastly, if the bill has no vendor, we can\u2019t do anything and the filter will be false for every transaction and the bill will not match any transaction", "title": "Label regex"}, {"location": "cozy-banks/docs/bills-matching/#sort-remaining-transactions", "text": "A score is given to the remaining transactions according to their \u00ab distance \u00bb to the bill\u2019s date and amount. The closest one wins and continues through the algorithm.", "title": "Sort remaining transactions"}, {"location": "cozy-banks/docs/bills-matching/#link-bills-to-debit-and-credit-transactions", "text": "When transactions were found for a given bill, we need to link the bill to them, either as a bill or as a reimbursement . When a bill matched with a transaction (debit or credit), it is added to the transaction\u2019s bills array. When a bill matched with a debit and a credit transactions, it is also added to the debit transaction\u2019s reimbursements array. A last safety net is applied by checking if adding the bill to the transaction would make the bills sum overflowing the transaction amount or not. It it overflows, the bill is not added. For the bills property, a removed bill will be ignored. But for the reimbursements property, since we don\u2019t fetch the bill because the amount is already present in the transaction, a removed bill will not be ignored.", "title": "Link bills to debit and credit transactions"}, {"location": "cozy-banks/docs/bills-matching/#bills-combinations", "text": "Sometimes, bills need to be combined to match with a debit transaction. It is generally the case for health bills. For example, when your paid multiple medical procedures with a single transaction. It will generate multiple bills for a single debit transaction. In this case, we try to combine bills and find debit transaction for them. This combination process is not required to find debit transaction because in that case the bill\u2019s groupAmount (see io.cozy.bills documentation ) can be used. The bills that are candidates to be combined are the ones that: Didn\u2019t match with a debit transaction Are health costs or are from a vendor that groups bills These bills are then grouped by date and vendor, so we don\u2019t mix bills that have nothing in common. Then all possible combinations are generated for each group. For each combination, a \u00ab meta bill \u00bb is created from the grouped bills and this meta bill is passed in the matching algorithm to find a debit transaction that matches with it. If a transaction is found, then all the bills making the meta bill are linked to it using the same logic as before.", "title": "Bills combinations"}, {"location": "cozy-banks/docs/brand-dictionary/", "text": "Brand dictionary \u00b6 To be able to know which brands the user can connect, we use what we call the \u00ab brand dictionary \u00bb. This is a JSON file listing all the available brands with the following properties for each brand: name (string): the brand\u2019s name regexp (string): the regexp used to test if a given transaction label matches this brand or not konnectorSlug (string): the slug of the konnector for this brand health (boolean): whether this brand is in the health category or not maintenance (boolean): whether this brand is under maintenance or not (see below) Set a brand in maintenance \u00b6 When a given brand is under maintenance, its associated konnector can no longer be added and configured by the users. In this case, we want to stop proposing the user to add this konnector via the cozy-banks UI. To achieve that, you can turn the maintenance property of the given brand to true . Don\u2019t forget to update tests snapshots using yarn test -u .", "title": "Brand dictionary"}, {"location": "cozy-banks/docs/brand-dictionary/#brand-dictionary", "text": "To be able to know which brands the user can connect, we use what we call the \u00ab brand dictionary \u00bb. This is a JSON file listing all the available brands with the following properties for each brand: name (string): the brand\u2019s name regexp (string): the regexp used to test if a given transaction label matches this brand or not konnectorSlug (string): the slug of the konnector for this brand health (boolean): whether this brand is in the health category or not maintenance (boolean): whether this brand is under maintenance or not (see below)", "title": "Brand dictionary"}, {"location": "cozy-banks/docs/brand-dictionary/#set-a-brand-in-maintenance", "text": "When a given brand is under maintenance, its associated konnector can no longer be added and configured by the users. In this case, we want to stop proposing the user to add this konnector via the cozy-banks UI. To achieve that, you can turn the maintenance property of the given brand to true . Don\u2019t forget to update tests snapshots using yarn test -u .", "title": "Set a brand in maintenance"}, {"location": "cozy-banks/docs/categorization/", "text": "Categorization \u00b6 Concerning the categorization, we use two models (local and global), and a setting that the user can enable in his settings to send his bank transactions to an API via a remote doctype. Local model \u00b6 Presentation \u00b6 This model analyzes the transactions recategorized by the user to get his categorization habits and predict the category of some transactions based on this. This model is applied to transactions when the onOperationOrBillCreate service is run and write its results in the localCategoryId and localCategoryProba properties of the io.cozy.bank.operations documents. Implementation details \u00b6 Currently, the local categorization model fetches all the manually categorized transactions from the stack on every run. We decided it\u2019s the best for now to compute the entire model everytime because the pros/cons balance of saving the model in a specific doctype is not good for this model. Pros: Don\u2019t need to regenerate the whole model everytime the service is run Cons: Need to do some migrations if we want to update the model algorithm Since the CPU time needed to compute the whole model is low (users will never recategorize the majority of their transactions, as the global model has most of the time the correct category), the main advantage is weak in front of the disadvantage. Therefore we chose to recompute the model on every run. The solution of saving the model in the database was first implemented and then reverted following this decision. If we finally need to use this solution, we can find it in 9bbc96b0 which has been reverted by 77dd15ce Global model \u00b6 This model analyzes the category of transactions from instances that enabled the auto categorization setting in their Banks app. It is computed on a distant server, and we fetch it via the remote assets each time transactions are retrieved (learn more here and here ). The remote asset name used for this is bank_classifier_nb_and_voc . Its value should be an URL to a JSON file. This model is applied to transactions when the onOperationOrBillCreate service is run and writes its results in the cozyCategoryId and cozyCategoryProba properties of the io.cozy.bank.operations documents. Category choice \u00b6 After the categorization execution, we may have 4 different levels of categories for the transactions: manualCategoryId : the category manually chosen by the user. localCategoryId : computed by the local model. cozyCategoryId : computed by the global. automaticCategoryId : automatic category retrieved from our banking provider. To determine which category will be shown to the user, we use the following rules: If the manualCategoryId exists, use it. Else, use localCategoryId if localCategoryProba > LOCAL_MODEL_USAGE_THRESHOLD . Else, use cozyCategoryId if cozyCategoryProba > GLOBAL_MODEL_USAGE_THRESHOLD Else, use automaticCategoryId For more details, see the code . Auto categorization setting \u00b6 In banks, there is a setting that the user can enable (it is disabled by default) if he wants to share his bank transactions with us to improve our global categorization model. If this setting is enabled, when the onOperationOrBillCreate service is ran and the new transactions have been categorized using the global and local models, we anonymize the transactions and then send them to an API using the cc.cozycloud.autocategorization remote doctype. This API then uses the documents it receives to update the global categorization model. Service execution \u00b6 See the service documentation to know how the categorization is run and how to use it.", "title": "Categorization"}, {"location": "cozy-banks/docs/categorization/#categorization", "text": "Concerning the categorization, we use two models (local and global), and a setting that the user can enable in his settings to send his bank transactions to an API via a remote doctype.", "title": "Categorization"}, {"location": "cozy-banks/docs/categorization/#local-model", "text": "", "title": "Local model"}, {"location": "cozy-banks/docs/categorization/#presentation", "text": "This model analyzes the transactions recategorized by the user to get his categorization habits and predict the category of some transactions based on this. This model is applied to transactions when the onOperationOrBillCreate service is run and write its results in the localCategoryId and localCategoryProba properties of the io.cozy.bank.operations documents.", "title": "Presentation"}, {"location": "cozy-banks/docs/categorization/#implementation-details", "text": "Currently, the local categorization model fetches all the manually categorized transactions from the stack on every run. We decided it\u2019s the best for now to compute the entire model everytime because the pros/cons balance of saving the model in a specific doctype is not good for this model. Pros: Don\u2019t need to regenerate the whole model everytime the service is run Cons: Need to do some migrations if we want to update the model algorithm Since the CPU time needed to compute the whole model is low (users will never recategorize the majority of their transactions, as the global model has most of the time the correct category), the main advantage is weak in front of the disadvantage. Therefore we chose to recompute the model on every run. The solution of saving the model in the database was first implemented and then reverted following this decision. If we finally need to use this solution, we can find it in 9bbc96b0 which has been reverted by 77dd15ce", "title": "Implementation details"}, {"location": "cozy-banks/docs/categorization/#global-model", "text": "This model analyzes the category of transactions from instances that enabled the auto categorization setting in their Banks app. It is computed on a distant server, and we fetch it via the remote assets each time transactions are retrieved (learn more here and here ). The remote asset name used for this is bank_classifier_nb_and_voc . Its value should be an URL to a JSON file. This model is applied to transactions when the onOperationOrBillCreate service is run and writes its results in the cozyCategoryId and cozyCategoryProba properties of the io.cozy.bank.operations documents.", "title": "Global model"}, {"location": "cozy-banks/docs/categorization/#category-choice", "text": "After the categorization execution, we may have 4 different levels of categories for the transactions: manualCategoryId : the category manually chosen by the user. localCategoryId : computed by the local model. cozyCategoryId : computed by the global. automaticCategoryId : automatic category retrieved from our banking provider. To determine which category will be shown to the user, we use the following rules: If the manualCategoryId exists, use it. Else, use localCategoryId if localCategoryProba > LOCAL_MODEL_USAGE_THRESHOLD . Else, use cozyCategoryId if cozyCategoryProba > GLOBAL_MODEL_USAGE_THRESHOLD Else, use automaticCategoryId For more details, see the code .", "title": "Category choice"}, {"location": "cozy-banks/docs/categorization/#auto-categorization-setting", "text": "In banks, there is a setting that the user can enable (it is disabled by default) if he wants to share his bank transactions with us to improve our global categorization model. If this setting is enabled, when the onOperationOrBillCreate service is ran and the new transactions have been categorized using the global and local models, we anonymize the transactions and then send them to an API using the cc.cozycloud.autocategorization remote doctype. This API then uses the documents it receives to update the global categorization model.", "title": "Auto categorization setting"}, {"location": "cozy-banks/docs/categorization/#service-execution", "text": "See the service documentation to know how the categorization is run and how to use it.", "title": "Service execution"}, {"location": "cozy-banks/docs/category/", "text": "Categorization implementation solution \u00b6 We had a problem about categorization of bank operations since a manual categorization is always replaced by automatic categorization in the next linxo connector run The goal here was to find a way of defining and merging automatic categorization and manual categorization with the following constraints : 1) Manual categorization wins over automatic categorization and we do not want to spread this intelligence over all the actors 2) We want to keep a trace of manual categorization in each bank operation 3) We want to keep a trace of automatic categorization in each bank operation 4) Several actors can modify category : Banks application, linxo connector, a futur bank service which will handle automatic categorization for non-linxo bank connectors the Banks application will only modify the manual category the linxo connector and the bank service will only modify the automatic category 5) actors reading the category : Banks application, futur bank service for centralization of categorization data the Banks application needs the result of 1) the service needs automatic category and manual category Solutions \u00b6 We see that we can\u2019t avoid to keep to separated categories : manual and automatic, even if manual category can be null. As said in 4), Banks application will only modify \u2018manual category\u2019 fields and the others will only modify \u2018automatic category\u2019 fields. The only question remaining is where to put the intelligence of choosing manual category over automatic category for display : A) The automatic category modifiers could calculate a third \u2018category\u2019 field There is a case where this does not work, if the Banks application user changes the manual category, we need to wait a run of the bank connector or service to see the result of the change. Or the Banks application calculates the resulting category itself and we are in B). B) The Banks application could, for each operation choose itself the manual category, if any, over the automatic category (via an accessor or a conditional on display) Chosen solution \u00b6 There should be two category fields associated to each bank operation : manualCategoryId automaticCategoryId Each of them can be undefined and when displaying a category, the Banks application will calculated the resulting category by choosing manualCategoryId over automaticCategoryId. I do not see a need to keep the result of this computation in database.", "title": "Category"}, {"location": "cozy-banks/docs/category/#categorization-implementation-solution", "text": "We had a problem about categorization of bank operations since a manual categorization is always replaced by automatic categorization in the next linxo connector run The goal here was to find a way of defining and merging automatic categorization and manual categorization with the following constraints : 1) Manual categorization wins over automatic categorization and we do not want to spread this intelligence over all the actors 2) We want to keep a trace of manual categorization in each bank operation 3) We want to keep a trace of automatic categorization in each bank operation 4) Several actors can modify category : Banks application, linxo connector, a futur bank service which will handle automatic categorization for non-linxo bank connectors the Banks application will only modify the manual category the linxo connector and the bank service will only modify the automatic category 5) actors reading the category : Banks application, futur bank service for centralization of categorization data the Banks application needs the result of 1) the service needs automatic category and manual category", "title": "Categorization implementation solution"}, {"location": "cozy-banks/docs/category/#solutions", "text": "We see that we can\u2019t avoid to keep to separated categories : manual and automatic, even if manual category can be null. As said in 4), Banks application will only modify \u2018manual category\u2019 fields and the others will only modify \u2018automatic category\u2019 fields. The only question remaining is where to put the intelligence of choosing manual category over automatic category for display : A) The automatic category modifiers could calculate a third \u2018category\u2019 field There is a case where this does not work, if the Banks application user changes the manual category, we need to wait a run of the bank connector or service to see the result of the change. Or the Banks application calculates the resulting category itself and we are in B). B) The Banks application could, for each operation choose itself the manual category, if any, over the automatic category (via an accessor or a conditional on display)", "title": "Solutions"}, {"location": "cozy-banks/docs/category/#chosen-solution", "text": "There should be two category fields associated to each bank operation : manualCategoryId automaticCategoryId Each of them can be undefined and when displaying a category, the Banks application will calculated the resulting category by choosing manualCategoryId over automaticCategoryId. I do not see a need to keep the result of this computation in database.", "title": "Chosen solution"}, {"location": "cozy-banks/docs/code-conventions/", "text": "Code organisation \u00b6 Components \u00b6 If components have an associated style, group the style with the component into a folder. Ex: BackButton Ducks \u00b6 Ducks groups actions/reducers/views for a particular high-level function Sometimes you can have a duck without views, typically when it concerns a particular doctype. Code conventions \u00b6 Constructor \u00b6 Avoid constructor if you can by leveraging transform-class-properties \u274c Bad : class MyComponent extends Component { constructor () { super () this . state = { counter : 0 } } } \u2705 Good class MyComponent extends Component { state = { counter : 0 } } Binding event handlers \u00b6 Avoid binding event handlers in constructor , leverage transform-class-properties and arrow functions. \u274c Bad : class MyComponent extends Component { constructor () { super () this . onClick = this . onClick . bind ( this ) } onClick ( ev ) { ... } } \u2705 Good class MyComponent extends Component { onClick = ( ev ) => { ... } }", "title": "Code conventions"}, {"location": "cozy-banks/docs/code-conventions/#code-organisation", "text": "", "title": "Code organisation"}, {"location": "cozy-banks/docs/code-conventions/#components", "text": "If components have an associated style, group the style with the component into a folder. Ex: BackButton", "title": "Components"}, {"location": "cozy-banks/docs/code-conventions/#ducks", "text": "Ducks groups actions/reducers/views for a particular high-level function Sometimes you can have a duck without views, typically when it concerns a particular doctype.", "title": "Ducks"}, {"location": "cozy-banks/docs/code-conventions/#code-conventions", "text": "", "title": "Code conventions"}, {"location": "cozy-banks/docs/code-conventions/#constructor", "text": "Avoid constructor if you can by leveraging transform-class-properties \u274c Bad : class MyComponent extends Component { constructor () { super () this . state = { counter : 0 } } } \u2705 Good class MyComponent extends Component { state = { counter : 0 } }", "title": "Constructor"}, {"location": "cozy-banks/docs/code-conventions/#binding-event-handlers", "text": "Avoid binding event handlers in constructor , leverage transform-class-properties and arrow functions. \u274c Bad : class MyComponent extends Component { constructor () { super () this . onClick = this . onClick . bind ( this ) } onClick ( ev ) { ... } } \u2705 Good class MyComponent extends Component { onClick = ( ev ) => { ... } }", "title": "Binding event handlers"}, {"location": "cozy-banks/docs/credentials/", "text": "Credentials \u00b6 All credentials are encrypted in an archive file in scripts/encrypted.tar.gz.enc . Create encrypted file \u00b6 tar zcvf scripts/decrypted.tar.gz scripts/decrypted/ travis encrypt-file scripts/decrypted.tar.gz scripts/encrypted.tar.gz.enc -p You should save key and iv variables on pass. pass Gangsters/cozy-banks/ENCRYPTED_KEY pass Gangsters/cozy-banks/ENCRYPTED_IV Decrypt file \u00b6 export ENCRYPTED_KEY = ` pass Gangsters/cozy-banks/ENCRYPTED_KEY ` export ENCRYPTED_IV = ` pass Gangsters/cozy-banks/ENCRYPTED_IV ` yarn secrets:decrypt Update encrypt file \u00b6 If you want to update the credentials, you should update folder ./scripts/decrypted and launch these commands: export ENCRYPTED_KEY = ` pass Gangsters/cozy-banks/ENCRYPTED_KEY ` export ENCRYPTED_IV = ` pass Gangsters/cozy-banks/ENCRYPTED_IV ` yarn secrets:encrypt", "title": "Credentials"}, {"location": "cozy-banks/docs/credentials/#credentials", "text": "All credentials are encrypted in an archive file in scripts/encrypted.tar.gz.enc .", "title": "Credentials"}, {"location": "cozy-banks/docs/credentials/#create-encrypted-file", "text": "tar zcvf scripts/decrypted.tar.gz scripts/decrypted/ travis encrypt-file scripts/decrypted.tar.gz scripts/encrypted.tar.gz.enc -p You should save key and iv variables on pass. pass Gangsters/cozy-banks/ENCRYPTED_KEY pass Gangsters/cozy-banks/ENCRYPTED_IV", "title": "Create encrypted file"}, {"location": "cozy-banks/docs/credentials/#decrypt-file", "text": "export ENCRYPTED_KEY = ` pass Gangsters/cozy-banks/ENCRYPTED_KEY ` export ENCRYPTED_IV = ` pass Gangsters/cozy-banks/ENCRYPTED_IV ` yarn secrets:decrypt", "title": "Decrypt file"}, {"location": "cozy-banks/docs/credentials/#update-encrypt-file", "text": "If you want to update the credentials, you should update folder ./scripts/decrypted and launch these commands: export ENCRYPTED_KEY = ` pass Gangsters/cozy-banks/ENCRYPTED_KEY ` export ENCRYPTED_IV = ` pass Gangsters/cozy-banks/ENCRYPTED_IV ` yarn secrets:encrypt", "title": "Update encrypt file"}, {"location": "cozy-banks/docs/data-fetching/", "text": "This document lists data fetching strategies implemented in Banks. Doctypes used in Banks \u00b6 Accounts: io.cozy.bank.accounts Groups: io.cozy.bank.groups Accounts and groups are loaded right away and are necessary for most of the pages in Banks. No particular strategy for them is necessary since their general cardinality is low (a user has typically less than 100 accounts/groups). It is necessary for example to load account and groups to show the correct transactions when filter the transactions by account / group. Recurrence bundles: io.cozy.bank.recurrence Recurrence bundles are loaded on the recurrences page and could benefit from pagination if a user a more than 100 recurrence bundle. For the recurrence page where transactions pertaining to a particular recurrence bundle are shown, only its transactions are loaded. Triggers: io.cozy.triggers Necessary to display how fresh is the data for a particular account. Used in the balance page and the settings page. Transactions: io.cozy.bank.operations Transactions is the doctype with the highest cardinality and a user has typically several thousands of transactions. A banking transaction weigh less than a 1ko, but a user with 10 years of banking history with a mean of 3 transactions per days as 20000 transactions; in this case several Mo should be downloaded if we had stayed with querying all transactions at each page reload. This is why granular queries were implemented so that each page only loads what is necessary for its needs. Transactions fetching \u00b6 Since it is not performant to load all the transactions from a user at load, queries fetching a subset of the transactions are used. Filtering / indexing and paginated queries through fetchMore are used. Balances page \u00b6 On the balance page, we need account/groups and the transactions for the last year to draw the chart. Transactions are loaded with a subset of their fields so as to lower the data transmitted: only amount, account, date and currency are loaded. Transactions are fetched in batch of 1000 until no more data has been loaded. This is why if a user has more than 1000 transactions in the last year, the graph will be updated for each round of 1000 transactions being fetched. Transaction page \u00b6 The transaction query is based on the account/group filter to only fetch transactions pertaining to a group/account When the user jump from month to month, new queries are created that start at the selected month. This prevents easy infinite top scrolling since we cannot do fetchMore in reverse but this has been deemed OK functionally since the user can use the arrows after reaching the top Infinite fetching when reaching the bottom is implemented via the fetchMore function. Since we do not want data from other months to disturb one particular month, queries on the transactions pages are created with the query options { add: false }. This prevents transactions that have been fetched through the january query to end ud in the march query. This would prevent the infinite loading mechanism to work correctly (since we rely on a graphical element to trigger the fetchMore). Here are the different transaction queries that are made transactions- : transactions for a particular account when the user has not yet navigated in time. Transactions are fetched sorted by date, so we end up with the most recent transactions for a particular account. When the user scrolls down and we have more transactions (query.hasMore), we can request more transactions through query.fetchMore transactions-- When the user navigates from month to month via the date selector, we create a new query that contains the ending month ({ date: { $gt: endDate }}). This enables us to support the infinite loading through the previous mechanism of fetchMore. transactions- When the user selects a group. Very similar to the transactions- query but we fetch transactions for several accounts with a CouchDB $in query on the account attribute. transactions-- Similar to the transactions--endDate> , this is when the user has filtered by a group and has navigated to a month via the date selector. Date selector \u00b6 For the date selector to show the right available options, we need to have the full extent of dates that is available for the particular account/group that we have chosen. Here, we make 2 queries, one for the earliest transaction and one for the latest transaction and then we generate all the months between those two transactions to display the date selector options. Those queries are indexed by date and account and are quick (30ms). While those queries are in flight, the date selector is displayed but not functional. Categories page \u00b6 For this page, we do not need to support infinite loading since we stay in 1 particular month/year. Thus we end up with queries like transactions--- = queries only for the current month transactions, filtered by account and group. useFullyLoadedQuery is used to load all the documents via fetchMore since it is necessary to have all the docs to make aggregate statistics on them. Keeping previous data while loading next one \u00b6 To prevent a jarring loading screen while loading the month, the previous query\u2019s data is shown while the next query data is loading. While data is loading, a progress bar is shown below the transaction header.", "title": "Data fetching"}, {"location": "cozy-banks/docs/data-fetching/#doctypes-used-in-banks", "text": "Accounts: io.cozy.bank.accounts Groups: io.cozy.bank.groups Accounts and groups are loaded right away and are necessary for most of the pages in Banks. No particular strategy for them is necessary since their general cardinality is low (a user has typically less than 100 accounts/groups). It is necessary for example to load account and groups to show the correct transactions when filter the transactions by account / group. Recurrence bundles: io.cozy.bank.recurrence Recurrence bundles are loaded on the recurrences page and could benefit from pagination if a user a more than 100 recurrence bundle. For the recurrence page where transactions pertaining to a particular recurrence bundle are shown, only its transactions are loaded. Triggers: io.cozy.triggers Necessary to display how fresh is the data for a particular account. Used in the balance page and the settings page. Transactions: io.cozy.bank.operations Transactions is the doctype with the highest cardinality and a user has typically several thousands of transactions. A banking transaction weigh less than a 1ko, but a user with 10 years of banking history with a mean of 3 transactions per days as 20000 transactions; in this case several Mo should be downloaded if we had stayed with querying all transactions at each page reload. This is why granular queries were implemented so that each page only loads what is necessary for its needs.", "title": "Doctypes used in Banks"}, {"location": "cozy-banks/docs/data-fetching/#transactions-fetching", "text": "Since it is not performant to load all the transactions from a user at load, queries fetching a subset of the transactions are used. Filtering / indexing and paginated queries through fetchMore are used.", "title": "Transactions fetching"}, {"location": "cozy-banks/docs/data-fetching/#balances-page", "text": "On the balance page, we need account/groups and the transactions for the last year to draw the chart. Transactions are loaded with a subset of their fields so as to lower the data transmitted: only amount, account, date and currency are loaded. Transactions are fetched in batch of 1000 until no more data has been loaded. This is why if a user has more than 1000 transactions in the last year, the graph will be updated for each round of 1000 transactions being fetched.", "title": "Balances page"}, {"location": "cozy-banks/docs/data-fetching/#transaction-page", "text": "The transaction query is based on the account/group filter to only fetch transactions pertaining to a group/account When the user jump from month to month, new queries are created that start at the selected month. This prevents easy infinite top scrolling since we cannot do fetchMore in reverse but this has been deemed OK functionally since the user can use the arrows after reaching the top Infinite fetching when reaching the bottom is implemented via the fetchMore function. Since we do not want data from other months to disturb one particular month, queries on the transactions pages are created with the query options { add: false }. This prevents transactions that have been fetched through the january query to end ud in the march query. This would prevent the infinite loading mechanism to work correctly (since we rely on a graphical element to trigger the fetchMore). Here are the different transaction queries that are made transactions- : transactions for a particular account when the user has not yet navigated in time. Transactions are fetched sorted by date, so we end up with the most recent transactions for a particular account. When the user scrolls down and we have more transactions (query.hasMore), we can request more transactions through query.fetchMore transactions-- When the user navigates from month to month via the date selector, we create a new query that contains the ending month ({ date: { $gt: endDate }}). This enables us to support the infinite loading through the previous mechanism of fetchMore. transactions- When the user selects a group. Very similar to the transactions- query but we fetch transactions for several accounts with a CouchDB $in query on the account attribute. transactions-- Similar to the transactions--endDate> , this is when the user has filtered by a group and has navigated to a month via the date selector.", "title": "Transaction page"}, {"location": "cozy-banks/docs/data-fetching/#date-selector", "text": "For the date selector to show the right available options, we need to have the full extent of dates that is available for the particular account/group that we have chosen. Here, we make 2 queries, one for the earliest transaction and one for the latest transaction and then we generate all the months between those two transactions to display the date selector options. Those queries are indexed by date and account and are quick (30ms). While those queries are in flight, the date selector is displayed but not functional.", "title": "Date selector"}, {"location": "cozy-banks/docs/data-fetching/#categories-page", "text": "For this page, we do not need to support infinite loading since we stay in 1 particular month/year. Thus we end up with queries like transactions--- = queries only for the current month transactions, filtered by account and group. useFullyLoadedQuery is used to load all the documents via fetchMore since it is necessary to have all the docs to make aggregate statistics on them.", "title": "Categories page"}, {"location": "cozy-banks/docs/data-fetching/#keeping-previous-data-while-loading-next-one", "text": "To prevent a jarring loading screen while loading the month, the previous query\u2019s data is shown while the next query data is loading. While data is loading, a progress bar is shown below the transaction header.", "title": "Keeping previous data while loading next one"}, {"location": "cozy-banks/docs/demo/", "text": "Demo \u00b6 Fake connectors success state in Cozy Home \u00b6 On demo instances, we use fixtures, not real data. But we need to show some connectors successfully connected in Collect. Here is how to do that : Install a connector via the Store Configure an account that doesn\u2019t exist on this service In the Home, the connector shows an error, it\u2019s normal for the moment Connect to CouchDB of the environment the instance lives on Find the latest job for the connector and update its state to done and remove its error property Find the trigger for the connector and update its arguments to a yearly CRON. For example 0 0 0 15 1 * will run this trigger once every january 15th If the connector frequency is daily, you have to update the job one more time the next day. If the frequency is weekly, you have to update the job one more time the next week. After that, you don\u2019t have to update it before the next year", "title": "Demo"}, {"location": "cozy-banks/docs/demo/#demo", "text": "", "title": "Demo"}, {"location": "cozy-banks/docs/demo/#fake-connectors-success-state-in-cozy-home", "text": "On demo instances, we use fixtures, not real data. But we need to show some connectors successfully connected in Collect. Here is how to do that : Install a connector via the Store Configure an account that doesn\u2019t exist on this service In the Home, the connector shows an error, it\u2019s normal for the moment Connect to CouchDB of the environment the instance lives on Find the latest job for the connector and update its state to done and remove its error property Find the trigger for the connector and update its arguments to a yearly CRON. For example 0 0 0 15 1 * will run this trigger once every january 15th If the connector frequency is daily, you have to update the job one more time the next day. If the frequency is weekly, you have to update the job one more time the next week. After that, you don\u2019t have to update it before the next year", "title": "Fake connectors success state in Cozy Home"}, {"location": "cozy-banks/docs/dev/", "text": "Development \u00b6 Table of Contents \u00b6 Getting started Fixtures Doctypes Continuous build Release Start a release branch Workflow Publish manually on the Cozy registry Notifications How to develop on templates Under the covers Assets Debug notification triggers Emails Push notifications When creating a notification End to end tests Alert rules Automatic tests Manual insertion test Misc Icons Pouch On Web Important credentials Getting started \u00b6 You need to have yarn installed. If you don\u2019t, please check the official documentation and follow the instructions to install it on your system. Then you can install the dependencies: $ yarn Install the fixtures: $ yarn fixtures Build the app: $ yarn build And running the app: $ yarn start Please note that for the project to work, you will need to have a working cozy-stack. See how to run a cozy application for more information. When watching, you still need to have a cozy-stack running to serve the files of the app (do not use the webpack-dev-server directly). This is important as the stack injects through template variables the token and domain used to connect to the cozy. \u26a0\ufe0f CSPs must be disabled when working with the development server (as the index.html is served via the stack but the JS assets are served via webpack-dev-server). You can do this via a browser extension ( Chrome ) or you can tell the stack to disable CSPs via its config file ( disable_csp: true , check here for more info on the config file). See an example config file here . Fixtures \u00b6 While developing, it is convenient to be able to inject and remove arbitrary data on your local instance. You can add fixtures by installing ACH globally and using data from test/fixtures . We have a set of fake banking data in the test/fixtures/demo.json file that you can inject in your instance using the yarn fixtures command. If you want to inject other data or remove some data, you can use ACH . Doctypes \u00b6 The doctypes used in Banks are described in the cozy-doctypes repository. Continuous build \u00b6 The application is built automatically and published on Cozy Registry by Travis . Release \u00b6 A release consists in publishing the app on all platforms: web (via the Cozy Registry ), Android (via the Google Play Store, APKs are also linked to Github releases ) and iOS (via the App Store). Start a release branch \u00b6 When starting a release, start the checklist PR with: yarn release This will ask for the next version number and create a release branch with it. If you have Hub installed (recommended), it will also create the related pull request for you. Workflow \u00b6 When a release branch is created, features are frozen and the branch should only receive bugfixes. To create beta versions, you have to do two things: Commit it and create a tag with the X.Y.Z-beta.M scheme (for example 1.5.0-beta.1 ) and push them The web app beta version will be automatically built and published on the cozy registry. An APK for Android will also be automatically created. For iOS, you have to build the app and upload it on Testflight. Publish manually on the Cozy registry \u00b6 To publish manually on the Cozy registry, you need a token also stored in Cozy internal password store : export REGISTRY_TOKEN=`pass registry/spaces/banks/banks.token` After, you can use cozy-app-publish to push the app to the registry. More information : https://github.com/cozy/cozy-stack/blob/master/docs/registry-publish.md Notifications \u00b6 How to develop on templates \u00b6 With the TEST_TEMPLATES environment variable, an express server serving the HTML emails will be built. $ env TEST_TEMPLATES = true yarn watch:services $ node build/testTemplates.js Rendering emails at http://localhost:8081! You can open your browser to check the emails. The Preview feature in Mailchimp is also useful to check that everything is correctly rendered on the various email clients (just copy/paste the content of the page). Under the covers \u00b6 The templates are Handlebars templates using the mjml language. mjml greatly reduces the pains to develop an email template as it deals with a lot of quirks for you. It features ready-made components to make responsive email templates. Behind the scene, it uses React to implement custom components, and juice to inline the CSS into the HTML. The handlebars-layouts plugin is used to provide an easy way to extend a base template (\u00e0 la jinja ) Other templates : nodemon --exec \"node transactions-notification.js\" -e js,css,hbs,json Assets \u00b6 Assets in assets/ are uploaded to https://downcloud.cozycloud.cc on every deployment on CI. It can also be done manually with the yarn uploadStaticFiles script. Debug notification triggers \u00b6 To debug notifications, you have to launch a watch on the notifications.js and then launch it with cozy-run-dev . \u26a0\ufe0f You have to temporarily add io.cozy.accounts to your manifest so that you can create a dev account to test the service. \"type\": \"io.cozy.notifications\", \"verbs\": [\"POST\"] }, + \"account\": { + \"description\": \"Used to send notifications\", + \"type\": \"io.cozy.accounts\", + \"verbs\": [\"POST\"] + }, \"bank.settings\": { \"description\": \"Used to manage your bank settings\", \"type\": \"io.cozy.bank.settings\", $ yarn watch:services # will continuously build `build/notifications.js` $ nodemon --delay 1 -w build/notifications.js --exec \"cozy-konnector-dev -t /tmp/token.json -m manifest.webapp build/notifications.js\" # will launch build/notifications.js (and relaunch it when it changes) with the right COZY_CREDENTIALS, /tmp/token.json is where the token will be stored Emails \u00b6 To see the emails that the stack sends, launch a MailHog instance : docker run -p 1025:1025 -p 8025:8025 mailhog/mailhog The stack will send the emails through the SMTP port of MailHog and you will be able to see the mails in its web interface on http://localhost:8025. Push notifications \u00b6 Similarly, to debug push notifications, you can configure the stack to send push notifications to a local server, and launch a fake push notifications server locally. env PORT=3001 node test/e2e/mock-server.js To configure the stack, edit your cozy.yml config file: + notifications: + android_api_key: 'fake_android_api_key' + fcm_server: 'http://localhost:3001' https://github.com/cozy/cozy-banks/tree/master/src/ducks/notifications/html When creating a notification \u00b6 If you want to test the notifications in a workflow that is very close to the real one, you can import some fixtures to trigger the service execution. For that, you must open the test/fixtures/operations-notifs.json file and edit the following : the _id field of the documents, so they are unique and will create a new document the account field of the io.cozy.bank.operations documents to match an account id that exist on the instance you will import the fixtures to the dates and the labels to be able to see the imported documents easily Then you can use ACH to import the fixtures : ACH import test/fixtures/notifications-service/operations-notifs.json test/fixtures/helpers/index.js --url End to end tests \u00b6 Alert rules \u00b6 Automatic tests \u00b6 Alert rules are tested with automatic tests that Inserts data inside the local cozy-stack Launches the onOperationOrBillCreate service Checks on mailhog the emails received Checks on a mock push server the push notifications received $ export COZY_URL = http://cozy.tools:8080 $ export COZY_CREDENTIALS = $( cozy-stack instances token-app cozy.tools:8080 banks ) $ docker run -p 1025 :1025 -p 8025 :8025 mailhog/mailhog # Deactivate minification with minimize: false in webpack.optimize inside webpack.target.services.js $ env NODE_ENV = services:production yarn webpack --config webpack.config.js --bail --watch $ yarn test:e2e:alerts At the moment, it needs to be launched on the computer of the developer but should be done on the CI in the future. \u26a0\ufe0f You need to have the services built for production for E2E tests to work. \u26a0\ufe0f For push notifications tests to work, you need first to configure the stack so that it uses a fake server that will receive push notifications. Add this to your stack config file : notifications : android_api_key : 'fake_android_api_key' fcm_server : 'http://localhost:3001' Manual insertion test \u00b6 To test on a real Cozy, a script can insert fake transactions on accounts corresponding to alerts, for the onOperationOrBillCreate service to be started. # Insert fake transactions yarn test:e2e:alerts-existing-cozy --url https://mydemocozy.mycozy.cloud insert # Cleanup fake transactions yarn test:e2e:alerts-existing-cozy --url https://mydemocozy.mycozy.cloud cleanup Misc \u00b6 Icons \u00b6 \ud83d\uddbc The PNG icons that are included in the emails are generated manually from the SVG via scripts/icons-to-png.sh and uploaded automatically to files.cozycloud.cc via Jenkins (which follows the file files.cozycloud.cc at the root of the repo). Pouch On Web \u00b6 If you want activate Pouch on web app, you need: - a token - launch your build with FORCE_POUCH cozy-stack instances token-cli cozy.tools:8080 $(cat manifest.webapp | jq -r '[.permissions[] | .type] | join(\" \")') env FORCE_POUCH=true yarn start Launch your web application and in console javascript fill in the token and refresh the page: flag('cozyToken', ) Now you can play with replication: cozyClient.links[0].startReplication() cozyClient.links[0].stopReplication() Important credentials \u00b6 All important credentials are stored in Cozy internal password store .", "title": "Development"}, {"location": "cozy-banks/docs/dev/#development", "text": "", "title": "Development"}, {"location": "cozy-banks/docs/dev/#table-of-contents", "text": "Getting started Fixtures Doctypes Continuous build Release Start a release branch Workflow Publish manually on the Cozy registry Notifications How to develop on templates Under the covers Assets Debug notification triggers Emails Push notifications When creating a notification End to end tests Alert rules Automatic tests Manual insertion test Misc Icons Pouch On Web Important credentials", "title": "Table of Contents"}, {"location": "cozy-banks/docs/dev/#getting-started", "text": "You need to have yarn installed. If you don\u2019t, please check the official documentation and follow the instructions to install it on your system. Then you can install the dependencies: $ yarn Install the fixtures: $ yarn fixtures Build the app: $ yarn build And running the app: $ yarn start Please note that for the project to work, you will need to have a working cozy-stack. See how to run a cozy application for more information. When watching, you still need to have a cozy-stack running to serve the files of the app (do not use the webpack-dev-server directly). This is important as the stack injects through template variables the token and domain used to connect to the cozy. \u26a0\ufe0f CSPs must be disabled when working with the development server (as the index.html is served via the stack but the JS assets are served via webpack-dev-server). You can do this via a browser extension ( Chrome ) or you can tell the stack to disable CSPs via its config file ( disable_csp: true , check here for more info on the config file). See an example config file here .", "title": "Getting started"}, {"location": "cozy-banks/docs/dev/#fixtures", "text": "While developing, it is convenient to be able to inject and remove arbitrary data on your local instance. You can add fixtures by installing ACH globally and using data from test/fixtures . We have a set of fake banking data in the test/fixtures/demo.json file that you can inject in your instance using the yarn fixtures command. If you want to inject other data or remove some data, you can use ACH .", "title": "Fixtures"}, {"location": "cozy-banks/docs/dev/#doctypes", "text": "The doctypes used in Banks are described in the cozy-doctypes repository.", "title": "Doctypes"}, {"location": "cozy-banks/docs/dev/#continuous-build", "text": "The application is built automatically and published on Cozy Registry by Travis .", "title": "Continuous build"}, {"location": "cozy-banks/docs/dev/#release", "text": "A release consists in publishing the app on all platforms: web (via the Cozy Registry ), Android (via the Google Play Store, APKs are also linked to Github releases ) and iOS (via the App Store).", "title": "Release"}, {"location": "cozy-banks/docs/dev/#start-a-release-branch", "text": "When starting a release, start the checklist PR with: yarn release This will ask for the next version number and create a release branch with it. If you have Hub installed (recommended), it will also create the related pull request for you.", "title": "Start a release branch"}, {"location": "cozy-banks/docs/dev/#workflow", "text": "When a release branch is created, features are frozen and the branch should only receive bugfixes. To create beta versions, you have to do two things: Commit it and create a tag with the X.Y.Z-beta.M scheme (for example 1.5.0-beta.1 ) and push them The web app beta version will be automatically built and published on the cozy registry. An APK for Android will also be automatically created. For iOS, you have to build the app and upload it on Testflight.", "title": "Workflow"}, {"location": "cozy-banks/docs/dev/#publish-manually-on-the-cozy-registry", "text": "To publish manually on the Cozy registry, you need a token also stored in Cozy internal password store : export REGISTRY_TOKEN=`pass registry/spaces/banks/banks.token` After, you can use cozy-app-publish to push the app to the registry. More information : https://github.com/cozy/cozy-stack/blob/master/docs/registry-publish.md", "title": "Publish manually on the Cozy registry"}, {"location": "cozy-banks/docs/dev/#notifications", "text": "", "title": "Notifications"}, {"location": "cozy-banks/docs/dev/#how-to-develop-on-templates", "text": "With the TEST_TEMPLATES environment variable, an express server serving the HTML emails will be built. $ env TEST_TEMPLATES = true yarn watch:services $ node build/testTemplates.js Rendering emails at http://localhost:8081! You can open your browser to check the emails. The Preview feature in Mailchimp is also useful to check that everything is correctly rendered on the various email clients (just copy/paste the content of the page).", "title": "How to develop on templates"}, {"location": "cozy-banks/docs/dev/#under-the-covers", "text": "The templates are Handlebars templates using the mjml language. mjml greatly reduces the pains to develop an email template as it deals with a lot of quirks for you. It features ready-made components to make responsive email templates. Behind the scene, it uses React to implement custom components, and juice to inline the CSS into the HTML. The handlebars-layouts plugin is used to provide an easy way to extend a base template (\u00e0 la jinja ) Other templates : nodemon --exec \"node transactions-notification.js\" -e js,css,hbs,json", "title": "Under the covers"}, {"location": "cozy-banks/docs/dev/#assets", "text": "Assets in assets/ are uploaded to https://downcloud.cozycloud.cc on every deployment on CI. It can also be done manually with the yarn uploadStaticFiles script.", "title": "Assets"}, {"location": "cozy-banks/docs/dev/#debug-notification-triggers", "text": "To debug notifications, you have to launch a watch on the notifications.js and then launch it with cozy-run-dev . \u26a0\ufe0f You have to temporarily add io.cozy.accounts to your manifest so that you can create a dev account to test the service. \"type\": \"io.cozy.notifications\", \"verbs\": [\"POST\"] }, + \"account\": { + \"description\": \"Used to send notifications\", + \"type\": \"io.cozy.accounts\", + \"verbs\": [\"POST\"] + }, \"bank.settings\": { \"description\": \"Used to manage your bank settings\", \"type\": \"io.cozy.bank.settings\", $ yarn watch:services # will continuously build `build/notifications.js` $ nodemon --delay 1 -w build/notifications.js --exec \"cozy-konnector-dev -t /tmp/token.json -m manifest.webapp build/notifications.js\" # will launch build/notifications.js (and relaunch it when it changes) with the right COZY_CREDENTIALS, /tmp/token.json is where the token will be stored", "title": "Debug notification triggers"}, {"location": "cozy-banks/docs/dev/#emails", "text": "To see the emails that the stack sends, launch a MailHog instance : docker run -p 1025:1025 -p 8025:8025 mailhog/mailhog The stack will send the emails through the SMTP port of MailHog and you will be able to see the mails in its web interface on http://localhost:8025.", "title": "Emails"}, {"location": "cozy-banks/docs/dev/#push-notifications", "text": "Similarly, to debug push notifications, you can configure the stack to send push notifications to a local server, and launch a fake push notifications server locally. env PORT=3001 node test/e2e/mock-server.js To configure the stack, edit your cozy.yml config file: + notifications: + android_api_key: 'fake_android_api_key' + fcm_server: 'http://localhost:3001' https://github.com/cozy/cozy-banks/tree/master/src/ducks/notifications/html", "title": "Push notifications"}, {"location": "cozy-banks/docs/dev/#when-creating-a-notification", "text": "If you want to test the notifications in a workflow that is very close to the real one, you can import some fixtures to trigger the service execution. For that, you must open the test/fixtures/operations-notifs.json file and edit the following : the _id field of the documents, so they are unique and will create a new document the account field of the io.cozy.bank.operations documents to match an account id that exist on the instance you will import the fixtures to the dates and the labels to be able to see the imported documents easily Then you can use ACH to import the fixtures : ACH import test/fixtures/notifications-service/operations-notifs.json test/fixtures/helpers/index.js --url ", "title": "When creating a notification"}, {"location": "cozy-banks/docs/dev/#end-to-end-tests", "text": "", "title": "End to end tests"}, {"location": "cozy-banks/docs/dev/#alert-rules", "text": "", "title": "Alert rules"}, {"location": "cozy-banks/docs/dev/#automatic-tests", "text": "Alert rules are tested with automatic tests that Inserts data inside the local cozy-stack Launches the onOperationOrBillCreate service Checks on mailhog the emails received Checks on a mock push server the push notifications received $ export COZY_URL = http://cozy.tools:8080 $ export COZY_CREDENTIALS = $( cozy-stack instances token-app cozy.tools:8080 banks ) $ docker run -p 1025 :1025 -p 8025 :8025 mailhog/mailhog # Deactivate minification with minimize: false in webpack.optimize inside webpack.target.services.js $ env NODE_ENV = services:production yarn webpack --config webpack.config.js --bail --watch $ yarn test:e2e:alerts At the moment, it needs to be launched on the computer of the developer but should be done on the CI in the future. \u26a0\ufe0f You need to have the services built for production for E2E tests to work. \u26a0\ufe0f For push notifications tests to work, you need first to configure the stack so that it uses a fake server that will receive push notifications. Add this to your stack config file : notifications : android_api_key : 'fake_android_api_key' fcm_server : 'http://localhost:3001'", "title": "Automatic tests"}, {"location": "cozy-banks/docs/dev/#manual-insertion-test", "text": "To test on a real Cozy, a script can insert fake transactions on accounts corresponding to alerts, for the onOperationOrBillCreate service to be started. # Insert fake transactions yarn test:e2e:alerts-existing-cozy --url https://mydemocozy.mycozy.cloud insert # Cleanup fake transactions yarn test:e2e:alerts-existing-cozy --url https://mydemocozy.mycozy.cloud cleanup", "title": "Manual insertion test"}, {"location": "cozy-banks/docs/dev/#misc", "text": "", "title": "Misc"}, {"location": "cozy-banks/docs/dev/#icons", "text": "\ud83d\uddbc The PNG icons that are included in the emails are generated manually from the SVG via scripts/icons-to-png.sh and uploaded automatically to files.cozycloud.cc via Jenkins (which follows the file files.cozycloud.cc at the root of the repo).", "title": "Icons"}, {"location": "cozy-banks/docs/dev/#pouch-on-web", "text": "If you want activate Pouch on web app, you need: - a token - launch your build with FORCE_POUCH cozy-stack instances token-cli cozy.tools:8080 $(cat manifest.webapp | jq -r '[.permissions[] | .type] | join(\" \")') env FORCE_POUCH=true yarn start Launch your web application and in console javascript fill in the token and refresh the page: flag('cozyToken', ) Now you can play with replication: cozyClient.links[0].startReplication() cozyClient.links[0].stopReplication()", "title": "Pouch On Web"}, {"location": "cozy-banks/docs/dev/#important-credentials", "text": "All important credentials are stored in Cozy internal password store .", "title": "Important credentials"}, {"location": "cozy-banks/docs/notifications/", "text": "Notifications \u00b6 When you launch Cozy Banks mobile application (iOS and Android), the app asks the right to push notifications. You can configure notifications directly on your Settings. By example when movement amount is greater than 30\u20ac. Technique \u00b6 We use cordova plugin to make this possible. When the mobile app connects to your Cozy, it creates an oauth client with notificationPlatform: firebase parameter. So Cozy Stack know you can receive notification on your mobile. Test \u00b6 COZY_DOMAIN=recette.cozy.works && \\ curl -X POST \"https://$COZY_DOMAIN/jobs/queue/push\" \\ -H \"Authorization: Bearer $(cozy-stack instances token-cli $COZY_DOMAIN io.cozy.jobs)\" \\ -H \"Accept: text/event-stream\" \\ -H \"Content-Type: application-json\" \\ -d'{\"data\":{\"attributes\":{\"arguments\":{\"platform\": \"firebase\", \"source\": \"toto\", \"title\": \"Mon Titre\", \"message\": \"Mon message !!!\", \"data\": {\"foo\": \"bar\"}}}}}' How to test push notifications \u00b6 Edit your cozy.yaml (ex: ~/.cozy/cozy.yaml ) Add notifications contexts : dev : ... notifications : android_api_key : \"fake_android_api_key\" fcm_server : \"http://localhost:3001\" In Fauxton - \u2026/io-cozy-oauth-clients doctype Edit a document and add the fields: notification_platform and notification_device_token : ... \"software_id\" : \"...\" , \"notification_platform\" : \"android\" , \"notification_device_token\" : \"fake-token\" , ... Add a document in \u2026/io-cozy-bank-operations doctype Ex: To test TransactionGreater, create a document with an amount greater than your settings value. Using operation-generic.json might be useful. $ ach import test/fixtures/matching-service/operation-generic.json -u http://cozy.localhost:8080/ In a shell $ env PORT = 3001 node test/e2e/mock-server.js In an other shell $ yarn watch:services In an other shell $ export COZY_URL = http://cozy.localhost:8080 $ export COZY_CREDENTIALS = $( cozy-stack instances token-app cozy.localhost:8080 banks ) $ node build/onOperationOrBillCreate.js You should receive your notification : Received push notification { to: 'fake-token' , content_available: true, notification: { title: 'Transaction greater than 10\u20ac' , body: 'SNCF: +300EUR' } , data: { body: 'SNCF: +300EUR' , notId: 149956241 , route: '/balances/461ef7bdb566ef19d28d976a230162d8/details' , title: '1 Transaction greater than 10\u20ac' } }", "title": "Notifications"}, {"location": "cozy-banks/docs/notifications/#notifications", "text": "When you launch Cozy Banks mobile application (iOS and Android), the app asks the right to push notifications. You can configure notifications directly on your Settings. By example when movement amount is greater than 30\u20ac.", "title": "Notifications"}, {"location": "cozy-banks/docs/notifications/#technique", "text": "We use cordova plugin to make this possible. When the mobile app connects to your Cozy, it creates an oauth client with notificationPlatform: firebase parameter. So Cozy Stack know you can receive notification on your mobile.", "title": "Technique"}, {"location": "cozy-banks/docs/notifications/#test", "text": "COZY_DOMAIN=recette.cozy.works && \\ curl -X POST \"https://$COZY_DOMAIN/jobs/queue/push\" \\ -H \"Authorization: Bearer $(cozy-stack instances token-cli $COZY_DOMAIN io.cozy.jobs)\" \\ -H \"Accept: text/event-stream\" \\ -H \"Content-Type: application-json\" \\ -d'{\"data\":{\"attributes\":{\"arguments\":{\"platform\": \"firebase\", \"source\": \"toto\", \"title\": \"Mon Titre\", \"message\": \"Mon message !!!\", \"data\": {\"foo\": \"bar\"}}}}}'", "title": "Test"}, {"location": "cozy-banks/docs/notifications/#how-to-test-push-notifications", "text": "Edit your cozy.yaml (ex: ~/.cozy/cozy.yaml ) Add notifications contexts : dev : ... notifications : android_api_key : \"fake_android_api_key\" fcm_server : \"http://localhost:3001\" In Fauxton - \u2026/io-cozy-oauth-clients doctype Edit a document and add the fields: notification_platform and notification_device_token : ... \"software_id\" : \"...\" , \"notification_platform\" : \"android\" , \"notification_device_token\" : \"fake-token\" , ... Add a document in \u2026/io-cozy-bank-operations doctype Ex: To test TransactionGreater, create a document with an amount greater than your settings value. Using operation-generic.json might be useful. $ ach import test/fixtures/matching-service/operation-generic.json -u http://cozy.localhost:8080/ In a shell $ env PORT = 3001 node test/e2e/mock-server.js In an other shell $ yarn watch:services In an other shell $ export COZY_URL = http://cozy.localhost:8080 $ export COZY_CREDENTIALS = $( cozy-stack instances token-app cozy.localhost:8080 banks ) $ node build/onOperationOrBillCreate.js You should receive your notification : Received push notification { to: 'fake-token' , content_available: true, notification: { title: 'Transaction greater than 10\u20ac' , body: 'SNCF: +300EUR' } , data: { body: 'SNCF: +300EUR' , notId: 149956241 , route: '/balances/461ef7bdb566ef19d28d976a230162d8/details' , title: '1 Transaction greater than 10\u20ac' } }", "title": "How to test push notifications"}, {"location": "cozy-banks/docs/perfs/", "text": "Measuring Banks performance \u00b6 There is ongoing work on improving Banks performance for people for have a lot of banking data. Fixtures \u00b6 To test more easily performance and performance regressions, fixtures can be created with adjustable number of documents for each doctype. This will help us measure performances on large cozies and in the future have performance regression tests. Medium fixture \u00b6 100 io.cozy.bills 10 io.cozy.bank.accounts 3000 io.cozy.bank.operations 3 io.cozy.bank.groups Saved to fixtures-m.json Approximatively 3 years saved Size of the fixture file : 1.2M Large fixture \u00b6 1000 io.cozy.bills 50 io.cozy.bank.accounts 20000 io.cozy.bank.operations 15 io.cozy.bank.groups", "title": "Measuring Banks performance"}, {"location": "cozy-banks/docs/perfs/#measuring-banks-performance", "text": "There is ongoing work on improving Banks performance for people for have a lot of banking data.", "title": "Measuring Banks performance"}, {"location": "cozy-banks/docs/perfs/#fixtures", "text": "To test more easily performance and performance regressions, fixtures can be created with adjustable number of documents for each doctype. This will help us measure performances on large cozies and in the future have performance regression tests.", "title": "Fixtures"}, {"location": "cozy-banks/docs/perfs/#medium-fixture", "text": "100 io.cozy.bills 10 io.cozy.bank.accounts 3000 io.cozy.bank.operations 3 io.cozy.bank.groups Saved to fixtures-m.json Approximatively 3 years saved Size of the fixture file : 1.2M", "title": "Medium fixture"}, {"location": "cozy-banks/docs/perfs/#large-fixture", "text": "1000 io.cozy.bills 50 io.cozy.bank.accounts 20000 io.cozy.bank.operations 15 io.cozy.bank.groups", "title": "Large fixture"}, {"location": "cozy-banks/docs/services/", "text": "Services \u00b6 This document describes services running as part of the Banks application. Developing Services Categorization onOperationOrBillCreate Automatic groups Budget alerts Recurrences Konnector alerts I am writing a banking konnector, what should I do? Developing \u00b6 You can manually create an app token and launch the built service. # Watch services $ yarn watch $ export COZY_URL = 'http://cozy.localhost:8080' $ export COZY_CREDENTIALS = $( cozy-stack instances token-app cozy.localhost:8080 banks ) $ node build/services/budgetAlerts/banks.js Services \u00b6 Categorization \u00b6 slug: categorization This service role is to categorize transactions. It is bound to no event at all, so it\u2019s not automatically triggered and needs to be explicitly called by a konnector or another service. This service is called from konnectors so that transactions are categorized as soon as possible (no debounce involved). When this service is ran, it gets all io.cozy.bank.operations that has the toCategorize property with a true value. Then it slices it into chunks and categorizes the most chunks it can before the service is stopped by the stack. If there are some uncategorized transactions remaining, it restarts itself to finish the work. If all transactions have been categorized, it calls the onOperationOrBillCreate service to trigger all other features. See the categorization documentation for more details about the categorization implementation. onOperationOrBillCreate \u00b6 slug: onOperationOrBillCreate This service has many roles. It does: Bills matching Notifications (push & email) Apps suggestions A PR is opened to have stateful notifications, please check it before doing more work on notifications. It is bound to the io.cozy.bills creation only. The creation of io.cozy.bank.operations should be managed by calling the categorization service. See the next section for more precise informations about that. Automatic groups \u00b6 slug: autogroups Whenever an io.cozy.bank.accounts is created, we check if it could belong in an automatic group based on its type (checkings, savings, credit cards). These io.cozy.bank.groups documents are created with the auto: true attributes. \u2139\ufe0f This service can be run via CLI via yarn service:autogroups Budget alerts \u00b6 slug: budgetAlerts A user can configure alerts to be alerted whenever the sum of its expenses has gone past a maximum threshold per month. The notification is sent as part of the onOperationOrBillCreate service. It is configured from a io.cozy.bank.settings document and the last notification date and amount are saved. A debug service is built to be able to only run this particular part and not the whole onOperationOrBillCreate service. It is possible to run it from the Debug tab in the application (or via Bender). Recurrences \u00b6 slug: recurrence Tries to find recurrence groups when new operations are inserted in the Cozy. It either creates new recurrence groups or attaches transactions to existing recurrence groups. See Paper \u201cPaiements recurrents\u201d for more information on the service. \u2139\ufe0f This service can be run via CLI via yarn service recurrence Konnector alerts \u00b6 slug: konnectorAlerts It monitors the jobs and sends a notification when a konnector has failed. Here are the rules for those notifications: They should only be sent for LOGIN_FAILED and USER_ACTION_NEEDED errors They should only be sent for automatic jobs (not manual) We should not send a notification if the state stays the same The service also determines if a delayed notification schedule at D+3 and D+7 is necessary. When a notification is scheduled, if there are no future reminders, the service will create them. \u2139\ufe0f This service can be run via CLI via yarn service konnectorAlerts Import \u00b6 slug: import Allows you to import bank data into Cozy, from the Cozy bank export file (.csv format) This service is launched manually once the import of the file has been successful on the cozy. It also saves the number of imported transactions in the doctype io.cozy.bank.settings ( lastImportSuccess.savedTransactionsCount ) \u2139\ufe0f This service can be run via CLI via yarn service import I am writing a banking konnector, what should I do? \u00b6 If you want to benefit from all the features of these services, the most straightforward is to add toCategorize: true to the io.cozy.bank.operations your konnector creates, save these documents and then call the categorization service. Here is an example: const { cozyClient , BaseKonnector } = require ( 'cozy-konnector-libs' ) class MyKonnector extends BaseKonnector { async saveTransactions () { const transactions = await this . fetchTransactions () transactions . forEach ( t => ( t . toCategorize = true )) // save `transactions` await cozyClient . jobs . create ( 'service' , { name : 'categorization' , slug : 'banks' }) } } Finally, you will need a permission to create io.cozy.jobs document. Add the following permission to your manifest.konnector : { \"permissions\" : { \"jobs\" : { \"description\" : \"Required to run applications services\" , \"type\" : \"io.cozy.jobs\" } } } With this, the transactions you created will be categorized, then the onOperationOrBillCreate service will be launched and do its work.", "title": "Services"}, {"location": "cozy-banks/docs/services/#services", "text": "This document describes services running as part of the Banks application. Developing Services Categorization onOperationOrBillCreate Automatic groups Budget alerts Recurrences Konnector alerts I am writing a banking konnector, what should I do?", "title": "Services"}, {"location": "cozy-banks/docs/services/#developing", "text": "You can manually create an app token and launch the built service. # Watch services $ yarn watch $ export COZY_URL = 'http://cozy.localhost:8080' $ export COZY_CREDENTIALS = $( cozy-stack instances token-app cozy.localhost:8080 banks ) $ node build/services/budgetAlerts/banks.js", "title": "Developing"}, {"location": "cozy-banks/docs/services/#services_1", "text": "", "title": "Services"}, {"location": "cozy-banks/docs/services/#categorization", "text": "slug: categorization This service role is to categorize transactions. It is bound to no event at all, so it\u2019s not automatically triggered and needs to be explicitly called by a konnector or another service. This service is called from konnectors so that transactions are categorized as soon as possible (no debounce involved). When this service is ran, it gets all io.cozy.bank.operations that has the toCategorize property with a true value. Then it slices it into chunks and categorizes the most chunks it can before the service is stopped by the stack. If there are some uncategorized transactions remaining, it restarts itself to finish the work. If all transactions have been categorized, it calls the onOperationOrBillCreate service to trigger all other features. See the categorization documentation for more details about the categorization implementation.", "title": "Categorization"}, {"location": "cozy-banks/docs/services/#onoperationorbillcreate", "text": "slug: onOperationOrBillCreate This service has many roles. It does: Bills matching Notifications (push & email) Apps suggestions A PR is opened to have stateful notifications, please check it before doing more work on notifications. It is bound to the io.cozy.bills creation only. The creation of io.cozy.bank.operations should be managed by calling the categorization service. See the next section for more precise informations about that.", "title": "onOperationOrBillCreate"}, {"location": "cozy-banks/docs/services/#automatic-groups", "text": "slug: autogroups Whenever an io.cozy.bank.accounts is created, we check if it could belong in an automatic group based on its type (checkings, savings, credit cards). These io.cozy.bank.groups documents are created with the auto: true attributes. \u2139\ufe0f This service can be run via CLI via yarn service:autogroups", "title": "Automatic groups"}, {"location": "cozy-banks/docs/services/#budget-alerts", "text": "slug: budgetAlerts A user can configure alerts to be alerted whenever the sum of its expenses has gone past a maximum threshold per month. The notification is sent as part of the onOperationOrBillCreate service. It is configured from a io.cozy.bank.settings document and the last notification date and amount are saved. A debug service is built to be able to only run this particular part and not the whole onOperationOrBillCreate service. It is possible to run it from the Debug tab in the application (or via Bender).", "title": "Budget alerts"}, {"location": "cozy-banks/docs/services/#recurrences", "text": "slug: recurrence Tries to find recurrence groups when new operations are inserted in the Cozy. It either creates new recurrence groups or attaches transactions to existing recurrence groups. See Paper \u201cPaiements recurrents\u201d for more information on the service. \u2139\ufe0f This service can be run via CLI via yarn service recurrence", "title": "Recurrences"}, {"location": "cozy-banks/docs/services/#konnector-alerts", "text": "slug: konnectorAlerts It monitors the jobs and sends a notification when a konnector has failed. Here are the rules for those notifications: They should only be sent for LOGIN_FAILED and USER_ACTION_NEEDED errors They should only be sent for automatic jobs (not manual) We should not send a notification if the state stays the same The service also determines if a delayed notification schedule at D+3 and D+7 is necessary. When a notification is scheduled, if there are no future reminders, the service will create them. \u2139\ufe0f This service can be run via CLI via yarn service konnectorAlerts", "title": "Konnector alerts"}, {"location": "cozy-banks/docs/services/#import", "text": "slug: import Allows you to import bank data into Cozy, from the Cozy bank export file (.csv format) This service is launched manually once the import of the file has been successful on the cozy. It also saves the number of imported transactions in the doctype io.cozy.bank.settings ( lastImportSuccess.savedTransactionsCount ) \u2139\ufe0f This service can be run via CLI via yarn service import", "title": "Import"}, {"location": "cozy-banks/docs/services/#i-am-writing-a-banking-konnector-what-should-i-do", "text": "If you want to benefit from all the features of these services, the most straightforward is to add toCategorize: true to the io.cozy.bank.operations your konnector creates, save these documents and then call the categorization service. Here is an example: const { cozyClient , BaseKonnector } = require ( 'cozy-konnector-libs' ) class MyKonnector extends BaseKonnector { async saveTransactions () { const transactions = await this . fetchTransactions () transactions . forEach ( t => ( t . toCategorize = true )) // save `transactions` await cozyClient . jobs . create ( 'service' , { name : 'categorization' , slug : 'banks' }) } } Finally, you will need a permission to create io.cozy.jobs document. Add the following permission to your manifest.konnector : { \"permissions\" : { \"jobs\" : { \"description\" : \"Required to run applications services\" , \"type\" : \"io.cozy.jobs\" } } } With this, the transactions you created will be categorized, then the onOperationOrBillCreate service will be launched and do its work.", "title": "I am writing a banking konnector, what should I do?"}, {"location": "cozy-banks/docs/tracking/", "text": "Tracking events \u00b6 Bills matching service \u00b6 Event Category Event Action Event name Event value Description Banks BillsMatching BillWithoutId No value We tried to add a bill to a transaction, but it doesn\u2019t have an ID, so we couldn\u2019t Banks BillsMatching BillAmountOverflowingOperationAmount No value We tried to add a bill to a transaction, but the sum of its amount and already linked bills amounts would overflow the transaction amount, so we couldn\u2019t Banks BillsMatching BillsMatched Number of matched bills Some bills matched with operations", "title": "Tracking events"}, {"location": "cozy-banks/docs/tracking/#tracking-events", "text": "", "title": "Tracking events"}, {"location": "cozy-banks/docs/tracking/#bills-matching-service", "text": "Event Category Event Action Event name Event value Description Banks BillsMatching BillWithoutId No value We tried to add a bill to a transaction, but it doesn\u2019t have an ID, so we couldn\u2019t Banks BillsMatching BillAmountOverflowingOperationAmount No value We tried to add a bill to a transaction, but the sum of its amount and already linked bills amounts would overflow the transaction amount, so we couldn\u2019t Banks BillsMatching BillsMatched Number of matched bills Some bills matched with operations", "title": "Bills matching service"}, {"location": "cozy-banks/scripts/visualizer/", "text": "Link visualizer \u00b6 This is an express server that serves a webpage meant to show links that are found between bills and banking operations by our matching algorithm. To launch the server, run the following commands: yarn build yarn serve Then you can go to http://localhost:3000. There you have a minimal interface where you can trigger a search for links between bills and operations. Developing \u00b6 To develop, you can use watch mode. Client \u00b6 For the client, you can run yarn watch:client . This will watch front-end files and compile them to the dist folder served by the express server. Also, yarn build:client will compile the client one time. Server \u00b6 For the server, you can run yarn watch:server to compile the server on every change, and yarn serve:watch to restart the server everytime it has been compiled. yarn build:server will compile the server one time.", "title": "Index"}, {"location": "cozy-banks/scripts/visualizer/#link-visualizer", "text": "This is an express server that serves a webpage meant to show links that are found between bills and banking operations by our matching algorithm. To launch the server, run the following commands: yarn build yarn serve Then you can go to http://localhost:3000. There you have a minimal interface where you can trigger a search for links between bills and operations.", "title": "Link visualizer"}, {"location": "cozy-banks/scripts/visualizer/#developing", "text": "To develop, you can use watch mode.", "title": "Developing"}, {"location": "cozy-banks/scripts/visualizer/#client", "text": "For the client, you can run yarn watch:client . This will watch front-end files and compile them to the dist folder served by the express server. Also, yarn build:client will compile the client one time.", "title": "Client"}, {"location": "cozy-banks/scripts/visualizer/#server", "text": "For the server, you can run yarn watch:server to compile the server on every change, and yarn serve:watch to restart the server everytime it has been compiled. yarn build:server will compile the server one time.", "title": "Server"}, {"location": "cozy-banks/src/components/DisplayError/", "text": "< DisplayError error = { new Error ( 'Burrito does not have extra guacamole' ) } />", "title": "DisplayError"}, {"location": "cozy-banks/src/components/Select/", "text": "const Select = require ( './Select.jsx' ). default const options = [ { name : 'Burritos' , value : 'burritos' }, { name : 'Lasagnes' , value : 'lasagnes' }, { name : 'G\u00e2teau au chocolat' , value : 'gateau' } ] const log = function ( selectName , selectValue ) { console . log ( selectName , selectValue ) }; < Select name = 'nourriture' value = 'burritos' options = { options } onChange = { log } />", "title": "Select"}, {"location": "cozy-banks/src/components/Switch/", "text": "
", "title": "Switch"}, {"location": "cozy-banks/src/components/Chart/LineChart/", "text": "< LineChart width = { 300 } height = { 150 } data = {[ { x : 0 , y : 0 }, { x : 1 , y : 2 }, { x : 2 , y : 4 }, { x : 3 , y : 6 } ]} margin = {{ top : 0 , bottom : 20 , left : 10 , right : 10 }} showAxis /> const d3 = require ( 'd3' ); < LineChart width = { 300 } height = { 150 } data = {[ { x : new Date ( 2018 , 7 , 3 ), y : 0 }, { x : new Date ( 2018 , 7 , 2 ), y : 2 }, { x : new Date ( 2018 , 7 , 1 ), y : 4 }, { x : new Date ( 2018 , 6 , 31 ), y : 6 } ]} margin = {{ top : 0 , bottom : 20 , left : 10 , right : 10 }} nbTicks = { 2 } tickFormat = { d3 . timeFormat ( '%x' )} xScale = { d3 . scaleTime } showAxis /> const d3 = require ( 'd3' ); < LineChart width = { 300 } height = { 150 } data = {[ { x : new Date ( 2018 , 7 , 3 ), y : 0 }, { x : new Date ( 2018 , 7 , 2 ), y : 2 }, { x : new Date ( 2018 , 7 , 1 ), y : 4 }, { x : new Date ( 2018 , 6 , 31 ), y : 6 } ]} margin = {{ top : 0 , bottom : 20 , left : 10 , right : 10 }} nbTicks = { 2 } tickFormat = { d3 . timeFormat ( '%x' )} xScale = { d3 . scaleTime } gradient = {{ '0%' : 'steelblue' , '100%' : 'white' }} showAxis />", "title": "LineChart"}, {"location": "cozy-banks/src/components/KonnectorChip/readme/", "text": "
", "title": "Readme"}, {"location": "cozy-banks/src/components/Loading/Loading/", "text": "< Loading />", "title": "Loading"}, {"location": "cozy-banks/src/components/Select/Readme/", "text": "const Select = require('react-select').default const handleChangeMonth = value => { setState({ value }) }; ", "title": "Readme"}, {"location": "cozy-banks/src/components/SelectDates/Readme/", "text": "const SelectDates = require ( './SelectDates' ) . default ; initialState = { value : undefined } ; < SelectDates periods = { [ '2018-08' , '2018-07' , '2018-06' , '2017-05' ] } value = { state.value } onChange = { value => setState({ value } ) } show12months />", "title": "Readme"}, {"location": "cozy-banks/src/components/SharingIcon/SharingIcon/", "text": "< div > < SharingIcon to = 'Richard Stallman' />< br /> < SharingIcon from = 'Rob Pike' />< br /> < SharingIcon from = 'Ken Thompson' /> With text beside div >", "title": "SharingIcon"}, {"location": "cozy-banks/src/components/Table/Readme/", "text": "const col1 = { 'flex-basis' : '35%' , 'max-width' : '35%' }; const col2 = { 'flex-basis' : '35%' , 'max-width' : '35%' }; const col3 = { 'flex-basis' : '30%' , 'max-width' : '30%' }; < Table > < thead > < tr > < th style = { col1 }> Pizzas th > < th style = { col2 }> Burritos th > < th style = { col3 }> Shawarma th > tr > thead > < tbody > < tr > < td style = { col1 }> 1 td > < td style = { col2 }> 2 td > < td style = { col3 }> 3 td > tr > < tr > < td style = { col1 }> 4 td > < td style = { col2 }> 5 td > < td style = { col3 }> 6 td > tr > tbody > Table >", "title": "Readme"}, {"location": "cozy-banks/src/ducks/balance/AccountRow/", "text": "", "title": "AccountRow"}, {"location": "cozy-banks/src/ducks/balance/History/", "text": "const data = require ( '../../../test/fixtures/unit-tests.json' ); < History accounts = { data [ 'io.cozy.bank.accounts' ]} chartProps = {{ data : [ { x : new Date ( 2018 , 7 , 3 ), y : 0 }, { x : new Date ( 2018 , 7 , 2 ), y : 2 }, { x : new Date ( 2018 , 7 , 1 ), y : 4 }, { x : new Date ( 2018 , 6 , 31 ), y : 6 } ], width : '100%' }} />", "title": "History"}, {"location": "cozy-banks/src/ducks/filters/Readme/", "text": "", "title": "Readme"}, {"location": "cozy-banks/src/targets/services/", "text": "See docs/service.md", "title": "Index"}, {"location": "cozy-banks/test/fixtures/", "text": "This fixtures contains bank operations linked to files. It will create a directory in your Cozy. Fichiers_de_d\u00e9mo/ \u251c\u2500\u2500 Free mobile \u2502 \u251c\u2500\u2500 Demo_cozy-freemobile_15082017.pdf \u2502 \u2514\u2500\u2500 Demo_cozy-freemobile_15092017.pdf \u251c\u2500\u2500 MAIF \u2502 \u2514\u2500\u2500 Demo_cozy-Appel_cotisation_MAIF_2017.pdf \u2514\u2500\u2500 Partag\u00e9 par Genevi\u00e8ve \u2514\u2500\u2500 Bouygues Telecom \u251c\u2500\u2500 Demo_cozy-Bouygues_Telecom_30072017.pdf \u2514\u2500\u2500 Demo_cozy-Bouygues_Telecom_30082017.pdf Usage \u00b6 ACH import demo.json helpers / index . js Other fixtures \u00b6 The reference file is demo.json . Other files should follow it. fixtures-l.json and fixtures-m.json are there if you want to test performance issue https://github.com/cozy/cozy-banks/blob/master/docs/perfs.md There are also more focused files that can be used to test specific usecases. See: Matching service Notifications service", "title": "Index"}, {"location": "cozy-banks/test/fixtures/#usage", "text": "ACH import demo.json helpers / index . js", "title": "Usage"}, {"location": "cozy-banks/test/fixtures/#other-fixtures", "text": "The reference file is demo.json . Other files should follow it. fixtures-l.json and fixtures-m.json are there if you want to test performance issue https://github.com/cozy/cozy-banks/blob/master/docs/perfs.md There are also more focused files that can be used to test specific usecases. See: Matching service Notifications service", "title": "Other fixtures"}, {"location": "cozy-banks/test/fixtures/matching-service/", "text": "Fixtures matching service \u00b6 Theses fixtures are useful to test the bills matching service. They cover the following cases. Classic matching \u00b6 Inject bill-generic.json and operation-generic.json . The service should run in the next 3 minutes (in you didn\u2019t customized the debounce time in manifest.webapp ). After that, if everything went well, you must have a link between the operation and the bill from the fixtures (ie. the operation has a bills array containing the bill ID). Health reimbursement \u00b6 Inject bill-reimbursement.json and operation-reimbursement.json . The service should run in the next 3 minutes (in you didn\u2019t customized the debounce time in manifest.webapp ). After that, if everything went well, you must have a link between the operation Visite chez le m\u00e9decin and the bill from the fixtures (ie. the operation has a reimbursement array containing the bill ID).", "title": "Fixtures matching service"}, {"location": "cozy-banks/test/fixtures/matching-service/#fixtures-matching-service", "text": "Theses fixtures are useful to test the bills matching service. They cover the following cases.", "title": "Fixtures matching service"}, {"location": "cozy-banks/test/fixtures/matching-service/#classic-matching", "text": "Inject bill-generic.json and operation-generic.json . The service should run in the next 3 minutes (in you didn\u2019t customized the debounce time in manifest.webapp ). After that, if everything went well, you must have a link between the operation and the bill from the fixtures (ie. the operation has a bills array containing the bill ID).", "title": "Classic matching"}, {"location": "cozy-banks/test/fixtures/matching-service/#health-reimbursement", "text": "Inject bill-reimbursement.json and operation-reimbursement.json . The service should run in the next 3 minutes (in you didn\u2019t customized the debounce time in manifest.webapp ). After that, if everything went well, you must have a link between the operation Visite chez le m\u00e9decin and the bill from the fixtures (ie. the operation has a reimbursement array containing the bill ID).", "title": "Health reimbursement"}, {"location": "cozy-banks/test/fixtures/notifications-service/", "text": "Fixtures notifications service \u00b6 Theses fixtures are useful to test the notifications service. They trigger all notifications types. Just make sure that you have enabled the types you want to test (check directly in Banks\u2019 settings page, or in the io.cozy.bank.settings database).", "title": "Fixtures notifications service"}, {"location": "cozy-banks/test/fixtures/notifications-service/#fixtures-notifications-service", "text": "Theses fixtures are useful to test the notifications service. They trigger all notifications types. Just make sure that you have enabled the types you want to test (check directly in Banks\u2019 settings page, or in the io.cozy.bank.settings database).", "title": "Fixtures notifications service"}, {"location": "cozy-client/architecture/", "text": "Cozy-client Architecture \u00b6 This is an overview of the cozy-client architecture: To explain the architecture, we will see how a request for data flows through cozy-client through links and finally how the data that has been fetched is stored in the redux store. Cozy-client Architecture Query definitions Links Store How does it works? Focus on receiveMutationResult : Query definitions \u00b6 To query data, we create a query definition : an object describing what documents to fetch. { doctype: \"io.cozy.todos\", selector: { \"finished\": true } } It is typically created via the helper Q that provides a fluid interface to create a Query Definition . const qdef = Q ( 'io.cozy.todos' ). where ({ finished : true }) Then we need to execute this query, fetch the data, and storing it. await client . query ( qdef ) Links \u00b6 When executed, Query definitions are passed down to Links . Links accept query definitions and can choose either to return a response or to pass the query definition down to the next link. \u2139\ufe0f This is how offline support is implemented: on mobile, a PouchLink (we use PouchDB under the hood) is added as a link to cozy-client, before the default StackLink. The PouchLink can decide: either to pass down the query definition to the next link (if the PouchLink has not been synchronized for example), or to respond to the request by communicating directly with PouchDB. At the moment there are only two links: StackLink : fetches data over HTTP by communicating to the Cozy\u2019s Stack via the StackClient. PouchLink : fetches data from a local PouchDB. Useful to have offline-ready applications. Store \u00b6 When links have responded with data, the data is stored inside the redux store that is internal to cozy-client. This redux store brings observability to cozy-client, and allows for connection of UI components to the data. \u2139\ufe0f You do not need to use Redux in your application to use cozy-client. \u2139\ufe0f You can connect your own store to cozy-client. It is useful for more advanced techniques where you create selectors directly on the data of cozy-client. The redux store is composed of two collections: documents and queries : documents stores the data indexed by doctype then _id queries store information for each query that has been done by cozy-client. ids of the documents that match the query whether the server has more documents that can be fetched (useful for pagination) whether the query is being loaded. { documents : { 'io.cozy.todos' : { 'todo-id-1' : { finished : true , label : \"Add architecture document for cozy-client\" } } }, queries : { finishedTodos : { data : [ 'todo-id-1' ] } } } \u26a0\ufe0f If queries are not named, a name is automatically generated, but this means that the queries collection can grow indefinitely. This is why you are encouraged to name your queries : client.query(qdef, { as: 'finishedTodos'}) . See these naming rules that are followed at Cozy. \u2139\ufe0f See the react integration for more insight about the glue between the redux store and the UI. React example \u00b6 Let\u2019s take a simple React example to demonstrate the connection of UI components to the data: const { data , fetchStatus } = useQuery ( Q ( 'io.cozy.todos' ), { 'as' : 'todoslist' }) if ( fetchStatus === 'loading' ) { return < Spinner /> } if ( fetchStatus === 'loaded' ) { return < TodoLists todos = { data } /> } if ( fetchStatus === 'failed' ) { return < Error /> } This way, a spinner will be displayed during the time the query is actually run. Once the query is done, data for this query is available and can be displayed. On this example, any data change on the io.cozy.todos doctype will be handled by cozy-client and reflected in the data array returned by useQuery . Thus, the app is reactive to any data change, with no hassle for the developer. See the auto query update mechanism for more insights about this mechanism. Queries \u00b6 Here, we describe what happens internally when a query is called from an app. First, it is important to understand that each query is stored in the store, in a queries associative array. Each query has a unique id, a set of metadata, and the list of retrieved document ids. For example: { query1 : { definition : { ... }, fetchStatus : \"loaded\" , lastFetch : 1716989816939 , lastUpdate : 1716989816939 , hasMore : false , count : 2 , bookmark : \"xyz\" , data : [ \"docId1\" , \"docId2\" ] // confusingly named `data`, but only stores ids } } Fetch status \u00b6 An important attribute used for the query lifecycle is the fetchStatus . It can take the following values: - pending : the query is about to be run for the first time. - loading : the query is currently running and might return results. From a UX perspective, it is often used by apps to display a spinner. - loaded : the query had been run and returned results. - failed : the last query execution failed. When a query is called for the first time, it is first initialized in the queries collection in the store, with the pending status. If the query already exists in the store, its status is checked to ensure that it is not already in a loading state. If it the case, a de-duplication mechanism is used to return the stored existing query. See the PR for more details. Then, the query is \u201cloaded\u201d, making its status on loading . Then, the query status is set on loading and the query actually run. When results are retrieved from the database, the status is set to loaded and some additional information are saved in the query store, such as lastFetch and lastUpdate . If any new data is retrieved by the query, all the documents ids retrieved by the query are then stored in the data array. Likewise, the documents collection is updated as well with the full documents content. Auto query update \u00b6 Since there is a link between queries and documents through the ids list in each query object, we need to be able to deal with changes occuring in the documents collection, i.e. when documents are added or deleted. For this, cozy-client has a mechanism called \u201cquery updater\u201d: each time a query is run, all the queries in the store are re-evaluated directly in the store. That means that for each query, we take its definition, convert it into a mango predicate (see here for details), and run it against the store\u2019s document collection. For each query result, we check if there is any change in the known ids list, and update it accordingly. Thanks to this, we ensure that all the queries are always up-to-date, and apps can be effectively rendered thanks to the react integration . Fetch policy and query naming \u00b6 The fetch policy is a useful mechanism to prevent excessive fetching. It is optionnaly defined for each query, to specify a minimum time between 2 actual fetches. It means that after a query is run, if it is called again within this time, it will not be executed. Here is an example to demonstrate how it works: const queryDef = Q ( 'io.cozy.todos' ). where ({ checked : true }) const queryOptions = { as : 'io.cozy.todos/checked/true' , // query unique name, to find it in the store fetchPolicy : CozyClient . fetchPolicies . olderThan ( 10 * 1000 ) // fetch policy, for 10 seconds } // First query let { data : result } = await client . query ( queryDef , queryOptions ) // result is filled // Second query, within the fetch policy time interval setTimeout ( async () => { { data : result } = await client . query ( queryDef , queryOptions ) // result is null }, 5000 ) // Third query, after the fetch policy time interval setTimeout ( async () => { { data : result } = await client . query ( queryDef , queryOptions ) // result is filled }, 10000 ) If the query had been run before the 10 seconds, an early return will happen and nothing will be updated in the store. \ud83d\udca1 In this example, we do not benefit from the React integration like demonstrated in this example with useQuery . When using it, the data is returned even though the fetch policy applies, by taking it directly from the store, to ensure the component is correctly rendered. \ud83d\udca1 In a React context, thanks to the auto-query updater, the data will not be stale if there is a data change in the app: indeed, any change on the documents will trigger the in-memory re-evaluation of the query and a render on the app if something is different. \u2139\ufe0f The as option is used to name the query, which is always a good idea to ensure that it has a unique name. When it\u2019s not specified, a random id is generated, resulting in potential query duplication in the store. Likewise, one must be very careful to prevent queries with the same name, as it would mixup results in the store. Note that you can easily view each query using Devtools to identify duplicates and follow the guidelines for the naming . Complete query flow \u00b6 --- title: Query with cozy-client --- sequenceDiagram participant App as App participant CC as cozy-client participant Store as Store participant Backend as Backend App->>CC: Query documents CC->>Store: Check query alt Query does not exist CC->>Store: Init query Store->>Store: Add query to collection else Query exists CC->>CC: Check fetch policy CC->>CC: Check loading status end CC->>Store: Load query Store->>Store: Update query status CC->>Backend: Execute query Backend->>CC: Data CC->>Store: Data Store->>Store: Update query status Store->>Store: Update data CC->>App: Results Store->>Store: Auto-update queries Persisted store and background fetching stategy \u00b6 An app can decide to persist its store in localstorage. See here for an example. When doing so, the app loads the store when it starts and benefit from the instant available cached data. But, the data could have significantly evolved between the last store save and the start, making the documents potentially stale. Hopefully, since the fetch policy is probably expired, queries will be run again, retrieving fresh data. Unfortunately, this might cause an immediate spinning display on the app when it starts, even though there is available data thanks to the persisted store. To solve this, a backgroundFetching option can be set, at the query level, or at the store level (enabled for all queries). When the query is loaded, it simply keeps the query status in loaded state (rather than setting a loading state) and set a new isFetching attribute, stored in the query. Thanks to this, the app can adapt its display to avoid the \u201cspinning effect\u201d, and might inform the user that data is being updated in the background, without refreshing the whole app. See this PR for more insights. Here is a simplified execution sequence with or without background fetching: --- title: Background fetching --- sequenceDiagram participant App as App participant CC as cozy-client participant Store as Store participant Backend as Backend App->>CC: Query documents CC->>Store: Load query alt Without background fetching Store->>Store: update query status Store->>App: Loading query status App->>App: Spinner else With background fetching Store->>Store: no change on query status Store->>App: isFetching status App->>App: Display persisted data end CC->>Backend: Execute query Backend->>CC: New data CC->>Store: Update store CC->>App: New data App->>App: Refresh display Updates \u00b6 Here, we detail what happens when a document is updated, i.e. a mutation happens, typically after a client.save . If the document _id does not exist in the store\u2019s documents collection, i.e. after the a creation, it is simply added. If it already exists, the document content is updated in this collection, after the backend response. Furthermore, just like with the queries, any mutation triggers the auto query updater , that can result in adding or removing document ids. Thanks to it, the app is guaranteed to have the up-to-date documents, returned from the documents collection. \u26a0\ufe0f As already mentioned, when a mutated document already exists in the store throught its _id , it is updated with the new content. However, this update never removes existing fields, it only merges or adds new fields. This is typically useful when two queries retrieve the same document, but not with all the fields. Let us illustrate with this example: const Q1 = { definition : Q ( 'io.cozy.todos' ). getById ( 'my-todo' ), options : { as : 'io.cozy.todos/my-todo' , fetchPolicy : lessThan30s }} const Q2 = { definition : Q ( 'io.cozy.todos' ). getById ( 'my-todo' ). select ([ 'label' ]), options : { as : 'io.cozy.todos/my-todo/withLabel' }} await client . query ( Q1 ) // returns { _id: 'my-todo', _type: 'io.cozy.todos', label: 'TODOTODO' }, from the database await client . query ( Q2 ) // returns { label: 'TODOTODO' }, from the database await client . query ( Q1 ) // returns { _id: 'my-todo', _type: 'io.cozy.todos', label: 'TODOTODO' }, from the store Q1 retrieves the full content of \u2018my-todo\u2019 while Q2 only retrieves its label. When Q2 is run, \u2018my-todo\u2019 already exists in the store, as Q1 was previsouly run. However, the fields retrieved by Q1 for \u2018my-todos\u2019 but absent from Q2 are not lost. This way, when Q1 is run again, the results fetched from the store (thanks to the fetch policy) will include all the fields. \u26a0\ufe0f The problem is when some fields are removed from a document: the store will not reflect this change and result in stale data. To avoid this side-effect, one could set an attribute to undefined instead of removing it, as a workaround. In-memory queries evaluation \u00b6 Each time a change occurs in the store\u2019s documents collection, either through a query or an update, all the stored queries are dynamically re-evaluated. As we do not want to request the actual database each time, we do the evaluation directly from the store, in memory. To achieve this, we need to evaluate queries the same way it would have been done on the database side. Our query system relies on mango, a mongo-like query system supported by CouchDB, the Cozy database. We rely on sift.js for the in-memory query evaluation. This library is able to take as input a mongo query definition and transform it into a javascript predicate. Then, all the queries are evaluated on the stores\u2019s documents , and efficiently updated accordingly to the results. \ud83d\udca1 If you want to know more about our query system and syntax, please check this documentation . \u26a0\ufe0f Please not that there is not a perfect matching between mango operators and sift, see this issue for instance.", "title": "Architecture"}, {"location": "cozy-client/architecture/#cozy-client-architecture", "text": "This is an overview of the cozy-client architecture: To explain the architecture, we will see how a request for data flows through cozy-client through links and finally how the data that has been fetched is stored in the redux store. Cozy-client Architecture Query definitions Links Store How does it works? Focus on receiveMutationResult :", "title": "Cozy-client Architecture"}, {"location": "cozy-client/architecture/#query-definitions", "text": "To query data, we create a query definition : an object describing what documents to fetch. { doctype: \"io.cozy.todos\", selector: { \"finished\": true } } It is typically created via the helper Q that provides a fluid interface to create a Query Definition . const qdef = Q ( 'io.cozy.todos' ). where ({ finished : true }) Then we need to execute this query, fetch the data, and storing it. await client . query ( qdef )", "title": "Query definitions"}, {"location": "cozy-client/architecture/#links", "text": "When executed, Query definitions are passed down to Links . Links accept query definitions and can choose either to return a response or to pass the query definition down to the next link. \u2139\ufe0f This is how offline support is implemented: on mobile, a PouchLink (we use PouchDB under the hood) is added as a link to cozy-client, before the default StackLink. The PouchLink can decide: either to pass down the query definition to the next link (if the PouchLink has not been synchronized for example), or to respond to the request by communicating directly with PouchDB. At the moment there are only two links: StackLink : fetches data over HTTP by communicating to the Cozy\u2019s Stack via the StackClient. PouchLink : fetches data from a local PouchDB. Useful to have offline-ready applications.", "title": "Links"}, {"location": "cozy-client/architecture/#store", "text": "When links have responded with data, the data is stored inside the redux store that is internal to cozy-client. This redux store brings observability to cozy-client, and allows for connection of UI components to the data. \u2139\ufe0f You do not need to use Redux in your application to use cozy-client. \u2139\ufe0f You can connect your own store to cozy-client. It is useful for more advanced techniques where you create selectors directly on the data of cozy-client. The redux store is composed of two collections: documents and queries : documents stores the data indexed by doctype then _id queries store information for each query that has been done by cozy-client. ids of the documents that match the query whether the server has more documents that can be fetched (useful for pagination) whether the query is being loaded. { documents : { 'io.cozy.todos' : { 'todo-id-1' : { finished : true , label : \"Add architecture document for cozy-client\" } } }, queries : { finishedTodos : { data : [ 'todo-id-1' ] } } } \u26a0\ufe0f If queries are not named, a name is automatically generated, but this means that the queries collection can grow indefinitely. This is why you are encouraged to name your queries : client.query(qdef, { as: 'finishedTodos'}) . See these naming rules that are followed at Cozy. \u2139\ufe0f See the react integration for more insight about the glue between the redux store and the UI.", "title": "Store"}, {"location": "cozy-client/architecture/#react-example", "text": "Let\u2019s take a simple React example to demonstrate the connection of UI components to the data: const { data , fetchStatus } = useQuery ( Q ( 'io.cozy.todos' ), { 'as' : 'todoslist' }) if ( fetchStatus === 'loading' ) { return < Spinner /> } if ( fetchStatus === 'loaded' ) { return < TodoLists todos = { data } /> } if ( fetchStatus === 'failed' ) { return < Error /> } This way, a spinner will be displayed during the time the query is actually run. Once the query is done, data for this query is available and can be displayed. On this example, any data change on the io.cozy.todos doctype will be handled by cozy-client and reflected in the data array returned by useQuery . Thus, the app is reactive to any data change, with no hassle for the developer. See the auto query update mechanism for more insights about this mechanism.", "title": "React example"}, {"location": "cozy-client/architecture/#queries", "text": "Here, we describe what happens internally when a query is called from an app. First, it is important to understand that each query is stored in the store, in a queries associative array. Each query has a unique id, a set of metadata, and the list of retrieved document ids. For example: { query1 : { definition : { ... }, fetchStatus : \"loaded\" , lastFetch : 1716989816939 , lastUpdate : 1716989816939 , hasMore : false , count : 2 , bookmark : \"xyz\" , data : [ \"docId1\" , \"docId2\" ] // confusingly named `data`, but only stores ids } }", "title": "Queries"}, {"location": "cozy-client/architecture/#fetch-status", "text": "An important attribute used for the query lifecycle is the fetchStatus . It can take the following values: - pending : the query is about to be run for the first time. - loading : the query is currently running and might return results. From a UX perspective, it is often used by apps to display a spinner. - loaded : the query had been run and returned results. - failed : the last query execution failed. When a query is called for the first time, it is first initialized in the queries collection in the store, with the pending status. If the query already exists in the store, its status is checked to ensure that it is not already in a loading state. If it the case, a de-duplication mechanism is used to return the stored existing query. See the PR for more details. Then, the query is \u201cloaded\u201d, making its status on loading . Then, the query status is set on loading and the query actually run. When results are retrieved from the database, the status is set to loaded and some additional information are saved in the query store, such as lastFetch and lastUpdate . If any new data is retrieved by the query, all the documents ids retrieved by the query are then stored in the data array. Likewise, the documents collection is updated as well with the full documents content.", "title": "Fetch status"}, {"location": "cozy-client/architecture/#auto-query-update", "text": "Since there is a link between queries and documents through the ids list in each query object, we need to be able to deal with changes occuring in the documents collection, i.e. when documents are added or deleted. For this, cozy-client has a mechanism called \u201cquery updater\u201d: each time a query is run, all the queries in the store are re-evaluated directly in the store. That means that for each query, we take its definition, convert it into a mango predicate (see here for details), and run it against the store\u2019s document collection. For each query result, we check if there is any change in the known ids list, and update it accordingly. Thanks to this, we ensure that all the queries are always up-to-date, and apps can be effectively rendered thanks to the react integration .", "title": "Auto query update"}, {"location": "cozy-client/architecture/#fetch-policy-and-query-naming", "text": "The fetch policy is a useful mechanism to prevent excessive fetching. It is optionnaly defined for each query, to specify a minimum time between 2 actual fetches. It means that after a query is run, if it is called again within this time, it will not be executed. Here is an example to demonstrate how it works: const queryDef = Q ( 'io.cozy.todos' ). where ({ checked : true }) const queryOptions = { as : 'io.cozy.todos/checked/true' , // query unique name, to find it in the store fetchPolicy : CozyClient . fetchPolicies . olderThan ( 10 * 1000 ) // fetch policy, for 10 seconds } // First query let { data : result } = await client . query ( queryDef , queryOptions ) // result is filled // Second query, within the fetch policy time interval setTimeout ( async () => { { data : result } = await client . query ( queryDef , queryOptions ) // result is null }, 5000 ) // Third query, after the fetch policy time interval setTimeout ( async () => { { data : result } = await client . query ( queryDef , queryOptions ) // result is filled }, 10000 ) If the query had been run before the 10 seconds, an early return will happen and nothing will be updated in the store. \ud83d\udca1 In this example, we do not benefit from the React integration like demonstrated in this example with useQuery . When using it, the data is returned even though the fetch policy applies, by taking it directly from the store, to ensure the component is correctly rendered. \ud83d\udca1 In a React context, thanks to the auto-query updater, the data will not be stale if there is a data change in the app: indeed, any change on the documents will trigger the in-memory re-evaluation of the query and a render on the app if something is different. \u2139\ufe0f The as option is used to name the query, which is always a good idea to ensure that it has a unique name. When it\u2019s not specified, a random id is generated, resulting in potential query duplication in the store. Likewise, one must be very careful to prevent queries with the same name, as it would mixup results in the store. Note that you can easily view each query using Devtools to identify duplicates and follow the guidelines for the naming .", "title": "Fetch policy and query naming"}, {"location": "cozy-client/architecture/#complete-query-flow", "text": "--- title: Query with cozy-client --- sequenceDiagram participant App as App participant CC as cozy-client participant Store as Store participant Backend as Backend App->>CC: Query documents CC->>Store: Check query alt Query does not exist CC->>Store: Init query Store->>Store: Add query to collection else Query exists CC->>CC: Check fetch policy CC->>CC: Check loading status end CC->>Store: Load query Store->>Store: Update query status CC->>Backend: Execute query Backend->>CC: Data CC->>Store: Data Store->>Store: Update query status Store->>Store: Update data CC->>App: Results Store->>Store: Auto-update queries", "title": "Complete query flow"}, {"location": "cozy-client/architecture/#persisted-store-and-background-fetching-stategy", "text": "An app can decide to persist its store in localstorage. See here for an example. When doing so, the app loads the store when it starts and benefit from the instant available cached data. But, the data could have significantly evolved between the last store save and the start, making the documents potentially stale. Hopefully, since the fetch policy is probably expired, queries will be run again, retrieving fresh data. Unfortunately, this might cause an immediate spinning display on the app when it starts, even though there is available data thanks to the persisted store. To solve this, a backgroundFetching option can be set, at the query level, or at the store level (enabled for all queries). When the query is loaded, it simply keeps the query status in loaded state (rather than setting a loading state) and set a new isFetching attribute, stored in the query. Thanks to this, the app can adapt its display to avoid the \u201cspinning effect\u201d, and might inform the user that data is being updated in the background, without refreshing the whole app. See this PR for more insights. Here is a simplified execution sequence with or without background fetching: --- title: Background fetching --- sequenceDiagram participant App as App participant CC as cozy-client participant Store as Store participant Backend as Backend App->>CC: Query documents CC->>Store: Load query alt Without background fetching Store->>Store: update query status Store->>App: Loading query status App->>App: Spinner else With background fetching Store->>Store: no change on query status Store->>App: isFetching status App->>App: Display persisted data end CC->>Backend: Execute query Backend->>CC: New data CC->>Store: Update store CC->>App: New data App->>App: Refresh display", "title": "Persisted store and background fetching stategy"}, {"location": "cozy-client/architecture/#updates", "text": "Here, we detail what happens when a document is updated, i.e. a mutation happens, typically after a client.save . If the document _id does not exist in the store\u2019s documents collection, i.e. after the a creation, it is simply added. If it already exists, the document content is updated in this collection, after the backend response. Furthermore, just like with the queries, any mutation triggers the auto query updater , that can result in adding or removing document ids. Thanks to it, the app is guaranteed to have the up-to-date documents, returned from the documents collection. \u26a0\ufe0f As already mentioned, when a mutated document already exists in the store throught its _id , it is updated with the new content. However, this update never removes existing fields, it only merges or adds new fields. This is typically useful when two queries retrieve the same document, but not with all the fields. Let us illustrate with this example: const Q1 = { definition : Q ( 'io.cozy.todos' ). getById ( 'my-todo' ), options : { as : 'io.cozy.todos/my-todo' , fetchPolicy : lessThan30s }} const Q2 = { definition : Q ( 'io.cozy.todos' ). getById ( 'my-todo' ). select ([ 'label' ]), options : { as : 'io.cozy.todos/my-todo/withLabel' }} await client . query ( Q1 ) // returns { _id: 'my-todo', _type: 'io.cozy.todos', label: 'TODOTODO' }, from the database await client . query ( Q2 ) // returns { label: 'TODOTODO' }, from the database await client . query ( Q1 ) // returns { _id: 'my-todo', _type: 'io.cozy.todos', label: 'TODOTODO' }, from the store Q1 retrieves the full content of \u2018my-todo\u2019 while Q2 only retrieves its label. When Q2 is run, \u2018my-todo\u2019 already exists in the store, as Q1 was previsouly run. However, the fields retrieved by Q1 for \u2018my-todos\u2019 but absent from Q2 are not lost. This way, when Q1 is run again, the results fetched from the store (thanks to the fetch policy) will include all the fields. \u26a0\ufe0f The problem is when some fields are removed from a document: the store will not reflect this change and result in stale data. To avoid this side-effect, one could set an attribute to undefined instead of removing it, as a workaround.", "title": "Updates"}, {"location": "cozy-client/architecture/#in-memory-queries-evaluation", "text": "Each time a change occurs in the store\u2019s documents collection, either through a query or an update, all the stored queries are dynamically re-evaluated. As we do not want to request the actual database each time, we do the evaluation directly from the store, in memory. To achieve this, we need to evaluate queries the same way it would have been done on the database side. Our query system relies on mango, a mongo-like query system supported by CouchDB, the Cozy database. We rely on sift.js for the in-memory query evaluation. This library is able to take as input a mongo query definition and transform it into a javascript predicate. Then, all the queries are evaluated on the stores\u2019s documents , and efficiently updated accordingly to the results. \ud83d\udca1 If you want to know more about our query system and syntax, please check this documentation . \u26a0\ufe0f Please not that there is not a perfect matching between mango operators and sift, see this issue for instance.", "title": "In-memory queries evaluation"}, {"location": "cozy-client/dev/", "text": "Publishing \u00b6 We use lerna for publishing. lerna publish These options are useful --scope to only care about one package lerna publish --scope cozy-client --npm-tag to change the default npm-tag (latest). Useful if you are testing and don\u2019t want your users to end up with your changes. $ lerna publish --scope cozy-client --npm-tag beta $ npm install cozy-client@beta \u26a0\ufe0f Even if you use an NPM tag, this creates a real version on NPM. If you want to create a beta version, change the version in the package.json of the package you are publishing and add for example beta.0 . This way, you do not take the space of the next version. --force-publish to force publication even if there were no changes lerna publish --scope cozy-client --force-publish cozy-client Linking \u00b6 Use yarn watch to watch on cozy-client side and yarn link on the app side. If you have a problem like \u201cReact is not found\u201d from cozy-client files, it may be because node is resolving the dependencies in cozy-client\u2019s node_modules , you may want to ln -s your app node_modules inside cozy-client\u2019s. $ ls code cozy-banks cozy-client $ cd cozy-client/packages/cozy-client $ rm -rf node_modules $ ln -s ~/code/cozy-banks/node_modules .", "title": "Dev"}, {"location": "cozy-client/dev/#publishing", "text": "We use lerna for publishing. lerna publish These options are useful --scope to only care about one package lerna publish --scope cozy-client --npm-tag to change the default npm-tag (latest). Useful if you are testing and don\u2019t want your users to end up with your changes. $ lerna publish --scope cozy-client --npm-tag beta $ npm install cozy-client@beta \u26a0\ufe0f Even if you use an NPM tag, this creates a real version on NPM. If you want to create a beta version, change the version in the package.json of the package you are publishing and add for example beta.0 . This way, you do not take the space of the next version. --force-publish to force publication even if there were no changes lerna publish --scope cozy-client --force-publish cozy-client", "title": "Publishing"}, {"location": "cozy-client/dev/#linking", "text": "Use yarn watch to watch on cozy-client side and yarn link on the app side. If you have a problem like \u201cReact is not found\u201d from cozy-client files, it may be because node is resolving the dependencies in cozy-client\u2019s node_modules , you may want to ln -s your app node_modules inside cozy-client\u2019s. $ ls code cozy-banks cozy-client $ cd cozy-client/packages/cozy-client $ rm -rf node_modules $ ln -s ~/code/cozy-banks/node_modules .", "title": "Linking"}, {"location": "cozy-client/devtools/", "text": "Devtools \u00b6 Cozy-client exposes a devtool that can be injected in an app for debug and better developer experience. It is inspired by the awesome devtools for react-query . To activate it, just run in your browser console: flag ( 'debug' , true ) Usage \u00b6 Before using the devtools, you need to install cozy-ui and react-inspector. yarn add cozy-ui # >= 48.0.0 yarn add react-inspector # >= 5.1.0 Next, you need to add it to your app, inside a CozyProvider. import CozyClient , { CozyProvider } from 'cozy-client' import CozyDevtools from 'cozy-client/dist/devtools' const App = () => { return < CozyProvider client = { client }> /* Your app is here */ { process . env . NODE_ENV !== 'production' ? < CozyDevtools /> : null } CozyProvider > } Panels \u00b6 The devtools is made of several \u201cpanels\u201d. There are default panels and the app can also inject its own adhoc panels. Queries \u00b6 Shows current queries inside cozy-client cache. Allows to see the data of the query. The execution time is also shown, and is very valuable to track down performance issues. It uses the execution statistics collected from CouchDB. Flags \u00b6 Shows all the current flags and allow to modify them. Libraries \u00b6 Show library versions based on the global VERSIONS variable that should be injected by the app. If it is defined, the panel will be blank. PouchLink \u00b6 If you use the PouchLink to synchronize your data to PouchDB, you can use the optional devtool PouchLink devtool panel. Since PouchDB is optional, it is not available by default and you need to explicitly tell the Devtools to display it. import PouchDevtools from 'cozy-client/dist/devtools/Pouch' () => < CozyDevTools panels = {{ id : 'pouch' , Component : PouchDevtools }} /> Ideas for next features \u00b6 Performance tips in query panels Show index related tips Show slow queries Show repeating queries Show queries downloading too much data Actions on queries Reset data inside query Refetch Set to error Delete from store If you have any other idea, please open an issue \ud83d\udc4d", "title": "Devtools"}, {"location": "cozy-client/devtools/#devtools", "text": "Cozy-client exposes a devtool that can be injected in an app for debug and better developer experience. It is inspired by the awesome devtools for react-query . To activate it, just run in your browser console: flag ( 'debug' , true )", "title": "Devtools"}, {"location": "cozy-client/devtools/#usage", "text": "Before using the devtools, you need to install cozy-ui and react-inspector. yarn add cozy-ui # >= 48.0.0 yarn add react-inspector # >= 5.1.0 Next, you need to add it to your app, inside a CozyProvider. import CozyClient , { CozyProvider } from 'cozy-client' import CozyDevtools from 'cozy-client/dist/devtools' const App = () => { return < CozyProvider client = { client }> /* Your app is here */ { process . env . NODE_ENV !== 'production' ? < CozyDevtools /> : null } CozyProvider > }", "title": "Usage"}, {"location": "cozy-client/devtools/#panels", "text": "The devtools is made of several \u201cpanels\u201d. There are default panels and the app can also inject its own adhoc panels.", "title": "Panels"}, {"location": "cozy-client/devtools/#queries", "text": "Shows current queries inside cozy-client cache. Allows to see the data of the query. The execution time is also shown, and is very valuable to track down performance issues. It uses the execution statistics collected from CouchDB.", "title": "Queries"}, {"location": "cozy-client/devtools/#flags", "text": "Shows all the current flags and allow to modify them.", "title": "Flags"}, {"location": "cozy-client/devtools/#libraries", "text": "Show library versions based on the global VERSIONS variable that should be injected by the app. If it is defined, the panel will be blank.", "title": "Libraries"}, {"location": "cozy-client/devtools/#pouchlink", "text": "If you use the PouchLink to synchronize your data to PouchDB, you can use the optional devtool PouchLink devtool panel. Since PouchDB is optional, it is not available by default and you need to explicitly tell the Devtools to display it. import PouchDevtools from 'cozy-client/dist/devtools/Pouch' () => < CozyDevTools panels = {{ id : 'pouch' , Component : PouchDevtools }} />", "title": "PouchLink"}, {"location": "cozy-client/devtools/#ideas-for-next-features", "text": "Performance tips in query panels Show index related tips Show slow queries Show repeating queries Show queries downloading too much data Actions on queries Reset data inside query Refetch Set to error Delete from store If you have any other idea, please open an issue \ud83d\udc4d", "title": "Ideas for next features"}, {"location": "cozy-client/entrypoints/", "text": "Different entrypoints for node/browser \u00b6 cozy-client has different entry points for browser and node (the node version does not export React components). It is implemented by using fields in package.json : browser field is the entrypoint for browsers main field is for node It causes an issue when writing tests that use React components from cozy-client ( Provider for example) since Jest does not support the browser field (contrary to webpack). \u26a0\ufe0f If you use react APIs, you should configure Jest with the browser option in your package.json or jest.config.js : \"jest\": { + \"browser\": true } There can be some problems since the browser field can clash with other node detection mechanism in other libraries (for example iconv-lite , see this PR ), an alternative is to use the moduleNameMapper option to point Jest to the correct entrypoint only for cozy-client . \"moduleNameMapper\": { \"^cozy-client$\": \"cozy-client/dist/index\" } This will force Jest to use the browser entry point. See this page for another alternative solution that overrides the jest resolver so that it supports the browser field.", "title": "Entrypoints"}, {"location": "cozy-client/entrypoints/#different-entrypoints-for-nodebrowser", "text": "cozy-client has different entry points for browser and node (the node version does not export React components). It is implemented by using fields in package.json : browser field is the entrypoint for browsers main field is for node It causes an issue when writing tests that use React components from cozy-client ( Provider for example) since Jest does not support the browser field (contrary to webpack). \u26a0\ufe0f If you use react APIs, you should configure Jest with the browser option in your package.json or jest.config.js : \"jest\": { + \"browser\": true } There can be some problems since the browser field can clash with other node detection mechanism in other libraries (for example iconv-lite , see this PR ), an alternative is to use the moduleNameMapper option to point Jest to the correct entrypoint only for cozy-client . \"moduleNameMapper\": { \"^cozy-client$\": \"cozy-client/dist/index\" } This will force Jest to use the browser entry point. See this page for another alternative solution that overrides the jest resolver so that it supports the browser field.", "title": "Different entrypoints for node/browser"}, {"location": "cozy-client/getting-started/", "text": "cozy-client is the sdk to interact with the cozy stack from a Javascript application. It aims at hiding all low level details and providing a simple high level API to fetch and cache documents. Main features: Authentication with a Cozy Querying and caching documents Transparent relations between couchdb documents Updates metadata in couch documents Offline: any data can be stored in a local PouchDB that is persisted across page loads React integration to connect your components to remote data Additional features with plugins: Realtime : Be notified when changes occur on the server side InterApp : Interact with other apps (example : file picking within your app) Flag : Use feature flags The following guide is an overview of a cozy-client integration to help you to get started. Install \u00b6 npm install --save cozy-client # or yarn add cozy-client \u26a0\ufe0f If you use Jest, you should also add a bit of configuration for imports to work properly, see this document for more information . Usage \u00b6 import CozyClient from 'cozy-client' const schema = { todos : { doctype : 'io.cozy.todos' , attributes : {...}, relationships : {...} } } const client = new CozyClient ({ uri : 'http://cozy.tools:8080' , schema , token : '...' }) Usually, the token and URI are provided by the stack on the DOM node
. When using this, you can instantiate a client with: const client = CozyClient.fromDOM({ schema }) // Note how token and uri are not passed, instead they are taken from the DOM If you need guidance to get the URI of your instance and/or the token, see the app tutorial . Every doctype accessed in cozy-client needs to be declared in the schema section of the options. See how to use the schema features Fetch data \u00b6 To fetch data, we first build a QueryDefinition with the Q helper: import { Q } from 'cozy-client' const allTodosQuery = Q ( 'io.cozy.todos' ) const singleTodoQuery = Q ( 'io.cozy.todos' ). getById ( '5fcbbf2cb171b1d5c3bc6df3d4affb32' ) QueryDefinition s describe which documents to be fetched from CouchDB. It uses a fluent interface: Q ( 'io.cozy.todos' ) . select ([ 'title' , 'checked' ]) . where ({ checked : false }) . include ([ 'dependencies' ]) . sortBy ([{ 'cozyMetadata.updatedAt' : 'desc' }]) . limitBy ( 20 ) select() lists the fields you want in the response (all by default) where() allows a mango selector include() will cause the query to fetch the related documents (see relationships ) sortBy sorts the documents by their updatedAt metadata in descending order limitBy limits the number of results to 20 By default, all fields in the where() are automatically indexed. You can turn off this behavior by specifying explicitly the list of fields to be indexed in indexFields() . Finally, client.query() will execute your query and return a promise with a data attribute containing the requested documents. import CozyClient from 'cozy-client' const client = new CozyClient ({ /*...*/ }) const { data } = await client . query ( Q ( 'io.cozy.todos' ). where ({ checked : false })) console . log ( data ) \u2705 Inside a React application, instead of using directly client.query , please use useQuery , or queryConnect to connect your components to cozy-client queries . \u2139\ufe0f Check out our dedicated query documentation to know more about querying with cozy-client and avoid common traps that can dramatically impact your app performances. \ud83d\ude80 Cozy-client\u2019s devtools allows to monitor your queries data and performance. Mutate the data \u00b6 An instance of CozyClient allows you to query and mutate (update) data, here\u2019s how it looks: import CozyClient from 'cozy-client' const client = new CozyClient ({ /*...*/ }) // create a new io.cozy.todo await client . save ({ _type : 'io.cozy.todos' , label : 'Buy bread' , checked : false }) const qdef = Q ( 'io.cozy.todos' ). where ({ checked : false }) const { data : todos } = await client . query ( qdef ) const doc = todos [ 0 ] // modify existing io.cozy.todo (will make an update if _rev is present inside the doc) await client . save ({... doc , checked : true }) save() will return a Promise with a data attribute containing the saved document. \u2139\ufe0f When mutating data, queries that depend on the mutated document(s) will automatically be refreshed: components that depend on these queries will be re-rendered. Mutate several documents in batch \u00b6 The saveAll() method can be used to save multiple documents in one request. const { data : updatedDocs } = await client . saveAll ([ { _type : 'io.cozy.todos' , checked : true , label : 'Buy milk' }, { _type : 'io.cozy.todos' , checked : false , label : 'Make dinner' } ])", "title": "Getting started"}, {"location": "cozy-client/getting-started/#install", "text": "npm install --save cozy-client # or yarn add cozy-client \u26a0\ufe0f If you use Jest, you should also add a bit of configuration for imports to work properly, see this document for more information .", "title": "Install"}, {"location": "cozy-client/getting-started/#usage", "text": "import CozyClient from 'cozy-client' const schema = { todos : { doctype : 'io.cozy.todos' , attributes : {...}, relationships : {...} } } const client = new CozyClient ({ uri : 'http://cozy.tools:8080' , schema , token : '...' }) Usually, the token and URI are provided by the stack on the DOM node
. When using this, you can instantiate a client with: const client = CozyClient.fromDOM({ schema }) // Note how token and uri are not passed, instead they are taken from the DOM If you need guidance to get the URI of your instance and/or the token, see the app tutorial . Every doctype accessed in cozy-client needs to be declared in the schema section of the options. See how to use the schema features", "title": "Usage"}, {"location": "cozy-client/getting-started/#fetch-data", "text": "To fetch data, we first build a QueryDefinition with the Q helper: import { Q } from 'cozy-client' const allTodosQuery = Q ( 'io.cozy.todos' ) const singleTodoQuery = Q ( 'io.cozy.todos' ). getById ( '5fcbbf2cb171b1d5c3bc6df3d4affb32' ) QueryDefinition s describe which documents to be fetched from CouchDB. It uses a fluent interface: Q ( 'io.cozy.todos' ) . select ([ 'title' , 'checked' ]) . where ({ checked : false }) . include ([ 'dependencies' ]) . sortBy ([{ 'cozyMetadata.updatedAt' : 'desc' }]) . limitBy ( 20 ) select() lists the fields you want in the response (all by default) where() allows a mango selector include() will cause the query to fetch the related documents (see relationships ) sortBy sorts the documents by their updatedAt metadata in descending order limitBy limits the number of results to 20 By default, all fields in the where() are automatically indexed. You can turn off this behavior by specifying explicitly the list of fields to be indexed in indexFields() . Finally, client.query() will execute your query and return a promise with a data attribute containing the requested documents. import CozyClient from 'cozy-client' const client = new CozyClient ({ /*...*/ }) const { data } = await client . query ( Q ( 'io.cozy.todos' ). where ({ checked : false })) console . log ( data ) \u2705 Inside a React application, instead of using directly client.query , please use useQuery , or queryConnect to connect your components to cozy-client queries . \u2139\ufe0f Check out our dedicated query documentation to know more about querying with cozy-client and avoid common traps that can dramatically impact your app performances. \ud83d\ude80 Cozy-client\u2019s devtools allows to monitor your queries data and performance.", "title": "Fetch data"}, {"location": "cozy-client/getting-started/#mutate-the-data", "text": "An instance of CozyClient allows you to query and mutate (update) data, here\u2019s how it looks: import CozyClient from 'cozy-client' const client = new CozyClient ({ /*...*/ }) // create a new io.cozy.todo await client . save ({ _type : 'io.cozy.todos' , label : 'Buy bread' , checked : false }) const qdef = Q ( 'io.cozy.todos' ). where ({ checked : false }) const { data : todos } = await client . query ( qdef ) const doc = todos [ 0 ] // modify existing io.cozy.todo (will make an update if _rev is present inside the doc) await client . save ({... doc , checked : true }) save() will return a Promise with a data attribute containing the saved document. \u2139\ufe0f When mutating data, queries that depend on the mutated document(s) will automatically be refreshed: components that depend on these queries will be re-rendered.", "title": "Mutate the data"}, {"location": "cozy-client/getting-started/#mutate-several-documents-in-batch", "text": "The saveAll() method can be used to save multiple documents in one request. const { data : updatedDocs } = await client . saveAll ([ { _type : 'io.cozy.todos' , checked : true , label : 'Buy milk' }, { _type : 'io.cozy.todos' , checked : false , label : 'Make dinner' } ])", "title": "Mutate several documents in batch"}, {"location": "cozy-client/hooks/", "text": "Embedded hooks \u00b6 In addition to our React Integration , Cozy Client comes with several hooks. useAppLinkWithStoreFallback : Returns the URL of an app if this app is installed. If not, returns the URL to the store to install it. useCapabilities : Returns the capabilities for an instance useFetchShortcut : Returns the data for a shortcut useClient : Returns client of actual context useFetchJSON : Hook to use the generic fetchJSON method. Returns object with the same keys { data, fetchStatus, error } as useQuery useQuery : Returns the queryState after fetching a queryDefinition useSettings : Query the cozy-app settings corresponding to the given slug Accessing and Mutating cozy-app settings with useSettings \u00b6 Sometimes cozy-apps need to access settings related data Those settings can be specific to the cozy-app, or global to the Cozy\u2019s instance In order to ease manipulating those settings we provide the hook useSettings This hook is based on useQuery and useMutation to provide the setting\u2019s values and a save method that allow to mutate the settings Additionally, the query and mutation object are provided in order to react to their corresponding states (fetch status, mutation status, etc) import { hasQueryBeenLoaded , useSettings } from 'cozy-client' function DefaultRedirectionSetting () { const [ inputValue , setInputValue ] = useState ( '' ) const { values , save , query , mutation } = useSettings ( 'instance' , // slug for acessing the global settings [ 'default_redirection' ], // setting names ) const handleChange = event => { setInputValue ( event . target . value ) } const handleBlur = () => { save ({ default_redirection : inputValue }) } useEffect (() => { setInputValue ( values . default_redirection ) }, [ values ]) return ( < div style = {{ display : 'flex' }}> < input type = \"text\" aria - label = \"Setting\" style = {{ marginRight : '1rem' }} value = { inputValue } onChange = { handleChange } onBlur = { handleBlur } disabled = { ! hasQueryBeenLoaded ( query )} /> { mutation . mutationStatus === 'loaded' ? '\u2713' : null } { mutation . mutationStatus === 'failed' ? '\u2717' : null } div > ) }", "title": "Hooks"}, {"location": "cozy-client/hooks/#embedded-hooks", "text": "In addition to our React Integration , Cozy Client comes with several hooks. useAppLinkWithStoreFallback : Returns the URL of an app if this app is installed. If not, returns the URL to the store to install it. useCapabilities : Returns the capabilities for an instance useFetchShortcut : Returns the data for a shortcut useClient : Returns client of actual context useFetchJSON : Hook to use the generic fetchJSON method. Returns object with the same keys { data, fetchStatus, error } as useQuery useQuery : Returns the queryState after fetching a queryDefinition useSettings : Query the cozy-app settings corresponding to the given slug", "title": "Embedded hooks"}, {"location": "cozy-client/hooks/#accessing-and-mutating-cozy-app-settings-with-usesettings", "text": "Sometimes cozy-apps need to access settings related data Those settings can be specific to the cozy-app, or global to the Cozy\u2019s instance In order to ease manipulating those settings we provide the hook useSettings This hook is based on useQuery and useMutation to provide the setting\u2019s values and a save method that allow to mutate the settings Additionally, the query and mutation object are provided in order to react to their corresponding states (fetch status, mutation status, etc) import { hasQueryBeenLoaded , useSettings } from 'cozy-client' function DefaultRedirectionSetting () { const [ inputValue , setInputValue ] = useState ( '' ) const { values , save , query , mutation } = useSettings ( 'instance' , // slug for acessing the global settings [ 'default_redirection' ], // setting names ) const handleChange = event => { setInputValue ( event . target . value ) } const handleBlur = () => { save ({ default_redirection : inputValue }) } useEffect (() => { setInputValue ( values . default_redirection ) }, [ values ]) return ( < div style = {{ display : 'flex' }}> < input type = \"text\" aria - label = \"Setting\" style = {{ marginRight : '1rem' }} value = { inputValue } onChange = { handleChange } onBlur = { handleBlur } disabled = { ! hasQueryBeenLoaded ( query )} /> { mutation . mutationStatus === 'loaded' ? '\u2713' : null } { mutation . mutationStatus === 'failed' ? '\u2717' : null } div > ) }", "title": "Accessing and Mutating cozy-app settings with useSettings"}, {"location": "cozy-client/link-authoring/", "text": "What is it ? Authoring a link What is it ? \u00b6 Cozy Link is a simple yet powerful way to describe how you want to get the result of a query. Think of it as a sort of \u201cmiddleware\u201d. Links are units that you can chain together to define how each query should be handled: this allows us to use different sources of data, or to control the request lifecycle in a way that makes sense for your app. The first link operates on an operation object and each subsequent link operates on the result of the previous link: In the chain example pictured above, the Dedup link would avoid re-fetching the same query, the PouchDB link would try to get the data from a local Pouch instance, and fallback to the Stack link, assisted by the Retry link that will try to fetch again the query in case of a network error. Authoring a link \u00b6 There are two ways of creating a new link. First, you can instantiate a CozyLink and pass a request handling function to its constructor: const logLink = new CozyLink (( operation , result , forward ) => { console . log ( JSON . stringify ( operation )) return forward ( operation , result ) }) Or you can subclass CozyLink : class LogLink extends CozyLink { request ( operation , result , forward ) { console . log ( JSON . stringify ( operation )) return forward ( operation , result ) } } At the core of a link is the request method. It takes the following arguments: - operation : the operation definition being passed through the link ; - result : the (maybe incomplete) result processed by the previous link ; - forward : (optional) specifies the next link in the chain of links. When the request method is called, the link has to return data back. Depending on where the link is in the chain, and its ability to provide the requested data, it will either use the forward callback to defer to the next link the task of providing (or completing) the data, or return back a result on its own.", "title": "Link authoring"}, {"location": "cozy-client/link-authoring/#what-is-it", "text": "Cozy Link is a simple yet powerful way to describe how you want to get the result of a query. Think of it as a sort of \u201cmiddleware\u201d. Links are units that you can chain together to define how each query should be handled: this allows us to use different sources of data, or to control the request lifecycle in a way that makes sense for your app. The first link operates on an operation object and each subsequent link operates on the result of the previous link: In the chain example pictured above, the Dedup link would avoid re-fetching the same query, the PouchDB link would try to get the data from a local Pouch instance, and fallback to the Stack link, assisted by the Retry link that will try to fetch again the query in case of a network error.", "title": "What is it ?"}, {"location": "cozy-client/link-authoring/#authoring-a-link", "text": "There are two ways of creating a new link. First, you can instantiate a CozyLink and pass a request handling function to its constructor: const logLink = new CozyLink (( operation , result , forward ) => { console . log ( JSON . stringify ( operation )) return forward ( operation , result ) }) Or you can subclass CozyLink : class LogLink extends CozyLink { request ( operation , result , forward ) { console . log ( JSON . stringify ( operation )) return forward ( operation , result ) } } At the core of a link is the request method. It takes the following arguments: - operation : the operation definition being passed through the link ; - result : the (maybe incomplete) result processed by the previous link ; - forward : (optional) specifies the next link in the chain of links. When the request method is called, the link has to return data back. Depending on where the link is in the chain, and its ability to provide the requested data, it will either use the forward callback to defer to the next link the task of providing (or completing) the data, or return back a result on its own.", "title": "Authoring a link"}, {"location": "cozy-client/logging/", "text": "How to activate logging ? \u00b6 Cozy-client libs use minilog for internal logging. If you need to see those logs, you need to tell minilog to show them, they are filtered by default. Each lib has a different namespace that can be enabled/disabled. For example if you want to allow cozy-pouch-link logs at debug level, you can do: // In your app , make sure to attach minilog to window for cozy - client to use it import minilog from 'minilog' window . minilog = minilog minilog . enable () // You can enable / disable loggers via minilog filters require ( 'minilog' ) . suggest . allow ( 'cozy-pouch-link' , 'debug' ) If you want to see everything : require('minilog').suggest.clear() More info on minilog docs .", "title": "Logging"}, {"location": "cozy-client/logging/#how-to-activate-logging", "text": "Cozy-client libs use minilog for internal logging. If you need to see those logs, you need to tell minilog to show them, they are filtered by default. Each lib has a different namespace that can be enabled/disabled. For example if you want to allow cozy-pouch-link logs at debug level, you can do: // In your app , make sure to attach minilog to window for cozy - client to use it import minilog from 'minilog' window . minilog = minilog minilog . enable () // You can enable / disable loggers via minilog filters require ( 'minilog' ) . suggest . allow ( 'cozy-pouch-link' , 'debug' ) If you want to see everything : require('minilog').suggest.clear() More info on minilog docs .", "title": "How to activate logging ?"}, {"location": "cozy-client/metadata/", "text": "Cozy documents have a cozyMetadata block with metadata about the document, like its schema version, its creation date, its source, etc. { \"_id\" : \"xxxx\" , \"cozyMetadata\" : { \"doctypeVersion\" : 4 , \"metadataVersion\" : 1 , \"createdAt\" : \"xxxxx\" , \"createdByApp\" : \"xxxx\" , \"createdByAppVersion\" : \"xxxx\" , \"updatedAt\" : \"xxxxx\" , \"updatedByApps\" : [ { \"slug\" : \"xxxxx\" , \"date\" : \"xxxxx\" , \"version\" : 3 } ], \"sourceAccount\" : \"xxxxx\" } } Options for cozy-client \u00b6 This cozyMetadata block is managed by the apps themselves. Cozy-Client is able to manage some parts of cozyMetadata automatically. For this it needs an appMetadata parameter with a few informations: slug : the slug of the app or konnector (will be used in createdByApp and updatedByApps ) version : version of the app (will be used in createdByAppVersion and updatedByApps ) when in a konnector, sourceAccount : the id of the io.cozy.accounts document that triggered the current execution (it will help to know which documents belong or are created by which account) when in a konnector, sourceAccountIdentifier : identifier unique to the account targetted by the konnector. It is the user login most of the time const client = new CozyClient({ appMetadata: { slug: 'banks', version: '1.27.1' } }) When you provide this information, cozy-client will automatically update metadata when it saves a document. For new documents \u00b6 Cozy-Client will set: metadataVersion : to the last version known to Cozy-Client. It\u2019s the version of the schema for the metadata block itself. doctypeVersion : if it\u2019s provided in the schema at Cozy-Client initialization slug : Slug of the app sourceAccount : : if it\u2019s provided in the appMetadata at initialization. Note it won\u2019t work for files (see below). creation date, app and version updated date, app and version const client = new CozyClient({ appMetadata: { slug: 'banks', version: '1.27.1' }, schema: { bankAccounts: { doctypeVersion: '1.0.0' } } }) If any of these fields already exists in the document you try to save, these values will override the defaults. This allows you to import a document with an existing history. For existing documents \u00b6 Cozy-Client will: Set the updated date Add your app and version in the updatedByApps list \u26a0\ufe0f These values will override any values that your document may already have. Specific case of io.cozy.files \u00b6 The io.cozy.files doctype is protected by cozy-stack, that restricts the attributes that can be saved by the client, including the cozyMetadata. This is the case for : * cozyMetadata.sourceAccount * cozyMetadata.sourceAccountIdentifier To save those attributes, you can pass them directly to the save method, like this: const client = new client() client.save({ _type: 'io.cozy.files', sourceAccount: '12ab3c', sourceAccountIdentifier: 'john@example.org', ... })", "title": "Metadata"}, {"location": "cozy-client/metadata/#options-for-cozy-client", "text": "This cozyMetadata block is managed by the apps themselves. Cozy-Client is able to manage some parts of cozyMetadata automatically. For this it needs an appMetadata parameter with a few informations: slug : the slug of the app or konnector (will be used in createdByApp and updatedByApps ) version : version of the app (will be used in createdByAppVersion and updatedByApps ) when in a konnector, sourceAccount : the id of the io.cozy.accounts document that triggered the current execution (it will help to know which documents belong or are created by which account) when in a konnector, sourceAccountIdentifier : identifier unique to the account targetted by the konnector. It is the user login most of the time const client = new CozyClient({ appMetadata: { slug: 'banks', version: '1.27.1' } }) When you provide this information, cozy-client will automatically update metadata when it saves a document.", "title": "Options for cozy-client"}, {"location": "cozy-client/metadata/#for-new-documents", "text": "Cozy-Client will set: metadataVersion : to the last version known to Cozy-Client. It\u2019s the version of the schema for the metadata block itself. doctypeVersion : if it\u2019s provided in the schema at Cozy-Client initialization slug : Slug of the app sourceAccount : : if it\u2019s provided in the appMetadata at initialization. Note it won\u2019t work for files (see below). creation date, app and version updated date, app and version const client = new CozyClient({ appMetadata: { slug: 'banks', version: '1.27.1' }, schema: { bankAccounts: { doctypeVersion: '1.0.0' } } }) If any of these fields already exists in the document you try to save, these values will override the defaults. This allows you to import a document with an existing history.", "title": "For new documents"}, {"location": "cozy-client/metadata/#for-existing-documents", "text": "Cozy-Client will: Set the updated date Add your app and version in the updatedByApps list \u26a0\ufe0f These values will override any values that your document may already have.", "title": "For existing documents"}, {"location": "cozy-client/metadata/#specific-case-of-iocozyfiles", "text": "The io.cozy.files doctype is protected by cozy-stack, that restricts the attributes that can be saved by the client, including the cozyMetadata. This is the case for : * cozyMetadata.sourceAccount * cozyMetadata.sourceAccountIdentifier To save those attributes, you can pass them directly to the save method, like this: const client = new client() client.save({ _type: 'io.cozy.files', sourceAccount: '12ab3c', sourceAccountIdentifier: 'john@example.org', ... })", "title": "Specific case of io.cozy.files"}, {"location": "cozy-client/mobile-guide/", "text": "Using CozyClient on a mobile app Configuration \ud83d\udee0 Starting the OAuth flow \ud83c\udfc4\u200d\u2642\ufe0f How to restore a previous token ? How to logout the client ? Support offline for some doctypes with cozy-pouch-link Using CozyClient on a mobile app \u00b6 Configuration \ud83d\udee0 \u00b6 On the web, the server pass the token and the domain to the page directly through template variables. This is not possible on mobile as there is no server to serve the page. CozyClient supports connecting to a Cozy via OAtuh. To get started, configure the OAuth settings when creating the client: import CozyClient from 'cozy-client' const client = new CozyClient ({ uri : 'http://cozy.tools:8080' , scope : [ 'io.cozy.mydoctype' ], oauth : { clientName : 'MyClient' , softwareID : 'MyAppId' , redirectURI : 'http://localhost' } }) scope is an array of permissions you require for your client oauth is a list of fields that identify your client for the user and the server. The complete list of field can be found here , although they should be camel-cased instead of snake-cased. Starting the OAuth flow \ud83c\udfc4\u200d\u2642\ufe0f \u00b6 Before you can start making requests to the server, you will need to get a token. cozy-client will provide a URL to a page where the user is shown what data you want to access, and asking for his or her permission. After the user accepts these permissions, he or she is redirected to the oauth.redirectURI that you declared earlier. You will then have to give this redirected URL back to cozy-client as it contains a code, that will be exchanged for the token. To get started, you call client.startOAuthFlow like this: import CozyClient from 'cozy-client' const client = new CozyClient ({ uri : 'http://cozy.tools:8080' , scope : [ 'io.cozy.mydoctype' ], oauth : { clientName : 'MyClient' , softwareID : 'MyAppId' , redirectURI : 'http://localhost' } }) client . startOAuthFlow ( openURL ) The openURL parameter is a callback. It will receive the URL to the page as a parameter, and it must return a Promise that resolves with the redirected URL. How exactly you do this depends on your environment \u2014 for a mobile app you may use a WebView, in a browser maybe a new tab\u2026 Here is an example that uses the browser\u2019s console and an experienced user: const openURL = url => { console . log ( 'Please visit the following URL, accept the permissions and copy the URL you are redirected to, then come back here. you have 10 seconds.' , url ) return new Promise ( resolve => { setTimeout ( async () => { const returnUrl = prompt ( 'Paste the new URL here.' ) resolve ( returnUrl ) }, 10000 ) }) } And that\u2019s it! After the promise is resolved, cozy-client finishes the OAuth flow and you can start using it. How to restore a previous token ? \u00b6 Nobody likes to enter passwords, and you don\u2019t want to make your user go through this whole process every time your app starts. In order to restore the client from a previous version, you need to give it a token and some extra information about itself. Both of these are returned by the openURL function, so you can store them wherever you see fit \u2014 in this example we\u2019ll use the localStorage API. import CozyClient from 'cozy-client' const client = new CozyClient ({ uri : 'http://cozy.tools:8080' , scope : [ 'io.cozy.mydoctype' ], oauth : { clientName : 'MyClient' , softwareID : 'MyAppId' , redirectURI : 'http://localhost' } }) const { token , infos } = client . startOAuthFlow ( openURL ) localStorage . setItem ( 'token' , token ) localStorage . setItem ( 'infos' , JSON . stringify ( infos )) Next time your app starts, you can pass these informations to the constructor. Here is a complete example of the OAuth client initilisation: const storedToken = localStorage . getItem ( 'token' ) || null const storedInfos = JSON . parse ( localStorage . getItem ( 'infos' )) || { clientName : 'MyClient' , softwareID : 'MyAppId' , redirectURI : 'http://localhost' } const client = new CozyClient ({ uri : 'http://cozy.tools:8080' , oauth : storedInfos , token : storedToken , scope : [ 'io.cozy.mydoctype' ] }); if ( ! storedToken ) { const { token , infos } = await client . startOAuthFlow ( openURL ) localStorage . setItem ( 'token' , token ) localStorage . setItem ( 'infos' , JSON . stringify ( infos )) } How to logout the client ? \u00b6 When a user logout, we would like remove all references on this instance and remove all user data. You can just use cozyClient.logout() . Support offline for some doctypes with cozy-pouch-link \u00b6 If you are already using cozy-client and the StackLink , you may want to go further and store some documents locally so you can retrieve them even while being offline. Currently, you have a code like this one : import CozyClient , { StackLink } from 'cozy-client' const stackLink = new StackLink () const client = new CozyClient ({ // ... links : [ stackLink ] }) To manage the offline aspect, we provide the cozy-pouch-link . First, let\u2019s install it : # using npm npm install cozy-pouch-link # using yarn yarn add cozy-pouch-link Then, we will create a new instance of this link and give it the list of doctypes that we want to access offline. We have to put the PouchLink first, so it is reached first when we query the link chain : import CozyClient , { StackLink } from 'cozy-client' import PouchLink from 'cozy-pouch-link' const stackLink = new StackLink () const offlineDoctypes = [ 'io.cozy.todos' ] const pouchLink = new PouchLink ({ doctypes : offlineDoctypes , initialSync : true // whether you want to trigger the synchronization on login or not }) const client = new CozyClient ({ // ... links : [ pouchLink , stackLink ] }) The PouchLink will create the PouchDB databases for all offline doctypes and synchronize them with the distant CouchDB. All doctypes that are not managed by the PouchLink will be passed to the next link in the chain (in the previous example, the StackLink ). Additionally, it is possible to replicate some doctypes only in a specific direction: const pouchLink = new PouchLink ({ doctypes : [ 'io.cozy.todos' , 'io.cozy.files' , 'io.cozy.localtype' ], doctypesReplicationOptions : { 'io.cozy.todos' : { strategy : 'sync' // default, replicate both ways }, 'io.cozy.files' : { strategy : 'fromRemote' // replicate changes from the remote locally, but don't push any changes }, 'io.cozy.localtype' : { strategy : 'toRemote' // push changes to remote, but don't replicate changes from it } } initialSync : true }) If you choose the fromRemote strategy, the cozy-client mutation will not be executed on the PouchLink but rather on the StackLink. Since making the first query can be long (PouchDB will create the index first), you can specify the queries you want to be \u201cwarmed up\u201d. It means that, those queries will be executed by CozyClient during the PouchLink\u2019s instanciation, but CozyClient will use PouchDB only if those queries have been resolved at least one time. const buildRecentQuery = () => ({ definition : () => Q ( 'io.cozy.files' ) . where ({ type : 'file' , trashed : false , updated_at : { $gt : null } }) options : { as : 'recent-view-query' , fetchPolicy : defaultFetchPolicy , } }) const pouchLink = new PouchLink ({ doctypes : [ 'io.cozy.todos' , 'io.cozy.files' , 'io.cozy.localtype' ], doctypesReplicationOptions : { 'io.cozy.files' : { warmupQueries : [ buildRecentQuery () ] } } initialSync : true })", "title": "Mobile guide"}, {"location": "cozy-client/mobile-guide/#using-cozyclient-on-a-mobile-app", "text": "", "title": "Using CozyClient on a mobile app"}, {"location": "cozy-client/mobile-guide/#configuration", "text": "On the web, the server pass the token and the domain to the page directly through template variables. This is not possible on mobile as there is no server to serve the page. CozyClient supports connecting to a Cozy via OAtuh. To get started, configure the OAuth settings when creating the client: import CozyClient from 'cozy-client' const client = new CozyClient ({ uri : 'http://cozy.tools:8080' , scope : [ 'io.cozy.mydoctype' ], oauth : { clientName : 'MyClient' , softwareID : 'MyAppId' , redirectURI : 'http://localhost' } }) scope is an array of permissions you require for your client oauth is a list of fields that identify your client for the user and the server. The complete list of field can be found here , although they should be camel-cased instead of snake-cased.", "title": "Configuration \ud83d\udee0"}, {"location": "cozy-client/mobile-guide/#starting-the-oauth-flow", "text": "Before you can start making requests to the server, you will need to get a token. cozy-client will provide a URL to a page where the user is shown what data you want to access, and asking for his or her permission. After the user accepts these permissions, he or she is redirected to the oauth.redirectURI that you declared earlier. You will then have to give this redirected URL back to cozy-client as it contains a code, that will be exchanged for the token. To get started, you call client.startOAuthFlow like this: import CozyClient from 'cozy-client' const client = new CozyClient ({ uri : 'http://cozy.tools:8080' , scope : [ 'io.cozy.mydoctype' ], oauth : { clientName : 'MyClient' , softwareID : 'MyAppId' , redirectURI : 'http://localhost' } }) client . startOAuthFlow ( openURL ) The openURL parameter is a callback. It will receive the URL to the page as a parameter, and it must return a Promise that resolves with the redirected URL. How exactly you do this depends on your environment \u2014 for a mobile app you may use a WebView, in a browser maybe a new tab\u2026 Here is an example that uses the browser\u2019s console and an experienced user: const openURL = url => { console . log ( 'Please visit the following URL, accept the permissions and copy the URL you are redirected to, then come back here. you have 10 seconds.' , url ) return new Promise ( resolve => { setTimeout ( async () => { const returnUrl = prompt ( 'Paste the new URL here.' ) resolve ( returnUrl ) }, 10000 ) }) } And that\u2019s it! After the promise is resolved, cozy-client finishes the OAuth flow and you can start using it.", "title": "Starting the OAuth flow \ud83c\udfc4\u200d\u2642\ufe0f"}, {"location": "cozy-client/mobile-guide/#how-to-restore-a-previous-token", "text": "Nobody likes to enter passwords, and you don\u2019t want to make your user go through this whole process every time your app starts. In order to restore the client from a previous version, you need to give it a token and some extra information about itself. Both of these are returned by the openURL function, so you can store them wherever you see fit \u2014 in this example we\u2019ll use the localStorage API. import CozyClient from 'cozy-client' const client = new CozyClient ({ uri : 'http://cozy.tools:8080' , scope : [ 'io.cozy.mydoctype' ], oauth : { clientName : 'MyClient' , softwareID : 'MyAppId' , redirectURI : 'http://localhost' } }) const { token , infos } = client . startOAuthFlow ( openURL ) localStorage . setItem ( 'token' , token ) localStorage . setItem ( 'infos' , JSON . stringify ( infos )) Next time your app starts, you can pass these informations to the constructor. Here is a complete example of the OAuth client initilisation: const storedToken = localStorage . getItem ( 'token' ) || null const storedInfos = JSON . parse ( localStorage . getItem ( 'infos' )) || { clientName : 'MyClient' , softwareID : 'MyAppId' , redirectURI : 'http://localhost' } const client = new CozyClient ({ uri : 'http://cozy.tools:8080' , oauth : storedInfos , token : storedToken , scope : [ 'io.cozy.mydoctype' ] }); if ( ! storedToken ) { const { token , infos } = await client . startOAuthFlow ( openURL ) localStorage . setItem ( 'token' , token ) localStorage . setItem ( 'infos' , JSON . stringify ( infos )) }", "title": "How to restore a previous token ?"}, {"location": "cozy-client/mobile-guide/#how-to-logout-the-client", "text": "When a user logout, we would like remove all references on this instance and remove all user data. You can just use cozyClient.logout() .", "title": "How to logout the client ?"}, {"location": "cozy-client/mobile-guide/#support-offline-for-some-doctypes-with-cozy-pouch-link", "text": "If you are already using cozy-client and the StackLink , you may want to go further and store some documents locally so you can retrieve them even while being offline. Currently, you have a code like this one : import CozyClient , { StackLink } from 'cozy-client' const stackLink = new StackLink () const client = new CozyClient ({ // ... links : [ stackLink ] }) To manage the offline aspect, we provide the cozy-pouch-link . First, let\u2019s install it : # using npm npm install cozy-pouch-link # using yarn yarn add cozy-pouch-link Then, we will create a new instance of this link and give it the list of doctypes that we want to access offline. We have to put the PouchLink first, so it is reached first when we query the link chain : import CozyClient , { StackLink } from 'cozy-client' import PouchLink from 'cozy-pouch-link' const stackLink = new StackLink () const offlineDoctypes = [ 'io.cozy.todos' ] const pouchLink = new PouchLink ({ doctypes : offlineDoctypes , initialSync : true // whether you want to trigger the synchronization on login or not }) const client = new CozyClient ({ // ... links : [ pouchLink , stackLink ] }) The PouchLink will create the PouchDB databases for all offline doctypes and synchronize them with the distant CouchDB. All doctypes that are not managed by the PouchLink will be passed to the next link in the chain (in the previous example, the StackLink ). Additionally, it is possible to replicate some doctypes only in a specific direction: const pouchLink = new PouchLink ({ doctypes : [ 'io.cozy.todos' , 'io.cozy.files' , 'io.cozy.localtype' ], doctypesReplicationOptions : { 'io.cozy.todos' : { strategy : 'sync' // default, replicate both ways }, 'io.cozy.files' : { strategy : 'fromRemote' // replicate changes from the remote locally, but don't push any changes }, 'io.cozy.localtype' : { strategy : 'toRemote' // push changes to remote, but don't replicate changes from it } } initialSync : true }) If you choose the fromRemote strategy, the cozy-client mutation will not be executed on the PouchLink but rather on the StackLink. Since making the first query can be long (PouchDB will create the index first), you can specify the queries you want to be \u201cwarmed up\u201d. It means that, those queries will be executed by CozyClient during the PouchLink\u2019s instanciation, but CozyClient will use PouchDB only if those queries have been resolved at least one time. const buildRecentQuery = () => ({ definition : () => Q ( 'io.cozy.files' ) . where ({ type : 'file' , trashed : false , updated_at : { $gt : null } }) options : { as : 'recent-view-query' , fetchPolicy : defaultFetchPolicy , } }) const pouchLink = new PouchLink ({ doctypes : [ 'io.cozy.todos' , 'io.cozy.files' , 'io.cozy.localtype' ], doctypesReplicationOptions : { 'io.cozy.files' : { warmupQueries : [ buildRecentQuery () ] } } initialSync : true })", "title": "Support offline for some doctypes with cozy-pouch-link"}, {"location": "cozy-client/node/", "text": "How to use the client on Node environment ( ReferenceError: fetch is not defined ) ? \u00b6 Cozy-Client relies on the fetch function included in browsers (or polyfilled). This function does not exist on Node environments so we have to provide a polyfill. An example using node-fetch : import fetch from 'node-fetch' import CozyClient from 'cozy-client' global . fetch = fetch Then you will be able to use all the client methods and fetch data correctly. When using cozy-client on Node environment, you don\u2019t have access to all React specific APIs. If, for any reason, you want to access these APIs, you can still import them from cozy-client/dist/react .", "title": "Node"}, {"location": "cozy-client/node/#how-to-use-the-client-on-node-environment-referenceerror-fetch-is-not-defined", "text": "Cozy-Client relies on the fetch function included in browsers (or polyfilled). This function does not exist on Node environments so we have to provide a polyfill. An example using node-fetch : import fetch from 'node-fetch' import CozyClient from 'cozy-client' global . fetch = fetch Then you will be able to use all the client methods and fetch data correctly. When using cozy-client on Node environment, you don\u2019t have access to all React specific APIs. If, for any reason, you want to access these APIs, you can still import them from cozy-client/dist/react .", "title": "How to use the client on Node environment (ReferenceError: fetch is not defined) ?"}, {"location": "cozy-client/react-integration/", "text": "What is the Cozy-Client React Integration? \u00b6 In addition to the Javascript client, Cozy-Client provides a way to connect directly the data from your Cozy instance to your React components. Once connected, your components will receive the requesting data and a fetch status in their props. The data will automatically be refreshed upon modification. 1. Setup 1.a Initialize a CozyClient provider 1.b Use your own Redux store 2. Usage 2.a Requesting data with useQuery 2.b Requesting data with the queryConnect HOC 2.c Using a fetch policy to decrease network requests 2.d Keeping data up to date in real time 3. Mutating data 3.a Mutating data with useMutation 3.b Mutating data with Query 4. Testing 1. Setup \u00b6 The following procedure requires you to already know how to initialize a CozyClient instance and create a query to fetch documents. \u26a0\ufe0f The fromDOM instantiation method assumes the page you use is served by the Cozy Stack, and that there is a DOM node with the stack info. See how the application works for more information. 1.a Initialize a CozyClient provider \u00b6 Import CozyClient and CozyProvider import CozyClient , { CozyProvider } from 'cozy-client' Initialize a CozyClient instance (see the CozyClient() documentation for additional parameters, for example to provide a schema) const client = CozyClient . fromDOM () Then wrap you React application inside a CozyProvider component with your newly instance of CozyClient in its props as client . function MyCozyApp ( props ) { return < CozyProvider client = { client }> < MyApp { ...props } /> CozyProvider > } ReactDOM . render (< MyCozyApp />, document . getElementById ( 'main' ) ) The CozyClient will be available for consumption to all components inside your wrapped application. 1.b Use your own Redux store \u00b6 cozy-client uses redux internally to centralize the statuses of the various fetches and replications triggered by the library, and to store locally the data in a normalized way. If you already have a redux store in your app, you can configure cozy-client to use this existing store: import CozyClient , { CozyProvider } from 'cozy-client' import { combineReducers , createStore , applyMiddleware } from 'redux' const client = CozyClient . fromDOM ({ store : false // Important, otherwise a default store is created }) const store = createStore ( combineReducers ({ ... myReducers , cozy : client . reducer () }), applyMiddleware ( myMiddleware ) ) function MyCozyApp ( props ) { return < CozyProvider client = { client } store = { store }> < MyApp { ...props } /> CozyProvider > } ReactDOM . render (< MyCozyApp />, document . getElementById ( 'main' ) ) 2. Usage \u00b6 2.a Requesting data with useQuery \u00b6 useQuery is the most straightforward to fetch data from the Cozy. Query results are cached and can be reused across components, you just have to name the query results (\u201cchecked-todos\u201d) below. import CozyClient , { useQuery , isQueryLoading , Q } from 'cozy-client' const client = CozyClient . fromDOM () client . ensureStore () const todos = 'io.cozy.todos' const checked = { checked : false } // Use the Q helper to build queries const queryDefinition = Q ( todos ). where ( checked ) function TodoList ( props ) { const queryResult = useQuery ( queryDefinition , { as : 'checked-todos' , fetchPolicy : CozyClient . fetchPolicies . olderThan ( 30 * 1000 ) }) return <> { queryResult => isQueryLoading ( queryResult ) ? < h1 > Loading ... h1 > : < ul >{ queryResult . data . map ( todo => < li >{ todo . label } li >)} ul > } < /> } function App () { return < CozyProvider client = { client }> < TodoList /> CozyProvider > } useQuery also supports a \u201cdisabled\u201d parameter: if set to false the query won\u2019t be executed. This is useful when you have dependent queries that rely on the results of another query to have been fetched. 2.b Requesting data with \u00b6 If you cannot use a hook, you can use the Query render-prop component. Basic example of usage: import { Query , isQueryLoading , Q } from 'cozy-client' import React from 'react' const todos = 'io.cozy.todos' const checked = { checked : false } // Use the Q helper to build queries const queryDefinition = Q ( todos ). where ( checked ) const TodoList = () => ( < Query query = { queryDefinition }> { queryResult => isQueryLoading ( queryResult ) ? < h1 > Loading ... h1 > : < ul >{ queryResult . data . map ( todo => < li >{ todo . label } li >)} ul > } Query > ) When we use Query to \u201cwrap\u201d a component, three things happen: - The query passed as a prop will be executed when Query mounts, resulting in the loading of data from the local Pouchdb (if any) or from the server; in the future it may load the data directly from the client-side store; - Query subscribes to the store, so that it is updated if the data changes; - Query passes the result of the query as props to the children function. The following props will be given to your wrapped component: - data : an array of documents - fetchStatus : the status of the fetch ( pending , loading , loaded or error ) - lastFetch : when the last fetch occurred - hasMore : the fetches being paginated, this property indicates if there are more documents to load You can also pass a function instead of a direct query definition. Your function will be given the props of the component and should return the requested query definition: import { Query , Q } from 'cozy-client' import React from 'react' const queryDefinition = function ( props ) { const todos = 'io.cozy.todos' const where = { checked : props . checked } return Q ( todos ). where ( where ) } const TodoList = ({ props }) => ( < Query query = { queryDefinition } checked = { props . checked }> {({ data , fetchStatus }) => ( fetchStatus !== 'loaded' ? < h1 > Loading ... h1 > : < ul >{ data . map ( todo => < li >{ todo . label } li >)} ul > ) } Query > ) // use Note: Your query definition will be bound when the component mounts. Future changes in props will not modify the query. 2.c Requesting data with the queryConnect HOC \u00b6 At your preference, you can use a higher-order component. queryConnect will take the name of the props field where it should send the result of the query and the actual query: import { queryConnect , Q } from 'cozy-client' function TodoList ( props ) { const { data , fetchStatus } = props . result if ( fetchStatus !== 'loaded' ) { return < h1 > Loading ... h1 > } else { return < ul >{ data . map ( todo => < li >{ todo . label } li >)} ul > } } const ConnectedTodoList = queryConnect ({ result : { query : Q ( 'io.cozy.todos' ). where ({ checked : false }) } })( TodoList ) queryConnect will use internally, so you will inherit the same behaviour. With the same syntax, you may register multiple queries to run: import { queryConnect , Q } from 'cozy-client' function TodoList ( props ) { const { data , fetchStatus } = props . checked if ( fetchStatus !== 'loaded' ) { return < h1 > Loading ... h1 > } else { return < ul >{ data . map ( todo => < li >{ todo . label } li >)} ul > } } const todos = 'io.cozy.todos' const checked = { query : Q ( todos ). where ({ checked : false }) } const archived = { query : Q ( todos ). where ({ archive : false }) } const queries = { checked , archived } const ConnectedTodoList = queryConnect ( queries )( TodoList ) 2.d Using a fetch policy to decrease network requests \u00b6 When multiple components share the same data, you might want to share the data between the two components. In this case, you do not want to execute 2 network requests for the same data, the two components should share the same data and only 1 network request should be executed. There are two solutions: 1) Lift the data fetching up the React tree: make a parent of the two components be the responsible for the data. 2) Using fetch policies to prevent re-fetching of the data 1 can be a good solution but sometimes the components needing the data are too far down the tree and/or too decoupled; it might not make sense to lift the data fetching up only to have to drill the data down the tree again. Using useQuery , Query and queryConnect , you can declare a fetch policy . It tells cozy-client if it should execute the query at componentDidMount time. It enables N components to be connected to the same query without triggering N requests. A fetch policy is a function receiving the state of the current query and returning true if it should be fetched and false otherwise. It is important to name the query with as when using fetch policies otherwise query data cannot be shared across components. import { Q } from 'cozy-client' const queryDefinition = () => Q ( 'io.cozy.todos' ) const MyComponent = () => { // io.cozy.todos will not be refetched if there are already io.cozy.todos // in the store and the data is fresh (updated less than 30s ago). const fetchPolicy = CozyClient . olderThan ( 30 * 1000 ) const as = 'my-query' // With Query and a render prop return (< Query as = { as } query = { queryDefinition } fetchPolicy = { fetchPolicy }>{ ({ data : todos }) => {< TodoList todos = { todos } />} } Query >) } // With queryConnect queryConnect ({ todos : { as , query , fetchPolicy } })( TodoList ) See CozyClient::fetchPolicies for the API documentation. 2.e Keeping data up to date in real time \u00b6 Sometimes the data you are displaying will be changed from other places than your app. Maybe the data is shared and someone else has updated it, or maybe it simply changes over time. You can however keep your UI always up to date without constantly re-running your queries, by subscribing to changes in real time. This is done with the RealTimeQueries component: import { RealTimeQueries } from 'cozy-client' function MyParentComponent ( props ) { return ( <> < ConnectedTodoList /> < RealTimeQueries doctype = \"io.cozy.todos\" /> < /> ) } You subscribe to changes for an entire doctype using RealTimeQueries , and as long as that component is rendered all documents from the given doctype in your queries will automatically stay up to date. 3. Mutating data \u00b6 The simplest way is to use the hook useClient to get the CozyClient instance you gave to the upper. import { useClient } from 'cozy-client' function TodoList ( props ) { const client = useClient () const createNewTodo = e => client . create ( 'io.cozy.todos' , { label : e . target . elements [ 'new-todo' ], checked : false } ) return ( <> < ul > { /* todo items */ } ul > < form onSubmit = { createNewTodo }> < label htmlFor = \"new-todo\" > Todo label > < input id = \"new-todo\" name = \"new-todo\" /> < button type = \"submit\" > Add todo button > form > < /> ) } 3.a Mutating data with useMutation \u00b6 We also provides a hook to manage client.save mutation state called useMutation . import { useMutation } from 'cozy-client' function TodoLabelInlineEdit ({ todo }) { const [ label , setLabel ] = useState ( todo . label ) const { mutate , mutationStatus } = useMutation () const handleChange = event => { setLabel ( event . target . value ) } const handleBlur = () => { mutate ({ ... todo , label }) } return ( < div style = {{ display : 'flex' }}> < input type = \"text\" aria - label = \"Label\" style = {{ marginRight : '1rem' }} value = { label } onChange = { handleChange } onBlur = { handleBlur } /> { mutationStatus === 'loaded' ? '\u2713' : null } { mutationStatus === 'failed' ? '\u2717' : null } div > ) } 3.b Mutating data with Query \u00b6 also takes a mutations optional props. It should have a function that will receive the CozyClient instance, the query requested and the rest of props given to the component, and should return a keyed object which will be added to the props of your wrapped component. import { Query } from 'cozy-client' const todos = 'io.cozy.todos' const checked = { checked : false } const queryDefinition = Q ( todos ). where ( checked ) const mutations = client => ({ createDocument : client . create . bind ( client ) }) function TodoList () { return < Query query = { queryDefinition } mutations = { mutations }> { ({ data , fetchStatus }) => fetchStatus !== 'loaded' ? < h1 > Loading ... h1 > : < ul >{ data . map ( todo => < li >{ todo . label } li >)} ul > } Query > } 4. Testing \u00b6 When testing, it is useful to prefill the client with data and mock the network. You can use createMockClient for this. Say we want to test the following component: import React from 'react' import { useQuery , Q } from 'cozy-client' function TodoList () { const { data , fetchStatus , lastError } = useQuery ( Q ( 'io.cozy.todos' ), { as : 'todos' }) if ( fetchStatus === 'failed' ) { return < h1 > An error occurred : { lastError . message } h1 > } else if ( fetchStatus !== 'loaded' ) { return < h1 > Loading ... h1 > } else { return ( <> < h1 id = \"todos-heading\" > Todos h1 > < ul aria - labelledby = \"todos-heading\" > { data . map ( todo => ( < li key = { todo . id }>{ todo . label } li > ))} ul > < /> ) } } export default TodoList We want to make sure the component renders correctly. In our test, we can create a mocked client with predefined data for the todos query, and test it with testing-library : import React from 'react' import { createMockClient , CozyProvider } from 'cozy-client' import { render , screen , within } from '@testing-library/react' import TodoList from './TodoList' describe ( 'TodoList' , () => { const setup = client => { return render ( < CozyProvider client = { client }> < TodoList /> CozyProvider > ) } it ( 'should show the todos' , () => { const mockClient = createMockClient ({ queries : { todos : { doctype : 'io.cozy.todos' , data : [ { id : 'todo1' , name : 'Write tests' , done : true }, { id : 'todo2' , name : 'Write code' , done : true }, { id : 'todo3' , name : 'Take breaks' , done : true }, { id : 'todo4' , name : 'Write documentation' , done : false } ] } } }) setup ( mockClient ) const list = screen . getByRole ( 'list' , { name : /todos/i }) const { getAllByRole } = within ( list ) const items = getAllByRole ( 'listitem' ) expect ( items . length ). toBe ( 4 ) }) it ( 'should display the error message' , () => { const mockClient = createMockClient ({ queries : { todos : { doctype : 'io.cozy.todos' , queryError : new Error ( 'Network error' ) } } }) setup ( mockClient ) expect ( screen . getByText ( /network error/i )). toBeDefined () }) })", "title": "React integration"}, {"location": "cozy-client/react-integration/#what-is-the-cozy-client-react-integration", "text": "In addition to the Javascript client, Cozy-Client provides a way to connect directly the data from your Cozy instance to your React components. Once connected, your components will receive the requesting data and a fetch status in their props. The data will automatically be refreshed upon modification. 1. Setup 1.a Initialize a CozyClient provider 1.b Use your own Redux store 2. Usage 2.a Requesting data with useQuery 2.b Requesting data with the queryConnect HOC 2.c Using a fetch policy to decrease network requests 2.d Keeping data up to date in real time 3. Mutating data 3.a Mutating data with useMutation 3.b Mutating data with Query 4. Testing", "title": "What is the Cozy-Client React Integration?"}, {"location": "cozy-client/react-integration/#1-setup", "text": "The following procedure requires you to already know how to initialize a CozyClient instance and create a query to fetch documents. \u26a0\ufe0f The fromDOM instantiation method assumes the page you use is served by the Cozy Stack, and that there is a DOM node with the stack info. See how the application works for more information. ", "title": "1. Setup"}, {"location": "cozy-client/react-integration/#1a-initialize-a-cozyclient-provider", "text": "Import CozyClient and CozyProvider import CozyClient , { CozyProvider } from 'cozy-client' Initialize a CozyClient instance (see the CozyClient() documentation for additional parameters, for example to provide a schema) const client = CozyClient . fromDOM () Then wrap you React application inside a CozyProvider component with your newly instance of CozyClient in its props as client . function MyCozyApp ( props ) { return < CozyProvider client = { client }> < MyApp { ...props } /> CozyProvider > } ReactDOM . render (< MyCozyApp />, document . getElementById ( 'main' ) ) The CozyClient will be available for consumption to all components inside your wrapped application.", "title": "1.a Initialize a CozyClient provider"}, {"location": "cozy-client/react-integration/#1b-use-your-own-redux-store", "text": "cozy-client uses redux internally to centralize the statuses of the various fetches and replications triggered by the library, and to store locally the data in a normalized way. If you already have a redux store in your app, you can configure cozy-client to use this existing store: import CozyClient , { CozyProvider } from 'cozy-client' import { combineReducers , createStore , applyMiddleware } from 'redux' const client = CozyClient . fromDOM ({ store : false // Important, otherwise a default store is created }) const store = createStore ( combineReducers ({ ... myReducers , cozy : client . reducer () }), applyMiddleware ( myMiddleware ) ) function MyCozyApp ( props ) { return < CozyProvider client = { client } store = { store }> < MyApp { ...props } /> CozyProvider > } ReactDOM . render (< MyCozyApp />, document . getElementById ( 'main' ) )", "title": "1.b Use your own Redux store"}, {"location": "cozy-client/react-integration/#2-usage", "text": "", "title": "2. Usage"}, {"location": "cozy-client/react-integration/#2a-requesting-data-with-usequery", "text": "useQuery is the most straightforward to fetch data from the Cozy. Query results are cached and can be reused across components, you just have to name the query results (\u201cchecked-todos\u201d) below. import CozyClient , { useQuery , isQueryLoading , Q } from 'cozy-client' const client = CozyClient . fromDOM () client . ensureStore () const todos = 'io.cozy.todos' const checked = { checked : false } // Use the Q helper to build queries const queryDefinition = Q ( todos ). where ( checked ) function TodoList ( props ) { const queryResult = useQuery ( queryDefinition , { as : 'checked-todos' , fetchPolicy : CozyClient . fetchPolicies . olderThan ( 30 * 1000 ) }) return <> { queryResult => isQueryLoading ( queryResult ) ? < h1 > Loading ... h1 > : < ul >{ queryResult . data . map ( todo => < li >{ todo . label } li >)} ul > } < /> } function App () { return < CozyProvider client = { client }> < TodoList /> CozyProvider > } useQuery also supports a \u201cdisabled\u201d parameter: if set to false the query won\u2019t be executed. This is useful when you have dependent queries that rely on the results of another query to have been fetched.", "title": "2.a Requesting data with useQuery"}, {"location": "cozy-client/react-integration/#2b-requesting-data-with-ltquery-gt", "text": "If you cannot use a hook, you can use the Query render-prop component. Basic example of usage: import { Query , isQueryLoading , Q } from 'cozy-client' import React from 'react' const todos = 'io.cozy.todos' const checked = { checked : false } // Use the Q helper to build queries const queryDefinition = Q ( todos ). where ( checked ) const TodoList = () => ( < Query query = { queryDefinition }> { queryResult => isQueryLoading ( queryResult ) ? < h1 > Loading ... h1 > : < ul >{ queryResult . data . map ( todo => < li >{ todo . label } li >)} ul > } Query > ) When we use Query to \u201cwrap\u201d a component, three things happen: - The query passed as a prop will be executed when Query mounts, resulting in the loading of data from the local Pouchdb (if any) or from the server; in the future it may load the data directly from the client-side store; - Query subscribes to the store, so that it is updated if the data changes; - Query passes the result of the query as props to the children function. The following props will be given to your wrapped component: - data : an array of documents - fetchStatus : the status of the fetch ( pending , loading , loaded or error ) - lastFetch : when the last fetch occurred - hasMore : the fetches being paginated, this property indicates if there are more documents to load You can also pass a function instead of a direct query definition. Your function will be given the props of the component and should return the requested query definition: import { Query , Q } from 'cozy-client' import React from 'react' const queryDefinition = function ( props ) { const todos = 'io.cozy.todos' const where = { checked : props . checked } return Q ( todos ). where ( where ) } const TodoList = ({ props }) => ( < Query query = { queryDefinition } checked = { props . checked }> {({ data , fetchStatus }) => ( fetchStatus !== 'loaded' ? < h1 > Loading ... h1 > : < ul >{ data . map ( todo => < li >{ todo . label } li >)} ul > ) } Query > ) // use Note: Your query definition will be bound when the component mounts. Future changes in props will not modify the query.", "title": "2.b Requesting data with <Query />"}, {"location": "cozy-client/react-integration/#2c-requesting-data-with-the-queryconnect-hoc", "text": "At your preference, you can use a higher-order component. queryConnect will take the name of the props field where it should send the result of the query and the actual query: import { queryConnect , Q } from 'cozy-client' function TodoList ( props ) { const { data , fetchStatus } = props . result if ( fetchStatus !== 'loaded' ) { return < h1 > Loading ... h1 > } else { return < ul >{ data . map ( todo => < li >{ todo . label } li >)} ul > } } const ConnectedTodoList = queryConnect ({ result : { query : Q ( 'io.cozy.todos' ). where ({ checked : false }) } })( TodoList ) queryConnect will use internally, so you will inherit the same behaviour. With the same syntax, you may register multiple queries to run: import { queryConnect , Q } from 'cozy-client' function TodoList ( props ) { const { data , fetchStatus } = props . checked if ( fetchStatus !== 'loaded' ) { return < h1 > Loading ... h1 > } else { return < ul >{ data . map ( todo => < li >{ todo . label } li >)} ul > } } const todos = 'io.cozy.todos' const checked = { query : Q ( todos ). where ({ checked : false }) } const archived = { query : Q ( todos ). where ({ archive : false }) } const queries = { checked , archived } const ConnectedTodoList = queryConnect ( queries )( TodoList )", "title": "2.c Requesting data with the queryConnect HOC"}, {"location": "cozy-client/react-integration/#2d-using-a-fetch-policy-to-decrease-network-requests", "text": "When multiple components share the same data, you might want to share the data between the two components. In this case, you do not want to execute 2 network requests for the same data, the two components should share the same data and only 1 network request should be executed. There are two solutions: 1) Lift the data fetching up the React tree: make a parent of the two components be the responsible for the data. 2) Using fetch policies to prevent re-fetching of the data 1 can be a good solution but sometimes the components needing the data are too far down the tree and/or too decoupled; it might not make sense to lift the data fetching up only to have to drill the data down the tree again. Using useQuery , Query and queryConnect , you can declare a fetch policy . It tells cozy-client if it should execute the query at componentDidMount time. It enables N components to be connected to the same query without triggering N requests. A fetch policy is a function receiving the state of the current query and returning true if it should be fetched and false otherwise. It is important to name the query with as when using fetch policies otherwise query data cannot be shared across components. import { Q } from 'cozy-client' const queryDefinition = () => Q ( 'io.cozy.todos' ) const MyComponent = () => { // io.cozy.todos will not be refetched if there are already io.cozy.todos // in the store and the data is fresh (updated less than 30s ago). const fetchPolicy = CozyClient . olderThan ( 30 * 1000 ) const as = 'my-query' // With Query and a render prop return (< Query as = { as } query = { queryDefinition } fetchPolicy = { fetchPolicy }>{ ({ data : todos }) => {< TodoList todos = { todos } />} } Query >) } // With queryConnect queryConnect ({ todos : { as , query , fetchPolicy } })( TodoList ) See CozyClient::fetchPolicies for the API documentation.", "title": "2.d Using a fetch policy to decrease network requests"}, {"location": "cozy-client/react-integration/#2e-keeping-data-up-to-date-in-real-time", "text": "Sometimes the data you are displaying will be changed from other places than your app. Maybe the data is shared and someone else has updated it, or maybe it simply changes over time. You can however keep your UI always up to date without constantly re-running your queries, by subscribing to changes in real time. This is done with the RealTimeQueries component: import { RealTimeQueries } from 'cozy-client' function MyParentComponent ( props ) { return ( <> < ConnectedTodoList /> < RealTimeQueries doctype = \"io.cozy.todos\" /> < /> ) } You subscribe to changes for an entire doctype using RealTimeQueries , and as long as that component is rendered all documents from the given doctype in your queries will automatically stay up to date.", "title": "2.e Keeping data up to date in real time"}, {"location": "cozy-client/react-integration/#3-mutating-data", "text": "The simplest way is to use the hook useClient to get the CozyClient instance you gave to the upper. import { useClient } from 'cozy-client' function TodoList ( props ) { const client = useClient () const createNewTodo = e => client . create ( 'io.cozy.todos' , { label : e . target . elements [ 'new-todo' ], checked : false } ) return ( <> < ul > { /* todo items */ } ul > < form onSubmit = { createNewTodo }> < label htmlFor = \"new-todo\" > Todo label > < input id = \"new-todo\" name = \"new-todo\" /> < button type = \"submit\" > Add todo button > form > < /> ) }", "title": "3. Mutating data"}, {"location": "cozy-client/react-integration/#3a-mutating-data-with-usemutation", "text": "We also provides a hook to manage client.save mutation state called useMutation . import { useMutation } from 'cozy-client' function TodoLabelInlineEdit ({ todo }) { const [ label , setLabel ] = useState ( todo . label ) const { mutate , mutationStatus } = useMutation () const handleChange = event => { setLabel ( event . target . value ) } const handleBlur = () => { mutate ({ ... todo , label }) } return ( < div style = {{ display : 'flex' }}> < input type = \"text\" aria - label = \"Label\" style = {{ marginRight : '1rem' }} value = { label } onChange = { handleChange } onBlur = { handleBlur } /> { mutationStatus === 'loaded' ? '\u2713' : null } { mutationStatus === 'failed' ? '\u2717' : null } div > ) }", "title": "3.a Mutating data with useMutation"}, {"location": "cozy-client/react-integration/#3b-mutating-data-with-query", "text": " also takes a mutations optional props. It should have a function that will receive the CozyClient instance, the query requested and the rest of props given to the component, and should return a keyed object which will be added to the props of your wrapped component. import { Query } from 'cozy-client' const todos = 'io.cozy.todos' const checked = { checked : false } const queryDefinition = Q ( todos ). where ( checked ) const mutations = client => ({ createDocument : client . create . bind ( client ) }) function TodoList () { return < Query query = { queryDefinition } mutations = { mutations }> { ({ data , fetchStatus }) => fetchStatus !== 'loaded' ? < h1 > Loading ... h1 > : < ul >{ data . map ( todo => < li >{ todo . label } li >)} ul > } Query > }", "title": "3.b Mutating data with Query"}, {"location": "cozy-client/react-integration/#4-testing", "text": "When testing, it is useful to prefill the client with data and mock the network. You can use createMockClient for this. Say we want to test the following component: import React from 'react' import { useQuery , Q } from 'cozy-client' function TodoList () { const { data , fetchStatus , lastError } = useQuery ( Q ( 'io.cozy.todos' ), { as : 'todos' }) if ( fetchStatus === 'failed' ) { return < h1 > An error occurred : { lastError . message } h1 > } else if ( fetchStatus !== 'loaded' ) { return < h1 > Loading ... h1 > } else { return ( <> < h1 id = \"todos-heading\" > Todos h1 > < ul aria - labelledby = \"todos-heading\" > { data . map ( todo => ( < li key = { todo . id }>{ todo . label } li > ))} ul > < /> ) } } export default TodoList We want to make sure the component renders correctly. In our test, we can create a mocked client with predefined data for the todos query, and test it with testing-library : import React from 'react' import { createMockClient , CozyProvider } from 'cozy-client' import { render , screen , within } from '@testing-library/react' import TodoList from './TodoList' describe ( 'TodoList' , () => { const setup = client => { return render ( < CozyProvider client = { client }> < TodoList /> CozyProvider > ) } it ( 'should show the todos' , () => { const mockClient = createMockClient ({ queries : { todos : { doctype : 'io.cozy.todos' , data : [ { id : 'todo1' , name : 'Write tests' , done : true }, { id : 'todo2' , name : 'Write code' , done : true }, { id : 'todo3' , name : 'Take breaks' , done : true }, { id : 'todo4' , name : 'Write documentation' , done : false } ] } } }) setup ( mockClient ) const list = screen . getByRole ( 'list' , { name : /todos/i }) const { getAllByRole } = within ( list ) const items = getAllByRole ( 'listitem' ) expect ( items . length ). toBe ( 4 ) }) it ( 'should display the error message' , () => { const mockClient = createMockClient ({ queries : { todos : { doctype : 'io.cozy.todos' , queryError : new Error ( 'Network error' ) } } }) setup ( mockClient ) expect ( screen . getByText ( /network error/i )). toBeDefined () }) })", "title": "4. Testing"}, {"location": "cozy-client/relationships/", "text": "What are relations in Cozy-Client? \u00b6 CouchDB is a document store. It does not materialize relations between documents. We do, however, have a standardized way of describing relations between cozy documents. This allows Cozy-Client to give us some automation. In CouchDB \u00b6 Relations between documents are materialized under a relationships object at the root of the document. Relations are referenced by their names, e.g. authors . Each relation is an object with a data property, containing either one reference , or an array of references . A reference is an object containing at least: * _type : the name of the referenced doctype, e.g. io.cozy.contacts * _id : the id of the referenced document. For instance, a book -> authors relationship might be represented like this: { \"_id\" : \"mobydick\" , \"relationships\" : { \"authors\" : { \"data\" : [{ \"_id\" : \"hermanmelville\" , \"_type\" : \"io.cozy.contacts\" }] } } } Please see the cozy-doctypes documentation for more insights about the syntax. In the Cozy-Client schema \u00b6 Cozy-client knows how to handle these relations thanks to the schema you provide at initialization: const schema = { books : { doctype : 'io.cozy.books' , attributes : {}, relationships : { authors : { doctype : 'io.cozy.contacts' , type : 'has-many' } } } } const client = new CozyClient ({ uri : 'http://cozy.tools:8080' , token : '...' , schema }) We explain below what are the different types of relations. Relation types \u00b6 Cozy-Client predefines two basic relation types that must be specified in the schema: 'has-one' : the relation has a unique reference. 'has-many' : the relation can have several references. Files relations \u00b6 The files implements a special type of relation: 'io.cozy.files:has-many' . This relation name is referenced_by , which is an array of references, just like the 'has-many' relation. The stack implements routes to handle this kind of relation on the /files endpoint. See the stack documentation . Note specific view index are defined on referenced_by relationships, allowing fast queries on it. Customize relations \u00b6 You are free to create your own relation type if you need a special behaviour. For instance, Banks doctypes implements HasManyBills or HasManyReimbursements . Old relation types \u00b6 Note there are two others basic relations, that are here for backward compatibility: 'has-one-in-place' 'has-many-in-place' \u26a0\ufe0f For new doctypes, you should not use those relations, prefer 'has-one' or 'has-many' . With these relations, instead of using the relationships attribute, you reference directly the ids of linked documents at the root of your data: const schema = { books : { doctype : 'io.cozy.books' , attributes : {}, relationships : { authors : { doctype : 'io.cozy.contacts' , type : 'has-many-in-place' } } } } const book = { \"_id\" : \"mobydick\" , \"authors\" : [ \"hermanmelville\" ] } Metadata \u00b6 It is possible to assign metadatas to relationships. You need to modify the content of the document relationships somehow and save the modified document. const doc = { _id : \"mobydick\" , relationships : { authors : { data : [{ _id : \"hermanmelville\" , _type : \"io.cozy.contacts\" }] } } } doc . relationships . authors . data [ 0 ]. metadata = { addressId : \"123\" } await client . save ( doc ) Usage \u00b6 Include relations in your query \u00b6 Relations are not loaded eagerly by default. If you want your query to load your relations for you, you will have to name them in an include() request. const query = Q ( 'io.cozy.books' ) . include ([ 'authors' ]) . limitBy ( 20 ) You will then find your relations under the data attribute: const response = await client . query ( query ) const docs = response . data const firstDoc = docs [ 0 ] const firstAuthors = firstDoc . authors . data Add a relation to an existing document \u00b6 When the relationship is a has-many type, you can call the add(docs) to create the relationship: const otherAuthors = [{ _id : 'Rivest' }, { _id : 'Shamir' }] const response = await client . query ( query ) const docs = response . data const firstDoc = docs [ 0 ] firstDoc . authors . add ( otherAuthors ) add also accepts single document: firstDoc . authors . add ({ _id : 'Adleman' }) Likewise, when the relationship is a has-one , use add(doc) : const printer = { _id : 'abc123' , _type : 'io.cozy.company' , name : 'Harper & Brothers' } const response = await client . query ( query ) const docs = response . data const firstDoc = docs [ 0 ] firstDoc . printingCompany . add ( printer ) Remove a relation to an existing document \u00b6 For has-many relationships, use the remove(docs) method: const wrongAuthors = [{ _id : 'James Wrong' }, { _id : 'Henry Mistake' }] const response = await client . query ( query ) const docs = response . data const firstDoc = docs [ 0 ] firstDoc . authors . remove ( wrongAuthors ) Just like add , remove accepts a single document. For has-one relationships, just use remove() , with no argument: const response = await client . query ( query ) const docs = response . data const firstDoc = docs [ 0 ] firstDoc . printingCompany . remove () Create a new file with existing relations \u00b6 Simply pass the reference to your file as a third parameter to create() : const photo = { _id : \"sunset.jpg\" } const reference = { _id : \"1324\" , _type : \"io.cozy.photos.albums\" } const albumReference = { albums : [ albumReference ] } await client . create ( 'io.cozy.files' , photo , albumReference )", "title": "Using relationships"}, {"location": "cozy-client/relationships/#what-are-relations-in-cozy-client", "text": "CouchDB is a document store. It does not materialize relations between documents. We do, however, have a standardized way of describing relations between cozy documents. This allows Cozy-Client to give us some automation.", "title": "What are relations in Cozy-Client?"}, {"location": "cozy-client/relationships/#in-couchdb", "text": "Relations between documents are materialized under a relationships object at the root of the document. Relations are referenced by their names, e.g. authors . Each relation is an object with a data property, containing either one reference , or an array of references . A reference is an object containing at least: * _type : the name of the referenced doctype, e.g. io.cozy.contacts * _id : the id of the referenced document. For instance, a book -> authors relationship might be represented like this: { \"_id\" : \"mobydick\" , \"relationships\" : { \"authors\" : { \"data\" : [{ \"_id\" : \"hermanmelville\" , \"_type\" : \"io.cozy.contacts\" }] } } } Please see the cozy-doctypes documentation for more insights about the syntax.", "title": "In CouchDB"}, {"location": "cozy-client/relationships/#in-the-cozy-client-schema", "text": "Cozy-client knows how to handle these relations thanks to the schema you provide at initialization: const schema = { books : { doctype : 'io.cozy.books' , attributes : {}, relationships : { authors : { doctype : 'io.cozy.contacts' , type : 'has-many' } } } } const client = new CozyClient ({ uri : 'http://cozy.tools:8080' , token : '...' , schema }) We explain below what are the different types of relations.", "title": "In the Cozy-Client schema"}, {"location": "cozy-client/relationships/#relation-types", "text": "Cozy-Client predefines two basic relation types that must be specified in the schema: 'has-one' : the relation has a unique reference. 'has-many' : the relation can have several references.", "title": "Relation types"}, {"location": "cozy-client/relationships/#files-relations", "text": "The files implements a special type of relation: 'io.cozy.files:has-many' . This relation name is referenced_by , which is an array of references, just like the 'has-many' relation. The stack implements routes to handle this kind of relation on the /files endpoint. See the stack documentation . Note specific view index are defined on referenced_by relationships, allowing fast queries on it.", "title": "Files relations"}, {"location": "cozy-client/relationships/#customize-relations", "text": "You are free to create your own relation type if you need a special behaviour. For instance, Banks doctypes implements HasManyBills or HasManyReimbursements .", "title": "Customize relations"}, {"location": "cozy-client/relationships/#old-relation-types", "text": "Note there are two others basic relations, that are here for backward compatibility: 'has-one-in-place' 'has-many-in-place' \u26a0\ufe0f For new doctypes, you should not use those relations, prefer 'has-one' or 'has-many' . With these relations, instead of using the relationships attribute, you reference directly the ids of linked documents at the root of your data: const schema = { books : { doctype : 'io.cozy.books' , attributes : {}, relationships : { authors : { doctype : 'io.cozy.contacts' , type : 'has-many-in-place' } } } } const book = { \"_id\" : \"mobydick\" , \"authors\" : [ \"hermanmelville\" ] }", "title": "Old relation types"}, {"location": "cozy-client/relationships/#metadata", "text": "It is possible to assign metadatas to relationships. You need to modify the content of the document relationships somehow and save the modified document. const doc = { _id : \"mobydick\" , relationships : { authors : { data : [{ _id : \"hermanmelville\" , _type : \"io.cozy.contacts\" }] } } } doc . relationships . authors . data [ 0 ]. metadata = { addressId : \"123\" } await client . save ( doc )", "title": "Metadata"}, {"location": "cozy-client/relationships/#usage", "text": "", "title": "Usage"}, {"location": "cozy-client/relationships/#include-relations-in-your-query", "text": "Relations are not loaded eagerly by default. If you want your query to load your relations for you, you will have to name them in an include() request. const query = Q ( 'io.cozy.books' ) . include ([ 'authors' ]) . limitBy ( 20 ) You will then find your relations under the data attribute: const response = await client . query ( query ) const docs = response . data const firstDoc = docs [ 0 ] const firstAuthors = firstDoc . authors . data", "title": "Include relations in your query"}, {"location": "cozy-client/relationships/#add-a-relation-to-an-existing-document", "text": "When the relationship is a has-many type, you can call the add(docs) to create the relationship: const otherAuthors = [{ _id : 'Rivest' }, { _id : 'Shamir' }] const response = await client . query ( query ) const docs = response . data const firstDoc = docs [ 0 ] firstDoc . authors . add ( otherAuthors ) add also accepts single document: firstDoc . authors . add ({ _id : 'Adleman' }) Likewise, when the relationship is a has-one , use add(doc) : const printer = { _id : 'abc123' , _type : 'io.cozy.company' , name : 'Harper & Brothers' } const response = await client . query ( query ) const docs = response . data const firstDoc = docs [ 0 ] firstDoc . printingCompany . add ( printer )", "title": "Add a relation to an existing document"}, {"location": "cozy-client/relationships/#remove-a-relation-to-an-existing-document", "text": "For has-many relationships, use the remove(docs) method: const wrongAuthors = [{ _id : 'James Wrong' }, { _id : 'Henry Mistake' }] const response = await client . query ( query ) const docs = response . data const firstDoc = docs [ 0 ] firstDoc . authors . remove ( wrongAuthors ) Just like add , remove accepts a single document. For has-one relationships, just use remove() , with no argument: const response = await client . query ( query ) const docs = response . data const firstDoc = docs [ 0 ] firstDoc . printingCompany . remove ()", "title": "Remove a relation to an existing document"}, {"location": "cozy-client/relationships/#create-a-new-file-with-existing-relations", "text": "Simply pass the reference to your file as a third parameter to create() : const photo = { _id : \"sunset.jpg\" } const reference = { _id : \"1324\" , _type : \"io.cozy.photos.albums\" } const albumReference = { albums : [ albumReference ] } await client . create ( 'io.cozy.files' , photo , albumReference )", "title": "Create a new file with existing relations"}, {"location": "cozy-client/schema/", "text": "What is a Cozy-Client schema? \u00b6 Schemas help Cozy-Client to know about the structure of your documents. With schemas, Cozy-Client may automatically fill the version attributes in cozyMetadata , it will allows traversal of links between documents, and it will help you validate your document before saving them in the CouchDB database. Structure of a schema \u00b6 A schema for a doctype is an object with the following attributes: doctype : the actual doctype name in cozy doctypeVersion : the version of the schema for this doctype ; it will help you to manage documents from different versions or migrate documents from a version to another attributes : the list of attributes with their constraints relationships : the description of the relations between documents All attributes but the doctype one are entirely optional. { \"doctype\" : \"io.cozy.todos\" , \"doctypeVersion\" : 45 , \"attributes\" : { \"label\" : { \"unique\" : true }, }, \"relationships\" : { \"tasks\" : { \"doctype\" : \"io.cozy.tasks\" , \"type\" : \"has-many\" } } } Today, attributes have only a unique property which, when at true will validate the uniqueness of the value. Other properties will be added in the future. You do not need to list every attribute you use. You may only add those for which you have a constraint to list. Relations are described in the \u201cUsing relationship\u201d document. Providing schemas \u00b6 Schemas are provided with a keyed object in the schema parameter at CozyClient initialization: const schema = { todos : { doctype : 'io.cozy.books' , attributes : {}, relationships : { items : { doctype : 'io.cozy.contact' , type : 'has-many' } } } } const client = new CozyClient ({ uri : 'http://cozy.tools:8080' , token : '...' , schema }) Adding a schema to an already initialized CozyClient instance \u00b6 Provide your schemas to the addSchema() method, in the same form as for initialization: const client = new CozyClient ({ uri : 'http://cozy.tools:8080' , token : '...' , schema : { } }) const additionalSchema = { todos : { doctype : 'io.cozy.books' , attributes : {}, relationships : { items : { doctype : 'io.cozy.contact' , type : 'has-many' } } } } client . addSchema ( additionalSchema ) Validation \u00b6 Today Cozy-Client only validates uniqueness of fields described as is in the schema. If you provide a schema, Cozy-Client will automatically try to validate your documents when you save them. An exception will be thrown if the validation fails. You can validate a document explicitly with validate() . Be sure the document has a _type attribute with the doctype name if it has never been saved to CouchDB. const book = { _type : 'io.cozy.books' , name : 'La horde de contrevent' } if ( ! client . validate ( book )) { throw new Error ( 'Something is wrong with this book document' ) }", "title": "Schema"}, {"location": "cozy-client/schema/#what-is-a-cozy-client-schema", "text": "Schemas help Cozy-Client to know about the structure of your documents. With schemas, Cozy-Client may automatically fill the version attributes in cozyMetadata , it will allows traversal of links between documents, and it will help you validate your document before saving them in the CouchDB database.", "title": "What is a Cozy-Client schema?"}, {"location": "cozy-client/schema/#structure-of-a-schema", "text": "A schema for a doctype is an object with the following attributes: doctype : the actual doctype name in cozy doctypeVersion : the version of the schema for this doctype ; it will help you to manage documents from different versions or migrate documents from a version to another attributes : the list of attributes with their constraints relationships : the description of the relations between documents All attributes but the doctype one are entirely optional. { \"doctype\" : \"io.cozy.todos\" , \"doctypeVersion\" : 45 , \"attributes\" : { \"label\" : { \"unique\" : true }, }, \"relationships\" : { \"tasks\" : { \"doctype\" : \"io.cozy.tasks\" , \"type\" : \"has-many\" } } } Today, attributes have only a unique property which, when at true will validate the uniqueness of the value. Other properties will be added in the future. You do not need to list every attribute you use. You may only add those for which you have a constraint to list. Relations are described in the \u201cUsing relationship\u201d document.", "title": "Structure of a schema"}, {"location": "cozy-client/schema/#providing-schemas", "text": "Schemas are provided with a keyed object in the schema parameter at CozyClient initialization: const schema = { todos : { doctype : 'io.cozy.books' , attributes : {}, relationships : { items : { doctype : 'io.cozy.contact' , type : 'has-many' } } } } const client = new CozyClient ({ uri : 'http://cozy.tools:8080' , token : '...' , schema })", "title": "Providing schemas"}, {"location": "cozy-client/schema/#adding-a-schema-to-an-already-initialized-cozyclient-instance", "text": "Provide your schemas to the addSchema() method, in the same form as for initialization: const client = new CozyClient ({ uri : 'http://cozy.tools:8080' , token : '...' , schema : { } }) const additionalSchema = { todos : { doctype : 'io.cozy.books' , attributes : {}, relationships : { items : { doctype : 'io.cozy.contact' , type : 'has-many' } } } } client . addSchema ( additionalSchema )", "title": "Adding a schema to an already initialized CozyClient instance"}, {"location": "cozy-client/schema/#validation", "text": "Today Cozy-Client only validates uniqueness of fields described as is in the schema. If you provide a schema, Cozy-Client will automatically try to validate your documents when you save them. An exception will be thrown if the validation fails. You can validate a document explicitly with validate() . Be sure the document has a _type attribute with the doctype name if it has never been saved to CouchDB. const book = { _type : 'io.cozy.books' , name : 'La horde de contrevent' } if ( ! client . validate ( book )) { throw new Error ( 'Something is wrong with this book document' ) }", "title": "Validation"}, {"location": "cozy-client/timeseries/", "text": "How-to manipulate time series \u00b6 Save time series \u00b6 This example shows how to save a time series of an electrical consumption: const electricalConsumption = { dataType : 'electricity' , startDate : \"2021-02-14T00:30:00+01:00\" , endDate : \"2021-02-14T02:30:00+01:00\" , source : \"enedis.fr\" , theme : \"energy\" series : [ { date : \"2021-02-14T00:30:00+01:00\" , consumption : 474 }, { date : \"2021-02-14T01:30:00+01:00\" , consumption : 184 }, { date : \"2021-02-14T02:30:00+01:00\" , consumption : 152 } ] } await saveTimeSerie ( client , electricalConsumption ) Retrieve time series \u00b6 This example shows how to fetch time series of an electrical consumption, for a specific time interval and data source: const params = { dataType : 'electricity' , startDate : \"2021-02-14\" , endDate : \"2021-02-15\" , source : \"enedis.fr\" , limit : 100 } const electricalConsumption = await fetchTimeSerieByIntervalAndSource ( client , params )", "title": "Using time series"}, {"location": "cozy-client/timeseries/#how-to-manipulate-time-series", "text": "", "title": "How-to manipulate time series"}, {"location": "cozy-client/timeseries/#save-time-series", "text": "This example shows how to save a time series of an electrical consumption: const electricalConsumption = { dataType : 'electricity' , startDate : \"2021-02-14T00:30:00+01:00\" , endDate : \"2021-02-14T02:30:00+01:00\" , source : \"enedis.fr\" , theme : \"energy\" series : [ { date : \"2021-02-14T00:30:00+01:00\" , consumption : 474 }, { date : \"2021-02-14T01:30:00+01:00\" , consumption : 184 }, { date : \"2021-02-14T02:30:00+01:00\" , consumption : 152 } ] } await saveTimeSerie ( client , electricalConsumption )", "title": "Save time series"}, {"location": "cozy-client/timeseries/#retrieve-time-series", "text": "This example shows how to fetch time series of an electrical consumption, for a specific time interval and data source: const params = { dataType : 'electricity' , startDate : \"2021-02-14\" , endDate : \"2021-02-15\" , source : \"enedis.fr\" , limit : 100 } const electricalConsumption = await fetchTimeSerieByIntervalAndSource ( client , params )", "title": "Retrieve time series"}, {"location": "cozy-client/api/cozy-pouch-link/", "text": "Classes \u00b6 PouchLink Link to be passed to a CozyClient instance to support CouchDB. It instantiates PouchDB collections for each doctype that it supports and knows how to respond to queries and mutations. Loop Utility to call a function (task) periodically and on demand immediately. Public API start stop scheduleImmediateTask waitForCurrentTask PouchManager Handles the lifecycle of several pouches Creates/Destroys the pouches Replicates periodically Constants \u00b6 persistLastReplicatedDocID Persist the last replicated doc id for a doctype getLastReplicatedDocID \u21d2 string Get the last replicated doc id for a doctype destroyAllLastReplicatedDocID Destroy all the replicated doc id getPersistedSyncedDoctypes \u21d2 object Get the persisted doctypes destroySyncedDoctypes Destroy the synced doctypes persistDoctypeLastSequence Persist the last CouchDB sequence for a synced doctype getDoctypeLastSequence \u21d2 string Get the last CouchDB sequence for a doctype destroyAllDoctypeLastSequence Destroy all the last sequence destroyDoctypeLastSequence Destroy the last sequence for a doctype persistWarmedUpQueries Persist the warmed up queries getPersistedWarmedUpQueries \u21d2 object Get the warmed up queries destroyWarmedUpQueries Destroy the warmed queries getAdapterName \u21d2 string Get the adapter name persistAdapterName Persist the adapter name fetchRemoteInstance \u21d2 object Fetch remote instance fetchRemoteLastSequence \u21d2 string Fetch last sequence from remote instance replicateAllDocs \u21d2 Array Replicate all docs locally from a remote URL. It uses the _all_docs view, and bulk insert the docs. Note it saves the last replicated _id for each run and starts from there in case the process stops before the end. getDatabaseName \u21d2 string Get the database name based on prefix and doctype getPrefix \u21d2 string Get the URI prefix Functions \u00b6 getQueryAlias(query) \u21d2 string Typedefs \u00b6 SyncStatus : \"idle\" | \"replicating\" MigrationParams : object Migrate the current adapter SyncInfo : object Persist the synchronized doctypes MigrationParams \u21d2 object Migrate a PouchDB database to a new adapter. PouchLink \u00b6 Link to be passed to a CozyClient instance to support CouchDB. It instantiates PouchDB collections for each doctype that it supports and knows how to respond to queries and mutations. Kind : global class PouchLink new PouchLink([opts]) .replicationStatus : Record. .getPouchAdapterName \u21d2 string .handleOnSync() .startReplication() \u21d2 void .stopReplication() \u21d2 void .needsToWaitWarmup(doctype) \u21d2 boolean new PouchLink([opts]) \u00b6 constructor - Initializes a new PouchLink Returns : object - The PouchLink instance Param Type Default Description [opts] object [opts.replicationInterval] number Milliseconds between replications opts.doctypes Array. Doctypes to replicate opts.doctypesReplicationOptions Array.