Files
what-to-eat/apps/web/app/composables/useYunlefunAuth.ts
T
toor 76a5d71252 refactor: 只保留 Web,移除 Capacitor 原生壳
删除 android/、ios/ 两个 Capacitor 原生工程与 capacitor.config.ts、
ionic.config.json,以及 scripts/android、scripts/ios.sh 构建脚本;
根与 apps/web 的 @capacitor/* 依赖和相关 npm scripts 一并移除。

Web 侧去掉原生分支:登录只走云乐坊容器授权面板或顶层重定向,
暗色模式不再改原生状态栏,移除 Android 物理返回键处理。

保留 @nuxtjs/ionic(Web UI 框架)、云乐坊 window.ylf 桥接与 PWA。

决策记录见 docs/decisions/0004-web-only.md。
2026-10-21 12:27:50 +08:00

130 lines
3.9 KiB
TypeScript

import type {
YunlefunAuthController,
YunlefunAuthSnapshot,
} from '~/utils/yunlefunAuth'
import {
callCloudbaseFunction,
createCloudbaseIdentityAdapter,
createWebYunlefunAuthorizationAdapter,
} from '~/adapters/yunlefunAuth'
import { createYunlefunAuthController } from '~/utils/yunlefunAuth'
import { resolveYunlefunSsoConfig } from '~/utils/yunlefunSsoConfig'
interface YunlefunRuntimeConfig {
public: {
yunlefunCloudbaseEnv?: string
yunlefunSsoClientId?: string
yunlefunSsoExchangeUrl?: string
yunlefunSsoOrigin?: string
yunlefunSsoRedirectUri?: string
yunlefunSsoRedirectUris?: string
yunlefunSsoScope?: string
}
}
let controller: YunlefunAuthController | undefined
let cloudbaseEnv = ''
let initialization: Promise<void> | undefined
export function useYunlefunAuth() {
const runtimeConfig = useRuntimeConfig() as unknown as YunlefunRuntimeConfig
const snapshot = useState<YunlefunAuthSnapshot>('yunlefun:auth:snapshot', () => ({
account: null,
errorMessage: '',
status: 'idle',
}))
const configurationMessage = useState<string>('yunlefun:auth:configuration-message', () => '')
const isConfigured = computed(() => !configurationMessage.value)
const isAuthenticated = computed(() => snapshot.value.status === 'signed-in' && Boolean(snapshot.value.account))
async function initialize(): Promise<void> {
if (!initialization)
initialization = initializeOnce(runtimeConfig, snapshot, configurationMessage)
await initialization
publishSnapshot(snapshot)
}
async function signIn(): Promise<void> {
if (!controller || !isConfigured.value)
return
await controller.signIn()
publishSnapshot(snapshot)
}
async function signOut(): Promise<void> {
if (!controller)
return
await controller.signOut()
publishSnapshot(snapshot)
}
/** Call a CloudBase cloud function as the signed-in account. */
async function callFunction(name: string, data: Record<string, unknown>): Promise<unknown> {
if (!cloudbaseEnv)
throw new Error('CloudBase is not configured')
return callCloudbaseFunction(cloudbaseEnv, name, data)
}
return {
account: computed(() => snapshot.value.account),
configurationMessage: readonly(configurationMessage),
errorMessage: computed(() => snapshot.value.errorMessage),
callFunction,
initialize,
isAuthenticated,
isConfigured,
signIn,
signOut,
status: computed(() => snapshot.value.status),
}
}
async function initializeOnce(
runtimeConfig: YunlefunRuntimeConfig,
snapshot: Ref<YunlefunAuthSnapshot>,
configurationMessage: Ref<string>,
): Promise<void> {
if (!import.meta.client)
return
const result = resolveYunlefunSsoConfig({
clientId: runtimeConfig.public.yunlefunSsoClientId,
cloudbaseEnv: runtimeConfig.public.yunlefunCloudbaseEnv,
exchangeUrl: runtimeConfig.public.yunlefunSsoExchangeUrl,
redirectUri: runtimeConfig.public.yunlefunSsoRedirectUri,
redirectUris: runtimeConfig.public.yunlefunSsoRedirectUris,
scope: runtimeConfig.public.yunlefunSsoScope,
ssoOrigin: runtimeConfig.public.yunlefunSsoOrigin,
}, {
currentOrigin: window.location.origin,
})
if (!result.ok) {
configurationMessage.value = result.message
snapshot.value = {
account: null,
errorMessage: '',
status: 'signed-out',
}
return
}
cloudbaseEnv = result.config.cloudbaseEnv
controller = createYunlefunAuthController({
identity: createCloudbaseIdentityAdapter(result.config),
web: createWebYunlefunAuthorizationAdapter(result.config),
})
await controller.initialize()
publishSnapshot(snapshot)
if (window.location.pathname === '/auth/callback'
&& controller.snapshot().status === 'signed-in') {
await navigateTo('/my', { replace: true })
}
}
function publishSnapshot(snapshot: Ref<YunlefunAuthSnapshot>): void {
if (controller)
snapshot.value = controller.snapshot()
}