Skip to content

Commit

Permalink
fix: ship type definition on build package (#69)
Browse files Browse the repository at this point in the history
resolve #67
  • Loading branch information
nogic1008 authored Feb 29, 2024
1 parent af70ca3 commit 36bdb2a
Show file tree
Hide file tree
Showing 15 changed files with 112 additions and 79 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,23 @@
# Changelog

## v0.3.2

- No enhancements on packages

[compare changes](https://github.com/ddradar/nuxt-swa/compare/v0.3.1...v0.3.2)

### 🩹 Fixes

- ship type definition on build package ([#69](https://github.com/ddradar/nuxt-swa/pull/69), resolve [#67](https://github.com/ddradar/nuxt-swa/issues/67))

### 🏡 Chore

- **lint:** Add eslint-plugin-simple-import ([#68](https://github.com/ddradar/nuxt-swa/pull/68))

### ❤️ Contributors

- Nogic

## v0.3.1

- No enhancements on packages
Expand Down
4 changes: 2 additions & 2 deletions docs/content/index.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ hero:
description: Provides Azure Static Web Apps features to your Nuxt apps.
orientation: horizontal
headline:
label: Released v0.3.0
to: https://github.com/ddradar/nuxt-swa/releases/tag/v0.3.0
label: Released v0.3.2
to: https://github.com/ddradar/nuxt-swa/releases/tag/v0.3.2
icon: i-heroicons-rocket-launch-20-solid
links:
- label: Get started
Expand Down
2 changes: 1 addition & 1 deletion docs/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "nuxt-swa-docs",
"private": true,
"version": "0.3.1",
"version": "0.3.2",
"description": "Nuxt SWA module documentation and playground",
"type": "module",
"engines": {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "nuxt-swa-monorepo",
"private": true,
"version": "0.3.1",
"version": "0.3.2",
"description": "Nuxt 3 module for Azure Static Web Apps",
"repository": "ddradar/nuxt-swa",
"license": "MIT",
Expand Down
3 changes: 1 addition & 2 deletions packages/nuxt-swa/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "nuxt-swa",
"version": "0.3.1",
"version": "0.3.2",
"description": "Nuxt module for Azure Static Web Apps",
"repository": {
"type": "git",
Expand Down Expand Up @@ -35,7 +35,6 @@
},
"dependencies": {
"@nuxt/kit": "^3.10.3",
"consola": "^3.2.3",
"defu": "^6.1.4",
"ufo": "^1.4.0"
},
Expand Down
63 changes: 37 additions & 26 deletions packages/nuxt-swa/src/runtime/composables/useDataApi.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,26 @@
import type { $Fetch } from 'nitropack'
import type { FetchError } from 'ofetch'
import { joinURL } from 'ufo'
import type { MaybeRef } from 'vue'
import { computed, type MaybeRef, toRef } from 'vue'

import type { UseFetchOptions } from '#app'
import {
type AsyncData,
useFetch,
type UseFetchOptions,
useRuntimeConfig,
} from '#app'

/**
* Use Azure Static Web Apps Data API Feature (preview).
* @returns `$fetch` object pre-configured for Data API
*/
export function useDataApi(): {
export const useDataApi = (): {
/** `$fetch` object pre-configured for GraphQL API */
$graphql: $Fetch
/** `$fetch` object pre-configured for REST API */
$rest: $Fetch
} {
} => {
const { graphql, rest } = useRuntimeConfig().public.swa
console.info(useRequestHeaders())
return {
$graphql: $fetch.create({ baseURL: graphql, method: 'POST' }),
$rest: $fetch.create({ baseURL: rest }),
Expand All @@ -30,22 +34,24 @@ export function useDataApi(): {
* @returns useFetch object
* @see https://learn.microsoft.com/azure/data-api-builder/rest
*/
export function useFetchRest<T>(
export const useFetchRest = <
SchemaT,
DataT = SchemaT[],
PickKeys extends KeysOf<DataT> = KeysOf<DataT>,
DefaultT = null,
>(
request: MaybeRef<string>,
opts?: Omit<UseFetchOptions<RestResult<T>, T[]>, 'transform'>
): ReturnType<typeof useFetch<T[] | null>> {
opts?: UseFetchOptions<RestResult<SchemaT>, DataT, PickKeys, DefaultT>
): AsyncData<PickFrom<DataT, PickKeys> | DefaultT, FetchError<any> | null> => {
const endpoint = useRuntimeConfig().public.swa.rest
const requestRef = toRef(request)
const computedUrl = computed(() => joinURL(endpoint, requestRef.value))
return useFetch(computedUrl, {
transform: (d: RestResult<SchemaT>) => d.value as DataT,
...opts,
transform: (d: RestResult<T>) => d.value,
})
}

type KeysOf<T> = Array<
T extends T ? (keyof T extends string ? keyof T : never) : never
>
/**
* Use fetch from/to Azure Static Web Apps Data API (GraphQL).
* @param key `useFetch` key
Expand All @@ -55,11 +61,11 @@ type KeysOf<T> = Array<
* @returns` useFetch` object
* @see https://learn.microsoft.com/azure/data-api-builder/graphql
*/
export function useFetchGraphQL<
export const useFetchGraphQL = <
SchemaT,
DataT = SchemaT,
PickKeys extends KeysOf<DataT> = KeysOf<DataT>,
DefaultT = DataT,
DefaultT = null,
>(
key: string,
query: string,
Expand All @@ -68,18 +74,7 @@ export function useFetchGraphQL<
UseFetchOptions<GraphQLResult<SchemaT>, DataT, PickKeys, DefaultT>,
'body' | 'key' | 'method'
>
): ReturnType<
typeof useFetch<
GraphQLResult<SchemaT>,
FetchError<any>,
string,
'post',
GraphQLResult<SchemaT>,
DataT,
PickKeys,
DefaultT
>
> {
): AsyncData<PickFrom<DataT, PickKeys> | DefaultT, FetchError<any> | null> => {
const endpoint = useRuntimeConfig().public.swa.graphql
const variablesRef = toRef(variables)

Expand All @@ -100,3 +95,19 @@ export function useFetchGraphQL<
...opts,
})
}

/** Port from nuxt runtime */
type KeysOf<T> = Array<
T extends T ? (keyof T extends string ? keyof T : never) : never
>
/** Port from nuxt runtime */
type PickFrom<T, K extends Array<string>> =
T extends Array<any>
? T
: T extends Record<string, any>
? keyof T extends K[number]
? T
: K[number] extends never
? T
: Pick<T, K[number]>
: T
35 changes: 3 additions & 32 deletions packages/nuxt-swa/src/runtime/composables/useEasyAuth.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,46 +8,17 @@ import {
_authDataKey,
_clientPrincipalHeader,
} from '../constants'
import type { ClientPrincipal } from '../types'
import { parseClientPrincipal } from '../utils/auth'

interface Claim {
typ: string
val: string
}
/**
* User-identifiable information to your app.
* @see https://learn.microsoft.com/azure/static-web-apps/user-information?tabs=javascript#client-principal-data
*/
export interface ClientPrincipal {
/** The name of the identity provider. */
identityProvider: IdentityProvider
/**
* An Azure Static Web Apps-specific unique identifier for the user.
* - The value is unique on a per-app basis. For instance, the same user returns a different `userId` value on a different Static Web Apps resource.
* - The value persists for the lifetime of a user. If you delete and add the same user back to the app, a new `userId` is generated.
*/
userId: string
/**
* Username or email address of the user.
* Some providers return the user's email address, while others send the user handle.
*/
userDetails: string
/** An array of the user's assigned roles. */
userRoles: UserRole[]
/**
* An array of claims returned by your custom authentication provider.
* Only accessible in the direct-access endpoint (/.auth/me).
*/
claims?: Claim[]
}
/** return type of `/.auth/me` endpoint */
type AuthMeResult = { clientPrincipal: ClientPrincipal | null }

/**
* Use authentication & authorization features provided by Azure Static Web Apps.
* @see https://learn.microsoft.com/en-us/azure/static-web-apps/authentication-authorization
*/
export async function useEasyAuth(): Promise<{
export const useEasyAuth = async (): Promise<{
/** Client Principal data */
clientPrincipal: DeepReadonly<Ref<ClientPrincipal | null>>
/** Returns user is logged in app or not. (shorthand of `!!clientPrincipal.value`) */
Expand Down Expand Up @@ -77,7 +48,7 @@ export async function useEasyAuth(): Promise<{
* @see https://learn.microsoft.com/azure/static-web-apps/authentication-authorization#remove-personal-data
*/
purge: (provider: IdentityProvider) => Promise<void>
}> {
}> => {
const { data: _auth, refresh } = await useAsyncData<ClientPrincipal | null>(
_authDataKey,
async () => {
Expand Down
3 changes: 0 additions & 3 deletions packages/nuxt-swa/src/runtime/constants.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import { consola } from 'consola'

// Azure Static Web Apps
export const _authBasePath = '/.auth'
export const _dataApiBasePath = '/data-api'
Expand All @@ -13,5 +11,4 @@ export const _knownIdentityProviders = [
] as const

// My App
export const logger = consola.withTag('nuxt-swa')
export const _authDataKey = 'swa-principal'
2 changes: 2 additions & 0 deletions packages/nuxt-swa/src/runtime/middleware/auth.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import { defineNuxtRouteMiddleware } from '#app'

export default defineNuxtRouteMiddleware(async to => {
if (!to.meta.allowedRoles) return

Expand Down
8 changes: 4 additions & 4 deletions packages/nuxt-swa/src/runtime/server/utils/swa-auth.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
import { getHeader, type H3Event } from 'h3'

import type { ClientPrincipal } from '../../composables/useEasyAuth'
import { _clientPrincipalHeader } from '../../constants'
import type { ClientPrincipal } from '../../types'
import { parseClientPrincipal } from '../../utils/auth'

/**
* Get user client principal data from request.
* @param event H3Event
* @returns Client Principal if parsed, otherwise null.
*/
export function getClientPrincipal(event: H3Event): ClientPrincipal | null {
export const getClientPrincipal = (event: H3Event): ClientPrincipal | null => {
const header = getHeader(event, _clientPrincipalHeader)
return parseClientPrincipal(header)
}
Expand All @@ -20,10 +20,10 @@ export function getClientPrincipal(event: H3Event): ClientPrincipal | null {
* @param roles User roles
* @returns true if the user has any of the specified roles; false otherwise.
*/
export function hasRole(
export const hasRole = (
event: H3Event,
...roles: Exclude<UserRole, 'anonymous'>[]
): boolean {
): boolean => {
const auth = getClientPrincipal(event)
return !!auth?.userRoles.some(s =>
roles.includes(s as (typeof roles)[number])
Expand Down
30 changes: 30 additions & 0 deletions packages/nuxt-swa/src/runtime/types.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
interface Claim {
typ: string
val: string
}
/**
* User-identifiable information to your app.
* @see https://learn.microsoft.com/azure/static-web-apps/user-information?tabs=javascript#client-principal-data
*/
export interface ClientPrincipal {
/** The name of the identity provider. */
identityProvider: IdentityProvider
/**
* An Azure Static Web Apps-specific unique identifier for the user.
* - The value is unique on a per-app basis. For instance, the same user returns a different `userId` value on a different Static Web Apps resource.
* - The value persists for the lifetime of a user. If you delete and add the same user back to the app, a new `userId` is generated.
*/
userId: string
/**
* Username or email address of the user.
* Some providers return the user's email address, while others send the user handle.
*/
userDetails: string
/** An array of the user's assigned roles. */
userRoles: UserRole[]
/**
* An array of claims returned by your custom authentication provider.
* Only accessible in the direct-access endpoint (/.auth/me).
*/
claims?: Claim[]
}
13 changes: 10 additions & 3 deletions packages/nuxt-swa/src/runtime/types/nuxt-swa.meta.d.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,17 @@
// Generated by nuxt-swa
type SpecifiedRole = Exclude<UserRole, 'anonymous'>

declare module '#app' {
interface PageMeta {
/** List of roles required to view this page */
allowedRoles?:
| Exclude<UserRole, 'anonymous'>
| Exclude<UserRole, 'anonymous'>[]
allowedRoles?: SpecifiedRole | SpecifiedRole[]
}
}

declare module 'vue-router' {
interface RouteMeta {
/** List of roles required to view this page */
allowedRoles?: SpecifiedRole | SpecifiedRole[]
}
}

Expand Down
2 changes: 1 addition & 1 deletion packages/nuxt-swa/src/runtime/utils/auth.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { ClientPrincipal } from '../composables/useEasyAuth'
import type { ClientPrincipal } from '../types'

export function parseClientPrincipal(
header: string | null | undefined
Expand Down
3 changes: 2 additions & 1 deletion packages/nuxt-swa/tsconfig.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
{
"extends": "./.nuxt/tsconfig.json"
"extends": "./.nuxt/tsconfig.json",
"exclude": ["docs"]
}
3 changes: 0 additions & 3 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 36bdb2a

Please sign in to comment.