Skip to content

Commit

Permalink
Merge pull request #209 from IIIF-Commons/feature/more-apis
Browse files Browse the repository at this point in the history
More APIs
  • Loading branch information
stephenwf committed Mar 4, 2024
2 parents fabc557 + a4075bc commit 6fb5253
Show file tree
Hide file tree
Showing 9 changed files with 729 additions and 7 deletions.
3 changes: 3 additions & 0 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';
Expand All @@ -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';
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
126 changes: 126 additions & 0 deletions src/change-discovery.d.ts
Original file line number Diff line number Diff line change
@@ -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<ChangeDiscoveryActivityType, 'Move'>;
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[];
};
4 changes: 3 additions & 1 deletion src/resources/annotation.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ export type W3CMotivation =
| 'moderating'
| 'questioning'
| 'replying'
| 'tagging';
| 'tagging'
// Search2
| 'contextualizing';

export type AnyMotivation = LiteralUnion<W3CMotivation>;

Expand Down
4 changes: 3 additions & 1 deletion src/resources/service.d.ts
Original file line number Diff line number Diff line change
@@ -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;
167 changes: 167 additions & 0 deletions src/services/auth-2.d.ts
Original file line number Diff line number Diff line change
@@ -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 extends AuthAccessTokenService2, Origin extends string> =
| `${S['id']}?origin=${Origin}&messageId=${string}`
| `${S['id']}?&messageId=${string}&origin=${Origin}`;
Loading

0 comments on commit 6fb5253

Please sign in to comment.