> ## Documentation Index
> Fetch the complete documentation index at: https://docs.kobble.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Javascript

> Learn how to integrate Kobble in any Javascript Application.

## Quick start

<Steps>
  <Step title="Install @kobbleio/javascript">
    Our SDK for javascript applications helps you to easily authenticate your users in your Vue.js application and manage their session.

    <CodeGroup>
      ```bash npm theme={null}
      npm install @kobbleio/javascript
      ```

      ```bash yarn theme={null}
      yarn add @kobbleio/javascript
      ```

      ```bash pnpm theme={null}
      pnpm add @kobbleio/javascript
      ```
    </CodeGroup>
  </Step>

  <Step title="Initialize the SDK">
    Create a file `src/kobble/index.ts` where you will initialize the SDK and export the Kobble instance.

    ```typescript theme={null}

    import { createKobbleClient } from '@kobbleio/javascript'

    export const kobble = createKobbleClient({
        domain: '<DOMAIN_OF_YOUR_KOBBLE_APPLICATION>',
        clientId: '<CLIENT_ID_OF_YOUR_KOBBLE_APPLICATION>',
        redirectUri: '<YOUR_CALLBACK_PAGE_URL>',
    })
    ```

    <Note>**KOBBLE\_DOMAIN** and **KOBBLE\_CLIENT\_ID** can be found in your [Kobble Application](https://app.kobble.io/p/applications). The **REDIRECT\_URI** must match the callback route we're going to configure in the next step of this tutorial.</Note>
  </Step>

  <Step title="Create a callback handler">
    Once the user is logged in or signed up, Kobble will redirect the user back to your application with the user's session information. You need to create a callback handler to handle this redirect.

    In this example we demonstrate how to do it in Vue.js but you can adapt it to any other javascript page.

    Use the Kobble client to handle the callback and redirect the user to the home page.

    ```typescript theme={null}
    async mounted() {
        try {
            await kobble.handleRedirectCallback()
            this.$router.replace({ name: 'home' })
        } catch (e: any) {
            console.error('Error handling redirect callback:', e)
        }
    }
    ```
  </Step>

  <Step title="Use the loginWithRedirect method">
    Then we can use the `loginWithRedirect` method to redirect the user to the Kobble login page whenever we want to authenticate the user.

    For example with a simple button in vue.js:

    ```typescript theme={null}
    <script>
        import { kobble } from '../kobble'

        const login = async () => {
        await kobble.loginWithRedirect()
    }
    </script>
    <template>
        <button @click="login">Login</button>
    </template>
    ```
  </Step>
</Steps>

## Authentication

The kobble client exposes various methods to manipulate the user authentication state.

### Login with redirect

This method triggers a redirect to your Kobble customer portal to start the authentication flow.

Once the user is authenticated, Kobble will redirect the user back to your Callback URL configured while initializing the SDK.

```typescript theme={null}
// In an async context
await kobble.loginWithRedirect()
```

### Logout

Delete the user session and redirect the user to the Kobble logout page.

This method does redirect the user anywhere, you need to handle the redirection yourself if needed.

Returns `Promise<void>`

```typescript theme={null}
// In an async context
await kobble.logout()
```

### Handle redirect callback

```typescript theme={null}
// In an async context
await kobble.handleRedirectCallback()
```

Returns `Promise<void>`

### Get user

```typescript theme={null}
// In an async context
const user = await kobble.getUser()
```

Returns `Promise<User | null>`
Where User is matching the following type:

```typescript theme={null}
export type User = {
  id: string
  email: string | null
  name: string | null
  pictureUrl: string | null
  isVerified: boolean
  stripeId: string | null
  updatedAt: Date
  createdAt: Date
}
```

### Get access token

```typescript theme={null}
// In an async context
const accessToken = await kobble.getAccessToken()
```

Returns `Promise<string | null>`

### Get id token

```typescript theme={null}
// In an async context
const idToken = await kobble.getIdToken()
```

Returns `Promise<string | null>`

### Is authenticated

Allows you to check if the user is authenticated.

```typescript theme={null}
// In an async context
const isAuthenticated = await kobble.isAuthenticated()
```

Returns `Promise<boolean>`

### Listen to user state changes

The javascript SDK will keep track of the user state.

However, you can also listen to the user state changes to trigger some custom logic in your application.

<Note>The callback may be called multiple times. For example when you refresh the page, the callback will be called with user = null and then with the user object if present.</Note>

```typescript theme={null}
kobble.onUserStateChanged((data) => {
    console.log('User state changed:', data.user) // User | null
})
```

## Permissions

### List all permissions

Returns the list of permissions applied to the authenticated user.

```typescript theme={null}
// In an async context
const permissions = await kobble.acl.listPermissions();
```

Returns `Promise<Permission[]>`

Where Permission is matching the following type:

```typescript theme={null}
export type Permission = {
    id: string
    name: string
}
```

### Check if the user has a permission

```typescript theme={null}
// In an async context
const hasPermission = await kobble.acl.hasPermission('generate-image');

// can take an array of permission names
const hasPermissionVariant = await kobble.acl.hasPermission(['permission-one', 'permission-two']);
```

Returns `Promise<boolean>`

## Quotas

### List all quotas

Returns the list of quotas applied to the authenticated user.

```typescript theme={null}
// In an async context
const quotas = await kobble.acl.listQuotas();
```

Returns `Promise<Quota[]>`

Where Quota is matching the following type:

```typescript theme={null}
export type Quota = {
    id: string
    name: string
    remaining: number
    limit: number
    usage: number
}
```

### Has remaining quota

You can check how much credit is left for a specific quota of the authenticated user by using the `hasRemainingQuota` method.

```typescript theme={null}
// In an async context
const hasRemainingQuota = await kobble.acl.hasRemainingQuota('generate-image');

// can take an array of quota names
const hasRemainingQuotaVariant = await kobble.acl.hasRemainingQuota(['quota-one', 'quota-two']);
```

Returns `Promise<boolean>`

## Integrations

### Supabase

If you are using Supabase, you can easily integrate Kobble with your Supabase application and then generate a Supabase token for the authenticated user.

<Note>Learn more about our Supabase integration in our [Supabase guide](/learning/quickstart/supabase)</Note>

```typescript theme={null}
// In an async context
const supabaseToken = await kobble.getSupabaseToken()
```

Returns `Promise<string | null>`

## Utils

### Open profile page

Open your customer portal profile page in a new tab or the same tab depending on the target parameter.

```typescript theme={null}
// In an async context
await kobble.openPortalProfile()
```

Parameters:

* target (optional): `'_blank' | '_self'` - default is `'_self'`

Returns `Promise<void>`

### Open portal pricing page

Open your customer portal pricing page in a new tab or the same tab depending on the target parameter.

```typescript theme={null}
// In an async context
await kobble.openPortalPricing()

```

Parameters:

* target (optional): `'_blank' | '_self'` - default is `'_self'`

Returns `Promise<void>`

### Get portal URL

Get the URL of your customer portal page.

```typescript theme={null}
const url = kobble.getPortalUrl()
```

Returns `string`

### Get portal profile URL

Get the URL of your customer portal profile page.

```typescript theme={null}
const url = kobble.getPortalProfileUrl()
```

Returns `string`

### Get portal pricing URL

Get the URL of your customer portal pricing page.

```typescript theme={null}
const url = kobble.getPortalPricingUrl()
```

Returns `string`

## Using it in a Chrome Extension

It's possible to use this SDK in a chrome extension, however you will have some prerequisites to make it work.

### Setup

Instead of importing the `KobbleClient` from `@kobbleio/javascript`, you will need to import the `KobbleWebExtensionClient` from `@kobbleio/javascript/web-extension`.

```typescript theme={null}
import { createKobbleWebExtensionClient } from '@kobbleio/javascript/web-extension'

export const kobble = createKobbleWebExtensionClient({
    domain: 'KOBBLE_DOMAIN',
    clientId: 'KOBBLE_CLIENT_ID',
})
```

<Note>Due to how chrome extensions work, you won't need to pass the redirectUri parameter.</Note>

### Update your manifest

You must add the following permissions in your Manifest.json file.

```json theme={null}
// manifest.json
{
    "permissions": [
        "storage",
        "identity",
        "*://*.kobble.io/*",
        "tabs",
    ]
    // rest of the file...
}
```

### Add the redirect URI

You must add the redirect URI of your Chrome Extension to your application in your Kobble dashboard.

1. Open the [Applications tab](https://app.kobble.io/p/applications) of your Kobble dashboard.
2. Click on the application you're using in your Chrome extension.
3. Scroll to the `Authorized redirect URIs` section and click on `Edit`.
4. Add the following URI: `https://ID.chromiumapp.org/callback` where `ID` is the ID of your Chrome extension.

<Note>The **ID** of your extension can be found on this page `chrome://extensions/`. Here is [more information about how to find your ID](https://developer.chrome.com/docs/extensions/how-to/distribute/install-extensions?#prereq-crx). Note that the ID may change if you remove and reload your extension.</Note>

### Usage differences

Both SDKs are quite similar, however, the `KobbleWebExtensionClient` does not need to handle the redirect callback.

Which means that the `loginWithRedirect` method will directly return the user tokens and you won't have to create a callback page nor using the `handleRedirectCallback` method.

```typescript theme={null}
// In an async function
const result = await kobble.loginWithRedirect()
const user = await kobble.getUser()
```

Other methods work the same way as the regular Kobble Client. There are differences in the way they implement the interface (such as for storage) but these differences must not affect your development.
