UNPKG

digitaltwin-core

Version:

Minimalist framework to collect and handle data in a Digital Twin project

414 lines 13.5 kB
import type { Component, Servable } from './interfaces.js'; import type { ComponentConfiguration, DataResponse } from './types.js'; import type { HttpMethod } from '../engine/endpoints.js'; import type { StorageService } from '../storage/storage_service.js'; import type { DatabaseAdapter, MetadataRow } from '../database/database_adapter.js'; import type { DataRecord } from '../types/data_record.js'; /** * Extended metadata row for assets with additional fields. * This will be stored as separate columns in the database table. * * @interface AssetMetadataRow * @extends {MetadataRow} * * @example * ```typescript * const assetMeta: AssetMetadataRow = { * name: 'gltf', * type: 'model/gltf-binary', * url: '/storage/gltf/model.glb', * date: new Date(), * description: '3D building model', * source: 'https://example.com/data-source', * owner_id: 'user123', * filename: 'building.glb' * } * ``` */ export interface AssetMetadataRow extends MetadataRow { /** Human-readable description of the asset */ description: string; /** Source URL for data provenance and licensing compliance (must be valid URL) */ source: string; /** ID of the user who owns this asset (for access control) */ owner_id: string | null; /** Original filename provided by the user */ filename: string; } /** * Request payload for creating a new asset. * * @interface CreateAssetRequest * * @example * ```typescript * const request: CreateAssetRequest = { * description: '3D model of building', * source: 'https://city-data.example.com/buildings', * owner_id: 'user123', * filename: 'building.glb', * file: fileBuffer * } * ``` */ export interface CreateAssetRequest { /** Human-readable description of the asset */ description: string; /** Source URL for data provenance (validated as proper URL) */ source: string; /** Owner user ID for access control (can be null) */ owner_id: string | null; /** Original filename */ filename: string; /** File content as Buffer */ file: Buffer; } /** * Request payload for updating asset metadata. * * @interface UpdateAssetRequest * * @example * ```typescript * const updates: UpdateAssetRequest = { * description: 'Updated building model with new textures', * source: 'https://updated-source.example.com' * } * ``` */ export interface UpdateAssetRequest { /** Updated description (optional) */ description?: string; /** Updated source URL (optional, validated if provided) */ source?: string; } /** * Abstract base class for Assets Manager components. * * Provides file upload, storage, and retrieval capabilities following the Digital Twin framework patterns. * Each concrete implementation manages a specific type of asset and creates its own database table. * * @abstract * @class AssetsManager * @implements {Component} * @implements {Servable} * * @example * ```typescript * // Create concrete implementations for different asset types * class GLTFAssetsManager extends AssetsManager { * getConfiguration() { * return { name: 'gltf', description: 'GLTF 3D models manager', ... } * } * } * * class PointCloudAssetsManager extends AssetsManager { * getConfiguration() { * return { name: 'pointcloud', description: 'Point cloud data manager', ... } * } * } * * // Usage in engine * const gltfManager = new GLTFAssetsManager() * gltfManager.setDependencies(database, storage) * * // Each creates its own table and endpoints: * // - GLTFAssetsManager → table 'gltf', endpoints /gltf/* * // - PointCloudAssetsManager → table 'pointcloud', endpoints /pointcloud/* * ``` * * @remarks * Asset metadata is stored as dedicated columns in the database table: * - id, name, url, date (standard columns) * - description, source, owner_id, filename (asset-specific columns) * * Each concrete AssetsManager creates its own table based on the configuration name. */ export declare abstract class AssetsManager implements Component, Servable { protected db: DatabaseAdapter; protected storage: StorageService; /** * Injects dependencies into the assets manager. * * Called by the framework during component initialization. * * @param {DatabaseAdapter} db - The database adapter for metadata storage * @param {StorageService} storage - The storage service for file persistence * * @example * ```typescript * const assetsManager = new MyAssetsManager() * assetsManager.setDependencies(databaseAdapter, storageService) * ``` */ setDependencies(db: DatabaseAdapter, storage: StorageService): void; /** * Returns the configuration of the assets manager. * * Must be implemented by subclasses to define the asset type, * table name, and content types. * * @abstract * @returns {ComponentConfiguration} The component configuration * * @example * ```typescript * class GLTFAssetsManager extends AssetsManager { * getConfiguration(): ComponentConfiguration { * return { * name: 'gltf', * description: 'GLTF 3D models manager', * contentType: 'model/gltf-binary', * tags: ['assets', '3d', 'gltf'] * } * } * } * ``` */ abstract getConfiguration(): ComponentConfiguration; /** * Validates that a source string is a valid URL. * * Used internally to ensure data provenance URLs are properly formatted. * * @private * @param {string} source - The source URL to validate * @returns {boolean} True if the source is a valid URL, false otherwise * * @example * ```typescript * this.validateSourceURL('https://example.com/data') // returns true * this.validateSourceURL('not-a-url') // returns false * ``` */ private validateSourceURL; /** * Upload a new asset file with metadata. * * Stores the file using the storage service and saves metadata to the database. * Asset metadata is stored as dedicated columns in the database table. * * @param {CreateAssetRequest} request - The asset upload request * @throws {Error} If source URL is invalid * * @example * ```typescript * await assetsManager.uploadAsset({ * description: '3D building model', * source: 'https://city-data.example.com/buildings', * owner_id: 'user123', * filename: 'building.glb', * file: fileBuffer * }) * ``` */ uploadAsset(request: CreateAssetRequest): Promise<void>; /** * Retrieve all assets for this component (like other components). * * Returns a JSON list of all assets with their metadata, following the * framework pattern but adapted for assets management. * * @returns {Promise<DataResponse>} JSON response with all assets */ retrieve(): Promise<DataResponse>; /** * Get all assets for this component type. * * Retrieves all assets managed by this component, with their metadata. * Uses a very old start date to get all records. * * @returns {Promise<DataRecord[]>} Array of all asset records * * @example * ```typescript * const allAssets = await assetsManager.getAllAssets() * // Returns: [{ id, name, type, url, date, contentType }, ...] * ``` */ getAllAssets(): Promise<DataRecord[]>; /** * Get asset by specific ID. * * @param {string} id - The asset ID to retrieve * @returns {Promise<DataRecord | undefined>} The asset record or undefined if not found * * @example * ```typescript * const asset = await assetsManager.getAssetById('123') * if (asset) { * const fileData = await asset.data() * } * ``` */ getAssetById(id: string): Promise<DataRecord | undefined>; /** * Update asset metadata by ID. * * Updates the metadata (description and/or source) of a specific asset. * Asset metadata is stored as dedicated columns in the database. * * @param {string} id - The ID of the asset to update * @param {UpdateAssetRequest} updates - The metadata updates to apply * @throws {Error} If source URL is invalid or asset not found * * @example * ```typescript * await assetsManager.updateAssetMetadata('123', { * description: 'Updated building model with new textures', * source: 'https://updated-source.example.com' * }) * ``` */ updateAssetMetadata(id: string, updates: UpdateAssetRequest): Promise<void>; /** * Delete asset by ID. * * Removes a specific asset. * * @param {string} id - The ID of the asset to delete * @throws {Error} If asset not found or doesn't belong to this component * * @example * ```typescript * await assetsManager.deleteAssetById('123') * ``` */ deleteAssetById(id: string): Promise<void>; /** * Delete latest asset (simplified) * * Removes the most recently uploaded asset for this component type. * * @throws {Error} If no assets exist to delete * * @example * ```typescript * await assetsManager.deleteLatestAsset() * ``` */ deleteLatestAsset(): Promise<void>; /** * Upload multiple assets in batch for better performance * * @param {CreateAssetRequest[]} requests - Array of asset upload requests * @throws {Error} If any source URL is invalid * * @example * ```typescript * await assetsManager.uploadAssetsBatch([ * { description: 'Model 1', source: 'https://example.com/1', file: buffer1, ... }, * { description: 'Model 2', source: 'https://example.com/2', file: buffer2, ... } * ]) * ``` */ uploadAssetsBatch(requests: CreateAssetRequest[]): Promise<void>; /** * Delete multiple assets by IDs in batch * * @param {string[]} ids - Array of asset IDs to delete * @throws {Error} If any asset not found or doesn't belong to this component */ deleteAssetsBatch(ids: string[]): Promise<void>; /** * Get endpoints following the framework pattern */ /** * Get HTTP endpoints exposed by this assets manager. * * Returns the standard CRUD endpoints following the framework pattern. * * @returns {Array} Array of endpoint descriptors with methods, paths, and handlers * * @example * ```typescript * // For a manager with assetType: 'gltf', provides: * GET /gltf - Get all assets * POST /gltf/upload - Upload new asset * GET /gltf/123 - Get specific asset * PUT /gltf/123 - Update asset metadata * GET /gltf/123/download - Download asset * DELETE /gltf/123 - Delete asset * ``` */ getEndpoints(): Array<{ method: HttpMethod; path: string; handler: (...args: any[]) => any; responseType?: string; }>; /** * Handle upload endpoint */ handleUpload(req: any): Promise<DataResponse>; /** * Handle update endpoint (PUT). * * Updates metadata for a specific asset by ID. * * @param {any} req - HTTP request object with params.id and body containing updates * @returns {Promise<DataResponse>} HTTP response * * @example * ```typescript * // PUT /gltf/123 * // Body: { "description": "Updated model", "source": "https://new-source.com" } * ``` */ handleUpdate(req: any): Promise<DataResponse>; /** * Handle get asset endpoint (GET). * * Returns the file content of a specific asset by ID for display/use in front-end. * No download headers - just the raw file content. * * @param {any} req - HTTP request object with params.id * @returns {Promise<DataResponse>} HTTP response with file content * * @example * ```typescript * // GET /gltf/123 * // Returns the .glb file content for display in 3D viewer * ``` */ handleGetAsset(req: any): Promise<DataResponse>; /** * Handle download endpoint (GET). * * Downloads the file content of a specific asset by ID with download headers. * Forces browser to download the file rather than display it. * * @param {any} req - HTTP request object with params.id * @returns {Promise<DataResponse>} HTTP response with file content and download headers * * @example * ```typescript * // GET /gltf/123/download * // Returns the .glb file with download headers - browser will save it * ``` */ handleDownload(req: any): Promise<DataResponse>; /** * Handle delete endpoint (DELETE). * * Deletes a specific asset by ID. * * @param {any} req - HTTP request object with params.id * @returns {Promise<DataResponse>} HTTP response * * @example * ```typescript * // DELETE /gltf/123 * ``` */ handleDelete(req: any): Promise<DataResponse>; /** * Handle batch upload endpoint */ handleUploadBatch(req: any): Promise<DataResponse>; /** * Handle batch delete endpoint */ handleDeleteBatch(req: any): Promise<DataResponse>; } //# sourceMappingURL=assets_manager.d.ts.map