diff --git a/index.d.ts b/index.d.ts index 39a513d..51c7dfd 100644 --- a/index.d.ts +++ b/index.d.ts @@ -11,6 +11,8 @@ export * from './src/services/auth-service'; export * from './src/services/geo-json'; export * from './src/services/image-service'; export * from './src/services/search'; +export * from './src/services/search-2'; +export * from './src/services/auth-2'; export * from './src/iiif/descriptive'; export * from './src/iiif/linking'; export * from './src/iiif/structural'; @@ -19,3 +21,4 @@ export * from './src/utility'; export * from './src/reference'; export * from './src/extensions/nav-place'; export * from './src/extensions/text-granularity'; +export * from './src/change-discovery'; diff --git a/package.json b/package.json index 978f2be..4e01149 100644 --- a/package.json +++ b/package.json @@ -27,7 +27,7 @@ "dts-bundle-generator": "^6.12.0", "eslint": "^8.20.0", "eslint-plugin-prettier": "^4.2.1", - "prettier": "^2.7.1", + "prettier": "^3.2.5", "tsd": "^0.30.0", "tslib": "^2.4.0", "typescript": "^4.7.4" diff --git a/src/change-discovery.d.ts b/src/change-discovery.d.ts new file mode 100644 index 0000000..c7a04ea --- /dev/null +++ b/src/change-discovery.d.ts @@ -0,0 +1,126 @@ +// Based on: https://iiif.io/api/discovery/1.0/ + +import { InternationalString } from './iiif/descriptive'; +import { Manifest } from './resources/manifest'; +import { Prettify } from './utility'; + +export type ChangeDiscoveryActivityRequest = { + startTime?: string; // xsd:dateTime + summary?: string; + actor?: ChangeDiscoveryActor; + target?: ChangeDiscoveryBaseObject; + object: ChangeDiscoveryBaseObject; +}; + +export type ChangeDiscoveryActivity = Prettify< + { + id: string; + endTime: string; // xsd:dateTime + startTime?: string; // xsd:dateTime + summary?: string; + actor?: ChangeDiscoveryActor; + target?: ChangeDiscoveryBaseObject; + } & ( + | { + type: Exclude; + object: ChangeDiscoveryBaseObject; + } + | { + type: 'Move'; + object: ChangeDiscoveryBaseObject; + target: ChangeDiscoveryBaseObject; + } + ) +>; + +export type ChangeDiscoveryBaseObject = { + id: string; + canonical?: string; + name?: string; // Non-standard. + type: 'Collection' | 'Manifest' | 'Canvas'; // Technically also: Range, Canvas etc. + seeAlso?: ChangeDiscoverySeeAlso[]; + provider?: Manifest['provider']; +}; + +type ChangeDiscoveryActor = { + id: string; + type: 'Person' | 'Application' | 'Organization'; +}; + +export type ChangeDiscoveryGenesisRequest = { + ids: string[]; +}; + +export type ChangeDiscoveryGenesisResponse = { + prefix: string; + ids: string[]; +}; + +export type ChangeDiscoveryImplementationState = { + processItems: any[]; + lastCrawl: number; + onlyDelete: boolean; +}; + +export type ActivityCollectionProcessor = ( + collection: ActivityOrderedCollection, + state: ChangeDiscoveryImplementationState +) => ChangeDiscoveryImplementationState; + +export type ActivityPageProcessor = ( + page: ActivityOrderedCollectionPage, + state: ChangeDiscoveryImplementationState +) => ChangeDiscoveryImplementationState; + +export type ChangeDiscoveryActivityType = 'Create' | 'Update' | 'Delete' | 'Move' | 'Add' | 'Remove'; + +export type ChangeDiscoverySeeAlso = { + id: string; + type: 'Dataset'; + format: string; + label: InternationalString; + profile: string; +}; + +export type ActivityOrderedCollection = { + '@context': 'http://iiif.io/api/discovery/1/context.json' | string[]; + id: string; + type: 'OrderedCollection'; + first?: { + id: string; + type: 'OrderedCollectionPage'; + }; + last: { + id: string; + type: 'OrderedCollectionPage'; + }; + totalItems?: number; + seeAlso?: ChangeDiscoverySeeAlso[]; + partOf?: Array<{ + id: string; + type: 'OrderedCollection'; + }>; + rights: string; + // Non-standard + totalPages?: number; +}; + +export type ActivityOrderedCollectionPage = { + '@context': 'http://iiif.io/api/discovery/1/context.json' | string[]; + id: string; + type: 'OrderedCollectionPage'; + partOf?: { + id: string; + type: 'OrderedCollection'; + }; + startIndex?: number; + next?: { + id: string; + type: 'OrderedCollectionPage'; + }; + prev?: { + id: string; + type: 'OrderedCollectionPage'; + }; + orderedItems: ChangeDiscoveryActivity[]; +}; diff --git a/src/resources/annotation.d.ts b/src/resources/annotation.d.ts index 832f5c8..f35faec 100644 --- a/src/resources/annotation.d.ts +++ b/src/resources/annotation.d.ts @@ -33,7 +33,9 @@ export type W3CMotivation = | 'moderating' | 'questioning' | 'replying' - | 'tagging'; + | 'tagging' + // Search2 + | 'contextualizing'; export type AnyMotivation = LiteralUnion; diff --git a/src/resources/service.d.ts b/src/resources/service.d.ts index c280e6f..0bf95c3 100644 --- a/src/resources/service.d.ts +++ b/src/resources/service.d.ts @@ -1,6 +1,8 @@ +import { AuthProbeService2 } from '../services/auth-2'; import { AuthService } from '../services/auth-service'; import { GeoJsonService } from '../services/geo-json'; import { ImageService } from '../services/image-service'; import { SearchService } from '../services/search'; +import { Search2Service } from '../services/search-2'; -export type Service = AuthService | GeoJsonService | ImageService | SearchService; +export type Service = AuthService | GeoJsonService | ImageService | SearchService | AuthProbeService2 | Search2Service; diff --git a/src/services/auth-2.d.ts b/src/services/auth-2.d.ts new file mode 100644 index 0000000..9f3855d --- /dev/null +++ b/src/services/auth-2.d.ts @@ -0,0 +1,167 @@ +// Based on IIIF Auth v2.0 +// https://iiif.io/api/auth/2.0/ + +import { InternationalString } from '../iiif/descriptive'; + +/** + * The user will be required to visit the user interface of an external authentication system + */ +type Active = 'active'; + +/** + * The user will not be required to interact with an authentication system, the client is expected to use the access service automatically. + */ +type Kiosk = 'kiosk'; + +/** + * The user is expected to have already acquired the authorizing aspect, and no access service will be used. + */ +type External = 'external'; + +export type AuthAccessService2 = AuthAccessService2_Active | AuthAccessService2_Kiosk | AuthAccessService2_External; + +interface AuthAccessService2_Common { + id: string; + type: 'AuthAccessService2'; + + // This wasn't clear in the spec. It looked like only `active` was allow to have a logout service. + service: + | [AuthAccessTokenService2] + | [AuthAccessTokenService2, AuthLogoutService2] + | [AuthLogoutService2, AuthAccessTokenService2]; +} + +/** + * This pattern requires the user to interact in the opened tab. Typical scenarios are: + * + * - The user interface presents a login process, in which the user provides credentials to the + * content provider and the content provider sets an access cookie. + * - The user interface presents a usage agreement, a content advisory notice, or some other form + * of clickthrough interaction in which credentials are not required, but deliberate confirmation of + * terms is required, to set an access cookie. + * - The access service stores the result of a user interaction in browser local storage, which is + * later available to the token service. + * + */ +export interface AuthAccessService2_Active extends AuthAccessService2_Common { + profile: 'active'; + /** The name of the access service */ + label: InternationalString; + /** Heading text to be shown with the user interface element that opens the access service. */ + heading?: InternationalString; + /** Additional text to be shown with the user interface element that opens the access service. */ + note?: InternationalString; + /** The label for the user interface element that opens the access service. */ + confirmLabel?: InternationalString; + + // See note above. + // service: + // | [AuthAccessTokenService2] + // | [AuthAccessTokenService2, AuthLogoutService2] + // | [AuthLogoutService2, AuthAccessTokenService2]; +} + +/** + * This pattern requires no user interaction in the opened tab. This pattern supports exhibitions, + * in-gallery interactives and other IIIF user experiences on managed devices that are configured in + * advance. + * + * For the kiosk pattern the interaction has the following steps: + * + * - There is no user interaction before opening the access service URI. + * - he client must immediately open the URI from id with the added origin query parameter. This + * must be done in a new window or tab. + * - After the opened window or tab is closed, the client must then use the related access token + * service, as described below. + * + * Non-user-driven clients simply access the URI from id to obtain any access cookie, and then use the related access token service, as described below. + */ +export interface AuthAccessService2_Kiosk extends AuthAccessService2_Common { + profile: 'kiosk'; + // See note above. + // service: [AuthAccessTokenService2]; + + // This isn't mentioned in the specification, but is in the demos. + label: InternationalString; +} + +export interface AuthAccessService2_External extends AuthAccessService2_Common { + profile: 'external'; + /** The name of the access service */ + label: InternationalString; + + // See note above. + // service: [AuthAccessTokenService2]; +} + +export interface AuthAccessTokenService2 { + id: string; + type: 'AuthAccessTokenService2'; + /** Default heading text to render if an error occurs. If the access token service returns an error object, the heading property of the error object must be used instead if supplied */ + errorHeading?: InternationalString; + /** Default additional text to render if an error occurs. If the access token service returns an error object, the note property of the error object must be used instead if supplied. If present, errorHeading must also be present */ + errorNote?: InternationalString; +} + +export interface AuthAccessToken2 { + '@context': 'http://iiif.io/api/auth/2/context.json'; + type: 'AuthAccessToken2'; + /** The message identifier supplied by the client. */ + messageId: string; + /** The access token to be sent to the probe service. */ + accessToken: string; + /** The number of seconds until the token ceases to be valid. */ + expiresIn: number; +} + +export interface AuthAccessTokenError2 { + '@context': 'http://iiif.io/api/auth/2/context.json'; + type: 'AuthAccessTokenError2'; + profile: 'invalidRequest' | 'invalidOrigin' | 'missingAspect' | 'expiredAspect' | 'unavailable'; + /** The message identifier supplied by the client. */ + messageId: string; + heading?: InternationalString; + note?: InternationalString; +} + +export interface AuthProbeService2 { + id: string; + type: 'AuthProbeService2'; + service: AuthAccessService2[]; + errorHeading?: InternationalString; + errorNote?: InternationalString; +} + +export interface Auth2LocationResource { + id: string; + type: string; + service: any[]; +} + +export interface Auth2SubstituteResource { + id: string; + label: InternationalString; + type: string; + service: AuthProbeService2[]; +} + +export interface AuthProbeResult2 { + '@context': 'http://iiif.io/api/auth/2/context.json'; + + type: 'AuthProbeResult2'; + status: number; + substitute: Auth2SubstituteResource; + location: Auth2LocationResource; + heading: InternationalString; + note: InternationalString; +} + +export interface AuthLogoutService2 { + id: string; + type: 'AuthLogoutService2'; + label: InternationalString; +} + +export type AccessTokenServiceRequest = + | `${S['id']}?origin=${Origin}&messageId=${string}` + | `${S['id']}?&messageId=${string}&origin=${Origin}`; diff --git a/src/services/search-2.d.ts b/src/services/search-2.d.ts new file mode 100644 index 0000000..d309d23 --- /dev/null +++ b/src/services/search-2.d.ts @@ -0,0 +1,107 @@ +// Based on: https://iiif.io/api/search/2.0/ + +import { InternationalString } from '../iiif/descriptive'; +import { Annotation, TextQuoteSelector } from '../resources/annotation'; +import { AnnotationCollection } from '../resources/annotationCollection'; +import { AnnotationPage } from '../resources/annotationPage'; +import { Prettify } from '../utility'; + +// https://iiif.io/api/registry/motivations/ +export interface Search2QueryParams { + q?: string; + motivation?: 'contextualizing' | 'highlighting' | 'commenting' | 'tagging'; + date?: string; + user?: string; +} + +export interface Search2AutocompleteQueryParams extends Search2QueryParams { + min?: number; +} + +export type Search2AnnotationPage = Prettify< + AnnotationPage & { + /** The Annotation Page must have a partOf property. The value is a JSON object, which is the embedded Annotation Collection resource, following the structure defined below. */ + partOf: Prettify< + AnnotationCollection & { + total?: number; + first: { id: string; type: 'AnnotationPage' }; + last?: { id: string; type: 'AnnotationPage' }; + } + >; + /** + * The Annotation Page may have a startIndex property, which is the position of the first Annotation in this page’s items list, relative to the overall ordering of Annotations across all pages within the Annotation Collection. The value is a zero-based integer. + */ + startIndex?: number; + next?: { id: string; type: 'AnnotationPage' }; + prev?: { id: string; type: 'AnnotationPage' }; + /** If the server has ignored any of the parameters in the request, then an ignored property must be present, and must contain a list of the ignored parameters. Servers may omit ignored query parameters from the id of the Annotation Page. */ + ignored?: string[]; + /** + * Clients may require additional information about the matches in order to generate a rich user experience for search. This additional + * information about matches in search results is provided by further Annotations in a property called annotations. This structure + * maintains the distinction in the Presentation API, where the main content annotations are listed in items and additional + * annotations such as comments are listed in annotations. The value of annotations is an array containing a single Annotation + * Page, in which all of the Annotations reference Annotations in the items property. + */ + annotations?: AnnotationPage[]; + } +>; + +export type Search2ContextualizingAnnotation = Prettify< + Annotation & { + motivation: 'contextualizing'; + target: { + type: 'SpecificResource'; + source: string; + selector: TextQuoteSelector[]; + }; + } +>; + +export interface TermPage { + '@context': 'http://iiif.io/api/search/2/context.json'; + type: 'TermPage'; + ignored?: string[]; + items: Term; +} + +/* +Term resources have the following properties: + +type - The Term may have a type property. If present, the value must be Term. The use of the property is not recommended to keep the response shorter. +value - The Term must have a value property. The value is a the string form of the term. +total - The Term may have a total property. The value is an integer, which is the number of times the term occurs in the index. +label - The Term may have a label property. The value is a JSON object which follows the definition of a language map. This label should be displayed to the user instead of the value, for example when the value is a URI or a string that has been manipulated with stemming or other normalization. +language - The Term may have a language property. The value is a string conforming to the BCP 47 language code specification, and gives the language of the term string in the value property. +service - The Term may have a service property. The value is an array of JSON objects, where each object is a Service. The Term must include an entry for the full link to the related SearchService2, when the value cannot be used directly in the q parameter. In this case, the id of the service is the full link including the q and other parameters. +*/ +export interface Term { + /** The Term may have a type property. If present, the value must be Term. The use of the property is not recommended to keep the response shorter. */ + type: 'Term'; + /** The Term must have a value property. The value is a the string form of the term. */ + value: string; + /** The Term may have a total property. The value is an integer, which is the number of times the term occurs in the index. */ + total?: number; + /** The Term may have a label property. The value is a JSON object which follows the definition of a language map. This label should be displayed to the user instead of the value, for example when the value is a URI or a string that has been manipulated with stemming or other normalization. */ + label?: InternationalString; + /** The Term may have a language property. The value is a string conforming to the BCP 47 language code specification, and gives the language of the term string in the value property. */ + language?: string; + /** The Term may have a service property. The value is an array of JSON objects, where each object is a Service. The Term must include an entry for the full link to the related SearchService2, when the value cannot be used directly in the q parameter. In this case, the id of the service is the full link including the q and other parameters. */ + service?: Search2Service[]; +} + +// An alias +export type Search2AutocompleteResponse = TermPage; + +export interface AutoCompleteService2 { + id: string; + type: 'AutoCompleteService2'; + label?: InternationalString; +} + +export interface Search2Service { + id: string; + type: 'SearchService2'; + label?: InternationalString; + service?: [AutoCompleteService2]; +} diff --git a/tests/manifest.test-d.ts b/tests/manifest.test-d.ts index 544737e..e48e0b2 100644 --- a/tests/manifest.test-d.ts +++ b/tests/manifest.test-d.ts @@ -1,4 +1,5 @@ import { Manifest } from '../src/resources/manifest'; +import { AuthProbeService2 } from '../src/services/auth-2'; import { ImageService, ImageService3 } from '../src/services/image-service'; const cookbook1: Manifest = { @@ -200,3 +201,317 @@ const imageService2: ImageService3 = { type: 'ImageService3', width: 3497, }; + +const auth2_1: AuthProbeService2 = { + id: 'https://iiif-auth2-server.herokuapp.com/probe/01_Icarus_Breughel.jpg', + type: 'AuthProbeService2', + service: [ + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/access/active-login/01_Icarus_Breughel.jpg', + type: 'AuthAccessService2', + profile: 'active', + service: [ + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/token/active-login/01_Icarus_Breughel.jpg', + type: 'AuthAccessTokenService2', + errorHeading: { + en: ['Authentication Failed'], + }, + errorNote: { + en: ['Access Policy'], + }, + }, + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/logout/active-login/01_Icarus_Breughel.jpg', + type: 'AuthLogoutService2', + label: { + en: ['Log out'], + }, + }, + ], + label: { + en: ['Login to Example Institution'], + }, + heading: { + en: ['Please Log In'], + }, + note: { + en: ['Example Institution requires that you log in with your example account to view this content.'], + }, + confirmLabel: { + en: ['Login'], + }, + }, + ], +}; + +const auth2_2: AuthProbeService2 = { + id: 'https://iiif-auth2-server.herokuapp.com/probe/02_gauguin.jpg', + type: 'AuthProbeService2', + service: [ + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/access/active-login/02_gauguin.jpg', + type: 'AuthAccessService2', + profile: 'active', + service: [ + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/token/active-login/02_gauguin.jpg', + type: 'AuthAccessTokenService2', + errorHeading: { + en: ['Viewing greyscale version'], + }, + errorNote: { + en: [ + 'You don\'t appear to have access to the full colour version. Access Policy', + ], + }, + }, + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/logout/active-login/02_gauguin.jpg', + type: 'AuthLogoutService2', + label: { + en: ['Log out'], + }, + }, + ], + label: { + en: ['Login to Example Institution for full quality'], + }, + heading: { + en: ['Please Log In'], + }, + note: { + en: [ + 'Example Institution requires that you log in with your example account to view the full-quality content.', + ], + }, + confirmLabel: { + en: ['Login'], + }, + }, + ], +}; + +const auth2_3_clickthrough: AuthProbeService2 = { + id: 'https://iiif-auth2-server.herokuapp.com/probe/03_clickthrough.jpg', + type: 'AuthProbeService2', + service: [ + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/access/active-clickthrough/03_clickthrough.jpg', + type: 'AuthAccessService2', + profile: 'active', + service: [ + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/token/active-clickthrough/03_clickthrough.jpg', + type: 'AuthAccessTokenService2', + errorHeading: { + en: ['Terms of Use Not Accepted'], + }, + errorNote: { + en: ['You must accept the terms of use to see the content.'], + }, + }, + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/logout/active-clickthrough/03_clickthrough.jpg', + type: 'AuthLogoutService2', + label: { + en: ['Log out'], + }, + }, + ], + label: { + en: ['Terms of Use for Example Institution'], + }, + heading: { + en: ['Restricted Material with Terms of Use'], + }, + note: { + en: ['... terms of use ... '], + }, + confirmLabel: { + en: ['I Agree'], + }, + }, + ], +}; + +const auth2_4_kiosk: AuthProbeService2 = { + id: 'https://iiif-auth2-server.herokuapp.com/probe/04_gene_cernan.jpg', + type: 'AuthProbeService2', + service: [ + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/access/kiosk/04_gene_cernan.jpg', + type: 'AuthAccessService2', + profile: 'kiosk', + service: [ + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/token/kiosk/04_gene_cernan.jpg', + type: 'AuthAccessTokenService2', + errorHeading: { + en: ['Ooops!'], + }, + errorNote: { + en: ['Call Bob at ext. 1234 to reboot the cookie server'], + }, + }, + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/logout/kiosk/04_gene_cernan.jpg', + type: 'AuthLogoutService2' as const, + label: { + en: ['Log out'], + }, + }, + ], + label: { + en: ['Internal cookie granting service'], + }, + }, + ], +}; + +const auth2_5_external: AuthProbeService2 = { + id: 'https://iiif-auth2-server.herokuapp.com/probe/05_cader_idris.jpg', + type: 'AuthProbeService2', + service: [ + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/access/external/05_cader_idris.jpg', + type: 'AuthAccessService2', + profile: 'external', + service: [ + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/token/external/05_cader_idris.jpg', + type: 'AuthAccessTokenService2', + errorHeading: { + en: ['Restricted Material'], + }, + errorNote: { + en: ['This material is not viewable without prior agreement'], + }, + }, + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/logout/external/05_cader_idris.jpg', + type: 'AuthLogoutService2' as const, + label: { + en: ['Log out'], + }, + }, + ], + label: { + en: ['External Authentication Required'], + }, + }, + ], +}; + +const auth2_6_shared: AuthProbeService2 = { + id: 'https://iiif-auth2-server.herokuapp.com/probe/06_1959.jpg', + type: 'AuthProbeService2', + service: [ + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/access/active-login/shared', + type: 'AuthAccessService2', + profile: 'active', + service: [ + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/token/active-login/shared', + type: 'AuthAccessTokenService2', + errorHeading: { + en: ['Authentication Failed'], + }, + errorNote: { + en: ['Access Policy'], + }, + }, + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/logout/active-login/shared', + type: 'AuthLogoutService2', + label: { + en: ['Log out'], + }, + }, + ], + label: { + en: ['Login to Example Institution'], + }, + heading: { + en: ['Please Log In'], + }, + note: { + en: ['You can still use the service information to vary the strings presented to the user.'], + }, + confirmLabel: { + en: ['Login'], + }, + }, + ], +}; + +const auth2_7_multiple: AuthProbeService2 = { + id: 'https://iiif-auth2-server.herokuapp.com/probe/08_portmeirion.jpg', + type: 'AuthProbeService2', + service: [ + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/access/active-clickthrough/08_portmeirion.jpg', + type: 'AuthAccessService2', + profile: 'active', + service: [ + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/token/active-clickthrough/08_portmeirion.jpg', + type: 'AuthAccessTokenService2', + errorHeading: { + en: ['Terms of Use Not Accepted'], + }, + errorNote: { + en: ['You must accept the terms of use to see the content.'], + }, + }, + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/logout/active-clickthrough/08_portmeirion.jpg', + type: 'AuthLogoutService2', + label: { + en: ['Log out'], + }, + }, + ], + label: { + en: ['Terms of Use for Example Institution'], + }, + heading: { + en: ['Restricted Material with Terms of Use'], + }, + note: { + en: ['... terms of use ... '], + }, + confirmLabel: { + en: ['I Agree'], + }, + }, + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/access/external/08_portmeirion.jpg', + type: 'AuthAccessService2', + profile: 'external', + service: [ + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/token/external/08_portmeirion.jpg', + type: 'AuthAccessTokenService2', + errorHeading: { + en: ['Restricted Material'], + }, + errorNote: { + en: ['This material is not viewable without prior agreement'], + }, + }, + { + id: 'https://iiif-auth2-server.herokuapp.com/auth/logout/external/08_portmeirion.jpg', + type: 'AuthLogoutService2', + label: { + en: ['Log out'], + }, + }, + ], + label: { + en: ['External Authentication Required'], + }, + }, + ], +}; diff --git a/yarn.lock b/yarn.lock index 8707c01..4eeaaae 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1211,10 +1211,10 @@ prettier-linter-helpers@^1.0.0: dependencies: fast-diff "^1.1.2" -prettier@^2.7.1: - version "2.8.8" - resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.8.tgz#e8c5d7e98a4305ffe3de2e1fc4aca1a71c28b1da" - integrity sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q== +prettier@^3.2.5: + version "3.2.5" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.2.5.tgz#e52bc3090586e824964a8813b09aba6233b28368" + integrity sha512-3/GWa9aOC0YeD7LUfvOG2NiDyhOWRvt1k+rcKhOuYnMY24iiCphgneUfJDyFXd6rZCAnuLBv6UeAULtrhT/F4A== pretty-format@^29.7.0: version "29.7.0"