Merge branch '1.6.x' of https://github.com/appwrite/console into feat-custom-execution-headers
@@ -61,6 +61,7 @@ Follow the [install instructions](https://appwrite.io/docs/advanced/self-hosting
|
||||
### 4. Setup environment variables
|
||||
|
||||
Add a `.env` file by copying the `.env.example` file as a template in the project's root directory.
|
||||
|
||||
> **Note**
|
||||
> If you are updating from Appwrite `1.5.x`, be aware that the variables for the console in the `.env` / `.env.example` file have changed in `1.6.x`.
|
||||
|
||||
|
||||
@@ -120,7 +120,7 @@
|
||||
bind:this={tooltip}
|
||||
class:u-width-full-line={fullWidth}
|
||||
style:--arrow-size={`${arrowSize}px`}
|
||||
style:z-index="10">
|
||||
style:z-index="21">
|
||||
<div
|
||||
class="drop-arrow"
|
||||
class:is-popover={isPopover}
|
||||
|
||||
@@ -31,9 +31,8 @@
|
||||
<div
|
||||
class="drop is-no-arrow"
|
||||
class:u-max-width-100-percent={fullWidth}
|
||||
style={`${width ? `--drop-width-size-desktop:${width}rem; ` : ''} ${
|
||||
position === 'static' ? 'position:static' : 'position:relative'
|
||||
}`}>
|
||||
style:--drop-width-size-desktop={width ? `${width}rem` : ''}
|
||||
style:position>
|
||||
{#if $$slots.list}
|
||||
<section
|
||||
class:u-overflow-y-auto={scrollable}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
:global(.theme-dark) .floating-action-bar {
|
||||
border: 1px solid hsl(var(--color-neutral-85));
|
||||
background: hsl(var(--color-neutral-90));
|
||||
box-shadow: 0px 6px 16px 8px #14141f;
|
||||
box-shadow: 0px 6px 16px 8px hsl(var(--color-neutral-105));
|
||||
}
|
||||
|
||||
:global(.theme-light) .floating-action-bar {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
$organization?.billingPlan === BillingPlan.PRO ||
|
||||
$organization?.billingPlan === BillingPlan.SCALE;
|
||||
|
||||
$: supportTimings = `${utcHourToLocaleHour('09:00')} - ${utcHourToLocaleHour('17:00')} ${localeTimezoneName()}`;
|
||||
$: supportTimings = `${utcHourToLocaleHour('16:00')} - ${utcHourToLocaleHour('00:00')} ${localeTimezoneName()}`;
|
||||
</script>
|
||||
|
||||
{#if isCloud}
|
||||
|
||||
@@ -65,200 +65,239 @@ export const scopes: {
|
||||
scope: string;
|
||||
description: string;
|
||||
category: string;
|
||||
icon: string;
|
||||
}[] = [
|
||||
{
|
||||
scope: 'sessions.write',
|
||||
description: "Access to create, update and delete your project's sessions",
|
||||
category: 'Auth'
|
||||
category: 'Auth',
|
||||
icon: 'user-group'
|
||||
},
|
||||
{
|
||||
scope: 'users.read',
|
||||
description: "Access to read your project's users",
|
||||
category: 'Auth'
|
||||
category: 'Auth',
|
||||
icon: 'user-group'
|
||||
},
|
||||
{
|
||||
scope: 'users.write',
|
||||
description: "Access to create, update, and delete your project's users",
|
||||
category: 'Auth'
|
||||
category: 'Auth',
|
||||
icon: 'user-group'
|
||||
},
|
||||
{
|
||||
scope: 'teams.read',
|
||||
description: "Access to read your project's teams",
|
||||
category: 'Auth'
|
||||
category: 'Auth',
|
||||
icon: 'user-group'
|
||||
},
|
||||
{
|
||||
scope: 'teams.write',
|
||||
description: "Access to create, update, and delete your project's teams",
|
||||
category: 'Auth'
|
||||
category: 'Auth',
|
||||
icon: 'user-group'
|
||||
},
|
||||
{
|
||||
scope: 'databases.read',
|
||||
description: "Access to read your project's databases",
|
||||
category: 'Database'
|
||||
category: 'Database',
|
||||
icon: 'database'
|
||||
},
|
||||
{
|
||||
scope: 'databases.write',
|
||||
description: "Access to create, update, and delete your project's databases",
|
||||
category: 'Database'
|
||||
category: 'Database',
|
||||
icon: 'database'
|
||||
},
|
||||
{
|
||||
scope: 'collections.read',
|
||||
description: "Access to read your project's database collections",
|
||||
category: 'Database'
|
||||
category: 'Database',
|
||||
icon: 'database'
|
||||
},
|
||||
{
|
||||
scope: 'collections.write',
|
||||
description: "Access to create, update, and delete your project's database collections",
|
||||
category: 'Database'
|
||||
category: 'Database',
|
||||
icon: 'database'
|
||||
},
|
||||
{
|
||||
scope: 'attributes.read',
|
||||
description: "Access to read your project's database collection's attributes",
|
||||
category: 'Database'
|
||||
category: 'Database',
|
||||
icon: 'database'
|
||||
},
|
||||
{
|
||||
scope: 'attributes.write',
|
||||
description:
|
||||
"Access to create, update, and delete your project's database collection's attributes",
|
||||
category: 'Database'
|
||||
category: 'Database',
|
||||
icon: 'database'
|
||||
},
|
||||
{
|
||||
scope: 'indexes.read',
|
||||
description: "Access to read your project's database collection's indexes",
|
||||
category: 'Database'
|
||||
category: 'Database',
|
||||
icon: 'database'
|
||||
},
|
||||
{
|
||||
scope: 'indexes.write',
|
||||
description:
|
||||
"Access to create, update, and delete your project's database collection's indexes",
|
||||
category: 'Database'
|
||||
category: 'Database',
|
||||
icon: 'database'
|
||||
},
|
||||
{
|
||||
scope: 'documents.read',
|
||||
description: "Access to read your project's database documents",
|
||||
category: 'Database'
|
||||
category: 'Database',
|
||||
icon: 'database'
|
||||
},
|
||||
{
|
||||
scope: 'documents.write',
|
||||
description: "Access to create, update, and delete your project's database documents",
|
||||
category: 'Database'
|
||||
category: 'Database',
|
||||
icon: 'database'
|
||||
},
|
||||
{
|
||||
scope: 'files.read',
|
||||
description: "Access to read your project's storage files and preview images",
|
||||
category: 'Storage'
|
||||
category: 'Storage',
|
||||
icon: 'folder'
|
||||
},
|
||||
{
|
||||
scope: 'files.write',
|
||||
description: "Access to create, update, and delete your project's storage files",
|
||||
category: 'Storage'
|
||||
category: 'Storage',
|
||||
icon: 'folder'
|
||||
},
|
||||
{
|
||||
scope: 'buckets.read',
|
||||
description: "Access to read your project's storage buckets",
|
||||
category: 'Storage'
|
||||
category: 'Storage',
|
||||
icon: 'folder'
|
||||
},
|
||||
{
|
||||
scope: 'buckets.write',
|
||||
description: "Access to create, update, and delete your project's storage buckets",
|
||||
category: 'Storage'
|
||||
category: 'Storage',
|
||||
icon: 'folder'
|
||||
},
|
||||
{
|
||||
scope: 'functions.read',
|
||||
description: "Access to read your project's functions and code deployments",
|
||||
category: 'Functions'
|
||||
category: 'Functions',
|
||||
icon: 'lightning-bolt'
|
||||
},
|
||||
{
|
||||
scope: 'functions.write',
|
||||
description:
|
||||
"Access to create, update, and delete your project's functions and code deployments",
|
||||
category: 'Functions'
|
||||
category: 'Functions',
|
||||
icon: 'lightning-bolt'
|
||||
},
|
||||
{
|
||||
scope: 'execution.read',
|
||||
description: "Access to read your project's execution logs",
|
||||
category: 'Functions'
|
||||
category: 'Functions',
|
||||
icon: 'lightning-bolt'
|
||||
},
|
||||
{
|
||||
scope: 'execution.write',
|
||||
description: "Access to execute your project's functions",
|
||||
category: 'Functions'
|
||||
category: 'Functions',
|
||||
icon: 'lightning-bolt'
|
||||
},
|
||||
{
|
||||
scope: 'targets.read',
|
||||
description: "Access to read your project's messaging targets",
|
||||
category: 'Messaging'
|
||||
category: 'Messaging',
|
||||
icon: 'send'
|
||||
},
|
||||
{
|
||||
scope: 'targets.write',
|
||||
description: "Access to create, update, and delete your project's messaging targets",
|
||||
category: 'Messaging'
|
||||
category: 'Messaging',
|
||||
icon: 'send'
|
||||
},
|
||||
{
|
||||
scope: 'providers.read',
|
||||
description: "Access to read your project's messaging providers",
|
||||
category: 'Messaging'
|
||||
category: 'Messaging',
|
||||
icon: 'send'
|
||||
},
|
||||
{
|
||||
scope: 'providers.write',
|
||||
description: "Access to create, update, and delete your project's messaging providers",
|
||||
category: 'Messaging'
|
||||
category: 'Messaging',
|
||||
icon: 'send'
|
||||
},
|
||||
{
|
||||
scope: 'messages.read',
|
||||
description: "Access to read your project's messages",
|
||||
category: 'Messaging'
|
||||
category: 'Messaging',
|
||||
icon: 'send'
|
||||
},
|
||||
{
|
||||
scope: 'messages.write',
|
||||
description: "Access to create, update, and delete your project's messages",
|
||||
category: 'Messaging'
|
||||
category: 'Messaging',
|
||||
icon: 'send'
|
||||
},
|
||||
{
|
||||
scope: 'topics.read',
|
||||
description: "Access to read your project's messaging topics",
|
||||
category: 'Messaging'
|
||||
category: 'Messaging',
|
||||
icon: 'send'
|
||||
},
|
||||
{
|
||||
scope: 'topics.write',
|
||||
description: "Access to create, update, and delete your project's messaging topics",
|
||||
category: 'Messaging'
|
||||
category: 'Messaging',
|
||||
icon: 'send'
|
||||
},
|
||||
{
|
||||
scope: 'subscribers.read',
|
||||
description: "Access to read your project's messaging topic subscribers",
|
||||
category: 'Messaging'
|
||||
category: 'Messaging',
|
||||
icon: 'send'
|
||||
},
|
||||
{
|
||||
scope: 'subscribers.write',
|
||||
description:
|
||||
"Access to create, update, and delete your project's messaging topic subscribers",
|
||||
category: 'Messaging'
|
||||
category: 'Messaging',
|
||||
icon: 'send'
|
||||
},
|
||||
{
|
||||
scope: 'locale.read',
|
||||
description: "Access to access your project's Locale service",
|
||||
category: 'Other'
|
||||
category: 'Other',
|
||||
icon: 'globe'
|
||||
},
|
||||
{
|
||||
scope: 'avatars.read',
|
||||
description: "Access to access your project's Avatars service",
|
||||
category: 'Other'
|
||||
category: 'Other',
|
||||
icon: 'globe'
|
||||
},
|
||||
{
|
||||
scope: 'health.read',
|
||||
description: "Access to read your project's health status",
|
||||
category: 'Other'
|
||||
category: 'Other',
|
||||
icon: 'globe'
|
||||
},
|
||||
{
|
||||
scope: 'migrations.read',
|
||||
description: "Access to read your project's migration status",
|
||||
category: 'Other'
|
||||
category: 'Other',
|
||||
icon: 'globe'
|
||||
},
|
||||
{
|
||||
scope: 'migrations.write',
|
||||
description: 'Access to create migrations',
|
||||
category: 'Other'
|
||||
category: 'Other',
|
||||
icon: 'globe'
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
}
|
||||
|
||||
function isFileExtensionAllowed(fileExtension: string) {
|
||||
if (allowedFileExtensions.length && !allowedFileExtensions.includes(fileExtension)) {
|
||||
if (allowedFileExtensions?.length && !allowedFileExtensions.includes(fileExtension)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
@@ -42,7 +42,7 @@
|
||||
hovering = false;
|
||||
if (!ev.dataTransfer.items) return;
|
||||
for (let i = 0; i < ev.dataTransfer.items.length; i++) {
|
||||
const fileExtension = ev.dataTransfer.items[i].getAsFile().name.split('.')[1];
|
||||
const fileExtension = ev.dataTransfer.items[i].getAsFile().name.split('.').pop();
|
||||
if (!isFileExtensionAllowed(fileExtension)) {
|
||||
error = 'Invalid file extension';
|
||||
return;
|
||||
@@ -183,15 +183,16 @@
|
||||
{#if files?.length}
|
||||
<ul class="upload-file-box-list u-min-width-0">
|
||||
{#each fileArray as file}
|
||||
{@const fileName = file.name.split('.')}
|
||||
{@const fileName = file.name.split('.').slice(0, -1).join('.')}
|
||||
{@const extension = file.name.split('.').pop()}
|
||||
{@const fileSize = humanFileSize(file.size)}
|
||||
<li class="u-flex u-cross-center u-min-width-0">
|
||||
<span class="icon-document" aria-hidden="true" />
|
||||
<span class="upload-file-box-name u-trim u-min-width-0">
|
||||
<Trim>{fileName[0]}</Trim>
|
||||
<Trim>{fileName}</Trim>
|
||||
</span>
|
||||
<span class="upload-file-box-name u-min-width-0 u-flex-shrink-0">
|
||||
.{fileName[1]}
|
||||
.{extension}
|
||||
</span>
|
||||
<span
|
||||
class="upload-file-box-size u-margin-inline-start-4 u-margin-inline-end-16">
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { hoursToDays, toLocaleDateTime } from '$lib/helpers/date';
|
||||
import { hoursToDays, timeFromNow, toLocaleDateTime } from '$lib/helpers/date';
|
||||
import { log } from '$lib/stores/logs';
|
||||
import { Alert, Card, Code, Heading, Id, SvgIcon, Tab, Tabs } from '../components';
|
||||
import { Alert, Card, Code, Copy, Heading, Id, SvgIcon, Tab, Tabs } from '../components';
|
||||
import { calculateTime } from '$lib/helpers/timeConversion';
|
||||
import {
|
||||
TableBody,
|
||||
@@ -18,6 +18,7 @@
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import { BillingPlan } from '$lib/constants';
|
||||
import { tooltip } from '$lib/actions/tooltip';
|
||||
|
||||
let selectedRequest = 'parameters';
|
||||
let selectedResponse = 'logs';
|
||||
@@ -124,13 +125,26 @@
|
||||
{/if}
|
||||
</ul>
|
||||
<div class="status u-margin-inline-start-auto">
|
||||
<Pill
|
||||
warning={execution.status === 'waiting' ||
|
||||
execution.status === 'building'}
|
||||
danger={execution.status === 'failed'}
|
||||
info={execution.status === 'completed' || execution.status === 'ready'}>
|
||||
{execution.status}
|
||||
</Pill>
|
||||
<div
|
||||
use:tooltip={{
|
||||
content: `Scheduled to execute on ${toLocaleDateTime(execution.scheduledAt)}`,
|
||||
disabled:
|
||||
!execution?.scheduledAt || execution.status !== 'scheduled'
|
||||
}}>
|
||||
<Pill
|
||||
warning={execution.status === 'waiting' ||
|
||||
execution.status === 'building'}
|
||||
danger={execution.status === 'failed'}
|
||||
info={execution.status === 'completed' ||
|
||||
execution.status === 'ready'}>
|
||||
{#if execution.status === 'scheduled'}
|
||||
<span class="icon-clock" aria-hidden="true" />
|
||||
{timeFromNow(execution.scheduledAt)}
|
||||
{:else}
|
||||
{execution.status}
|
||||
{/if}
|
||||
</Pill>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -145,7 +159,23 @@
|
||||
</div>
|
||||
<div class="u-flex u-gap-16">
|
||||
<h4 class="text u-bold">Path:</h4>
|
||||
<span class="u-text-color-gray">{execution.requestPath}</span>
|
||||
|
||||
<Copy value={execution.requestPath}>
|
||||
<div
|
||||
class="interactive-text-output is-textarea"
|
||||
style:min-inline-size="0">
|
||||
<span class="text u-line-height-1-5 u-break-all">
|
||||
{execution.requestPath}
|
||||
</span>
|
||||
<div class="u-flex u-cross-child-start u-gap-8">
|
||||
<button
|
||||
class="interactive-text-output-button"
|
||||
aria-label="copy text">
|
||||
<span class="icon-duplicate" aria-hidden="true" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Copy>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -156,8 +186,9 @@
|
||||
</div>
|
||||
<div class="u-flex u-gap-16">
|
||||
<h4 class="text u-bold">Status Code:</h4>
|
||||
<span class="u-text-color-gray"
|
||||
>{execution.responseStatusCode}</span>
|
||||
<span class="u-text-color-gray">
|
||||
{execution.responseStatusCode}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
@@ -139,7 +139,18 @@
|
||||
}
|
||||
|
||||
$: sortedSteps = [...steps].sort(([a], [b]) => (a > b ? 1 : -1));
|
||||
$: isLastStep = $wizard.step === steps.size;
|
||||
$: isLastStep = (() => {
|
||||
if ($wizard.step === steps.size) {
|
||||
return true;
|
||||
}
|
||||
let lastStep = true;
|
||||
steps.forEach((step, i) => {
|
||||
if (i > $wizard.step && !step.disabled) {
|
||||
lastStep = false;
|
||||
}
|
||||
});
|
||||
return lastStep;
|
||||
})();
|
||||
$: currentStep = steps.get($wizard.step);
|
||||
</script>
|
||||
|
||||
@@ -187,7 +198,7 @@
|
||||
<svelte:component this={component} />
|
||||
{/if}
|
||||
{/each}
|
||||
<div class="u-z-index-20 form-footer">
|
||||
<div class="u-z-index-5 form-footer">
|
||||
<div class="u-flex u-main-end u-gap-12">
|
||||
{#if !isLastStep && currentStep?.optional}
|
||||
<Button text on:click={() => dispatch('finish')}>
|
||||
|
||||
@@ -111,6 +111,7 @@ export type Credit = {
|
||||
};
|
||||
|
||||
export type CreditList = {
|
||||
available: number;
|
||||
credits: Credit[];
|
||||
total: number;
|
||||
};
|
||||
|
||||
@@ -84,6 +84,42 @@ campaigns
|
||||
]
|
||||
}
|
||||
})
|
||||
.set('FreeCodeCamp', {
|
||||
template: 'card',
|
||||
title: 'Claim your $50 FreeCodeCamp credits.',
|
||||
description:
|
||||
'Get $50 in Cloud credits when you upgrade or create an organization with a Pro plan'
|
||||
})
|
||||
.set('AniaKubow', {
|
||||
template: 'card',
|
||||
title: 'Claim your $50 Ania Kubów credits.',
|
||||
description:
|
||||
'Get $50 in Cloud credits when you upgrade or create an organization with a Pro plan'
|
||||
})
|
||||
.set('Fireship', {
|
||||
template: 'card',
|
||||
title: 'Claim your $50 Fireship credits.',
|
||||
description:
|
||||
'Get $50 in Cloud credits when you upgrade or create an organization with a Pro plan'
|
||||
})
|
||||
.set('Hyperplexed', {
|
||||
template: 'card',
|
||||
title: 'Claim your $50 Hyperplexed credits.',
|
||||
description:
|
||||
'Get $50 in Cloud credits when you upgrade or create an organization with a Pro plan'
|
||||
})
|
||||
.set('TraversyMedia', {
|
||||
template: 'card',
|
||||
title: 'Claim your $50 TraversyMedia credits.',
|
||||
description:
|
||||
'Get $50 in Cloud credits when you upgrade or create an organization with a Pro plan'
|
||||
})
|
||||
.set('VueJS', {
|
||||
template: 'card',
|
||||
title: 'Claim your $50 VueJS credits.',
|
||||
description:
|
||||
'Get $50 in Cloud credits when you upgrade or create an organization with a Pro plan'
|
||||
})
|
||||
.set('FusionVC', {
|
||||
template: 'review',
|
||||
title: 'Welcome to Appwrite!',
|
||||
|
||||
@@ -65,7 +65,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'APPWRITE_API_KEY',
|
||||
@@ -75,7 +75,8 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
required: false,
|
||||
type: 'password'
|
||||
}
|
||||
]
|
||||
],
|
||||
scopes: ['functions.read', 'functions.write', 'documents.write']
|
||||
},
|
||||
{
|
||||
icon: 'icon-upstash',
|
||||
@@ -99,7 +100,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'UPSTASH_URL',
|
||||
@@ -142,7 +143,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'REDIS_HOST',
|
||||
@@ -184,7 +185,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'NEO4J_URI',
|
||||
@@ -235,7 +236,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'MONGO_URI',
|
||||
@@ -271,7 +272,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'PGHOST',
|
||||
@@ -355,7 +356,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'OPENAI_API_KEY',
|
||||
@@ -403,7 +404,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'DISCORD_PUBLIC_KEY',
|
||||
@@ -453,7 +454,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'PERSPECTIVE_API_KEY',
|
||||
@@ -500,7 +501,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'PANGEA_REDACT_TOKEN',
|
||||
@@ -529,7 +530,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: []
|
||||
},
|
||||
{
|
||||
@@ -555,7 +556,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'GITHUB_TOKEN',
|
||||
@@ -597,7 +598,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'APPWRITE_API_KEY',
|
||||
@@ -675,7 +676,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'APPWRITE_API_KEY',
|
||||
@@ -783,7 +784,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'APPWRITE_API_KEY',
|
||||
@@ -897,7 +898,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'VONAGE_API_KEY',
|
||||
@@ -952,7 +953,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'FCM_PROJECT_ID',
|
||||
@@ -1019,7 +1020,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'SMTP_HOST',
|
||||
@@ -1089,7 +1090,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'APPWRITE_API_KEY',
|
||||
@@ -1145,7 +1146,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'APPWRITE_API_KEY',
|
||||
@@ -1217,7 +1218,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'HUGGINGFACE_ACCESS_TOKEN',
|
||||
@@ -1250,7 +1251,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'HUGGINGFACE_ACCESS_TOKEN',
|
||||
@@ -1283,7 +1284,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'APPWRITE_API_KEY',
|
||||
@@ -1356,7 +1357,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'APPWRITE_API_KEY',
|
||||
@@ -1429,7 +1430,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'APPWRITE_API_KEY',
|
||||
@@ -1502,7 +1503,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'APPWRITE_API_KEY',
|
||||
@@ -1575,7 +1576,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'REPLICATE_API_KEY',
|
||||
@@ -1609,7 +1610,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'TOGETHER_API_KEY',
|
||||
@@ -1666,7 +1667,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'PERPLEXITY_API_KEY',
|
||||
@@ -1706,7 +1707,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'REPLICATE_API_KEY',
|
||||
@@ -1740,7 +1741,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'OPENAI_API_KEY',
|
||||
@@ -1818,7 +1819,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'OPENAI_API_KEY',
|
||||
@@ -1896,7 +1897,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'ELEVENLABS_API_KEY',
|
||||
@@ -1966,7 +1967,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'LMNT_API_KEY',
|
||||
@@ -2022,7 +2023,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'ANYSCALE_API_KEY',
|
||||
@@ -2062,7 +2063,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'APPWRITE_API_KEY',
|
||||
@@ -2119,7 +2120,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'FAL_API_KEY',
|
||||
@@ -2153,7 +2154,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'APPWRITE_API_KEY',
|
||||
@@ -2223,7 +2224,7 @@ export const marketplace: MarketplaceTemplate[] = [
|
||||
vcsProvider: 'github',
|
||||
providerRepositoryId: 'templates',
|
||||
providerOwner: 'appwrite',
|
||||
providerBranch: 'main',
|
||||
providerBranch: '0.1.*',
|
||||
variables: [
|
||||
{
|
||||
name: 'APPWRITE_API_KEY',
|
||||
@@ -2322,4 +2323,5 @@ export type MarketplaceTemplate = {
|
||||
providerOwner: string;
|
||||
providerBranch: string;
|
||||
variables: Variable[];
|
||||
scopes?: string[];
|
||||
};
|
||||
|
||||
@@ -1,39 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { Box } from '$lib/components';
|
||||
import { FormList, Helper, InputChoice, InputPassword } from '$lib/elements/forms';
|
||||
import type { Variable } from '$lib/stores/marketplace';
|
||||
import { templateConfig } from '../store';
|
||||
|
||||
export let appwriteVariable: Variable;
|
||||
</script>
|
||||
|
||||
<Box radius="small" padding={16}>
|
||||
<FormList>
|
||||
<div>
|
||||
<InputPassword
|
||||
id={appwriteVariable.name}
|
||||
label={appwriteVariable.name}
|
||||
placeholder={appwriteVariable.placeholder ?? 'Enter value'}
|
||||
showPasswordButton
|
||||
required={appwriteVariable.required && !$templateConfig.generateKey}
|
||||
bind:value={$templateConfig.appwriteApiKey}
|
||||
disabled={!!$templateConfig.generateKey} />
|
||||
<Helper type="neutral">
|
||||
This API key will allow you to interact with the Appwrite server APIs. <a
|
||||
href="https://appwrite.io/docs/advanced/platform/api-keys"
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
class="link">Learn more</a
|
||||
>.
|
||||
</Helper>
|
||||
</div>
|
||||
<InputChoice
|
||||
bind:value={$templateConfig.generateKey}
|
||||
id="generate"
|
||||
label="Generate API key on completion"
|
||||
disabled={!!$templateConfig.appwriteApiKey}>
|
||||
The <code class="inline-code">APPWRITE_API_KEY</code> will be automatically generated for
|
||||
your project and applied to this function once it's created.
|
||||
</InputChoice>
|
||||
</FormList>
|
||||
</Box>
|
||||
@@ -16,8 +16,8 @@
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import Details from './steps/details.svelte';
|
||||
import Configuration from './steps/configuration.svelte';
|
||||
import Details from './steps/manualDetails.svelte';
|
||||
import Configuration from './steps/manualConfiguration.svelte';
|
||||
import ExecuteAccess from './steps/executeAccess.svelte';
|
||||
import { isValueOfStringEnum } from '$lib/helpers/types';
|
||||
|
||||
|
||||
@@ -1,22 +1,28 @@
|
||||
<script lang="ts">
|
||||
import { ID, Runtime } from '@appwrite.io/console';
|
||||
import { Wizard } from '$lib/layout';
|
||||
import type { WizardStepsType } from '$lib/layout/wizard.svelte';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
import { goto } from '$app/navigation';
|
||||
import { choices, installation, repository, template, templateConfig } from './store';
|
||||
import {
|
||||
choices,
|
||||
installation,
|
||||
repository,
|
||||
template,
|
||||
templateConfig,
|
||||
templateStepsComponents
|
||||
} from './store';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { Submit, trackError, trackEvent } from '$lib/actions/analytics';
|
||||
import { base } from '$app/paths';
|
||||
import { page } from '$app/stores';
|
||||
import GitConfiguration from './steps/gitConfiguration.svelte';
|
||||
import TemplateConfiguration from './steps/templateConfiguration.svelte';
|
||||
import RepositoryBehaviour from './steps/repositoryBehaviour.svelte';
|
||||
import CreateRepository from './steps/createRepository.svelte';
|
||||
import TemplateVariables from './steps/templateVariables.svelte';
|
||||
import { scopes } from '$lib/constants';
|
||||
import { isValueOfStringEnum } from '$lib/helpers/types';
|
||||
import TemplateConfiguration from './steps/templateConfiguration.svelte';
|
||||
import TemplatePermissions from './steps/templatePermissions.svelte';
|
||||
import TemplateVariables from './steps/templateVariables.svelte';
|
||||
import TemplateDeployment from './steps/templateDeployment.svelte';
|
||||
import CreateRepository from './steps/createRepository.svelte';
|
||||
import GitConfiguration from './steps/gitConfiguration.svelte';
|
||||
|
||||
async function create() {
|
||||
try {
|
||||
@@ -26,22 +32,12 @@
|
||||
const runtimeDetail = $template.runtimes.find(
|
||||
(r) => r.name === $templateConfig.runtime
|
||||
);
|
||||
if ($templateConfig.appwriteApiKey) {
|
||||
$templateConfig.variables['APPWRITE_API_KEY'] = $templateConfig.appwriteApiKey;
|
||||
} else if ($templateConfig?.generateKey) {
|
||||
const key = await sdk.forConsole.projects.createKey(
|
||||
$page.params.project,
|
||||
'Generated for Template',
|
||||
scopes.map((scope) => scope.scope)
|
||||
);
|
||||
$templateConfig.variables['APPWRITE_API_KEY'] = key.secret;
|
||||
}
|
||||
|
||||
const response = await sdk.forProject.functions.create(
|
||||
$templateConfig.$id || ID.unique(),
|
||||
$templateConfig.name,
|
||||
$templateConfig.runtime,
|
||||
$template.permissions || undefined,
|
||||
$templateConfig?.execute ? $template.permissions || undefined : undefined,
|
||||
$template.events || undefined,
|
||||
$template.cron || undefined,
|
||||
$template.timeout || undefined,
|
||||
@@ -49,16 +45,28 @@
|
||||
undefined,
|
||||
runtimeDetail.entrypoint,
|
||||
runtimeDetail.commands || undefined,
|
||||
undefined,
|
||||
$installation.$id,
|
||||
$repository.id,
|
||||
$choices.branch,
|
||||
$choices.silentMode || undefined,
|
||||
$choices.rootDir || undefined,
|
||||
$template.providerRepositoryId,
|
||||
$template.providerOwner,
|
||||
runtimeDetail.providerRootDirectory,
|
||||
$template.providerBranch
|
||||
$templateConfig?.scopes?.length ? $templateConfig.scopes : undefined,
|
||||
$templateConfig.repositoryBehaviour === 'manual' ? undefined : $installation.$id,
|
||||
$templateConfig.repositoryBehaviour === 'manual' ? undefined : $repository.id,
|
||||
$templateConfig.repositoryBehaviour === 'manual' ? undefined : $choices.branch,
|
||||
$templateConfig.repositoryBehaviour === 'manual'
|
||||
? undefined
|
||||
: $choices.silentMode || undefined,
|
||||
$templateConfig.repositoryBehaviour === 'manual'
|
||||
? undefined
|
||||
: $choices.rootDir || undefined,
|
||||
$templateConfig.repositoryBehaviour === 'manual'
|
||||
? undefined
|
||||
: $template.providerRepositoryId,
|
||||
$templateConfig.repositoryBehaviour === 'manual'
|
||||
? undefined
|
||||
: $template.providerOwner,
|
||||
$templateConfig.repositoryBehaviour === 'manual'
|
||||
? undefined
|
||||
: runtimeDetail.providerRootDirectory,
|
||||
$templateConfig.repositoryBehaviour === 'manual'
|
||||
? undefined
|
||||
: $template.providerBranch
|
||||
);
|
||||
|
||||
if ($templateConfig.variables) {
|
||||
@@ -75,7 +83,10 @@
|
||||
type: 'success'
|
||||
});
|
||||
trackEvent(Submit.FunctionCreate, {
|
||||
customId: !!response.$id
|
||||
customId: !!response.$id,
|
||||
runtime: response.runtime,
|
||||
deployment_type: $templateConfig.repositoryBehaviour,
|
||||
scopes: $templateConfig.scopes
|
||||
});
|
||||
resetState();
|
||||
} catch (error) {
|
||||
@@ -93,27 +104,36 @@
|
||||
installation.set(null);
|
||||
}
|
||||
|
||||
const stepsComponents: WizardStepsType = new Map();
|
||||
stepsComponents.set(1, {
|
||||
$templateStepsComponents.set(1, {
|
||||
label: 'Configuration',
|
||||
component: TemplateConfiguration
|
||||
});
|
||||
stepsComponents.set(2, {
|
||||
$templateStepsComponents.set(2, {
|
||||
label: 'Permissions',
|
||||
component: TemplatePermissions,
|
||||
disabled: !$template?.scopes?.length
|
||||
});
|
||||
$templateStepsComponents.set(3, {
|
||||
label: 'Variables',
|
||||
component: TemplateVariables
|
||||
component: TemplateVariables,
|
||||
disabled: !$template?.variables?.length
|
||||
});
|
||||
stepsComponents.set(3, {
|
||||
label: 'Connect',
|
||||
component: RepositoryBehaviour
|
||||
$templateStepsComponents.set(4, {
|
||||
label: 'Deployment',
|
||||
component: TemplateDeployment
|
||||
});
|
||||
stepsComponents.set(4, {
|
||||
$templateStepsComponents.set(5, {
|
||||
label: 'Repository',
|
||||
component: CreateRepository
|
||||
});
|
||||
stepsComponents.set(5, {
|
||||
$templateStepsComponents.set(6, {
|
||||
label: 'Branch',
|
||||
component: GitConfiguration
|
||||
});
|
||||
</script>
|
||||
|
||||
<Wizard title="Create Function" steps={stepsComponents} on:finish={create} on:exit={resetState} />
|
||||
<Wizard
|
||||
title="Create Function"
|
||||
steps={$templateStepsComponents}
|
||||
on:finish={create}
|
||||
on:exit={resetState} />
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
<script lang="ts">
|
||||
import { LabelCard } from '$lib/components';
|
||||
import { WizardStep } from '$lib/layout';
|
||||
import { app } from '$lib/stores/app';
|
||||
import { templateConfig } from '../store';
|
||||
|
||||
async function beforeSubmit() {
|
||||
if (!$templateConfig.repositoryBehaviour) {
|
||||
throw new Error('Please select repository behaviour.');
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<WizardStep {beforeSubmit}>
|
||||
<svelte:fragment slot="title">Connect</svelte:fragment>
|
||||
<svelte:fragment slot="subtitle">
|
||||
Connect function to a new repository or to an existing one within a selected Git
|
||||
organization.
|
||||
</svelte:fragment>
|
||||
|
||||
<ul class="u-flex u-flex-vertical u-gap-16">
|
||||
<LabelCard
|
||||
name="behaviour"
|
||||
value="new"
|
||||
backgroundColor={$app.themeInUse === 'light' ? 'var(--color-neutral-5)' : null}
|
||||
backgroundColorHover={$app.themeInUse === 'light' ? 'var(--color-neutral-10)' : null}
|
||||
bind:group={$templateConfig.repositoryBehaviour}>
|
||||
<svelte:fragment slot="title">Create a new repository</svelte:fragment>
|
||||
Clone the template and create a new repository in your selected organization.
|
||||
</LabelCard>
|
||||
<LabelCard
|
||||
name="behaviour"
|
||||
value="existing"
|
||||
backgroundColor={$app.themeInUse === 'light' ? 'var(--color-neutral-5)' : null}
|
||||
backgroundColorHover={$app.themeInUse === 'light' ? 'var(--color-neutral-10)' : null}
|
||||
bind:group={$templateConfig.repositoryBehaviour}>
|
||||
<svelte:fragment slot="title">Add to existing repository</svelte:fragment>
|
||||
Clone the template to an existing repository in your selected organization.
|
||||
</LabelCard>
|
||||
</ul>
|
||||
</WizardStep>
|
||||
@@ -0,0 +1,53 @@
|
||||
<script lang="ts">
|
||||
import { LabelCard } from '$lib/components';
|
||||
import { FormList } from '$lib/elements/forms';
|
||||
import { WizardStep } from '$lib/layout';
|
||||
import { templateConfig, templateStepsComponents } from '../store';
|
||||
|
||||
async function beforeSubmit() {
|
||||
if (!$templateConfig.repositoryBehaviour) {
|
||||
throw new Error('Please select repository behaviour.');
|
||||
}
|
||||
}
|
||||
|
||||
$: if ($templateConfig.repositoryBehaviour === 'manual') {
|
||||
$templateStepsComponents.get(5).disabled = true;
|
||||
$templateStepsComponents.get(6).disabled = true;
|
||||
$templateStepsComponents = $templateStepsComponents;
|
||||
} else {
|
||||
$templateStepsComponents.get(5).disabled = false;
|
||||
$templateStepsComponents.get(6).disabled = false;
|
||||
$templateStepsComponents = $templateStepsComponents;
|
||||
}
|
||||
</script>
|
||||
|
||||
<WizardStep {beforeSubmit}>
|
||||
<svelte:fragment slot="title">Deployment</svelte:fragment>
|
||||
<svelte:fragment slot="subtitle">
|
||||
Connect your function to a Git repository for automatic deployments or deploy your function
|
||||
using the CLI.
|
||||
</svelte:fragment>
|
||||
|
||||
<h3>Automatic with Git <span class="inline-code">Recommended</span></h3>
|
||||
<FormList gap={16} class="u-margin-block-start-8">
|
||||
<LabelCard name="behaviour" value="new" bind:group={$templateConfig.repositoryBehaviour}>
|
||||
<svelte:fragment slot="title">Create a new repository</svelte:fragment>
|
||||
Clone the template to a newly created repository in your organization.
|
||||
</LabelCard>
|
||||
<LabelCard
|
||||
name="behaviour"
|
||||
value="existing"
|
||||
bind:group={$templateConfig.repositoryBehaviour}>
|
||||
<svelte:fragment slot="title">Add to existing repository</svelte:fragment>
|
||||
Clone the template to an existing repository in your organization.
|
||||
</LabelCard>
|
||||
</FormList>
|
||||
|
||||
<h3 class="u-margin-block-start-24">Manual with CLI</h3>
|
||||
<ul class="u-margin-block-start-8">
|
||||
<LabelCard name="behaviour" value="manual" bind:group={$templateConfig.repositoryBehaviour}>
|
||||
<svelte:fragment slot="title">Create manually</svelte:fragment>
|
||||
Deploy a function from a template and change the code using the CLI.
|
||||
</LabelCard>
|
||||
</ul>
|
||||
</WizardStep>
|
||||
@@ -0,0 +1,86 @@
|
||||
<script lang="ts">
|
||||
import { scopes } from '$lib/constants';
|
||||
import { FormList, InputChoice } from '$lib/elements/forms';
|
||||
import { WizardStep } from '$lib/layout';
|
||||
import { onMount } from 'svelte';
|
||||
import { template, templateConfig } from '../store';
|
||||
import { tooltip } from '$lib/actions/tooltip';
|
||||
|
||||
let templateScopes = [];
|
||||
onMount(() => {
|
||||
$templateConfig.execute = $template.permissions.includes('any');
|
||||
templateScopes = scopes
|
||||
.filter((scope) => $template.scopes.includes(scope.scope))
|
||||
.map((scope) => ({
|
||||
...scope,
|
||||
active: true
|
||||
}));
|
||||
});
|
||||
|
||||
$: $templateConfig.scopes = templateScopes
|
||||
?.filter((scope) => scope.active)
|
||||
?.map((scope) => scope.scope);
|
||||
</script>
|
||||
|
||||
<WizardStep>
|
||||
<svelte:fragment slot="title">Permissions</svelte:fragment>
|
||||
<svelte:fragment slot="subtitle">
|
||||
Enable recommended scopes and execute access for when your function is deployed.
|
||||
</svelte:fragment>
|
||||
<h3 class="label">Execute permissions</h3>
|
||||
<FormList class="u-margin-block-start-16">
|
||||
<div class="user-profile">
|
||||
<span class="avatar" style:--p-text-size="1rem">
|
||||
<span class="icon-lock-open" />
|
||||
</span>
|
||||
<span class="user-profile-info u-flex u-main-space-between u-gap-16">
|
||||
<div>
|
||||
<p class="name u-bold">
|
||||
Public (anyone can execute) <span
|
||||
class="icon-info"
|
||||
use:tooltip={{
|
||||
content:
|
||||
'You can further customize execute permissions in your function settings.'
|
||||
}} />
|
||||
</p>
|
||||
<p class="text u-margin-block-start-4">
|
||||
This could include unauthorized users and search engines.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<InputChoice
|
||||
type="switchbox"
|
||||
id="execute"
|
||||
label="Execute"
|
||||
showLabel={false}
|
||||
bind:value={$templateConfig.execute}></InputChoice>
|
||||
</span>
|
||||
</div>
|
||||
</FormList>
|
||||
<h3 class="label u-margin-block-start-48">Function scopes</h3>
|
||||
<FormList class="u-margin-block-start-16">
|
||||
{#each templateScopes as scope, i}
|
||||
<div class="user-profile">
|
||||
<span class="avatar" style:--p-text-size="1rem">
|
||||
<span class={`icon-${scope.icon}`} />
|
||||
</span>
|
||||
<span class="user-profile-info u-flex u-main-space-between u-gap-16">
|
||||
<div>
|
||||
<p class="name u-bold">{scope.scope}</p>
|
||||
<p class="text u-margin-block-start-4">{scope.description}</p>
|
||||
</div>
|
||||
<InputChoice
|
||||
type="switchbox"
|
||||
id={scope.scope}
|
||||
label={scope.scope}
|
||||
showLabel={false}
|
||||
bind:value={scope.active}>
|
||||
</InputChoice>
|
||||
</span>
|
||||
</div>
|
||||
{#if i < templateScopes.length - 1}
|
||||
<div class="with-separators"></div>
|
||||
{/if}
|
||||
{/each}
|
||||
</FormList>
|
||||
</WizardStep>
|
||||
@@ -12,7 +12,6 @@
|
||||
InputNumber
|
||||
} from '$lib/elements/forms';
|
||||
import { Card, Collapsible, CollapsibleItem } from '$lib/components';
|
||||
import AppwriteVariable from '../components/appwriteVariable.svelte';
|
||||
import type { SvelteComponent } from 'svelte';
|
||||
|
||||
async function beforeSubmit() {
|
||||
@@ -20,10 +19,6 @@
|
||||
if (!variable.required) {
|
||||
continue;
|
||||
}
|
||||
if (variable.name === 'APPWRITE_API_KEY') {
|
||||
if ($templateConfig.appwriteApiKey || $templateConfig.generateKey) continue;
|
||||
else throw new Error(`Please set ${variable.name} variable or generate it.`);
|
||||
}
|
||||
if (!$templateConfig.variables[variable.name]) {
|
||||
throw new Error(`Please set ${variable.name} variable.`);
|
||||
}
|
||||
@@ -72,25 +67,21 @@
|
||||
|
||||
<FormList>
|
||||
{#each requiredVariables as variable}
|
||||
{#if variable.name === 'APPWRITE_API_KEY'}
|
||||
<AppwriteVariable appwriteVariable={variable} />
|
||||
{:else}
|
||||
<div>
|
||||
<svelte:component
|
||||
this={selectComponent(variable.type)}
|
||||
id={variable.name}
|
||||
label={variable.name}
|
||||
placeholder={variable.placeholder ?? 'Enter value'}
|
||||
required={variable.required}
|
||||
autocomplete={false}
|
||||
minlength={variable.type === 'password' ? 0 : null}
|
||||
showPasswordButton={variable.type === 'password'}
|
||||
bind:value={$templateConfig.variables[variable.name]} />
|
||||
<Helper type="neutral">
|
||||
{@html variable.description}
|
||||
</Helper>
|
||||
</div>
|
||||
{/if}
|
||||
<div>
|
||||
<svelte:component
|
||||
this={selectComponent(variable.type)}
|
||||
id={variable.name}
|
||||
label={variable.name}
|
||||
placeholder={variable.placeholder ?? 'Enter value'}
|
||||
required={variable.required}
|
||||
autocomplete={false}
|
||||
minlength={variable.type === 'password' ? 0 : null}
|
||||
showPasswordButton={variable.type === 'password'}
|
||||
bind:value={$templateConfig.variables[variable.name]} />
|
||||
<Helper type="neutral">
|
||||
{@html variable.description}
|
||||
</Helper>
|
||||
</div>
|
||||
{/each}
|
||||
</FormList>
|
||||
</CollapsibleItem>
|
||||
@@ -107,25 +98,21 @@
|
||||
|
||||
<FormList>
|
||||
{#each optionalVariables as variable}
|
||||
{#if variable.name === 'APPWRITE_API_KEY'}
|
||||
<AppwriteVariable appwriteVariable={variable} />
|
||||
{:else}
|
||||
<div>
|
||||
<svelte:component
|
||||
this={selectComponent(variable.type)}
|
||||
id={variable.name}
|
||||
label={variable.name}
|
||||
placeholder={variable.placeholder ?? 'Enter value'}
|
||||
required={variable.required}
|
||||
autocomplete={false}
|
||||
showPasswordButton={variable.type === 'password'}
|
||||
bind:value={$templateConfig.variables[variable.name]} />
|
||||
<div>
|
||||
<svelte:component
|
||||
this={selectComponent(variable.type)}
|
||||
id={variable.name}
|
||||
label={variable.name}
|
||||
placeholder={variable.placeholder ?? 'Enter value'}
|
||||
required={variable.required}
|
||||
autocomplete={false}
|
||||
showPasswordButton={variable.type === 'password'}
|
||||
bind:value={$templateConfig.variables[variable.name]} />
|
||||
|
||||
<Helper type="neutral">
|
||||
{@html variable.description}
|
||||
</Helper>
|
||||
</div>
|
||||
{/if}
|
||||
<Helper type="neutral">
|
||||
{@html variable.description}
|
||||
</Helper>
|
||||
</div>
|
||||
{/each}
|
||||
</FormList>
|
||||
</CollapsibleItem>
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { page } from '$app/stores';
|
||||
import type { WizardStepsType } from '$lib/layout/wizard.svelte';
|
||||
import type { MarketplaceTemplate } from '$lib/stores/marketplace';
|
||||
import type { Models } from '@appwrite.io/console';
|
||||
import { derived, writable } from 'svelte/store';
|
||||
import { derived, writable, type Writable } from 'svelte/store';
|
||||
|
||||
export const template = writable<MarketplaceTemplate>();
|
||||
export const templateConfig = writable<{
|
||||
@@ -9,12 +10,12 @@ export const templateConfig = writable<{
|
||||
name: string;
|
||||
runtime: string;
|
||||
variables: { [key: string]: unknown };
|
||||
repositoryBehaviour: 'new' | 'existing';
|
||||
repositoryName: string;
|
||||
repositoryPrivate: boolean;
|
||||
repositoryBehaviour: 'new' | 'existing' | 'manual';
|
||||
repositoryName?: string;
|
||||
repositoryPrivate?: boolean;
|
||||
repositoryId: string;
|
||||
appwriteApiKey?: string;
|
||||
generateKey?: boolean;
|
||||
execute?: boolean;
|
||||
scopes?: string[];
|
||||
}>();
|
||||
export const repository = writable<Models.ProviderRepository>();
|
||||
export const installation = writable<Models.Installation>();
|
||||
@@ -59,3 +60,5 @@ function createFunctionStore() {
|
||||
export const createFunction = createFunctionStore();
|
||||
|
||||
export const createFunctionDeployment = writable<FileList>();
|
||||
|
||||
export const templateStepsComponents: Writable<WizardStepsType> = writable(new Map());
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
import type { PageLoad } from './$types';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { redirect } from '@sveltejs/kit';
|
||||
import { base } from '$app/paths';
|
||||
|
||||
export const load: PageLoad = async () => {
|
||||
export const load: PageLoad = async ({ parent }) => {
|
||||
const { mfaRequired } = await parent();
|
||||
if (!mfaRequired) {
|
||||
redirect(303, base);
|
||||
}
|
||||
return {
|
||||
factors: await sdk.forConsole.account.listMfaFactors()
|
||||
};
|
||||
|
||||
@@ -119,8 +119,8 @@
|
||||
$provider.subdomain,
|
||||
$provider.region,
|
||||
$provider.adminSecret,
|
||||
$provider.database,
|
||||
$provider.username,
|
||||
$provider.database || $provider.subdomain,
|
||||
$provider.username || 'postgres',
|
||||
$provider.password
|
||||
);
|
||||
}
|
||||
@@ -186,7 +186,7 @@
|
||||
</div>
|
||||
</Box>
|
||||
|
||||
{#if report && !isVersionAtLeast(version, '1.4.0')}
|
||||
{#if report && !isVersionAtLeast(version, '1.4.0') && $provider.provider === 'appwrite'}
|
||||
<div class="u-margin-block-start-24">
|
||||
<Alert
|
||||
type="warning"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { page } from '$app/stores';
|
||||
import { InputSelect } from '$lib/elements/forms';
|
||||
import { FormList, InputSelect } from '$lib/elements/forms';
|
||||
import InputText from '$lib/elements/forms/inputText.svelte';
|
||||
import { WizardStep } from '$lib/layout';
|
||||
import { Query, type Models, ID } from '@appwrite.io/console';
|
||||
@@ -44,7 +44,7 @@
|
||||
<WizardStep {beforeSubmit}>
|
||||
<svelte:fragment slot="title">Project</svelte:fragment>
|
||||
|
||||
<div class="u-flex u-flex-vertical u-gap-24">
|
||||
<FormList>
|
||||
{#if organizations.length > 1}
|
||||
<InputSelect
|
||||
id="organization"
|
||||
@@ -107,7 +107,7 @@
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</FormList>
|
||||
</WizardStep>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -4,20 +4,17 @@
|
||||
import { Modal } from '$lib/components';
|
||||
import { Dependencies } from '$lib/constants';
|
||||
import { Button } from '$lib/elements/forms';
|
||||
import FormList from '$lib/elements/forms/formList.svelte';
|
||||
import InputDigits from '$lib/elements/forms/inputDigits.svelte';
|
||||
import { addNotification } from '$lib/stores/notifications';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { AuthenticatorType } from '@appwrite.io/console';
|
||||
|
||||
export let showDelete = false;
|
||||
|
||||
let code: string;
|
||||
let error: string;
|
||||
|
||||
async function deleteAuthenticator() {
|
||||
try {
|
||||
await sdk.forConsole.account.deleteMfaAuthenticator(AuthenticatorType.Totp, code);
|
||||
await sdk.forConsole.account.deleteMfaAuthenticator(AuthenticatorType.Totp);
|
||||
await invalidate(Dependencies.ACCOUNT);
|
||||
await invalidate(Dependencies.FACTORS);
|
||||
showDelete = false;
|
||||
@@ -33,7 +30,6 @@
|
||||
}
|
||||
|
||||
$: if (showDelete) {
|
||||
code = '';
|
||||
error = '';
|
||||
}
|
||||
</script>
|
||||
@@ -46,10 +42,10 @@
|
||||
state="warning"
|
||||
bind:error
|
||||
headerDivider={false}>
|
||||
<p>Enter the 6-digit verification code generated by your authenticator app to continue.</p>
|
||||
<FormList>
|
||||
<InputDigits autofocus required bind:value={code} autoSubmit={false} />
|
||||
</FormList>
|
||||
<p>
|
||||
Are you sure you want to delete this authentication method? You will no longer be able to
|
||||
use this method to authenticate your account.
|
||||
</p>
|
||||
|
||||
<svelte:fragment slot="footer">
|
||||
<Button text on:click={() => (showDelete = false)}>Cancel</Button>
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
<script lang="ts">
|
||||
import { Alert, CardGrid, Empty, Heading, PaginationInline } from '$lib/components';
|
||||
import {
|
||||
Table,
|
||||
TableBody,
|
||||
TableCellHead,
|
||||
TableCellText,
|
||||
TableHeader,
|
||||
TableRow
|
||||
TableRow,
|
||||
TableScroll
|
||||
} from '$lib/elements/table';
|
||||
import { toLocaleDate } from '$lib/helpers/date';
|
||||
import type { Credit, CreditList } from '$lib/sdk/billing';
|
||||
import type { CreditList } from '$lib/sdk/billing';
|
||||
import { organization } from '$lib/stores/organization';
|
||||
import { sdk } from '$lib/stores/sdk';
|
||||
import { wizard } from '$lib/stores/wizard';
|
||||
@@ -25,6 +25,7 @@
|
||||
|
||||
let offset = 0;
|
||||
let creditList: CreditList = {
|
||||
available: 0,
|
||||
credits: [],
|
||||
total: 0
|
||||
};
|
||||
@@ -56,9 +57,6 @@
|
||||
request();
|
||||
}
|
||||
|
||||
$: balance =
|
||||
creditList?.credits?.reduce((acc: number, curr: Credit) => acc + curr.credits, 0) ?? 0;
|
||||
|
||||
$: {
|
||||
if (reloadOnWizardClose && !$wizard.show) {
|
||||
request();
|
||||
@@ -86,8 +84,8 @@
|
||||
{:else}
|
||||
<div class="u-flex u-cross-center u-main-space-between">
|
||||
<div class="u-flex u-gap-8 u-cross-center">
|
||||
<h4 class="body-text-1 u-bold">Credit balance</h4>
|
||||
<span class="inline-tag">{formatCurrency(balance)}</span>
|
||||
<h4 class="body-text-1 u-bold">Balance</h4>
|
||||
<span class="inline-tag">{formatCurrency(creditList.available)}</span>
|
||||
</div>
|
||||
{#if creditList?.total}
|
||||
<Button secondary on:click={handleCredits}>
|
||||
@@ -97,30 +95,34 @@
|
||||
{/if}
|
||||
</div>
|
||||
{#if creditList?.total}
|
||||
<Table noStyles noMargin>
|
||||
<TableScroll noStyles noMargin class="u-margin-block-start-16">
|
||||
<TableHeader>
|
||||
<TableCellHead>Date Added</TableCellHead>
|
||||
<TableCellHead>Expiry Date</TableCellHead>
|
||||
<TableCellHead>Amount</TableCellHead>
|
||||
<TableCellHead>Code</TableCellHead>
|
||||
<TableCellHead>Total</TableCellHead>
|
||||
<TableCellHead>Remaining</TableCellHead>
|
||||
<TableCellHead>Expires at</TableCellHead>
|
||||
</TableHeader>
|
||||
<TableBody>
|
||||
{#each creditList.credits as credit}
|
||||
<TableRow>
|
||||
<TableCellText title="date added">
|
||||
{toLocaleDate(credit.$createdAt)}
|
||||
<TableCellText title="code">
|
||||
{credit?.couponId ?? '-'}
|
||||
</TableCellText>
|
||||
<TableCellText title="total">
|
||||
{formatCurrency(credit.total)}
|
||||
</TableCellText>
|
||||
<TableCellText title="remaining">
|
||||
{formatCurrency(credit.credits)}
|
||||
</TableCellText>
|
||||
<TableCellText title="expiry date">
|
||||
{toLocaleDate(credit.expiration)}
|
||||
</TableCellText>
|
||||
<TableCellText title="amount">
|
||||
{formatCurrency(credit.total)}
|
||||
</TableCellText>
|
||||
</TableRow>
|
||||
{/each}
|
||||
</TableBody>
|
||||
</Table>
|
||||
</TableScroll>
|
||||
<div class="u-flex u-main-space-between">
|
||||
<p class="text">Total results: {creditList?.total}</p>
|
||||
<p class="text">Total credits: {creditList?.total}</p>
|
||||
<PaginationInline {limit} bind:offset sum={creditList?.total} hidePages />
|
||||
</div>
|
||||
{:else}
|
||||
|
||||
@@ -53,8 +53,8 @@
|
||||
</p>
|
||||
<InputSwitch id="state" bind:value={enabled} label={enabled ? 'Enabled' : 'Disabled'} />
|
||||
<InputText
|
||||
id="bundleID"
|
||||
label="Bundle ID"
|
||||
id="servicesID"
|
||||
label="Services ID"
|
||||
autofocus={true}
|
||||
placeholder="com.company.appname"
|
||||
bind:value={appId} />
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
|
||||
<Form onSubmit={updatePrefs}>
|
||||
<CardGrid>
|
||||
<Heading tag="h6" size="7">Team preferences</Heading>
|
||||
<Heading tag="h6" size="7">Preferences</Heading>
|
||||
<p>
|
||||
You can update your team's preferences by storing shared information on the teams's
|
||||
objects so they can easily be shared across members.
|
||||
|
||||
@@ -11,11 +11,7 @@
|
||||
|
||||
$: if (prefs) {
|
||||
if (JSON.stringify(prefs) !== JSON.stringify(Object.entries($user.prefs))) {
|
||||
if (!!prefs[prefs.length - 1][0] && !!prefs[prefs.length - 1][1]) {
|
||||
arePrefsDisabled = false;
|
||||
} else {
|
||||
arePrefsDisabled = true;
|
||||
}
|
||||
arePrefsDisabled = false;
|
||||
} else {
|
||||
arePrefsDisabled = true;
|
||||
}
|
||||
@@ -86,7 +82,7 @@
|
||||
text
|
||||
disabled={(!key || !value) && index === 0}
|
||||
on:click={() => {
|
||||
if (index === 0) {
|
||||
if (index === 0 && prefs?.length === 1) {
|
||||
prefs = [['', '']];
|
||||
} else {
|
||||
prefs.splice(index, 1);
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
<FormList gap={16}>
|
||||
<InputFile
|
||||
label="Gzipped code (tar.gz)"
|
||||
allowedFileExtensions={['gz']}
|
||||
allowedFileExtensions={['gz', 'tar']}
|
||||
bind:files
|
||||
required={true} />
|
||||
|
||||
|
||||
@@ -66,8 +66,8 @@
|
||||
{@const status = execution.status}
|
||||
<div
|
||||
use:tooltip={{
|
||||
content: `Scheduled to execute on ${toLocaleDateTime(execution?.schedule)}`,
|
||||
disabled: !execution?.schedule
|
||||
content: `Scheduled to execute on ${toLocaleDateTime(execution.scheduledAt)}`,
|
||||
disabled: !execution?.scheduledAt || status !== 'scheduled'
|
||||
}}>
|
||||
<Pill
|
||||
warning={status === 'waiting' || status === 'building'}
|
||||
@@ -75,8 +75,10 @@
|
||||
info={status === 'completed' || status === 'ready'}>
|
||||
{#if status === 'scheduled'}
|
||||
<span class="icon-clock" aria-hidden="true" />
|
||||
{timeFromNow(execution.scheduledAt)}
|
||||
{:else}
|
||||
{status}
|
||||
{/if}
|
||||
{status}
|
||||
</Pill>
|
||||
</div>
|
||||
</TableCell>
|
||||
|
||||
@@ -84,8 +84,8 @@
|
||||
$wizard.finalAction = handleSubmit;
|
||||
|
||||
const workTimings = {
|
||||
start: '09:00',
|
||||
end: '17:00',
|
||||
start: '16:00',
|
||||
end: '00:00',
|
||||
startDay: 'Monday' as WeekDay,
|
||||
endDay: 'Friday' as WeekDay
|
||||
};
|
||||
|
||||
@@ -22,7 +22,7 @@ export function isSupportOnline() {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (hour < 9 || hour > 17) {
|
||||
if (hour < 14) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,12 +33,15 @@ export const load: LayoutLoad = async ({ depends, url, route }) => {
|
||||
}
|
||||
|
||||
const isPublicRoute = route.id?.startsWith('/(public)');
|
||||
if (url.pathname && !isPublicRoute) {
|
||||
if (!isPublicRoute) {
|
||||
url.searchParams.set('redirect', url.pathname);
|
||||
}
|
||||
|
||||
if (error.type === 'user_more_factors_required') {
|
||||
if (url.pathname === `${base}/mfa`) return; // Ensure any previous account/organizations are cleared
|
||||
if (url.pathname === `${base}/mfa`)
|
||||
return {
|
||||
mfaRequired: true
|
||||
};
|
||||
redirect(303, withParams(`${base}/mfa`, url.searchParams));
|
||||
}
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 416 KiB |
|
After Width: | Height: | Size: 384 KiB |
|
After Width: | Height: | Size: 416 KiB |
|
After Width: | Height: | Size: 384 KiB |
|
After Width: | Height: | Size: 416 KiB |
|
After Width: | Height: | Size: 384 KiB |
|
After Width: | Height: | Size: 416 KiB |
|
After Width: | Height: | Size: 384 KiB |
|
After Width: | Height: | Size: 416 KiB |
|
After Width: | Height: | Size: 384 KiB |
|
After Width: | Height: | Size: 416 KiB |
|
After Width: | Height: | Size: 384 KiB |