There are 3 APIs available for loading resources.
These are functionally identical, but the Typescript types returned are more specific for loadManifest
and loadCollection
. The remaining examples will all use .loadManifest()
.
When you call a load function a promise will always be returned, even if the data is cached and available.
import { Vault } from '@iiif/vault';
const vault = new Vault();
vault.loadManifest(`https://example.org/manifest`).then(manifest => {
// Do something with manifest.
});
If you are using in a context that supports
When you call a loader a status object will be created.
interface ResourceStatus {
loadingState: 'RESOURCE_ERROR' | 'RESOURCE_LOADING' | 'RESOURCE_READY';
uriMismatch: boolean;
requestUri: string;
resourceUri: string;
error?: string;
}
As soon as you call a load function the resource will transition to RESOURCE_LOADING
if it has not already been
fetched. It will then either progress to RESOURCE_ERROR
with status.error
populated with the text representation of
the exception, or it will progress to RESOURCE_READY
.
If the URL requested does not match the @id
or id
in the returned JSON then a mapping will be kept. In the status
there are 2 urls noted.
requestUri
- the string passed to load()
and the one requestedresourceUri
- the Identifier present in the resource (id
or @id
)uriMismatch
- True if the two Uris above do not matchInternally this allows vault to get a handle on the Manifest using either the URI or the Identifier of the resource. For all internal maps the Identifier is preferred, not the Uri.
Currently, there is no way to "evict" a resource from Vault.
Two helpers relating to status
vault.requestStatus(id)
- returns the current status, or undefinedvault.ensureLoaded(id)
- similar to load, but does not return anything. Only calls fetcher if there is no status. Additionally it will not retry errors. Useful for prefetch
or similar scenarios.const status = vault.requestStatus('https://example.org/manifest');
if (status) {
switch (status.loadingState) {
case 'RESOURCE_READY':
// ...
case 'RESOURCE_LOADING':
// ...
case 'RESOURCE_ERROR':
// ...
}
}
When you load a IIIF resource into Vault, a check will be made to see if conforms to the IIIF Presentation 2.1 specification. If the v2 context is found, the IIIF resource will be sent through an upgrade path. This aims to upgrade all 2.1 resource to IIIF Presentation 3.0 and in the future will upgrade to whichever is the latest version. You can read in detail how this works in the Upgrading section.
When reading IIIF resources loaded by vault, you can safely assume that they will be well-formed Presentation 3. This should reduce that code required to support features while still supporting as wide a range of IIIF as possible.
Currently, if you load Presentation 3 resources into Vault, no attempt will be made to fix any common mistakes or irregular IIIF. In the future this will change, with the current behaviour being an optional Strict Mode and a new compatibility mode will be introduced. This will allow Vault and the associated tools and types to be used as a way to validate IIIF for those implementing it. If Vault only had this loose/compatibility mode it could run the risk of incorrectly validating bugs from those creating IIIF implementations themselves.
There are some cases where you may want to load IIIF JSON before it goes to Vault. This could be for Authenticated resources
or resources that may not have been saved yet - or may not ever be saved. For each of the load()
methods on Vault there is
an optional second argument for the JSON to be provided.
const manifest = await vault.load('https://example.org/manifest-1', {
'@context': 'http://iiif.io/api/presentation/3/context.json'
id: 'https://example.org/manifest-1',
type: 'Manifest',
...
})
This will still return a promise, for consistency. Check the advanced docs if you need to load data into Vault synchronously.
When calling a load function in the browser, the native fetch()
api is used. You will need to provide a polyfill for this
if you need to target browser that do not support this.
Starting from Node 18+ you can use the built-in fetch()
api. Prior versions of Node will include the node-fetch
library
for fetching resources.
When you create a Vault you can optionally pass in a custom fetcher function.
import { Vault } from '@iiif/vault';
const customVault = new Vault({
customFetcher: async (url) => {
// custom loading logic.
},
})
This can either return a promise or just the javascript object for the resource.
If you need to completely replace the fetching mechanism, but retain the loading statuses provided by Vault, you can create a custom loader. This is included as a separate export.
import { createFetchHelper } from '@iiif/vault/utility';
const vault = new Vault();
const newFetch = createFetchHelper(vault.store, async (url, options) => {
// custom logic..
});
await newFetch('htts://example.org/manifest-1', { some: 'custom option' });
This custom fetcher will be tied to the store you created. Like the custom fetcher in Vault it should return the loaded
resource as a JS object. You can create as many of these custom fetch helpers for a single vault. Creating these fetchers
will not replace the vault.load()
functions, they continue to work.
In the browser, fetch()
is used without any arguments or CORS settings. This may be a common use-case for overwriting
the default fetcher if you required cookies to be sent to authenticate resources. Vault will not retry resources that run
into CORS errors. The most common cause of CORS errors is 5xx errors with Vault.