cleanup
This commit is contained in:
+17
-117
@@ -1,10 +1,10 @@
|
||||
import type { Identifier } from './types/identifiers';
|
||||
import type { AssetObject, AssetLike } from './types/assets';
|
||||
import type { Asset } from './types/assets';
|
||||
import type { DocumentVersion, Document } from './types/documents';
|
||||
|
||||
type Nullable<T> = T | null;
|
||||
|
||||
export type { AssetObject, AssetLike, DocumentVersion as DocumentVersionLike, Document };
|
||||
export type { Asset, DocumentVersion as DocumentVersionLike, Document };
|
||||
|
||||
export const resolveAssetExpiresAt = (asset?: { download?: { expires_at: number } | null } | null): number | null =>
|
||||
asset?.download?.expires_at ?? null;
|
||||
@@ -14,16 +14,16 @@ export const resolveAssetUrl = (asset?: { download?: { url: string } | null } |
|
||||
|
||||
export type EnsureAssetUrl = (
|
||||
documentId: Identifier,
|
||||
asset: AssetLike,
|
||||
asset: Asset,
|
||||
options?: { force?: boolean;[key: string]: unknown },
|
||||
) => Promise<unknown>;
|
||||
|
||||
export type GetAsset = (document: Document, assetType: string) => Nullable<AssetLike>;
|
||||
export type GetAsset = (document: Document, assetType: string) => Nullable<Asset>;
|
||||
|
||||
export const getAssetFromGroup = (
|
||||
assets?: AssetLike[] | Record<string, AssetLike> | null,
|
||||
assets?: Asset[] | Record<string, Asset> | null,
|
||||
assetType: string = '',
|
||||
): Nullable<AssetLike> => {
|
||||
): Nullable<Asset> => {
|
||||
if (!assetType || !assets) {
|
||||
return null;
|
||||
}
|
||||
@@ -42,97 +42,7 @@ export const getAssetFromVersion = (currentVersion: Nullable<DocumentVersion>, a
|
||||
return getAssetFromGroup(currentVersion.assets, assetType);
|
||||
};
|
||||
|
||||
const normalizeAssetObjects = (objects?: AssetObject[] | null): AssetObject[] => {
|
||||
if (!Array.isArray(objects)) {
|
||||
return [];
|
||||
}
|
||||
return objects
|
||||
.filter((entry) => Number.isInteger(entry?.ordinal))
|
||||
.slice()
|
||||
.sort((a, b) => a.ordinal - b.ordinal);
|
||||
};
|
||||
|
||||
export class AssetView {
|
||||
asset: AssetLike | null;
|
||||
private _objectsRef: AssetObject[] | null;
|
||||
private _sortedObjects: AssetObject[];
|
||||
|
||||
constructor(asset?: AssetLike | null) {
|
||||
this.asset = asset || null;
|
||||
this._objectsRef = null;
|
||||
this._sortedObjects = [];
|
||||
}
|
||||
|
||||
getCardinality(): number {
|
||||
if (!this.asset) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
const objectsCount = this.getObjects().length;
|
||||
if (objectsCount > 0) {
|
||||
return objectsCount;
|
||||
}
|
||||
|
||||
if (this.asset.url || this.asset.metadata) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
getObjects(): AssetObject[] {
|
||||
if (!this.asset || !Array.isArray(this.asset.objects) || this.asset.objects.length === 0) {
|
||||
return [];
|
||||
}
|
||||
|
||||
if (this._objectsRef === this.asset.objects) {
|
||||
return this._sortedObjects;
|
||||
}
|
||||
|
||||
this._objectsRef = this.asset.objects;
|
||||
this._sortedObjects = normalizeAssetObjects(this.asset.objects);
|
||||
return this._sortedObjects;
|
||||
}
|
||||
|
||||
getObject(ordinal = 1): AssetObject | null {
|
||||
const fromObjects = this.getObjects().find((entry) => entry.ordinal === ordinal);
|
||||
if (fromObjects) {
|
||||
return fromObjects;
|
||||
}
|
||||
|
||||
if (ordinal === 1 && this.asset) {
|
||||
const primaryUrl = resolveAssetUrl(this.asset);
|
||||
if (primaryUrl || this.asset.metadata) {
|
||||
return {
|
||||
ordinal: 1,
|
||||
url: primaryUrl || null,
|
||||
metadata: this.asset.metadata || null,
|
||||
expires_at: resolveAssetExpiresAt(this.asset),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
getPrimaryObject(): AssetObject | null {
|
||||
return this.getObject(1);
|
||||
}
|
||||
|
||||
getPrimaryMetadata(): Record<string, unknown> | null {
|
||||
return this.getPrimaryObject()?.metadata || null;
|
||||
}
|
||||
|
||||
getPrimaryUrl(): string | null {
|
||||
return this.getPrimaryObject()?.url || null;
|
||||
}
|
||||
|
||||
hasObject(ordinal: number): boolean {
|
||||
return Boolean(this.getObject(ordinal));
|
||||
}
|
||||
}
|
||||
|
||||
export const createAssetView = (asset?: AssetLike | null): AssetView => new AssetView(asset);
|
||||
|
||||
export const resolveDocumentAssetUrl = (
|
||||
doc: Nullable<Document>,
|
||||
@@ -154,10 +64,8 @@ export const resolveDocumentAssetUrl = (
|
||||
if (!asset) {
|
||||
return null;
|
||||
}
|
||||
const view = createAssetView(asset);
|
||||
const object = view.getPrimaryObject();
|
||||
const url = object?.url || view.getPrimaryUrl();
|
||||
const expiresAt = object?.expires_at ?? resolveAssetExpiresAt(asset);
|
||||
const url = resolveAssetUrl(asset);
|
||||
const expiresAt = resolveAssetExpiresAt(asset);
|
||||
const now = Date.now();
|
||||
if (url && (!expiresAt || expiresAt > now)) {
|
||||
return url;
|
||||
@@ -174,22 +82,22 @@ export const resolveDocumentAssetUrl = (
|
||||
};
|
||||
|
||||
class AssetManager {
|
||||
fetchAsset: ((id: Identifier) => Promise<AssetLike | null>) | null;
|
||||
fetchAsset: ((id: Identifier) => Promise<Asset | null>) | null;
|
||||
|
||||
assetCache: Map<Identifier, AssetLike>;
|
||||
assetInflight: Map<string, Promise<AssetLike | null>>;
|
||||
assetCache: Map<Identifier, Asset>;
|
||||
assetInflight: Map<string, Promise<Asset | null>>;
|
||||
|
||||
constructor({ fetchAsset }: { fetchAsset: ((id: Identifier) => Promise<AssetLike | null>) | null }) {
|
||||
constructor({ fetchAsset }: { fetchAsset: ((id: Identifier) => Promise<Asset | null>) | null }) {
|
||||
this.fetchAsset = fetchAsset;
|
||||
this.assetCache = new Map();
|
||||
this.assetInflight = new Map();
|
||||
}
|
||||
|
||||
setFetchAsset(fetchAsset: ((id: Identifier) => Promise<AssetLike | null>) | null) {
|
||||
setFetchAsset(fetchAsset: ((id: Identifier) => Promise<Asset | null>) | null) {
|
||||
this.fetchAsset = fetchAsset;
|
||||
}
|
||||
|
||||
rememberAsset(entry?: Nullable<AssetLike>) {
|
||||
rememberAsset(entry?: Nullable<Asset>) {
|
||||
if (entry?.id) {
|
||||
this.assetCache.set(entry.id, entry);
|
||||
}
|
||||
@@ -197,26 +105,18 @@ class AssetManager {
|
||||
|
||||
ensureAsset(
|
||||
documentId?: Identifier | null,
|
||||
asset?: Nullable<AssetLike>,
|
||||
asset?: Nullable<Asset>,
|
||||
{ force = false }: { force?: boolean } = {},
|
||||
): Promise<Nullable<AssetLike>> {
|
||||
): Promise<Nullable<Asset>> {
|
||||
if (!documentId || !asset?.id) {
|
||||
return Promise.resolve(asset);
|
||||
}
|
||||
|
||||
const baseAsset = this.assetCache.get(asset.id) || asset;
|
||||
const view = createAssetView(baseAsset);
|
||||
const assetExpiresAt = resolveAssetExpiresAt(baseAsset);
|
||||
const now = Date.now();
|
||||
|
||||
const isPrimarySatisfied = () => {
|
||||
const object = view.getObject(1);
|
||||
if (object?.url) {
|
||||
const objectExpiresAt = object.expires_at ?? null;
|
||||
if (!objectExpiresAt || objectExpiresAt > now) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
const assetUrl = resolveAssetUrl(baseAsset);
|
||||
if (assetUrl && (!assetExpiresAt || assetExpiresAt > now)) {
|
||||
return true;
|
||||
@@ -243,7 +143,7 @@ class AssetManager {
|
||||
return Promise.reject(new Error('AssetManager fetcher is not configured.'));
|
||||
}
|
||||
|
||||
const request: Promise<AssetLike | null> = this.fetchAsset(asset.id)
|
||||
const request: Promise<Asset | null> = this.fetchAsset(asset.id)
|
||||
.then((data) => {
|
||||
if (!data) return null;
|
||||
const cachedEntry = this.assetCache.get(asset.id) || baseAsset;
|
||||
|
||||
Reference in New Issue
Block a user