删除 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。
130 lines
3.9 KiB
TypeScript
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()
|
|
}
|