Metawrite Documentation
Support Us
Get free $100 credits on DigitalOcean:
Join our Discord:
Metawrite is Appwrite SDK with ready to go components for Svelte
/ SvelteKit
This package is maintained by Increasio.
Note: versions
x.x.n
neans some minor changes to package documentation or typings.versions
x.n.x
might include some minor breaking changes. See Release Notes.versions
n.x.x
might include some major breaking changes. See Release Notes.
Documentation
Installation
Using NPM:
npm install metawrite
Using Yarn:
yarn add metawrite
Usage
You need a running instance of Appwrite to use this library. Go to https://appwrite.io/docs/installation for more instructions.
Psuedo Example
Handle multiple levels of async relational data (and their loading & fallback states) entirely from the Svelte markup.
<!-- 1. πͺ Appwrite App -->
<Appwrite {...config}>
<!-- 2. π Get the current user if logged in -->
<User let:user>
<h1>Hello {user.name}!</h1>
<!-- 3. π Get all the documents from a collection -->
<Collection collectionId="5f56a3035a01f" let:documents>
You have {documents.length} documents.
{#each documents as document}
<!-- 4. π Get a document -->
<Document collectionId="5f56a3035a01f" documentId={document.$id} {document}>
Title: {document.title}
Text: {document.text}
...
Initialize
Must be initialised and wrap every metawrite
component.
<script>
import { Appwrite } from 'metawrite';
const config = {
endpoint: 'http://localhost/v1',
project: 'demo',
locale: 'fr'
};
</script>
<Appwrite {...config}>...</Appwrite>
Properties
Name | Description |
---|---|
endpoint | Your Appwrite endpoint. @type - {string} |
project | Your project ID. @type - {string} |
locale | Optional The users locale. @type - {string} |
Create user
Registers a new account.
<script>
import { Create } from 'metawrite';
let email = '';
let password = '';
let name = '';
const success = (e) => {
//success callback
// `e` contains the user object
};
const failure = (e) => {
//failure callback
};
</script>
<Create let:actions on:success on:failure>
<input type="text" bind:value={email} />
<input type="password" bind:value={password} />
<input type="text" bind:value={name} />
<button on:click={actions.create(email, password, name)}>Register</button>
</Create>
Directives
let:actions object
Object with function.
Arguments
Name | Description |
---|---|
create(email, password, name) | Registers a new user. @type - {string} |
Events
on:success
Triggers on successful register.
Arguments
Name | Description |
---|---|
response | Response |
on:failure
Triggers on failed register.
Arguments
Name | Description |
---|---|
response | Response |
Login via Email
Login via email and password.
<script>
import { AuthEmail } from 'metawrite';
let email = '';
let password = '';
const success = (e) => {
//success callback
// `e` contains the user object
};
const failure = (e) => {
//failure callback
};
</script>
<AuthEmail let:authorize on:success on:failure>
<input type="text" bind:value={email} />
<input type="text" bind:value={password} />
<button on:click={authorize(email, password)}>Login</button>
</AuthEmail>
Directives
let:authorize function
Initiates login.
Arguments
Name | Description |
---|---|
email | E-Mail. @type - {string} |
password | Password. @type - {string} |
Events
on:success
Triggers on successful login.
Arguments
Name | Description |
---|---|
email | E-Mail. @type - {string} |
on:failure
Triggers on failed login.
Arguments
Name | Description |
---|---|
error | Error object. |
Login via OAuth2
Login via an OAuth2 provider.
<script>
import { AuthOAuth2 } from 'metawrite';
</script>
<AuthOAuth2
provider="google"
success="http://localhost:3000?success"
failure="http://localhost:3000?failure"
let:authorize
>
<button on:click={authorize}>Login Google</button>
</AuthOAuth2>
Properties
Name | Description |
---|---|
provider | OAuth2 provider. @type - {string} |
success | Success url. @type - {string} |
failure | Failure url. @type - {string} |
Directives
let:authorize function
Get user
Requests current user to check if logged in.
<script>
import { User } from 'metawrite';
</script>
<User let:user>
<h1>Hello {user.name}!</h1>
<div>{user.email}</div>
<div slot="error">You are not logged in!</div>
</User>
Directives
let:user object
Get currently logged in user data.
Get Collection
Get a list of all the documents from a collection.
<script>
import { Collection } from 'metawrite';
</script>
<Collection collectionId="5f56a3035a01f" let:documents>
You have {documents.length} documents.
</Collection>
Properties
Name | Description |
---|---|
collectionId | Collection unique ID. @type - {string} |
additional | same as here |
Directives
let:documents array
Array of documents.
let:actions object
Object with function.
Arguments
Name | Description |
---|---|
reload() | Re-fetch collection. |
create(data, read, write) | Create a new Document in the collection. read /write is optional and current user by default @type - {string[]} . data is @type - {string} |
Get Document
Get a document. If you pass the document
property with data from
<script>
import { Document } from 'metawrite';
</script>
<Document documentId="5f56a3asda01f" let:document>
Title: {document.title}
Text: {document.text}
</Document>
Properties
Name | Description |
---|---|
documentId | Document unique ID. @type - {string} |
collectionId | Collection unique ID. @type - {string} |
or | |
document | Document passed from <Collection /> |
Directives
let:document object
A JSON object with the document data.
let:actions object
Object with function.
Arguments
Name | Description |
---|---|
update(data) | Update the document. data is @type - {string} |
remove() | Deletes the document. |
reload() | Re-fetch document. |
Events
on:change
Triggers on update or remove login.
API
Account
The Account components allow you to manage a user account.
<User />
Slots
- loading
- error
Directives
let:actions
| Name | Description |
| --- | --- |
| reload()
| Reload. |
| logout()
| Logout current session. |
| logoutAll()
| Logout from all session. |
| logoutFrom(session)
| Logout from specific session. session
is @type - {string}
|
- let:user
object
- let:error
Events
- on:success On user fetch success.
- on:failure On user fetch failure.
- on:successLogout On
logout
success. - on:failureLogout On
logout
failure. - on:successLogoutFrom On
logoutFrom
success. - on:failureLogoutFrom On
logoutFrom
failure. - on:successLogoutAll On
logoutAll
success. - on:failureLogoutAll On
logoutAll
failure.
Example
<script>
import { User } from 'metawrite';
</script>
<User let:actions let:user>
<button on:click={actions.reload()}>Reload user data</button>
<button on:click={actions.get()}>Get logged in user data</button>
<button on:click={actions.logout()}>Log out from current session</button>
<button on:click={actions.logoutFrom('sessionId')}>Log out from specific session</button>
<button on:click={actions.logoutAll()}>Log out from all sessions</button>
<!-- If logged in -->
<p>Hi, {user.name}</p>
</User>
<Create />
Directives
let:actions
| Name | Description |
| --- | --- |
| create(email, password, name)
| Creates a user. email
and password
are required - @type - {string}
. name
is optional - @type - {string}
|
Events
- on:success On
create
success. - on:failure On
create
failure.
Example
<script>
import { Create } from 'metawrite';
let name,
email,
password = '';
const success = (e) => {
// success callback
// `e` contains the user object
};
const failure = (e) => {
// failure callback
};
</script>
<Create let:actions on:success on:failure>
<input type="text" name="name" placeholder="name" bind:value={name} />
<input type="text" name="email" placeholder="email" bind:value={email} />
<input type="password" name="password" placeholder="password" bind:value={password} />
<button on:click={actions.create(name, email, password)}>Create Account</button>
</Create>
<Delete />
Deletes currently logged in user's account.
Directives
let:actions
| Name | Description |
| --- | --- |
| delete()
| Deletes currently logged in user. |
Events
- on:success On
delete
success. - on:failure On
delete
failure.
Example
<script>
import { Delete } from 'metawrite';
const success = (e) => {
//success callback
// `e` contains the user object
};
const failure = (e) => {
//failure callback
};
</script>
<Delete let:actions on:success on:failure>
<button on:click={actions.delete}>Delete my account</button>
</Delete>
<Preferences />
Slots
- loading
- error
Directives
let:actions
| Name | Description |
| --- | --- |
| reload()
| Reloads preferences. |
| update(prefs)
| Update preferences. prefs
- @type - {object}
|
Events
- on:success On init and
reload
success. - on:failure On init and
reload
failure. - on:successUpdate On
update
success. - on:failureUpdate On
update
failure.
Example
<script>
import { Preferences } from 'metawrite';
let prefs = {
// You can pass only the specific settings you wish to update.
};
</script>
<Preferences let:actions>
<button
on:click={() => {
actions.update(prefs);
actions.reload();
}}>Update Preferences</button
>
</Preferences>
<RecoverPassword />
Directives
let:actions
| Name | Description |
| --- | --- |
| recover(email, url)
| Recover password. email
and url
is required and @type - {string}
. url
is your page where you will handle secret
with complete
function. |
| complete(user, secret, password, passwordAgain)
| Complete password recovery. user
and secret
are set automatically by metawrite
, so you donβt have to set them. password
and passwordAgain
are required - @type - {string}
. |
Events
- on:successRecover On init and
reload
success. - on:failureRecover On init and
reload
failure. - on:successComplete On
update
success. - on:failureComplete On
update
failure.
Example
<script>
import { RecoverPassword } from "metawrite";
const url = "http://localhost:3000/reset-password"; // URL that will point to the next step.
let email = '';
const successRecover = e => {
//success callback
// `e` contains the user object
};
const failureRecover = e => {
//failure callback
}
</script>
<!-- localhost/forgot-password -->
<RecoverPassword let:actions on:successRecover on:failureRecover>
<input name="email" type="text" bind:value={email, url} placeholder="Email" />
<button on:click{actions.recover(email)}>Recover Password</button>
</RecoverPassword>
<!-- Then on localhost/reset-password -->
<script>
import { RecoverPassword } from "metawrite";
let password, passwordAgain = '';
const successComplete = e => {
//success callback
// `e` contains the user object
};
const failureComplete = e => {
//failure callback
}
</script>
<RecoverPassword let:actions on:successComplete on:failureComplete>
<input type="password" name="password" bind:value{password} placeholder="Password" />
<input type="password" name="password" bind:value{passwordAgain} placeholder="Confirm Password" />
<button on:click{actions.complete(password, passwordAgain)}>Set New Password</button>
</RecoverPassword>
<Update />
Directives
let:actions
| Name | Description |
| --- | --- |
| name(name)
| Update name. All fields are required. @type - {string}
|
| email(email, password)
| Update email. All fields are required. @type - {string}
|
| password(password, oldPassword)
| Update password. All fields are required. @type - {string}
|
Events
- on:successName On
name
success. - on:failureName On
name
failure. - on:successEmail On
email
success. - on:failureEmail On
email
failure. - on:successPassword On
password
success. - on:failurePassword On
password
failure.
Example
<script>
import { Update } from 'metawrite';
let name,
email,
password,
newPassword,
oldPassword = '';
</script>
<Update let:actions>
<button on:click={actions.name(name)}>This updates name</button>
<button on:click={actions.email(email, password)}>This updates email</button>
<button on:click={actions.password(newPassword, oldPassword)}>This updates password</button>
</Update>
<Verification />
Creates and automatically validates user email verification.
url
of type string for actioncreate
should be where your app is hosted orlocalhost
.- For
update
action you don't need to pass anything, the process is automated.
Directives
let:actions
| Name | Description |
| --- | --- |
| create(url)
| Create Verification. url
is what URL used to create verification link sent to your email inbox. @type - {string}
|
| update(user, secret)
| Complete Verification. user
and secret
are set automatically by metawrite
. |
Events
- on:successCreate On
create
success. - on:failureCreate On
create
failure. - on:successComplete On
complete
success. - on:failureComplete On
complete
failure.
Example
<script>
import { Verification } from 'metawrite';
const url = window.location.href;
</script>
<Verification let:actions>
<button on:click={actions.create(url)} />
<button on:click={actions.update()}>Update email verification status</button>
</Verification>
Auth
The Auth components allow you to authenticate a user account.
<AuthEmail />
Slots
- loading
- success
- error
Directives
- let:authorize(email, password)
- let:user
- let:error
Events
- on:success On
authorize
success. - on:failure On
authorize
failure.
Example
<script>
import { AuthEmail } from 'metawrite';
let email = '';
let password = '';
const success = (e) => {
//success callback
// `e` contains the user object
};
const failure = (e) => {
//failure callback
};
</script>
<AuthEmail let:authorize on:success on:failure>
<input type="text" bind:value={email} />
<input type="text" bind:value={password} />
<button on:click={authorize(email, password)}>Login</button>
</AuthEmail>
<AuthOAuth2 />
Properties
Name | Description |
---|---|
provider | OAuth2 provider. @type - {string} |
success | Success url. @type - {string} |
failure | Failure url. @type - {string} |
#### Directives |
let:authorize()
Example
<script>
import { AuthOAuth2 } from 'metawrite';
</script>
<AuthOAuth2
provider="google"
success="http://localhost:3000?success"
failure="http://localhost:3000?failure"
let:authorize
>
<button on:click={authorize}>Login Google</button>
</AuthOAuth2>
<CreateAnonymousSession />
Directives
let:actions
Name | Description |
---|---|
create() | Creates anonymous session. |
Example
<script>
import { CreateAnonymousSession } from 'metawrite';
</script>
<CreateAnonymousSession let:actions>
<button on:click={actions.create}>Create Anonymous Session</button>
</CreateAnonymousSession>
<CreateJWT />
Creates JWT token.
Directives
let:actions
Name | Description |
---|---|
create() | Creates JWT token. |
Example
<script>
import { CreateJWT } from 'metawrite';
</script>
<CreateJWT let:actions>
<button on:click={actions.create}>Create JWT token</button>
</CreateJWT>
<MagicURL />
Creates Magic URL Session.
Directives
let:actions
Name | Description |
---|---|
create() | Creates Magic URL Session. |
Example
<script>
import { MagicURL } from 'metawrite';
const userId = '32h2hj24h2';
const email = 'user@example.com';
const url = 'http://example.com'; // optional
</script>
<MagicURL let:actions>
<button on:click={actions.create(userId, email, url)}>Create MagicURL</button>
</MagicURL>
Avatars
The Avatar components aim to help you complete everyday tasks related to your app image, icons, and avatars.
<Browser />
Arguments
- code - required
@type - {string}
- width - optional
@type - {number}
- height - optional
@type - {string}
- quality - optional
@type - {string}
Directives
- let:src Image link
@type - {URL}
Example
<script>
import { Browser } from 'metawrite';
</script>
<Browser code="firefox" let:src>
<img src={String(src)} alt="Browser" />
</Browser>
<CreditCard />
Arguments
- code - required
@type - {string}
- width - optional
@type - {number}
- height - optional
@type - {string}
- quality - optional
@type - {string}
Directives
- let:src Image link
@type - {URL}
Example
<script>
import { CreditCard } from 'metawrite';
</script>
<CreditCard code="amex" let:src>
<img src={String(src)} alt="card" />
</CreditCard>
<Favicon />
Arguments
- url - required
@type - {string}
Directives
- let:src Image link
@type - {URL}
<script>
import { Favicon } from 'metawrite';
const url = window.location.href;
</script>
<Favicon {url} let:src>
<img src={String(src)} alt="favicon" />
</Favicon>
<Flag />
Arguments
- code - required
@type - {string}
- width - optional
@type - {number}
- height - optional
@type - {string}
- quality - optional
@type - {string}
Directives
- let:src Image link
@type - {URL}
Example
<script>
import { Flag } from 'metawrite';
</script>
<Flag code="canada" let:src>
<img src={String(src)} alt="flag" />
</Flag>
<Image />
Arguments
- url - required
@type - {string}
- width - optional
@type - {number}
- height - optional
@type - {number}
Directives
- let:src Image link
@type - {URL}
Example
<script>
import { Image } from 'metawrite';
let url = 'https://increas.io/';
let width,
height = 100;
</script>
<Image {url} {width} {height} let:src>
<img src={String(src)} alt="someImage" />
</Image>
<QR />
Arguments
- text - required
@type - {string}
- size - optional
@type - {optional}
- margin - optional
@type - {number}
- download - optional
@type - {boolean}
Directives
- let:src Image link
@type - {URL}
Example
<script>
import { QR } from 'metawrite';
let text = 'https://increas.io/'; // could be any text
let size = 500;
let margin = 1;
let download = false;
</script>
<QR {text} {size} {margin} {download} let:src>
<img src={String(src)} alt="QR Code" />
</QR>
Database
The Database components allow you to create structured collections of documents, query and filter lists of documents, and manage an advanced set of read and write access permissions.
<Collection />
Arguments
collectionId - required
@type - {string}
Cache - optional, by default set to false
@type - {boolean}
query:
@type - {object}
filters - optional
@type - {string[]}
offset - optional
@type - {number}
limit - optional
@type - {number}
orderField - optional
@type - {string}
orderType - optional
@type - {string}
orderCast - optional
@type - {string[]}
search - optional
@type - {string[]}
Slots
- loading
- error
Directives
let:actions
| Name | Description |
| --- | --- |
| reload()
| Reload. |
| create(data, read, write)
| Creates a Document. data
- @type - {string}
.
read
/write
is optional @type - {string[]}
|
- let:documents
- let:error
Example
<script>
import { Collection } from 'metawrite';
</script>
<Collection collectionId="5f56a3035a01f" let:documents>
You have {documents.length} documents.
</Collection>
<Document />
Arguments
- documentId - required
@type - {string}
- collectionId - required
@type - {string}
- document -
Promise<any>
Slots
- loading
- error
Directives
let:actions
| Name | Description |
| --- | --- |
| reload()
| Reload. |
| update(data)
| Updates a Document. data
- @type - {object}
|
| remove()
| Removes a Document. |
- let:document
- let:error
Example
<script>
import { Collection, Document } from 'metawrite';
const collectionId = '5f56a3035a01f';
</script>
<Collection {collectionId} let:documents>
You have {documents.length} documents:
{#each documents as document}
<Document {collectionId} documentId={document.$id} {document}>
Title: {document.title}
Text: {document.text}
</Document>
{/each}
</Collection>
Storage
The Storage components allow you to manage your project files. You can upload, view, download, and query all your project files.
<Storage />
Directives
let:actions
| Name | Description |
| --- | --- |
| create(fileId, file, read, write)
| Uploads a file. fileId
is required @type - {string}
, "unique()"
will generate random unique id, but you can use custom.file
is @type - {File}
and required.read
/write
is @type - {string[]}
and optional |
- let:files
Example
<script>
import { Storage } from 'metawrite';
// Required
/**@type {File}*/ let file;
/**@type {string}*/ let fileId = 'unique()'; // this will generate random unique id, but you can use custom
// Optional
/**@type {string[]}*/ let read;
/**@type {string[]}*/ let write;
</script>
<Storage {file} let:actions>
<button on:click={actions.create(fileId, file, read, write)}>Upload File</button>
</Storage>
<FileList />
Arguments
- search - optional
@type - {string}
- limit - optional
@type - {number}
- offset - optional
@type - {number}
- orderType - optional
@type - {string}
=> write"ASC"
or"DESC"
Slots
- loading
- error
Directives
let:actions
| Name | Description |
| --- | --- |
| reload()
| Reload. |
- let:files
- let:error
Example
<script>
import { FileList } from 'metawrite';
// Optional
let search = '';
let limit = 10;
let offset = 0;
let orderType = 'ASC';
</script>
<FileList {search} {limit} {offset} {orderType} let:actions let:files>
{#each files as file}
<p>File: {file.name}</p>
{/each}
<button on:click={actions.reload()}>Reload</button>
</FileList>
<File />
Arguments
- file - it is fileId
@type - {string}
Directives
let:actions
| Name | Description |
| --- | --- |
| download()
| Downloads file. |
| view(as)
| Get file for View. |
| preview(width, height, quality, background, output)
| Get file for preview. |
| update(read, write)
| Updates a file. |
| delete()
| Deletes a file. |
Example
<script>
import { File } from 'metawrite';
// Required
/**@type {File}*/ let file;
// OPTIONAL
/** @type {number} */ let width;
/** @type {number} */ let height;
/** @type {string} */ let gravity;
/** @type {number} */ let quality;
/** @type {number} */ let borderWidth;
/** @type {string} */ let borderColor;
/** @type {number} */ let borderRadius;
/** @type {number} */ let opacity;
/** @type {number} */ let rotation;
/** @type {string} */ let background;
/** @type {string} */ let output;
/** @type {string[]} */ let read;
/** @type {string[]} */ let write;
</script>
<File {file} let:actions>
<button on:click={actions.download()}>Download File</button>
<button on:click={actions.view()}>File View</button>
<button on:click={actions.preview()}>Preview File</button>
<button on:click={actions.update(read, write)}>Update File</button>
<button on:click={actions.delete()}>Delete File</button>
</File>
Functions
The Functions service allows you to create custom behaviour that can be triggered by any supported Appwrite system events or by a predefined schedule.
Appwrite Cloud Functions lets you automatically run backend code in response to events triggered by Appwrite or by setting it to be executed in a predefined schedule. Your code is stored in a secure way on your Appwrite instance and is executed in an isolated environment.
You can learn more by following Appwrite's Cloud Functions tutorial.
<Function />
Directives
let:actions
| Name | Description |
| --- | --- |
| reload()
| Reload. |
| create(functionId, data)
| Creates Execution. functionId
is required, data
could be empty string because optional. @type {string}
|
| create(functionId, executionId)
| Get Execution. Both parameters are required. @type {string}
|
- let:executions
Slots
- error
Example
<script>
import { Function } from 'metawrite';
let functionId = 'someExecution'; // required
let newFunctionId = '';
let data = 'String of custom data to send to function.'; // could be empty string because optional
</script>
<Function {functionId} {data} let:actions let:executions>
{#each executions as execution}
<p>
Execution ID: {execution.$id}, Function ID: {execution.functionId}, Date Created: {execution.dateCreated}
</p>
{/each}
<input type="text" name="functionId" placeholder="Function ID" bind:value={newFunctionId} />
<button on:click={actions.create(newFunctionId, data)}>Create Execution</button>
</Function>
Locale
The Locale components allow you to customize your app based on your users' location.
<Continents />
Directives
let:actions
| Name | Description |
| --- | --- |
| reload()
| Reload. |
- let:continents
Slots
- loading
- error
Example
<script>
import { Continents } from 'metawrite';
</script>
<Continents let:actions let:continents>
<button on:click={actions.reload()}>Reload</button>
<p>There are {continents.sum} continents:</p>
{#each continents.continents as continent}
<p>{continent.name}, {continent.code}</p>
{/each}
</Continents>
<Countries />
Arguments
- eu
Slots
- loading
- error
Directives
let:actions
| Name | Description |
| --- | --- |
| reload()
| Reload. |
- let:countries
Example
<script>
import { Countries } from 'metawrite';
let eu = true; // if you want to list only EU countries
</script>
<Countries let:actions let:countries>
<button on:click={actions.reload()}>Reload</button>
<p>There are {countries.sum} countries in the world:</p>
{#each countries.countries as country}
<p>{country.name}, {country.code}</p>
{/each}
</Countries>
<Countries {eu} let:actions let:countries>
<button on:click={actions.reload()}>Reload</button>
<p>There are {countries.sum} countries in EU:</p>
{#each countries.countries as country}
<p>{country.name}, {country.code}</p>
{/each}
</Countries>
<Currencies />
Slots
- loading
- error
Directives
let:actions
| Name | Description |
| --- | --- |
| reload()
| Reload. |
- let:currencies
Example
<script>
import { Currencies } from 'metawrite';
</script>
<Currencies let:actions let:currencies>
<button on:click={actions.reload()}>Reload</button>
<p>There are {currencies.sum} currencies:</p>
{#each currencies.currencies as currency}
<p>{currency.symbol} - {currency.name} ({currency.code})</p>
{/each}
</Currencies>
<Languages />
Slots
- loading
- error
Directives
let:actions
| Name | Description |
| --- | --- |
| reload()
| Reload. |
- let:languages
Example
<script>
import { Languages } from 'metawrite';
</script>
<Languages let:actions let:languages>
<button on:click={actions.reload()}>Reload</button>
<p>There are {languages.sum} languages:</p>
{#each languages.languages as language}
<p>{language.name}, {language.code}></p>
{/each}
</Languages>
<Locale />
Slots
- loading
- error
Directives
let:actions
| Name | Description |
| --- | --- |
| reload()
| Reload. |
- let:code
object
Example
<script>
import { Locale } from 'metawrite';
</script>
<Locale let:actions let:code>
<h1>Active Session</h1>
<button on:click={actions.reload()}>Reload</button>
<p>Location: {code.country}, {code.continentCode}</p>
<p>IP: {code.ip}</p>
</Locale>
<PhoneCodes />
Slots
- loading
- error
Directives
let:actions
| Name | Description |
| --- | --- |
| reload()
| Reload. |
- let:codes
Example
<script>
import { PhoneCodes } from 'metawrite';
</script>
<PhoneCodes let:actions let:codes>
<button on:click={actions.reload()}>Reload</button>
<p>There are {codes.sum} phone codes:</p>
{#each codes.phones as phone}
<p>{phone.code} - {phone.countyName}></p>
{/each}
</PhoneCodes>