Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions apps/docs/content/guides/auth/auth-anonymous.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -148,10 +148,10 @@ try await supabase.auth.updateUser(
</TabPanel>
<TabPanel id="kotlin" label="Kotlin">

You can use the [`modifyUser()`](/docs/reference/kotlin/auth-updateuser) method to link an email or phone identity to the anonymous user.
You can use the [`updateUser()`](/docs/reference/kotlin/auth-updateuser) method to link an email or phone identity to the anonymous user.

```kotlin
supabase.auth.modifyUser {
supabase.auth.updateUser {
email = "[email protected]"
}
```
Expand Down
13 changes: 6 additions & 7 deletions apps/docs/content/guides/auth/debugging/error-codes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -59,16 +59,15 @@ Errors originating from the server API classed as `AuthApiError` always have a `

</TabPanel>
<TabPanel id="kotlin" label="Kotlin">
All errors originating from the `supabase.auth` namespace of the JavaScript client library will be wrapped by the `AuthError` class.
All exceptions originating from the `supabase.auth` namespace of the Kotlin client library will be a subclass of `RestException`.

Error objects are split in a few classes:
Rest exceptions are split into a few classes:

- `AuthApiError` -- errors which originate from the Supabase Auth API.
- Use `isAuthApiError` instead of `instanceof` checks to see if an error you caught is of this type.
- `CustomAuthError` -- errors which generally originate from state in the client library.
- Use the `name` property on the error to identify the class of error received.
- `AuthRestException` -- exceptions which originate from the Supabase Auth API and have a `errorCode` property that can be used to identify the error returned by the server.
- `AuthWeakPasswordException` -- an `AuthRestException` which indicates that the password is too weak.
- `AuthSessionMissingException` -- an `AuthRestException` which indicates that the session is missing, if the user was logged out or deleted.

Errors originating from the server API classed as `AuthApiError` always have a `code` property that can be used to identify the error returned by the server. The `status` property is also present, encoding the HTTP status code received in the response.
All instances and subclasses of a `AuthRestException` have a `errorCode` property that can be used to identify the error returned by the server.

</TabPanel>

Expand Down
9 changes: 9 additions & 0 deletions apps/docs/content/guides/auth/phone-login.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,15 @@ try await supabase.auth.updateUser(
)
```

</TabPanel>
<TabPanel id="kotlin" label="Kotlin">

```kotlin
supabase.auth.updateUser {
phone = "123456789"
}
```

</TabPanel>
<TabPanel id="python" label="Python">

Expand Down
2 changes: 2 additions & 0 deletions apps/docs/docs/ref/kotlin/installing.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ custom_edit_url: https://github.com/supabase/supabase/edit/master/web/spec/supab

Checkout the different READMEs for information about supported Kotlin targets.

*Note that the minimum Android SDK version is 26. For lower versions, you need to enable [core library desugaring](https://developer.android.com/studio/write/java8-support#library-desugaring).*

</RefSubLayout.Details>
<RefSubLayout.Examples>
<Tabs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@ interface CronJobCardProps {
onDeleteCronJob: (job: CronJob) => void
}

const generateJobDetailsSQL = (jobId: number) => {
return `select * from cron.job_run_details where jobid = '${jobId}' order by start_time desc limit 10`
}

export const CronJobCard = ({ job, onEditCronJob, onDeleteCronJob }: CronJobCardProps) => {
const [toggleConfirmationModalShown, showToggleConfirmationModal] = useState(false)
const { ref } = useParams()
Expand Down Expand Up @@ -81,9 +77,7 @@ export const CronJobCard = ({ job, onEditCronJob, onDeleteCronJob }: CronJobCard
Edit cron job
</DropdownMenuItem>
<DropdownMenuItem asChild>
<Link
href={`/project/${ref}/sql/new?content=${encodeURIComponent(generateJobDetailsSQL(job.jobid))}`}
>
<Link href={`/project/${ref}/integrations/cron-jobs/cron-jobs/${job.jobname}`}>
View previous runs
</Link>
</DropdownMenuItem>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ export const CRONJOB_DEFINITIONS = [
{
value: 'sql_function',
icon: <ScrollText strokeWidth={1} />,
label: 'Postgres SQL Function',
description: 'Choose a Postgres SQL functions to run.',
label: 'Database function',
description: 'Choose a database function to run.',
},

{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,36 @@ export const parseCronJobCommand = (originalCommand: string): CronJobType => {
return DEFAULT_CRONJOB_COMMAND
}

export function calculateDuration(start: string, end: string): string {
const startTime = new Date(start).getTime()
const endTime = new Date(end).getTime()
const duration = endTime - startTime
return isNaN(duration) ? 'Invalid Date' : `${duration} ms`
}

export function formatDate(dateString: string): string {
const date = new Date(dateString)
if (isNaN(date.getTime())) {
return 'Invalid Date'
}
const options: Intl.DateTimeFormatOptions = {
year: 'numeric',
month: 'short', // Use 'long' for full month name
day: '2-digit',
hour: '2-digit',
minute: '2-digit',
second: '2-digit',
hour12: false, // Use 12-hour format if preferred
timeZoneName: 'short', // Optional: to include timezone
}
return date.toLocaleString(undefined, options)
}

// detect seconds like "10 seconds" or normal cron syntax like "*/5 * * * *"
export const secondsPattern = /^\d+\s+seconds$/
export const cronPattern =
/^(\*|(\d+|\*\/\d+)|\d+\/\d+|\d+-\d+|\d+(,\d+)*)(\s+(\*|(\d+|\*\/\d+)|\d+\/\d+|\d+-\d+|\d+(,\d+)*)){4}$/

export function isSecondsFormat(schedule: string): boolean {
return secondsPattern.test(schedule.trim())
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
export default function CronJobsEmptyState({ page }: { page: string }) {
return (
<div className=" text-center h-full w-full items-center justify-center rounded-md px-4 py-12 ">
<p className="text-sm text-foreground">
{page === 'jobs' ? 'No cron jobs created yet' : 'No runs for this cron job yet'}
</p>
<p className="text-sm text-foreground-lighter">
{page === 'jobs'
? 'Create one by clicking "Create a new cron job"'
: 'Check the schedule of your cron jobs to see when they run'}
</p>
</div>
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ export const CronjobsTab = () => {
projectRef: project?.ref,
connectionString: project?.connectionString,
})

if (isLoading)
return (
<div className="p-10">
Expand Down Expand Up @@ -95,9 +94,14 @@ export const CronjobsTab = () => {
Your search for "{searchQuery}" did not return any results
</p>
</div>
) : isLoading ? (
<div className="p-10">
<GenericSkeletonLoader />
</div>
) : (
filteredCronJobs.map((job) => (
<CronJobCard
key={job.jobid}
job={job}
onEditCronJob={(job) => setCreateCronJobSheetShown(job)}
onDeleteCronJob={(job) => setCronJobForDeletion(job)}
Expand Down
Loading
Loading