Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion apps/blog-next/app/auth-nav.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

import { useState } from 'react'
import Link from 'next/link'
import { useAuth } from '@holo-js/adapter-next/client'
import { useAuth } from '@holo-js/auth/next/client'

const linkStyle = {
color: '#cbd5e1',
Expand Down
4 changes: 2 additions & 2 deletions apps/blog-next/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import type { ReactNode } from 'react'
import type { Metadata } from 'next'
import Link from 'next/link'
import { AuthProvider } from '@holo-js/adapter-next/client'
import { auth } from '@holo-js/adapter-next/server'
import { AuthProvider } from '@holo-js/auth/next/client'
import { auth } from '@holo-js/auth/next/server'

import { AuthNav } from './auth-nav'

Expand Down
3 changes: 2 additions & 1 deletion apps/blog-next/app/login/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

import Link from 'next/link'
import { useRouter } from 'next/navigation'
import { useAuth, useForm } from '@holo-js/adapter-next/client'
import { useAuth } from '@holo-js/auth/next/client'
import { useForm } from '@holo-js/adapter-next/client'
import { loginForm } from '@/lib/schemas/auth'

const panelStyle = {
Expand Down
3 changes: 2 additions & 1 deletion apps/blog-next/app/verify-email/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import { useState } from 'react'
import Link from 'next/link'
import { useRouter, useSearchParams } from 'next/navigation'

import { useAuth, useForm } from '@holo-js/adapter-next/client'
import { useAuth } from '@holo-js/auth/next/client'
import { useForm } from '@holo-js/adapter-next/client'

import { verifyEmailForm } from '@/lib/schemas/auth'

Expand Down
18 changes: 12 additions & 6 deletions apps/blog-next/proxy.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { guestOnly } from '@holo-js/adapter-next/server'
import { authOnly, guestOnly, protectRoutes } from '@holo-js/auth/next/server'

export const proxy = guestOnly({
routes: ['/login', '/register', '/forgot-password', '/reset-password'],
redirectTo: '/admin',
})
export const proxy = protectRoutes(
guestOnly({
routes: ['/login', '/register', '/forgot-password', '/reset-password'],
redirectTo: '/admin',
}),
authOnly({
routes: ['/admin/*'],
redirectTo: '/login',
}),
)

export const config = {
matcher: ['/login', '/register', '/forgot-password', '/reset-password'],
matcher: ['/login', '/register', '/forgot-password', '/reset-password', '/admin/:path*'],
}
30 changes: 29 additions & 1 deletion apps/blog-next/tests/run.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,34 @@ async function waitForText(url, predicate, timeoutMs = 30000) {
throw new Error(`Timed out waiting for ${url}${lastError instanceof Error ? `: ${lastError.message}` : ''}`)
}

async function waitForRedirect(url, expectedPath, timeoutMs = 30000) {
const startedAt = Date.now()
let lastError = null

while (Date.now() - startedAt < timeoutMs) {
try {
const response = await fetch(url, { redirect: 'manual' })
const location = response.headers.get('location')
if (response.status >= 300 && response.status < 400 && location) {
const locationPath = new URL(location, url).pathname
if (locationPath === expectedPath) {
return
}

lastError = new Error(`Unexpected redirect ${response.status} to ${locationPath}`)
} else {
lastError = new Error(`Unexpected status ${response.status}`)
}
} catch (error) {
lastError = error
}

await new Promise(resolve => setTimeout(resolve, 250))
}

throw new Error(`Timed out waiting for ${url} to redirect to ${expectedPath}${lastError instanceof Error ? `: ${lastError.message}` : ''}`)
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

function pipeOutput(stream, target) {
if (!stream) {
return
Expand Down Expand Up @@ -208,7 +236,7 @@ try {
const initial = await waitForJson(healthUrl, payload => payload.ok === true)
assert.equal(initial.app, 'blog-next')
await waitForText(`http://localhost:${port}/`, payload => payload.includes('Shipping a Real Holo Blog on Next'))
await waitForText(`http://localhost:${port}/admin/posts`, payload => payload.includes('Designing the Example App Roadmap'))
await waitForRedirect(`http://localhost:${port}/admin/posts`, '/login')
await assertExampleAppAuthFlow({
baseUrl: `http://localhost:${port}`,
getOutput: () => capturedOutput,
Expand Down
2 changes: 2 additions & 0 deletions apps/blog-nuxt/app/app.vue
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
<script setup lang="ts">
import { useAuth } from '@holo-js/auth/nuxt'

const { authenticated, refreshUser, user } = await useAuth()
const displayName = computed(() => user.value?.name ?? user.value?.email ?? 'Account')

Expand Down
6 changes: 6 additions & 0 deletions apps/blog-nuxt/app/middleware/auth-only.global.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
import { authOnly } from '@holo-js/auth/nuxt/server'

export default authOnly({
routes: ['/admin/*'],
redirectTo: '/login',
})
2 changes: 1 addition & 1 deletion apps/blog-nuxt/app/middleware/guest-only.global.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { guestOnly } from '@holo-js/adapter-nuxt/server'
import { guestOnly } from '@holo-js/auth/nuxt/server'

export default guestOnly({
routes: ['/login', '/register', '/forgot-password', '/reset-password'],
Expand Down
3 changes: 3 additions & 0 deletions apps/blog-nuxt/app/pages/login.vue
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
<script setup lang="ts">
import { useAuth } from '@holo-js/auth/nuxt'
import { useForm } from '@holo-js/adapter-nuxt/client'
import { loginForm } from '#shared/schemas/auth'

const { refreshUser } = await useAuth()
const form = useForm(loginForm, {
validateOn: 'blur',
initialValues: { email: '', password: '', remember: false },
async submitter({ formData }) {
const submission = await $fetch('/api/login', { method: 'POST', body: formData })
if (submission?.ok === true && typeof submission.data?.redirectTo === 'string') {
await refreshUser()
await navigateTo(submission.data.redirectTo, {
external: true,
})
Expand Down
3 changes: 3 additions & 0 deletions apps/blog-nuxt/app/pages/register.vue
Original file line number Diff line number Diff line change
@@ -1,14 +1,17 @@
<script setup lang="ts">
import { navigateTo } from '#imports'
import { useAuth } from '@holo-js/auth/nuxt'
import { useForm } from '@holo-js/adapter-nuxt/client'
import { registerForm } from '#shared/schemas/auth'

const { refreshUser } = await useAuth()
const form = useForm(registerForm, {
validateOn: 'blur',
initialValues: { name: '', email: '', password: '', passwordConfirmation: '' },
async submitter({ formData }) {
const submission = await $fetch('/api/register', { method: 'POST', body: formData })
if (submission?.ok === true && typeof submission.data?.redirectTo === 'string') {
await refreshUser()
await navigateTo(submission.data.redirectTo, {
redirectCode: 302,
})
Expand Down
1 change: 1 addition & 0 deletions apps/blog-nuxt/app/pages/verify-email.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<script setup lang="ts">
import { navigateTo, useRoute } from '#imports'
import { useAuth } from '@holo-js/auth/nuxt'
import { useForm } from '@holo-js/adapter-nuxt/client'
import { ref } from 'vue'
import { verifyEmailForm } from '#shared/schemas/auth'
Expand Down
30 changes: 29 additions & 1 deletion apps/blog-nuxt/tests/run.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,34 @@ async function waitForText(url, predicate, timeoutMs = 30000) {
throw new Error(`Timed out waiting for ${url}${lastError instanceof Error ? `: ${lastError.message}` : ''}`)
}

async function waitForRedirect(url, expectedPath, timeoutMs = 30000) {
const startedAt = Date.now()
let lastError = null

while (Date.now() - startedAt < timeoutMs) {
try {
const response = await fetch(url, { redirect: 'manual' })
const location = response.headers.get('location')
if (response.status >= 300 && response.status < 400 && location) {
const locationPath = new URL(location, url).pathname
if (locationPath === expectedPath) {
return
}

lastError = new Error(`Unexpected redirect ${response.status} to ${locationPath}`)
} else {
lastError = new Error(`Unexpected status ${response.status}`)
}
} catch (error) {
lastError = error
}

await new Promise(resolve => setTimeout(resolve, 250))
}

throw new Error(`Timed out waiting for ${url} to redirect to ${expectedPath}${lastError instanceof Error ? `: ${lastError.message}` : ''}`)
}

function pipeOutput(stream, target) {
if (!stream) {
return
Expand Down Expand Up @@ -214,7 +242,7 @@ try {
const initial = await waitForJson(healthUrl, payload => payload.ok === true)
assert.equal(initial.app, 'blog-nuxt')
await waitForText(`http://localhost:${port}/`, payload => payload.includes('Shipping a Real Holo Blog on Nuxt'))
await waitForText(`http://localhost:${port}/admin/posts`, payload => payload.includes('Designing the Example App Roadmap'))
await waitForRedirect(`http://localhost:${port}/admin/posts`, '/login')
await assertExampleAppAuthFlow({
baseUrl: `http://localhost:${port}`,
getOutput: () => capturedOutput,
Expand Down
17 changes: 12 additions & 5 deletions apps/blog-sveltekit/src/hooks.server.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
import { guestOnly } from '@holo-js/adapter-sveltekit/server'
import { sequence } from '@sveltejs/kit/hooks'
import { authOnly, guestOnly } from '@holo-js/auth/sveltekit/server'

export const handle = guestOnly({
routes: ['/login', '/register', '/forgot-password', '/reset-password'],
redirectTo: '/admin',
})
export const handle = sequence(
guestOnly({
routes: ['/login', '/register', '/forgot-password', '/reset-password'],
redirectTo: '/admin',
}),
authOnly({
routes: ['/admin/*'],
redirectTo: '/login',
}),
)
2 changes: 1 addition & 1 deletion apps/blog-sveltekit/src/routes/+layout.server.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { auth } from '@holo-js/adapter-sveltekit/server'
import { auth } from '@holo-js/auth/sveltekit/server'

export async function load() {
const currentAuth = await auth()
Expand Down
2 changes: 1 addition & 1 deletion apps/blog-sveltekit/src/routes/+layout.svelte
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<script lang="ts">
import { invalidateAll } from '$app/navigation'
import { untrack } from 'svelte'
import { useAuth } from '@holo-js/adapter-sveltekit/client'
import { useAuth } from '@holo-js/auth/sveltekit/client'
import type { LayoutProps } from './$types'

let { data, children }: LayoutProps = $props()
Expand Down
3 changes: 2 additions & 1 deletion apps/blog-sveltekit/src/routes/login/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import { goto, invalidateAll } from '$app/navigation'
import { useAuth, useForm } from '@holo-js/adapter-sveltekit/client'
import { useAuth } from '@holo-js/auth/sveltekit/client'
import { useForm } from '@holo-js/adapter-sveltekit/client'
import { loginForm } from '$lib/schemas/auth'

const auth = useAuth()
Expand Down
3 changes: 2 additions & 1 deletion apps/blog-sveltekit/src/routes/register/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import { goto, invalidateAll } from '$app/navigation'
import { useAuth, useForm } from '@holo-js/adapter-sveltekit/client'
import { useAuth } from '@holo-js/auth/sveltekit/client'
import { useForm } from '@holo-js/adapter-sveltekit/client'
import { registerForm } from '$lib/schemas/auth'

const auth = useAuth()
Expand Down
3 changes: 2 additions & 1 deletion apps/blog-sveltekit/src/routes/verify-email/+page.svelte
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
<script lang="ts">
import { goto, invalidateAll } from '$app/navigation'
import { useAuth, useForm } from '@holo-js/adapter-sveltekit/client'
import { useAuth } from '@holo-js/auth/sveltekit/client'
import { useForm } from '@holo-js/adapter-sveltekit/client'
import { verifyEmailForm } from '$lib/schemas/auth'

export let data: {
Expand Down
30 changes: 29 additions & 1 deletion apps/blog-sveltekit/tests/run.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,34 @@ async function waitForText(url, predicate, timeoutMs = 30000) {
throw new Error(`Timed out waiting for ${url}${lastError instanceof Error ? `: ${lastError.message}` : ''}`)
}

async function waitForRedirect(url, expectedPath, timeoutMs = 30000) {
const startedAt = Date.now()
let lastError = null

while (Date.now() - startedAt < timeoutMs) {
try {
const response = await fetch(url, { redirect: 'manual' })
const location = response.headers.get('location')
if (response.status >= 300 && response.status < 400 && location) {
const locationPath = new URL(location, url).pathname
if (locationPath === expectedPath) {
return
}

lastError = new Error(`Unexpected redirect ${response.status} to ${locationPath}`)
} else {
lastError = new Error(`Unexpected status ${response.status}`)
}
} catch (error) {
lastError = error
}

await new Promise(resolve => setTimeout(resolve, 250))
}

throw new Error(`Timed out waiting for ${url} to redirect to ${expectedPath}${lastError instanceof Error ? `: ${lastError.message}` : ''}`)
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

function pipeOutput(stream, target, onLine) {
if (!stream) {
return
Expand Down Expand Up @@ -263,7 +291,7 @@ try {
const initial = await waitForJson(healthUrl, payload => payload.ok === true)
assert.equal(initial.app, 'blog-sveltekit')
await waitForText(`${devUrl}/`, payload => payload.includes('Shipping a Real Holo Blog on SvelteKit'))
await waitForText(`${devUrl}/admin/posts`, payload => payload.includes('Designing the Example App Roadmap'))
await waitForRedirect(`${devUrl}/admin/posts`, '/login')
await assertExampleAppAuthFlow({
baseUrl: devUrl,
getOutput: () => capturedOutput,
Expand Down
Loading